wip
This commit is contained in:
		
							
								
								
									
										34
									
								
								source/firmware/arch/stm32f4xx/driver/include/stm32f4_pwm.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								source/firmware/arch/stm32f4xx/driver/include/stm32f4_pwm.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,34 @@
 | 
			
		||||
/*
 | 
			
		||||
 * stm32f4_pwm.h
 | 
			
		||||
 *
 | 
			
		||||
 *  Created on: Aug 9, 2016
 | 
			
		||||
 *      Author: tkl
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef SOURCE_FIRMWARE_ARCH_STM32F4XX_DRIVER_INCLUDE_STM32F4_PWM_H_
 | 
			
		||||
#define SOURCE_FIRMWARE_ARCH_STM32F4XX_DRIVER_INCLUDE_STM32F4_PWM_H_
 | 
			
		||||
 | 
			
		||||
enum stm32f4_pwm_channel {
 | 
			
		||||
	channel_1 = 1,
 | 
			
		||||
	channel_2,
 | 
			
		||||
	channel_3,
 | 
			
		||||
	channel_4
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct stm32f4_pwm {
 | 
			
		||||
	TIM_TypeDef *timer;
 | 
			
		||||
	const TIM_TimeBaseInitTypeDef *timer_cfg;
 | 
			
		||||
	const TIM_OCInitTypeDef *output_compare_cfg;
 | 
			
		||||
	const TIM_BDTRInitTypeDef *bdtr_cfg;
 | 
			
		||||
	GPIO_TypeDef *port;
 | 
			
		||||
	uint8_t pin_src;
 | 
			
		||||
	const GPIO_InitTypeDef *port_cfg;
 | 
			
		||||
	enum stm32f4_pwm_channel channel;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int stm32f4_pwm_open(struct stm32f4_pwm *pwm);
 | 
			
		||||
int stm32f4_pwm_close(struct stm32f4_pwm *pwm);
 | 
			
		||||
int stm32f4_pwm_set_duty_cycle(struct stm32f4_pwm *pwm, unsigned int duty_cycle_percent);
 | 
			
		||||
 | 
			
		||||
#endif /* SOURCE_FIRMWARE_ARCH_STM32F4XX_DRIVER_INCLUDE_STM32F4_PWM_H_ */
 | 
			
		||||
							
								
								
									
										99
									
								
								source/firmware/arch/stm32f4xx/driver/stm32f4_pwm.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								source/firmware/arch/stm32f4xx/driver/stm32f4_pwm.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,99 @@
 | 
			
		||||
/*
 | 
			
		||||
  * stm32f4_pwm.c
 | 
			
		||||
 *
 | 
			
		||||
 *  Created on: Aug 9, 2016
 | 
			
		||||
 *      Author: tkl
 | 
			
		||||
 */
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
#include "stm32f4xx.h"
 | 
			
		||||
#include "stm32f4_pwm.h"
 | 
			
		||||
 | 
			
		||||
struct stm32f4_pwm_object {
 | 
			
		||||
	uint8_t used_channels;
 | 
			
		||||
	uint32_t channel_1_max_period;
 | 
			
		||||
	uint32_t channel_2_max_period;
 | 
			
		||||
	uint32_t channel_3_max_period;
 | 
			
		||||
	uint32_t channel_4_max_period;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static struct stm32f4_pwm_object stm32f4_pwm_object = {
 | 
			
		||||
		.used_channels = 0,
 | 
			
		||||
		.channel_1_max_period = 0,
 | 
			
		||||
		.channel_2_max_period = 0,
 | 
			
		||||
		.channel_3_max_period = 0,
 | 
			
		||||
		.channel_4_max_period = 0,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int stm32f4_pwm_open(struct stm32f4_pwm *pwm)
 | 
			
		||||
{
 | 
			
		||||
	uint32_t clk_ahb_timer = 0, clk_ahb_gpio = 0;
 | 
			
		||||
	uint8_t gpio_af_timer = 0;
 | 
			
		||||
	if(pwm->timer == TIM4) {
 | 
			
		||||
		clk_ahb_timer = RCC_APB1Periph_TIM4;
 | 
			
		||||
		gpio_af_timer = GPIO_AF_TIM4;
 | 
			
		||||
	}
 | 
			
		||||
	RCC_APB1PeriphClockCmd(clk_ahb_timer, ENABLE);
 | 
			
		||||
	if(pwm->port == GPIOD) {
 | 
			
		||||
		clk_ahb_gpio = RCC_AHB1Periph_GPIOD;
 | 
			
		||||
	}
 | 
			
		||||
	RCC_AHB1PeriphClockCmd(clk_ahb_gpio, ENABLE);
 | 
			
		||||
	GPIO_Init(pwm->port, (GPIO_InitTypeDef *)pwm->port_cfg);
 | 
			
		||||
	GPIO_PinAFConfig(pwm->port, pwm->pin_src, gpio_af_timer);
 | 
			
		||||
 | 
			
		||||
	TIM_TimeBaseInit(pwm->timer, (TIM_TimeBaseInitTypeDef *)pwm->timer_cfg);
 | 
			
		||||
 | 
			
		||||
	switch(pwm->channel) {
 | 
			
		||||
	case channel_1:
 | 
			
		||||
		TIM_OC1Init(pwm->timer, (TIM_OCInitTypeDef *)pwm->output_compare_cfg);
 | 
			
		||||
		TIM_OC1PreloadConfig(pwm->timer, TIM_OCPreload_Enable);
 | 
			
		||||
		stm32f4_pwm_object.channel_1_max_period = pwm->timer_cfg->TIM_Period + 1;
 | 
			
		||||
		break;
 | 
			
		||||
	case channel_2:
 | 
			
		||||
		TIM_OC2Init(pwm->timer, (TIM_OCInitTypeDef *)pwm->output_compare_cfg);
 | 
			
		||||
		TIM_OC2PreloadConfig(pwm->timer, TIM_OCPreload_Enable);
 | 
			
		||||
		stm32f4_pwm_object.channel_2_max_period = pwm->timer_cfg->TIM_Period + 1;
 | 
			
		||||
		break;
 | 
			
		||||
	case channel_3:
 | 
			
		||||
		TIM_OC3Init(pwm->timer, (TIM_OCInitTypeDef *)pwm->output_compare_cfg);
 | 
			
		||||
		TIM_OC3PreloadConfig(pwm->timer, TIM_OCPreload_Enable);
 | 
			
		||||
		stm32f4_pwm_object.channel_3_max_period = pwm->timer_cfg->TIM_Period + 1;
 | 
			
		||||
		break;
 | 
			
		||||
	case channel_4:
 | 
			
		||||
		TIM_OC4Init(pwm->timer, (TIM_OCInitTypeDef *)pwm->output_compare_cfg);
 | 
			
		||||
		TIM_OC4PreloadConfig(pwm->timer, TIM_OCPreload_Enable);
 | 
			
		||||
		stm32f4_pwm_object.channel_4_max_period = pwm->timer_cfg->TIM_Period + 1;
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
	TIM_ARRPreloadConfig(pwm->timer, ENABLE);
 | 
			
		||||
	TIM_Cmd(pwm->timer, ENABLE);
 | 
			
		||||
	stm32f4_pwm_object.used_channels++;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int stm32f4_pwm_close(struct stm32f4_pwm *pwm)
 | 
			
		||||
{
 | 
			
		||||
	stm32f4_pwm_object.used_channels--;
 | 
			
		||||
	if(stm32f4_pwm_object.used_channels == 0) {
 | 
			
		||||
		TIM_Cmd(pwm->timer, DISABLE);
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int stm32f4_pwm_set_duty_cycle(struct stm32f4_pwm *pwm, unsigned int duty_cycle_percent)
 | 
			
		||||
{
 | 
			
		||||
	switch(pwm->channel) {
 | 
			
		||||
	case channel_1:
 | 
			
		||||
		TIM_SetCompare1(pwm->timer, stm32f4_pwm_object.channel_1_max_period * duty_cycle_percent / 100);
 | 
			
		||||
		break;
 | 
			
		||||
	case channel_2:
 | 
			
		||||
		TIM_SetCompare2(pwm->timer, stm32f4_pwm_object.channel_2_max_period * duty_cycle_percent / 100);
 | 
			
		||||
		break;
 | 
			
		||||
	case channel_3:
 | 
			
		||||
		TIM_SetCompare3(pwm->timer, stm32f4_pwm_object.channel_3_max_period * duty_cycle_percent / 100);
 | 
			
		||||
		break;
 | 
			
		||||
	case channel_4:
 | 
			
		||||
		TIM_SetCompare4(pwm->timer, stm32f4_pwm_object.channel_4_max_period * duty_cycle_percent / 100);
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -17,24 +17,7 @@
 | 
			
		||||
#include "shell.h"
 | 
			
		||||
 | 
			
		||||
#include "stm32f4xx.h"
 | 
			
		||||
 | 
			
		||||
enum stm32f4_pwm_channel {
 | 
			
		||||
	channel_1 = 1,
 | 
			
		||||
	channel_2,
 | 
			
		||||
	channel_3,
 | 
			
		||||
	channel_4
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct stm32f4_pwm {
 | 
			
		||||
	TIM_TypeDef *timer;
 | 
			
		||||
	const TIM_TimeBaseInitTypeDef *timer_cfg;
 | 
			
		||||
	const TIM_OCInitTypeDef *output_compare_cfg;
 | 
			
		||||
	const TIM_BDTRInitTypeDef *bdtr_cfg;
 | 
			
		||||
	GPIO_TypeDef *port;
 | 
			
		||||
	uint8_t pin_src;
 | 
			
		||||
	const GPIO_InitTypeDef *port_cfg;
 | 
			
		||||
	enum stm32f4_pwm_channel channel;
 | 
			
		||||
};
 | 
			
		||||
#include "stm32f4_pwm.h"
 | 
			
		||||
 | 
			
		||||
/* apb1 clock = 84MHz */
 | 
			
		||||
/* period_reg = src_clk / presc   / cnt_clk     */
 | 
			
		||||
@@ -76,74 +59,25 @@ static struct stm32f4_pwm str32f4_pwm = {
 | 
			
		||||
		.channel = channel_4,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
extern uint32_t SystemCoreClock;
 | 
			
		||||
void pwm_open(struct stm32f4_pwm *pwm)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
	uint32_t clk_ahb_timer = 0, clk_ahb_gpio = 0;
 | 
			
		||||
	uint8_t gpio_af_timer = 0;
 | 
			
		||||
	if(pwm->timer == TIM4) {
 | 
			
		||||
		clk_ahb_timer = RCC_APB1Periph_TIM4;
 | 
			
		||||
		gpio_af_timer = GPIO_AF_TIM4;
 | 
			
		||||
	}
 | 
			
		||||
	RCC_APB1PeriphClockCmd(clk_ahb_timer, ENABLE);
 | 
			
		||||
	if(pwm->port == GPIOD) {
 | 
			
		||||
		clk_ahb_gpio = RCC_AHB1Periph_GPIOD;
 | 
			
		||||
	}
 | 
			
		||||
	/* LEDs are on GPIOD */
 | 
			
		||||
	RCC_AHB1PeriphClockCmd(clk_ahb_gpio, ENABLE);
 | 
			
		||||
	GPIO_Init(pwm->port, (GPIO_InitTypeDef *)pwm->port_cfg);
 | 
			
		||||
	GPIO_PinAFConfig(pwm->port, pwm->pin_src, gpio_af_timer);
 | 
			
		||||
 | 
			
		||||
	/* Time base configuration */
 | 
			
		||||
	TIM_TimeBaseInit(pwm->timer, (TIM_TimeBaseInitTypeDef *)pwm->timer_cfg);
 | 
			
		||||
 | 
			
		||||
	switch(pwm->channel) {
 | 
			
		||||
	case channel_1:
 | 
			
		||||
		TIM_OC1Init(pwm->timer, (TIM_OCInitTypeDef *)pwm->output_compare_cfg);
 | 
			
		||||
		TIM_OC1PreloadConfig(pwm->timer, TIM_OCPreload_Enable);
 | 
			
		||||
		break;
 | 
			
		||||
	case channel_2:
 | 
			
		||||
		TIM_OC2Init(pwm->timer, (TIM_OCInitTypeDef *)pwm->output_compare_cfg);
 | 
			
		||||
		TIM_OC2PreloadConfig(pwm->timer, TIM_OCPreload_Enable);
 | 
			
		||||
		break;
 | 
			
		||||
	case channel_3:
 | 
			
		||||
		TIM_OC3Init(pwm->timer, (TIM_OCInitTypeDef *)pwm->output_compare_cfg);
 | 
			
		||||
		TIM_OC3PreloadConfig(pwm->timer, TIM_OCPreload_Enable);
 | 
			
		||||
		break;
 | 
			
		||||
	case channel_4:
 | 
			
		||||
		TIM_OC4Init(pwm->timer, (TIM_OCInitTypeDef *)pwm->output_compare_cfg);
 | 
			
		||||
		TIM_OC4PreloadConfig(pwm->timer, TIM_OCPreload_Enable);
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
	TIM_ARRPreloadConfig(pwm->timer, ENABLE);
 | 
			
		||||
	TIM_Cmd(pwm->timer, ENABLE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define TH_STACK_SIZE  256
 | 
			
		||||
stack_t th_stack[TH_STACK_SIZE];
 | 
			
		||||
struct thread_context th_ctx;
 | 
			
		||||
static void th_func(void *arg)
 | 
			
		||||
{
 | 
			
		||||
	uint32_t brightness = 4200 / 2;
 | 
			
		||||
	TIM4->CCR4 = brightness;
 | 
			
		||||
	unsigned int duty = 0;
 | 
			
		||||
	while(1) {
 | 
			
		||||
		brightness++;
 | 
			
		||||
		if(brightness == UINT32_MAX)
 | 
			
		||||
			brightness = 0;
 | 
			
		||||
#if 0
 | 
			
		||||
		TIM4->CCR3 = 333 - (brightness + 0) % 333; // set brightness
 | 
			
		||||
		TIM4->CCR4 = 333 - (brightness + 166/2) % 333; // set brightness
 | 
			
		||||
		TIM4->CCR1 = 333 - (brightness + 333/2) % 333; // set brightness
 | 
			
		||||
		TIM4->CCR2 = 333 - (brightness + 499/2) % 333; // set brightness
 | 
			
		||||
#endif
 | 
			
		||||
		sleep_ms(1);
 | 
			
		||||
		stm32f4_pwm_set_duty_cycle(&str32f4_pwm, duty);
 | 
			
		||||
		sleep_ms(100);
 | 
			
		||||
		duty++;
 | 
			
		||||
		if(duty > 100)
 | 
			
		||||
			duty = 0;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main(void)
 | 
			
		||||
{
 | 
			
		||||
	pwm_open(&str32f4_pwm);
 | 
			
		||||
	stm32f4_pwm_open(&str32f4_pwm);
 | 
			
		||||
	thread_create(&th_ctx, th_stack, TH_STACK_SIZE, th_func, NULL, THREAD_PRIO_LOW);
 | 
			
		||||
 | 
			
		||||
	schedule_start();
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user