diff --git a/.cproject b/.cproject index aadf958..3c9689e 100755 --- a/.cproject +++ b/.cproject @@ -146,7 +146,6 @@ make - all true true @@ -154,7 +153,6 @@ make - clean true true @@ -162,6 +160,7 @@ make + distclean true false @@ -217,7 +216,6 @@ make - all true true @@ -249,7 +247,6 @@ make - distclean true true @@ -287,6 +284,14 @@ false true + + make + TEST_APP=pwm BOARD=stm32f4-discovery DEBUG=y + test + true + false + true + make APP=example_radio_rx BOARD=msp430-ccrf DEBUG=y @@ -313,7 +318,6 @@ make - all true true @@ -321,7 +325,6 @@ make - clean true true diff --git a/source/firmware/arch/stm32f4xx/board/stm32f4-discovery/include/stm32f4-discovery.h b/source/firmware/arch/stm32f4xx/board/stm32f4-discovery/include/stm32f4-discovery.h index 57c89d5..62b487a 100755 --- a/source/firmware/arch/stm32f4xx/board/stm32f4-discovery/include/stm32f4-discovery.h +++ b/source/firmware/arch/stm32f4xx/board/stm32f4-discovery/include/stm32f4-discovery.h @@ -8,12 +8,12 @@ #include #include -#if 0 -#include "../../../driver/include/stm32f4_pwm.h" -#include "pwm.h" -#endif + #include "stm32f4xx.h" +#include "pwm.h" +#include "stm32f4_pwm.h" + #include "uart.h" #include "stm32f4_uart.h" #include "ringbuffer.h" @@ -26,6 +26,7 @@ #include "stm32f4_gpio.h" #include "driver.h" +#if 0 // GPIO_D12 static const GPIO_InitTypeDef port_cfg_d12 = { .Pin = GPIO_PIN_12, @@ -48,7 +49,7 @@ static const struct driver gpio_d12 = { DRIVER_TYPE_GPIO, &__gpio_d12, }; - +#endif // SYSTEM TICK static const enum stm32_sys_tick_time_base stm23_sys_tick_time_base = @@ -65,46 +66,47 @@ static const struct loki_timer timer_1 = { .fp = &timer_fp }; -#if 0 // PWM CHANNEL 4 /* apb1 clock = 84MHz */ /* period_reg = src_clk / presc / cnt_clk */ /* 4199 = 84MHZ / (0 + 1) / 20kHz - 1 */ -static const TIM_TimeBaseInitTypeDef timer_4_cfg = { - .TIM_RepetitionCounter = 0x0000, - .TIM_Prescaler = 0, - .TIM_ClockDivision = TIM_CKD_DIV1, - .TIM_CounterMode = TIM_CounterMode_Up, - .TIM_Period = 4199 +static TIM_HandleTypeDef tim4_handle = { + .Instance = TIM4, + .Init.Prescaler = 0, + .Init.CounterMode = TIM_COUNTERMODE_UP, + .Init.Period = 4199, + .Init.ClockDivision = TIM_CLOCKDIVISION_DIV1, + .Init.RepetitionCounter = 0, }; -static const TIM_OCInitTypeDef t4_output_compare_cfg = { - .TIM_OutputNState = TIM_OutputNState_Disable, - .TIM_OCNPolarity = TIM_OCPolarity_High, - .TIM_OCIdleState = TIM_OCIdleState_Reset, - .TIM_OCNIdleState = TIM_OCNIdleState_Set, - .TIM_OCMode = TIM_OCMode_PWM1, - .TIM_OCPolarity = TIM_OCPolarity_High, - .TIM_OutputState = TIM_OutputState_Enable, - .TIM_Pulse = 0, +static TIM_OC_InitTypeDef t4_output_compare_cfg = { + .OCMode = TIM_OCMODE_PWM1, + .Pulse = 0, + .OCPolarity = TIM_OCPOLARITY_HIGH, + .OCNPolarity = TIM_OCNPOLARITY_HIGH, + .OCFastMode = TIM_OCFAST_DISABLE, + .OCIdleState = TIM_OCIDLESTATE_SET, + .OCNIdleState = TIM_OCNIDLESTATE_SET }; static const GPIO_InitTypeDef port_cfg_D15 = { - .GPIO_Pin = GPIO_Pin_15, - .GPIO_Mode = GPIO_Mode_AF, - .GPIO_OType = GPIO_OType_PP, - .GPIO_PuPd = GPIO_PuPd_UP, - .GPIO_Speed = GPIO_Speed_100MHz, + .Pin = GPIO_PIN_15, + .Mode = GPIO_MODE_AF_PP, + .Speed = GPIO_SPEED_FREQ_HIGH, + .Pull = GPIO_PULLUP, + .Alternate = GPIO_AF2_TIM4, +}; + +static const struct stm32f4_gpio t4c4_gpio = { + .port = GPIOD, + .pin = &port_cfg_D15, }; static struct stm32f4_pwm str32f4_pwm_4 = { - .timer = TIM4, - .timer_cfg = &timer_4_cfg, + .pwm_gpio = &t4c4_gpio, + .timer_handle = &tim4_handle, .output_compare_cfg = &t4_output_compare_cfg, - .port = GPIOD, - .pin_src = GPIO_PinSource15, - .port_cfg = &port_cfg_D15, - .channel = channel_4, + .channel = TIM_CHANNEL_4, }; static const struct pwm pwm_ch4 = { @@ -120,25 +122,25 @@ const struct driver pwm_4 = { DRIVER_TYPE_PWM, &pwm_ch4, }; -#endif -#if 0 + // PWM Channel 3 static const GPIO_InitTypeDef port_cfg_D14 = { - .GPIO_Pin = GPIO_Pin_14, - .GPIO_Mode = GPIO_Mode_AF, - .GPIO_OType = GPIO_OType_PP, - .GPIO_PuPd = GPIO_PuPd_UP, - .GPIO_Speed = GPIO_Speed_100MHz, + .Pin = GPIO_PIN_14, + .Mode = GPIO_MODE_AF_PP, + .Speed = GPIO_SPEED_FREQ_HIGH, + .Pull = GPIO_PULLUP, + .Alternate = GPIO_AF2_TIM4, +}; +static const struct stm32f4_gpio stm32f4_pwm_t4c3_gpio = { + .port = GPIOD, + .pin = &port_cfg_D14, }; static struct stm32f4_pwm str32f4_pwm_3 = { - .timer = TIM4, - .timer_cfg = &timer_4_cfg, + .pwm_gpio = &stm32f4_pwm_t4c3_gpio, + .timer_handle = &tim4_handle, .output_compare_cfg = &t4_output_compare_cfg, - .port = GPIOD, - .pin_src = GPIO_PinSource14, - .port_cfg = &port_cfg_D14, - .channel = channel_3, + .channel = TIM_CHANNEL_3, }; static const struct pwm pwm_ch3 = { @@ -154,25 +156,25 @@ const struct driver pwm_3 = { DRIVER_TYPE_PWM, &pwm_ch3, }; -#endif -#if 0 + // PWM Channel 2 static const GPIO_InitTypeDef port_cfg_D13 = { - .GPIO_Pin = GPIO_Pin_13, - .GPIO_Mode = GPIO_Mode_AF, - .GPIO_OType = GPIO_OType_PP, - .GPIO_PuPd = GPIO_PuPd_UP, - .GPIO_Speed = GPIO_Speed_100MHz, + .Pin = GPIO_PIN_13, + .Mode = GPIO_MODE_AF_PP, + .Speed = GPIO_SPEED_FREQ_HIGH, + .Pull = GPIO_PULLUP, + .Alternate = GPIO_AF2_TIM4, +}; +static const struct stm32f4_gpio stm32f4_pwm_t4c2_gpio = { + .port = GPIOD, + .pin = &port_cfg_D13, }; static struct stm32f4_pwm str32f4_pwm_2 = { - .timer = TIM4, - .timer_cfg = &timer_4_cfg, + .pwm_gpio = &stm32f4_pwm_t4c2_gpio, + .timer_handle = &tim4_handle, .output_compare_cfg = &t4_output_compare_cfg, - .port = GPIOD, - .pin_src = GPIO_PinSource13, - .port_cfg = &port_cfg_D13, - .channel = channel_2, + .channel = TIM_CHANNEL_2, }; static const struct pwm pwm_ch2 = { @@ -188,25 +190,25 @@ const struct driver pwm_2 = { DRIVER_TYPE_PWM, &pwm_ch2, }; -#endif -#if 0 + // PWM Channel 1 static const GPIO_InitTypeDef port_cfg_D12 = { - .GPIO_Pin = GPIO_Pin_12, - .GPIO_Mode = GPIO_Mode_AF, - .GPIO_OType = GPIO_OType_PP, - .GPIO_PuPd = GPIO_PuPd_UP, - .GPIO_Speed = GPIO_Speed_100MHz, + .Pin = GPIO_PIN_12, + .Mode = GPIO_MODE_AF_PP, + .Speed = GPIO_SPEED_FREQ_HIGH, + .Pull = GPIO_PULLUP, + .Alternate = GPIO_AF2_TIM4, +}; +static const struct stm32f4_gpio stm32f4_pwm_t4c1_gpio = { + .port = GPIOD, + .pin = &port_cfg_D12, }; static struct stm32f4_pwm str32f4_pwm_1 = { - .timer = TIM4, - .timer_cfg = &timer_4_cfg, + .pwm_gpio = &stm32f4_pwm_t4c1_gpio, + .timer_handle = &tim4_handle, .output_compare_cfg = &t4_output_compare_cfg, - .port = GPIOD, - .pin_src = GPIO_PinSource12, - .port_cfg = &port_cfg_D12, - .channel = channel_1, + .channel = TIM_CHANNEL_1, }; static const struct pwm pwm_ch1 = { @@ -222,7 +224,7 @@ const struct driver pwm_1 = { DRIVER_TYPE_PWM, &pwm_ch1, }; -#endif + // UART 1 static const GPIO_InitTypeDef port_cfg_uart1 = { .Pin = GPIO_PIN_6 | GPIO_PIN_7, diff --git a/source/firmware/arch/stm32f4xx/driver/include/stm32f4_pwm.h b/source/firmware/arch/stm32f4xx/driver/include/stm32f4_pwm.h new file mode 100644 index 0000000..709c838 --- /dev/null +++ b/source/firmware/arch/stm32f4xx/driver/include/stm32f4_pwm.h @@ -0,0 +1,32 @@ +/* + * 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_ + +#pragma pack(push) +#pragma pack(1) +struct stm32f4_pwm { + const struct stm32f4_gpio *pwm_gpio; + TIM_HandleTypeDef *timer_handle; + TIM_OC_InitTypeDef *output_compare_cfg; + uint32_t channel; +}; +#pragma pack(pop) + + +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 deleted file mode 100644 index 80faa5d..0000000 --- a/source/firmware/arch/stm32f4xx/driver/stm32f4_pwm._c +++ /dev/null @@ -1,113 +0,0 @@ -/* - * stm32f4_pwm.c - * - * Created on: Aug 9, 2016 - * Author: tkl - */ -#include -#include - -#include "stm32f4xx.h" - -#include "pwm.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(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(this->timer == TIM4) { - clk_ahb_timer = RCC_APB1Periph_TIM4; - gpio_af_timer = GPIO_AF_TIM4; - } - RCC_APB1PeriphClockCmd(clk_ahb_timer, ENABLE); - if(this->port == GPIOD) { - clk_ahb_gpio = RCC_AHB1Periph_GPIOD; - } - RCC_AHB1PeriphClockCmd(clk_ahb_gpio, ENABLE); - GPIO_Init(this->port, (GPIO_InitTypeDef *)this->port_cfg); - GPIO_PinAFConfig(this->port, this->pin_src, gpio_af_timer); - - TIM_TimeBaseInit(this->timer, (TIM_TimeBaseInitTypeDef *)this->timer_cfg); - - switch(this->channel) { - case channel_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(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(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(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(this->timer, ENABLE); - TIM_Cmd(this->timer, ENABLE); - stm32f4_pwm_object.used_channels++; - return 0; -} - -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(this->timer, DISABLE); - } - return 0; -} - -int stm32f4_pwm_set_duty_cycle(const void *pwm, unsigned int duty_cycle_percent) -{ - if(NULL == pwm) - return -1; - struct stm32f4_pwm *this = (struct stm32f4_pwm *)pwm; - switch(this->channel) { - case channel_1: - TIM_SetCompare1(this->timer, stm32f4_pwm_object.channel_1_max_period * duty_cycle_percent / 100); - break; - case channel_2: - TIM_SetCompare2(this->timer, stm32f4_pwm_object.channel_2_max_period * duty_cycle_percent / 100); - break; - case channel_3: - TIM_SetCompare3(this->timer, stm32f4_pwm_object.channel_3_max_period * duty_cycle_percent / 100); - break; - case channel_4: - TIM_SetCompare4(this->timer, stm32f4_pwm_object.channel_4_max_period * duty_cycle_percent / 100); - break; - } - return 0; -} diff --git a/source/firmware/arch/stm32f4xx/driver/stm32f4_pwm.c b/source/firmware/arch/stm32f4xx/driver/stm32f4_pwm.c new file mode 100644 index 0000000..bca8c13 --- /dev/null +++ b/source/firmware/arch/stm32f4xx/driver/stm32f4_pwm.c @@ -0,0 +1,83 @@ +/* + * stm32f4_pwm.c + * + * Created on: Aug 9, 2016 + * Author: tkl + */ +#include +#include + +#include "stm32f4xx.h" + +#include "gpio.h" +#include "stm32f4_gpio.h" + +#include "pwm.h" +#include "stm32f4_pwm.h" + +#pragma pack(push) +#pragma pack(1) +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; +}; +#pragma pack(pop) + +int stm32f4_pwm_open(const void *pwm) +{ + if(NULL == pwm) + return -1; + struct stm32f4_pwm *this = (struct stm32f4_pwm *)pwm; + stm32f4_gpio_open(this->pwm_gpio); + if(this->timer_handle->Instance == TIM4) { + __HAL_RCC_TIM4_CLK_ENABLE(); + } + HAL_TIM_PWM_Init(this->timer_handle); + HAL_TIM_PWM_ConfigChannel(this->timer_handle, this->output_compare_cfg, this->channel); + + TIM_MasterConfigTypeDef sMasterConfig; + sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; + sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; + HAL_TIMEx_MasterConfigSynchronization(this->timer_handle, &sMasterConfig); + + TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig; + sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE; + sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE; + sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF; + sBreakDeadTimeConfig.DeadTime = 0; + sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE; + sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH; + sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE; + HAL_TIMEx_ConfigBreakDeadTime(this->timer_handle, &sBreakDeadTimeConfig); + + + HAL_TIM_Base_Start(this->timer_handle); + HAL_TIM_PWM_Start(this->timer_handle, this->channel); + return 0; +} + +int stm32f4_pwm_close(const void *pwm) +{ + if(NULL == pwm) + return -1; + stm32f4_pwm_set_duty_cycle(pwm, 0); + struct stm32f4_pwm *this = (struct stm32f4_pwm *)pwm; + HAL_TIM_Base_Stop(this->timer_handle); + HAL_TIM_PWM_Stop(this->timer_handle, this->channel); + + return 0; +} + +int stm32f4_pwm_set_duty_cycle(const void *pwm, unsigned int duty_cycle_percent) +{ + if(NULL == pwm) + return -1; + + struct stm32f4_pwm *this = (struct stm32f4_pwm *)pwm; + __HAL_TIM_SET_COMPARE(this->timer_handle, this->channel, this->timer_handle->Init.Period * duty_cycle_percent / 100); + + return 0; +} diff --git a/source/firmware/arch/stm32f4xx/lib/system/src/stm32f4-hal/stm32f4xx_hal_tim.c b/source/firmware/arch/stm32f4xx/lib/system/src/stm32f4-hal/stm32f4xx_hal_tim.c index fe63704..27955d1 100644 --- a/source/firmware/arch/stm32f4xx/lib/system/src/stm32f4-hal/stm32f4xx_hal_tim.c +++ b/source/firmware/arch/stm32f4xx/lib/system/src/stm32f4-hal/stm32f4xx_hal_tim.c @@ -2963,7 +2963,7 @@ HAL_StatusTypeDef HAL_TIM_OC_ConfigChannel(TIM_HandleTypeDef *htim, TIM_OC_InitT { /* Check the parameters */ assert_param(IS_TIM_CHANNELS(Channel)); - assert_param(IS_TIM_OC_MODE(sConfig->OCMode)); + assert_param(IS_TIM_OC_MODE(sConfig->OCMode) || IS_TIM_PWM_MODE(sConfig->OCMode)); assert_param(IS_TIM_OC_POLARITY(sConfig->OCPolarity)); /* Check input state */ diff --git a/source/test/pwm/main.c b/source/test/pwm/main.c new file mode 100644 index 0000000..d3b8ebd --- /dev/null +++ b/source/test/pwm/main.c @@ -0,0 +1,53 @@ +/* + * main.c + * + * Created on: Aug 2, 2016 + * Author: tkl + */ + +#include + +#include "driver.h" +#include "board.h" +#include "stack.h" +#include "queue.h" +#include "kernel.h" +#include "driver.h" +#include "list.h" +#include "shell.h" + +#define TH_STACK_SIZE 256 +stack_t th_stack[TH_STACK_SIZE]; +struct thread_context th_ctx; +static void th_func(void *arg) +{ + drv_open(&pwm_1); + drv_open(&pwm_2); + drv_open(&pwm_3); + drv_open(&pwm_4); + while(1) { + for(unsigned int duty = 0; duty < 100; duty++) { + drv_ioctl(&pwm_1, IOCTL_PWM_SET_DUTY_CYCLE, (const void *)&duty); + drv_ioctl(&pwm_2, IOCTL_PWM_SET_DUTY_CYCLE, (const void *)&duty); + drv_ioctl(&pwm_3, IOCTL_PWM_SET_DUTY_CYCLE, (const void *)&duty); + drv_ioctl(&pwm_4, IOCTL_PWM_SET_DUTY_CYCLE, (const void *)&duty); + sleep_ms(10); + } + for(unsigned int duty = 98; duty > 0; duty--) { + drv_ioctl(&pwm_1, IOCTL_PWM_SET_DUTY_CYCLE, (const void *)&duty); + drv_ioctl(&pwm_2, IOCTL_PWM_SET_DUTY_CYCLE, (const void *)&duty); + drv_ioctl(&pwm_3, IOCTL_PWM_SET_DUTY_CYCLE, (const void *)&duty); + drv_ioctl(&pwm_4, IOCTL_PWM_SET_DUTY_CYCLE, (const void *)&duty); + sleep_ms(10); + } + } +} + +int main(void) +{ + board_init(); + thread_create(&th_ctx, th_stack, TH_STACK_SIZE, th_func, NULL, THREAD_PRIO_LOW); + schedule_start(); + + return 0; +} diff --git a/source/test/pwm/pwm.mk b/source/test/pwm/pwm.mk new file mode 100644 index 0000000..62073b4 --- /dev/null +++ b/source/test/pwm/pwm.mk @@ -0,0 +1 @@ +SRC_DIR += source/test/pwm