From 0cd8c3d5a8b983f6efcf3aa80b99a18c95734f28 Mon Sep 17 00:00:00 2001 From: Hierophect Date: Sun, 27 Oct 2019 19:17:01 -0400 Subject: [PATCH] Add all basic functions, never reset, dynamic pulse changes --- ports/stm32f4/common-hal/pulseio/PWMOut.c | 100 ++++++++++++++---- ports/stm32f4/common-hal/pulseio/PWMOut.h | 5 + .../peripherals/stm32f4/stm32f405xx/periph.c | 20 ++-- .../peripherals/stm32f4/stm32f405xx/periph.h | 5 +- ports/stm32f4/supervisor/port.c | 2 + 5 files changed, 99 insertions(+), 33 deletions(-) diff --git a/ports/stm32f4/common-hal/pulseio/PWMOut.c b/ports/stm32f4/common-hal/pulseio/PWMOut.c index c74eb670fe..48f8320fb9 100644 --- a/ports/stm32f4/common-hal/pulseio/PWMOut.c +++ b/ports/stm32f4/common-hal/pulseio/PWMOut.c @@ -31,13 +31,17 @@ #include "common-hal/pulseio/PWMOut.h" #include "shared-bindings/pulseio/PWMOut.h" #include "supervisor/shared/translate.h" + +#include "shared-bindings/microcontroller/__init__.h" #include "stm32f4xx_hal.h" +#include "common-hal/microcontroller/Pin.h" #define PWM_MAX_FREQ 6000000 #define ALL_CLOCKS 0xFFFF STATIC uint8_t reserved_tim[TIM_BANK_ARRAY_LEN]; STATIC uint32_t tim_frequencies[TIM_BANK_ARRAY_LEN]; +STATIC bool never_reset_tim[TIM_BANK_ARRAY_LEN]; STATIC void tim_clock_enable(uint16_t mask); STATIC void tim_clock_disable(uint16_t mask); @@ -62,13 +66,37 @@ static uint32_t timer_get_source_freq(uint32_t tim_id) { } void pwmout_reset(void) { - tim_clock_disable(ALL_CLOCKS); + uint16_t never_reset_mask = 0x00; + for(int i=0;ihandle.Instance) { + never_reset_tim[i] = true; + never_reset_pin_number(self->tim->pin->port, self->tim->pin->number); + break; + } + } } void common_hal_pulseio_pwmout_reset_ok(pulseio_pwmout_obj_t *self) { + //TODO: doesn't this need an equivalent release pin in microcontroller.c? + //I don't see that implemented in any port. + for(size_t i = 0 ; i < TIM_BANK_ARRAY_LEN; i++) { + if (mcu_tim_banks[i] == self->handle.Instance) { + never_reset_tim[i] = false; + break; + } + } } pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self, @@ -77,7 +105,8 @@ pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self, uint32_t frequency, bool variable_frequency) { if (frequency == 0 || frequency > 6000000) { - return PWMOUT_INVALID_FREQUENCY; + mp_raise_ValueError(translate("Invalid frequency supplied")); + //return PWMOUT_INVALID_FREQUENCY; } TIM_TypeDef * TIMx; @@ -92,9 +121,9 @@ pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self, for(uint i = 0; i < tim_num; i++) { //if pin is same - if(mcu_tim_pin_list[i].pin = pin) { + if(mcu_tim_pin_list[i].pin == pin) { //check if the timer has a channel active - if (reserved_tim[mcu_tim_pin_list[i].tim_index] != 0) { + if (reserved_tim[mcu_tim_pin_list[i].tim_index-1] != 0) { //is it the same channel? (or all channels reserved by a var-freq) if(reserved_tim[mcu_tim_pin_list[i].tim_index-1] & 1<<(mcu_tim_pin_list[i].channel_index-1)) { tim_chan_taken = true; @@ -128,8 +157,9 @@ pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self, if (variable_frequency) { reserved_tim[self->tim->tim_index-1] = 0x0F; } else { - reserved_tim[self->tim->tim_index-1] |= 1<tim->channel_index-1; + reserved_tim[self->tim->tim_index-1] |= 1<<(self->tim->channel_index-1); } + tim_frequencies[self->tim->tim_index-1] = frequency; } else { //no match found if (tim_chan_taken) { mp_raise_ValueError(translate("Timer hardware is reserved")); @@ -167,11 +197,13 @@ pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self, uint32_t source_freq = timer_get_source_freq(self->tim->tim_index); uint32_t period = PWM_MAX_FREQ/frequency; - mp_printf(&mp_plat_print, "SysCoreClock: %d\n", SystemCoreClock); - mp_printf(&mp_plat_print, "Source Freq: %d\n", source_freq); - mp_printf(&mp_plat_print, "Timer Freq: %d\n", source_freq/(source_freq / PWM_MAX_FREQ)); - mp_printf(&mp_plat_print, "Actual Freq: %d\n", (source_freq/(source_freq / PWM_MAX_FREQ))/period); - mp_printf(&mp_plat_print, "Period: %d\n", (PWM_MAX_FREQ/frequency)); + //TODO: remove before merging. + // mp_printf(&mp_plat_print, "SysCoreClock: %d\n", SystemCoreClock); + // mp_printf(&mp_plat_print, "Source Freq: %d\n", source_freq); + // mp_printf(&mp_plat_print, "Timer Freq: %d\n", source_freq/(source_freq / PWM_MAX_FREQ)); + // mp_printf(&mp_plat_print, "Actual Freq: %d\n", (source_freq/(source_freq / PWM_MAX_FREQ))/period); + // mp_printf(&mp_plat_print, "Duty: %d\n", duty); + // mp_printf(&mp_plat_print, "TIM#:%d CH:%d ALTF:%d\n", self->tim->tim_index, self->tim->channel_index, self->tim->altfn_index); //Timer init self->handle.Instance = TIMx; @@ -222,7 +254,7 @@ void common_hal_pulseio_pwmout_deinit(pulseio_pwmout_obj_t* self) { if(self->variable_frequency) { reserved_tim[self->tim->tim_index-1] = 0x00; } else { - reserved_tim[self->tim->tim_index-1] &= !(1<tim->channel_index); + reserved_tim[self->tim->tim_index-1] &= ~(1<tim->channel_index); HAL_TIM_PWM_Stop(&self->handle, self->channel); } reset_pin_number(self->tim->pin->port,self->tim->pin->number); @@ -236,15 +268,14 @@ void common_hal_pulseio_pwmout_deinit(pulseio_pwmout_obj_t* self) { } void common_hal_pulseio_pwmout_set_duty_cycle(pulseio_pwmout_obj_t* self, uint16_t duty_cycle) { - HAL_TIM_PWM_Stop(&self->handle, self->channel); + uint16_t duty = duty_cycle/655; + uint32_t period = PWM_MAX_FREQ/self->frequency; + uint32_t input = (period*duty)/100; + //TODO: remove before merging + //mp_printf(&mp_plat_print, "duty_cycle %d, Duty: %d, Input %d\n", duty_cycle, duty, input); + __HAL_TIM_SET_COMPARE(&self->handle, self->channel, input); - self->chan_handle.Pulse = ((PWM_MAX_FREQ/self->frequency)*duty_cycle)/100 - 1; - if(HAL_TIM_PWM_ConfigChannel(&self->handle, &self->chan_handle, self->channel) != HAL_OK) { - mp_raise_ValueError(translate("Channel Re-Init Error")); - } - if(HAL_TIM_PWM_Start(&self->handle, self->channel) != HAL_OK) { - mp_raise_ValueError(translate("Error restarting PWM")); - } + self->duty_cycle = duty; } uint16_t common_hal_pulseio_pwmout_get_duty_cycle(pulseio_pwmout_obj_t* self) { @@ -252,10 +283,39 @@ uint16_t common_hal_pulseio_pwmout_get_duty_cycle(pulseio_pwmout_obj_t* self) { } void common_hal_pulseio_pwmout_set_frequency(pulseio_pwmout_obj_t* self, uint32_t frequency) { + if (frequency == 0 || frequency > 6000000) { + mp_raise_ValueError(translate("Invalid PWM frequency")); + } + if (frequency == self->frequency) return; + + uint32_t source_freq = timer_get_source_freq(self->tim->tim_index); + uint32_t period = PWM_MAX_FREQ/frequency; + + //shut down + HAL_TIM_PWM_Stop(&self->handle, self->channel); + tim_clock_disable(1<<(self->tim->tim_index-1)); + + //Only change altered values + self->handle.Init.Period = period - 1; + self->handle.Init.Prescaler = (source_freq / PWM_MAX_FREQ) - 1; // TIM runs at ~6MHz + + //restart everything + if(HAL_TIM_PWM_Init(&self->handle) != HAL_OK) { + mp_raise_ValueError(translate("Timer Re-Init Error")); + } + if(HAL_TIM_PWM_ConfigChannel(&self->handle, &self->chan_handle, self->channel) != HAL_OK) { + mp_raise_ValueError(translate("Channel Re-Init Error")); + } + if(HAL_TIM_PWM_Start(&self->handle, self->channel) != HAL_OK) { + mp_raise_ValueError(translate("Error restarting PWM")); + } + + tim_frequencies[self->tim->tim_index-1] = frequency; + self->frequency = frequency; } uint32_t common_hal_pulseio_pwmout_get_frequency(pulseio_pwmout_obj_t* self) { - return 0; + return self->frequency; } bool common_hal_pulseio_pwmout_get_variable_frequency(pulseio_pwmout_obj_t* self) { diff --git a/ports/stm32f4/common-hal/pulseio/PWMOut.h b/ports/stm32f4/common-hal/pulseio/PWMOut.h index 97777d3ca6..a7784204ce 100644 --- a/ports/stm32f4/common-hal/pulseio/PWMOut.h +++ b/ports/stm32f4/common-hal/pulseio/PWMOut.h @@ -27,6 +27,11 @@ #ifndef MICROPY_INCLUDED_STM32F4_COMMON_HAL_PULSEIO_PWMOUT_H #define MICROPY_INCLUDED_STM32F4_COMMON_HAL_PULSEIO_PWMOUT_H +#include "common-hal/microcontroller/Pin.h" + +#include "stm32f4xx_hal.h" +#include "stm32f4/periph.h" + #include "py/obj.h" typedef struct { diff --git a/ports/stm32f4/peripherals/stm32f4/stm32f405xx/periph.c b/ports/stm32f4/peripherals/stm32f4/stm32f405xx/periph.c index 5b2c211cbd..35dc7eb7eb 100644 --- a/ports/stm32f4/peripherals/stm32f4/stm32f405xx/periph.c +++ b/ports/stm32f4/peripherals/stm32f4/stm32f405xx/periph.c @@ -148,15 +148,15 @@ const mcu_tim_pin_obj_t mcu_tim_pin_list[66] = { TIM(11,3,1,&pin_PF07), TIM(13,9,1,&pin_PF08), TIM(14,9,1,&pin_PF09), - TIM(12,9,1,&pin_PH06), - TIM(12,9,2,&pin_PH09), - TIM(5,2,1,&pin_PH10), - TIM(5,2,2,&pin_PH11), - TIM(5,2,3,&pin_PH12), - TIM(5,2,4,&pin_PI00), - TIM(8,3,4,&pin_PI02), - TIM(8,3,1,&pin_PI05), - TIM(8,3,2,&pin_PI06), - TIM(8,3,3,&pin_PI07), + // TIM(12,9,1,&pin_PH06), + // TIM(12,9,2,&pin_PH09), + // TIM(5,2,1,&pin_PH10), + // TIM(5,2,2,&pin_PH11), + // TIM(5,2,3,&pin_PH12), + // TIM(5,2,4,&pin_PI00), + // TIM(8,3,4,&pin_PI02), + // TIM(8,3,1,&pin_PI05), + // TIM(8,3,2,&pin_PI06), + // TIM(8,3,3,&pin_PI07), }; diff --git a/ports/stm32f4/peripherals/stm32f4/stm32f405xx/periph.h b/ports/stm32f4/peripherals/stm32f4/stm32f405xx/periph.h index 6ceb9c9908..0b75965d97 100644 --- a/ports/stm32f4/peripherals/stm32f4/stm32f405xx/periph.h +++ b/ports/stm32f4/peripherals/stm32f4/stm32f405xx/periph.h @@ -42,10 +42,9 @@ extern const mcu_spi_miso_obj_t mcu_spi_miso_list[6]; extern const mcu_spi_nss_obj_t mcu_spi_nss_list[6]; #define TIM_BANK_ARRAY_LEN 14 -TIM_TypeDef * mcu_tim_banks[14] = {TIM1, TIM2, TIM3, TIM4, TIM5, NULL, NULL, TIM8, TIM9, TIM10, - TIM11, TIM12, TIM13, TIM14}; +TIM_TypeDef * mcu_tim_banks[14]; #define TIM_PIN_ARRAY_LEN 66 -const mcu_tim_pin_obj_t mcu_tim_pin_list[66] = { +const mcu_tim_pin_obj_t mcu_tim_pin_list[66]; #endif // MICROPY_INCLUDED_STM32F4_PERIPHERALS_STM32F405XX_PERIPH_H \ No newline at end of file diff --git a/ports/stm32f4/supervisor/port.c b/ports/stm32f4/supervisor/port.c index 502202f522..602bec4be8 100644 --- a/ports/stm32f4/supervisor/port.c +++ b/ports/stm32f4/supervisor/port.c @@ -33,6 +33,7 @@ #include "common-hal/microcontroller/Pin.h" #include "common-hal/busio/I2C.h" #include "common-hal/busio/SPI.h" +#include "common-hal/pulseio/PWMOut.h" #include "stm32f4/clocks.h" #include "stm32f4/gpio.h" @@ -57,6 +58,7 @@ void reset_port(void) { reset_all_pins(); i2c_reset(); spi_reset(); + pwmout_reset(); } void reset_to_bootloader(void) {