From b80a44a4d9ccfea418be75185383be9ab14b10cc Mon Sep 17 00:00:00 2001 From: tkl Date: Tue, 9 Aug 2016 12:28:01 +0200 Subject: [PATCH] wip --- .../stm32f4xx/driver/include/stm32f4_pwm.h | 12 +++- .../arch/stm32f4xx/driver/stm32f4_pwm.c | 72 +++++++++++-------- source/firmware/kernel/driver/include/pwm.h | 35 +++++++++ source/firmware/kernel/driver/pwm.c | 33 +++++++++ source/test/pwm/main.c | 10 ++- 5 files changed, 128 insertions(+), 34 deletions(-) create mode 100644 source/firmware/kernel/driver/include/pwm.h create mode 100644 source/firmware/kernel/driver/pwm.c diff --git a/source/firmware/arch/stm32f4xx/driver/include/stm32f4_pwm.h b/source/firmware/arch/stm32f4xx/driver/include/stm32f4_pwm.h index 2e1dff4..c46174f 100644 --- a/source/firmware/arch/stm32f4xx/driver/include/stm32f4_pwm.h +++ b/source/firmware/arch/stm32f4xx/driver/include/stm32f4_pwm.h @@ -27,8 +27,14 @@ struct stm32f4_pwm { }; -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); +int stm32f4_pwm_open(const void *pwm); +int stm32f4_pwm_close(const void *pwm); +int stm32f4_pwm_set_duty_cycle(const void *pwm, unsigned int duty_cycle_percent); + +static const struct pwm_fp stm32f4_pwm_fp = { + .open = stm32f4_pwm_open, + .close = stm32f4_pwm_close, + .set_duty_cycle = stm32f4_pwm_set_duty_cycle, +}; #endif /* SOURCE_FIRMWARE_ARCH_STM32F4XX_DRIVER_INCLUDE_STM32F4_PWM_H_ */ diff --git a/source/firmware/arch/stm32f4xx/driver/stm32f4_pwm.c b/source/firmware/arch/stm32f4xx/driver/stm32f4_pwm.c index 8b8505d..80faa5d 100644 --- a/source/firmware/arch/stm32f4xx/driver/stm32f4_pwm.c +++ b/source/firmware/arch/stm32f4xx/driver/stm32f4_pwm.c @@ -5,8 +5,11 @@ * Author: tkl */ #include +#include #include "stm32f4xx.h" + +#include "pwm.h" #include "stm32f4_pwm.h" struct stm32f4_pwm_object { @@ -25,75 +28,86 @@ static struct stm32f4_pwm_object stm32f4_pwm_object = { .channel_4_max_period = 0, }; -int stm32f4_pwm_open(struct stm32f4_pwm *pwm) +int stm32f4_pwm_open(const void *pwm) { + if(NULL == pwm) + return -1; + struct stm32f4_pwm *this = (struct stm32f4_pwm *)pwm; uint32_t clk_ahb_timer = 0, clk_ahb_gpio = 0; uint8_t gpio_af_timer = 0; - if(pwm->timer == TIM4) { + if(this->timer == TIM4) { clk_ahb_timer = RCC_APB1Periph_TIM4; gpio_af_timer = GPIO_AF_TIM4; } RCC_APB1PeriphClockCmd(clk_ahb_timer, ENABLE); - if(pwm->port == GPIOD) { + if(this->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); + GPIO_Init(this->port, (GPIO_InitTypeDef *)this->port_cfg); + GPIO_PinAFConfig(this->port, this->pin_src, gpio_af_timer); - TIM_TimeBaseInit(pwm->timer, (TIM_TimeBaseInitTypeDef *)pwm->timer_cfg); + TIM_TimeBaseInit(this->timer, (TIM_TimeBaseInitTypeDef *)this->timer_cfg); - switch(pwm->channel) { + switch(this->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; + TIM_OC1Init(this->timer, (TIM_OCInitTypeDef *)this->output_compare_cfg); + TIM_OC1PreloadConfig(this->timer, TIM_OCPreload_Enable); + stm32f4_pwm_object.channel_1_max_period = this->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; + TIM_OC2Init(this->timer, (TIM_OCInitTypeDef *)this->output_compare_cfg); + TIM_OC2PreloadConfig(this->timer, TIM_OCPreload_Enable); + stm32f4_pwm_object.channel_2_max_period = this->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; + TIM_OC3Init(this->timer, (TIM_OCInitTypeDef *)this->output_compare_cfg); + TIM_OC3PreloadConfig(this->timer, TIM_OCPreload_Enable); + stm32f4_pwm_object.channel_3_max_period = this->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; + TIM_OC4Init(this->timer, (TIM_OCInitTypeDef *)this->output_compare_cfg); + TIM_OC4PreloadConfig(this->timer, TIM_OCPreload_Enable); + stm32f4_pwm_object.channel_4_max_period = this->timer_cfg->TIM_Period + 1; break; } - TIM_ARRPreloadConfig(pwm->timer, ENABLE); - TIM_Cmd(pwm->timer, ENABLE); + TIM_ARRPreloadConfig(this->timer, ENABLE); + TIM_Cmd(this->timer, ENABLE); stm32f4_pwm_object.used_channels++; return 0; } -int stm32f4_pwm_close(struct stm32f4_pwm *pwm) +int stm32f4_pwm_close(const void *pwm) { + if(NULL == pwm) + return -1; + struct stm32f4_pwm *this = (struct stm32f4_pwm *)pwm; + stm32f4_pwm_set_duty_cycle(pwm, 0); stm32f4_pwm_object.used_channels--; if(stm32f4_pwm_object.used_channels == 0) { - TIM_Cmd(pwm->timer, DISABLE); + TIM_Cmd(this->timer, DISABLE); } return 0; } -int stm32f4_pwm_set_duty_cycle(struct stm32f4_pwm *pwm, unsigned int duty_cycle_percent) +int stm32f4_pwm_set_duty_cycle(const void *pwm, unsigned int duty_cycle_percent) { - switch(pwm->channel) { + if(NULL == pwm) + return -1; + struct stm32f4_pwm *this = (struct stm32f4_pwm *)pwm; + switch(this->channel) { case channel_1: - TIM_SetCompare1(pwm->timer, stm32f4_pwm_object.channel_1_max_period * duty_cycle_percent / 100); + TIM_SetCompare1(this->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); + TIM_SetCompare2(this->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); + TIM_SetCompare3(this->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); + TIM_SetCompare4(this->timer, stm32f4_pwm_object.channel_4_max_period * duty_cycle_percent / 100); break; } + return 0; } diff --git a/source/firmware/kernel/driver/include/pwm.h b/source/firmware/kernel/driver/include/pwm.h new file mode 100644 index 0000000..6d1d883 --- /dev/null +++ b/source/firmware/kernel/driver/include/pwm.h @@ -0,0 +1,35 @@ +/* + * pwm.h + * + * Created on: Aug 9, 2016 + * Author: tkl + */ + +#ifndef SOURCE_FIRMWARE_KERNEL_DRIVER_INCLUDE_PWM_H_ +#define SOURCE_FIRMWARE_KERNEL_DRIVER_INCLUDE_PWM_H_ + +//! \brief Function pointer to the open function. +typedef int (*pwm_fp_open_t)(const void*); + +//! \brief Function pointer to the close function. +typedef int (*pwm_fp_close_t)(const void*); + +//! \brief Function pointer to the read function. +typedef int (*pwm_fp_set_duty_cycle_t)(const void*, unsigned int duty_cycle_percent); + +struct pwm_fp { + const pwm_fp_open_t open; + const pwm_fp_close_t close; + const pwm_fp_set_duty_cycle_t set_duty_cycle; +}; + +struct pwm { + const void *arch_dep_device; //!< Architecture depended pwm device (i.e. stm32f10x_pwm_t). + const struct pwm_fp *fp; //!< Function pointer for the pwm driver access. +}; + +int pwm_open(const struct pwm *device); +int pwm_close(const struct pwm *device); +int pwm_set_duty_cycle(const struct pwm *device, unsigned int duty_cycle_percent); + +#endif /* SOURCE_FIRMWARE_KERNEL_DRIVER_INCLUDE_PWM_H_ */ diff --git a/source/firmware/kernel/driver/pwm.c b/source/firmware/kernel/driver/pwm.c new file mode 100644 index 0000000..a8e733e --- /dev/null +++ b/source/firmware/kernel/driver/pwm.c @@ -0,0 +1,33 @@ +/* + * pwm.c + * + * Created on: Aug 9, 2016 + * Author: tkl + */ + +#include +#include + +int pwm_open(const struct pwm *device) +{ + if(NULL == device) + return -1; + pwm_fp_open_t open = device->fp->open; + return open(device->arch_dep_device); +} + +int pwm_close(const struct pwm *device) +{ + if(NULL == device) + return -1; + pwm_fp_close_t close = device->fp->close; + return close(device->arch_dep_device); +} + +int pwm_set_duty_cycle(const struct pwm *device, unsigned int duty_cycle_percent) +{ + if(NULL == device) + return -1; + pwm_fp_set_duty_cycle_t set = device->fp->set_duty_cycle; + return set(device->arch_dep_device, duty_cycle_percent); +} diff --git a/source/test/pwm/main.c b/source/test/pwm/main.c index edcbf59..9ad07bd 100644 --- a/source/test/pwm/main.c +++ b/source/test/pwm/main.c @@ -17,6 +17,8 @@ #include "shell.h" #include "stm32f4xx.h" + +#include "pwm.h" #include "stm32f4_pwm.h" /* apb1 clock = 84MHz */ @@ -59,6 +61,10 @@ static struct stm32f4_pwm str32f4_pwm = { .channel = channel_4, }; +static const struct pwm pwm_ch4 = { + .arch_dep_device = &str32f4_pwm, + .fp = &stm32f4_pwm_fp, +}; #define TH_STACK_SIZE 256 stack_t th_stack[TH_STACK_SIZE]; @@ -66,8 +72,9 @@ struct thread_context th_ctx; static void th_func(void *arg) { unsigned int duty = 0; + pwm_open(&pwm_ch4); while(1) { - stm32f4_pwm_set_duty_cycle(&str32f4_pwm, duty); + pwm_set_duty_cycle(&pwm_ch4, duty); sleep_ms(100); duty++; if(duty > 100) @@ -77,7 +84,6 @@ static void th_func(void *arg) int main(void) { - stm32f4_pwm_open(&str32f4_pwm); thread_create(&th_ctx, th_stack, TH_STACK_SIZE, th_func, NULL, THREAD_PRIO_LOW); schedule_start();