diff options
| author | hierophect <hierophect@gmail.com> | 2020-07-24 11:16:39 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-07-24 11:16:39 -0400 |
| commit | c735dceed521b325d441b84d0e4df40423584b1b (patch) | |
| tree | 9ff458924da8523b9bd54bd09f6988b34c8a844e /ports/stm/common-hal | |
| parent | 543708416bc19bc1e77d859d013c4757433ad255 (diff) | |
| parent | c1f731d62e6d7bce385baec9ead3bafc46234805 (diff) | |
Merge pull request #3099 from hierophect/stm32-timer-allocator
STM32: Add timer allocator, PulseIO adjustments
Diffstat (limited to 'ports/stm/common-hal')
| -rw-r--r-- | ports/stm/common-hal/analogio/AnalogIn.c | 4 | ||||
| -rw-r--r-- | ports/stm/common-hal/analogio/AnalogOut.c | 2 | ||||
| -rw-r--r-- | ports/stm/common-hal/busio/I2C.c | 6 | ||||
| -rw-r--r-- | ports/stm/common-hal/busio/SPI.c | 8 | ||||
| -rw-r--r-- | ports/stm/common-hal/busio/UART.c | 5 | ||||
| -rw-r--r-- | ports/stm/common-hal/digitalio/DigitalInOut.c | 3 | ||||
| -rw-r--r-- | ports/stm/common-hal/microcontroller/Pin.c | 19 | ||||
| -rw-r--r-- | ports/stm/common-hal/microcontroller/Pin.h | 2 | ||||
| -rw-r--r-- | ports/stm/common-hal/pulseio/PWMOut.c | 180 | ||||
| -rw-r--r-- | ports/stm/common-hal/pulseio/PulseIn.c | 84 | ||||
| -rw-r--r-- | ports/stm/common-hal/pulseio/PulseOut.c | 138 | ||||
| -rw-r--r-- | ports/stm/common-hal/rgbmatrix/RGBMatrix.c | 14 |
12 files changed, 150 insertions, 315 deletions
diff --git a/ports/stm/common-hal/analogio/AnalogIn.c b/ports/stm/common-hal/analogio/AnalogIn.c index 1d1b308b6..588d687ee 100644 --- a/ports/stm/common-hal/analogio/AnalogIn.c +++ b/ports/stm/common-hal/analogio/AnalogIn.c @@ -29,7 +29,7 @@ #include "py/runtime.h" #include "supervisor/shared/translate.h" -#include "common-hal/microcontroller/Pin.h" +#include "shared-bindings/microcontroller/Pin.h" #include "stm32f4xx_hal.h" #include "stm32f4xx_ll_gpio.h" @@ -57,7 +57,7 @@ void common_hal_analogio_analogin_construct(analogio_analogin_obj_t* self, } else { mp_raise_ValueError(translate("Invalid ADC Unit value")); } - claim_pin(pin); + common_hal_mcu_pin_claim(pin); self->pin = pin; } diff --git a/ports/stm/common-hal/analogio/AnalogOut.c b/ports/stm/common-hal/analogio/AnalogOut.c index a505b2bf0..69c1f3e04 100644 --- a/ports/stm/common-hal/analogio/AnalogOut.c +++ b/ports/stm/common-hal/analogio/AnalogOut.c @@ -86,7 +86,7 @@ void common_hal_analogio_analogout_construct(analogio_analogout_obj_t* self, dac_on[self->dac_index] = true; self->pin = pin; - claim_pin(pin); + common_hal_mcu_pin_claim(pin); #endif } diff --git a/ports/stm/common-hal/busio/I2C.c b/ports/stm/common-hal/busio/I2C.c index 6adcf5575..b05d28c85 100644 --- a/ports/stm/common-hal/busio/I2C.c +++ b/ports/stm/common-hal/busio/I2C.c @@ -32,7 +32,7 @@ #include "shared-bindings/microcontroller/__init__.h" #include "supervisor/shared/translate.h" -#include "common-hal/microcontroller/Pin.h" +#include "shared-bindings/microcontroller/Pin.h" // I2C timing specs for the H7 and F7 // Configured for maximum possible clock settings for the family @@ -161,8 +161,8 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, if (HAL_I2C_Init(&(self->handle)) != HAL_OK) { mp_raise_RuntimeError(translate("I2C Init Error")); } - claim_pin(sda); - claim_pin(scl); + common_hal_mcu_pin_claim(sda); + common_hal_mcu_pin_claim(scl); } void common_hal_busio_i2c_never_reset(busio_i2c_obj_t *self) { diff --git a/ports/stm/common-hal/busio/SPI.c b/ports/stm/common-hal/busio/SPI.c index d4dd6cb3f..15c746b62 100644 --- a/ports/stm/common-hal/busio/SPI.c +++ b/ports/stm/common-hal/busio/SPI.c @@ -33,7 +33,7 @@ #include "shared-bindings/microcontroller/__init__.h" #include "boards/board.h" #include "supervisor/shared/translate.h" -#include "common-hal/microcontroller/Pin.h" +#include "shared-bindings/microcontroller/Pin.h" // Note that any bugs introduced in this file can cause crashes at startup // for chips using external SPI flash. @@ -233,12 +233,12 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self, self->phase = 0; self->bits = 8; - claim_pin(sck); + common_hal_mcu_pin_claim(sck); if (self->mosi != NULL) { - claim_pin(mosi); + common_hal_mcu_pin_claim(mosi); } if (self->miso != NULL) { - claim_pin(miso); + common_hal_mcu_pin_claim(miso); } } diff --git a/ports/stm/common-hal/busio/UART.c b/ports/stm/common-hal/busio/UART.c index 7450f9897..08dae7e42 100644 --- a/ports/stm/common-hal/busio/UART.c +++ b/ports/stm/common-hal/busio/UART.c @@ -25,6 +25,7 @@ */ #include "shared-bindings/microcontroller/__init__.h" +#include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/busio/UART.h" #include "mpconfigport.h" @@ -224,10 +225,10 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self, mp_raise_ValueError(translate("UART Buffer allocation error")); } } - claim_pin(rx); + common_hal_mcu_pin_claim(rx); } if (self->tx != NULL) { - claim_pin(tx); + common_hal_mcu_pin_claim(tx); } self->baudrate = baudrate; self->timeout_ms = timeout * 1000; diff --git a/ports/stm/common-hal/digitalio/DigitalInOut.c b/ports/stm/common-hal/digitalio/DigitalInOut.c index 1354e1a32..a676aeb15 100644 --- a/ports/stm/common-hal/digitalio/DigitalInOut.c +++ b/ports/stm/common-hal/digitalio/DigitalInOut.c @@ -26,6 +26,7 @@ */ #include "shared-bindings/digitalio/DigitalInOut.h" +#include "shared-bindings/microcontroller/Pin.h" #include "py/runtime.h" #include "supervisor/shared/translate.h" @@ -46,7 +47,7 @@ void common_hal_digitalio_digitalinout_never_reset( digitalinout_result_t common_hal_digitalio_digitalinout_construct( digitalio_digitalinout_obj_t *self, const mcu_pin_obj_t *pin) { - claim_pin(pin); + common_hal_mcu_pin_claim(pin); self->pin = pin; GPIO_InitTypeDef GPIO_InitStruct = {0}; diff --git a/ports/stm/common-hal/microcontroller/Pin.c b/ports/stm/common-hal/microcontroller/Pin.c index 3e3fc0522..9fbdedead 100644 --- a/ports/stm/common-hal/microcontroller/Pin.c +++ b/ports/stm/common-hal/microcontroller/Pin.c @@ -89,6 +89,8 @@ void reset_pin_number(uint8_t pin_port, uint8_t pin_number) { void never_reset_pin_number(uint8_t pin_port, uint8_t pin_number) { never_reset_pins[pin_port] |= 1<<pin_number; + // Make sure never reset pins are also always claimed + claimed_pins[pin_port] |= 1<<pin_number; } void common_hal_never_reset_pin(const mcu_pin_obj_t* pin) { @@ -99,15 +101,9 @@ void common_hal_reset_pin(const mcu_pin_obj_t* pin) { reset_pin_number(pin->port, pin->number); } -void claim_pin(const mcu_pin_obj_t* pin) { +void claim_pin(uint8_t pin_port, uint8_t pin_number) { // Set bit in claimed_pins bitmask. - claimed_pins[pin->port] |= 1<<pin->number; - - #ifdef MICROPY_HW_NEOPIXEL - if (pin == MICROPY_HW_NEOPIXEL) { - neopixel_in_use = true; - } - #endif + claimed_pins[pin_port] |= 1<<pin_number; } bool pin_number_is_free(uint8_t pin_port, uint8_t pin_number) { @@ -137,7 +133,12 @@ uint8_t common_hal_mcu_pin_number(const mcu_pin_obj_t* pin) { } void common_hal_mcu_pin_claim(const mcu_pin_obj_t* pin) { - claim_pin(pin); + claim_pin(pin->port, pin->number); + #ifdef MICROPY_HW_NEOPIXEL + if (pin == MICROPY_HW_NEOPIXEL) { + neopixel_in_use = true; + } + #endif } void common_hal_mcu_pin_reset_number(uint8_t pin_no) { diff --git a/ports/stm/common-hal/microcontroller/Pin.h b/ports/stm/common-hal/microcontroller/Pin.h index d69ddfb1d..f461d3813 100644 --- a/ports/stm/common-hal/microcontroller/Pin.h +++ b/ports/stm/common-hal/microcontroller/Pin.h @@ -43,7 +43,7 @@ void reset_all_pins(void); // reset_pin_number takes the pin number instead of the pointer so that objects don't // need to store a full pointer. void reset_pin_number(uint8_t pin_port, uint8_t pin_number); -void claim_pin(const mcu_pin_obj_t* pin); +void claim_pin(uint8_t pin_port, uint8_t pin_number); bool pin_number_is_free(uint8_t pin_port, uint8_t pin_number); void never_reset_pin_number(uint8_t pin_port, uint8_t pin_number); GPIO_TypeDef * pin_port(uint8_t pin_port); diff --git a/ports/stm/common-hal/pulseio/PWMOut.c b/ports/stm/common-hal/pulseio/PWMOut.c index 304a1539c..ddbadaf4c 100644 --- a/ports/stm/common-hal/pulseio/PWMOut.c +++ b/ports/stm/common-hal/pulseio/PWMOut.c @@ -33,7 +33,9 @@ #include "shared-bindings/microcontroller/__init__.h" #include STM32_HAL_H -#include "common-hal/microcontroller/Pin.h" +#include "shared-bindings/microcontroller/Pin.h" + +#include "timers.h" #define ALL_CLOCKS 0xFFFF @@ -41,32 +43,6 @@ 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); - -// Get the frequency (in Hz) of the source clock for the given timer. -// On STM32F405/407/415/417 there are 2 cases for how the clock freq is set. -// If the APB prescaler is 1, then the timer clock is equal to its respective -// APB clock. Otherwise (APB prescaler > 1) the timer clock is twice its -// respective APB clock. See DM00031020 Rev 4, page 115. -STATIC uint32_t timer_get_source_freq(uint32_t tim_id) { - uint32_t source, clk_div; - if (tim_id == 1 || (8 <= tim_id && tim_id <= 11)) { - // TIM{1,8,9,10,11} are on APB2 - source = HAL_RCC_GetPCLK2Freq(); - clk_div = RCC->CFGR & RCC_CFGR_PPRE2; - } else { - // TIM{2,3,4,5,6,7,12,13,14} are on APB1 - source = HAL_RCC_GetPCLK1Freq(); - clk_div = RCC->CFGR & RCC_CFGR_PPRE1; - } - if (clk_div != 0) { - // APB prescaler for this timer is > 1 - source *= 2; - } - return source; -} - STATIC uint32_t timer_get_internal_duty(uint16_t duty, uint32_t period) { //duty cycle is duty/0xFFFF fraction x (number of pulses per period) return (duty*period) / ((1 << 16) - 1); @@ -97,7 +73,6 @@ void pwmout_reset(void) { never_reset_mask |= 1 << i; } } - tim_clock_disable(ALL_CLOCKS & ~(never_reset_mask)); } pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self, @@ -107,6 +82,7 @@ pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self, bool variable_frequency) { TIM_TypeDef * TIMx; uint8_t tim_num = MP_ARRAY_SIZE(mcu_tim_pin_list); + bool tim_taken_internal = false; bool tim_chan_taken = false; bool tim_taken_f_mismatch = false; bool var_freq_mismatch = false; @@ -119,8 +95,13 @@ pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self, //if pin is same if (l_tim->pin == pin) { - //check if the timer has a channel active + //check if the timer has a channel active, or is reserved by main timer system if (reserved_tim[l_tim_index] != 0) { + // Timer has already been reserved by an internal module + if (stm_peripherals_timer_is_reserved(mcu_tim_banks[l_tim_index])) { + tim_taken_internal = true; + continue; //keep looking + } //is it the same channel? (or all channels reserved by a var-freq) if (reserved_tim[l_tim_index] & 1 << (l_tim_channel)) { tim_chan_taken = true; @@ -155,9 +136,12 @@ pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self, reserved_tim[self->tim->tim_index - 1] |= 1 << (self->tim->channel_index - 1); } tim_frequencies[self->tim->tim_index - 1] = frequency; + stm_peripherals_timer_reserve(TIMx); } else { //no match found if (tim_chan_taken) { mp_raise_ValueError(translate("No more timers available on this pin.")); + } else if (tim_taken_internal) { + mp_raise_ValueError(translate("Timer was reserved for internal use - declare PWM pins earlier in the program")); } else if (tim_taken_f_mismatch) { mp_raise_ValueError(translate("Frequency must match existing PWMOut using this timer")); } else if (var_freq_mismatch) { @@ -182,8 +166,8 @@ pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self, uint32_t prescaler = 0; //prescaler is 15 bit uint32_t period = 0; //period is 16 bit - timer_get_optimal_divisors(&period, &prescaler, frequency, - timer_get_source_freq(self->tim->tim_index)); + uint32_t source_freq = stm_peripherals_timer_get_source_freq(TIMx); + timer_get_optimal_divisors(&period, &prescaler, frequency, source_freq); //Timer init self->handle.Instance = TIMx; @@ -260,7 +244,7 @@ void common_hal_pulseio_pwmout_deinit(pulseio_pwmout_obj_t* self) { //if reserved timer has no active channels, we can disable it if (!reserved_tim[self->tim->tim_index - 1]) { tim_frequencies[self->tim->tim_index - 1] = 0x00; - tim_clock_disable(1 << (self->tim->tim_index - 1)); + stm_peripherals_timer_free(self->handle.Instance); } } @@ -282,8 +266,8 @@ void common_hal_pulseio_pwmout_set_frequency(pulseio_pwmout_obj_t* self, uint32_ uint32_t prescaler = 0; uint32_t period = 0; - timer_get_optimal_divisors(&period, &prescaler, frequency, - timer_get_source_freq(self->tim->tim_index)); + uint32_t source_freq = stm_peripherals_timer_get_source_freq(self->handle.Instance); + timer_get_optimal_divisors(&period, &prescaler, frequency, source_freq); //shut down HAL_TIM_PWM_Stop(&self->handle, self->channel); @@ -318,131 +302,3 @@ uint32_t common_hal_pulseio_pwmout_get_frequency(pulseio_pwmout_obj_t* self) { bool common_hal_pulseio_pwmout_get_variable_frequency(pulseio_pwmout_obj_t* self) { return self->variable_frequency; } - -STATIC void tim_clock_enable(uint16_t mask) { - #ifdef TIM1 - if (mask & (1 << 0)) { - __HAL_RCC_TIM1_CLK_ENABLE(); - } - #endif - #ifdef TIM2 - if (mask & (1 << 1)) { - __HAL_RCC_TIM2_CLK_ENABLE(); - } - #endif - #ifdef TIM3 - if (mask & (1 << 2)) { - __HAL_RCC_TIM3_CLK_ENABLE(); - } - #endif - #ifdef TIM4 - if (mask & (1 << 3)) { - __HAL_RCC_TIM4_CLK_ENABLE(); - } - #endif - #ifdef TIM5 - if (mask & (1 << 4)) { - __HAL_RCC_TIM5_CLK_ENABLE(); - } - #endif - //6 and 7 are reserved ADC timers - #ifdef TIM8 - if (mask & (1 << 7)) { - __HAL_RCC_TIM8_CLK_ENABLE(); - } - #endif - #ifdef TIM9 - if (mask & (1 << 8)) { - __HAL_RCC_TIM9_CLK_ENABLE(); - } - #endif - #ifdef TIM10 - if (mask & (1 << 9)) { - __HAL_RCC_TIM10_CLK_ENABLE(); - } - #endif - #ifdef TIM11 - if (mask & (1 << 10)) { - __HAL_RCC_TIM11_CLK_ENABLE(); - } - #endif - #ifdef TIM12 - if (mask & (1 << 11)) { - __HAL_RCC_TIM12_CLK_ENABLE(); - } - #endif - #ifdef TIM13 - if (mask & (1 << 12)) { - __HAL_RCC_TIM13_CLK_ENABLE(); - } - #endif - #ifdef TIM14 - if (mask & (1 << 13)) { - __HAL_RCC_TIM14_CLK_ENABLE(); - } - #endif -} - -STATIC void tim_clock_disable(uint16_t mask) { - #ifdef TIM1 - if (mask & (1 << 0)) { - __HAL_RCC_TIM1_CLK_DISABLE(); - } - #endif - #ifdef TIM2 - if (mask & (1 << 1)) { - __HAL_RCC_TIM2_CLK_DISABLE(); - } - #endif - #ifdef TIM3 - if (mask & (1 << 2)) { - __HAL_RCC_TIM3_CLK_DISABLE(); - } - #endif - #ifdef TIM4 - if (mask & (1 << 3)) { - __HAL_RCC_TIM4_CLK_DISABLE(); - } - #endif - #ifdef TIM5 - if (mask & (1 << 4)) { - __HAL_RCC_TIM5_CLK_DISABLE(); - } - #endif - //6 and 7 are reserved ADC timers - #ifdef TIM8 - if (mask & (1 << 7)) { - __HAL_RCC_TIM8_CLK_DISABLE(); - } - #endif - #ifdef TIM9 - if (mask & (1 << 8)) { - __HAL_RCC_TIM9_CLK_DISABLE(); - } - #endif - #ifdef TIM10 - if (mask & (1 << 9)) { - __HAL_RCC_TIM10_CLK_DISABLE(); - } - #endif - #ifdef TIM11 - if (mask & (1 << 10)) { - __HAL_RCC_TIM11_CLK_DISABLE(); - } - #endif - #ifdef TIM12 - if (mask & (1 << 11)) { - __HAL_RCC_TIM12_CLK_DISABLE(); - } - #endif - #ifdef TIM13 - if (mask & (1 << 12)) { - __HAL_RCC_TIM13_CLK_DISABLE(); - } - #endif - #ifdef TIM14 - if (mask & (1 << 13)) { - __HAL_RCC_TIM14_CLK_DISABLE(); - } - #endif -} diff --git a/ports/stm/common-hal/pulseio/PulseIn.c b/ports/stm/common-hal/pulseio/PulseIn.c index 9d82a18a0..4052c240f 100644 --- a/ports/stm/common-hal/pulseio/PulseIn.c +++ b/ports/stm/common-hal/pulseio/PulseIn.c @@ -31,40 +31,38 @@ #include "py/gc.h" #include "py/runtime.h" #include "shared-bindings/microcontroller/__init__.h" +#include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/pulseio/PulseIn.h" +#include "timers.h" #include STM32_HAL_H #define STM32_GPIO_PORT_SIZE 16 - static pulseio_pulsein_obj_t* _objs[STM32_GPIO_PORT_SIZE]; -STATIC TIM_HandleTypeDef t6_handle; +STATIC TIM_HandleTypeDef tim_handle; static uint32_t overflow_count = 0; STATIC uint8_t refcount = 0; static void assign_EXTI_Interrupt(pulseio_pulsein_obj_t* self, uint8_t num); -void TIM6_IRQHandler(void) +void pulsein_timer_event_handler(void) { // Detect TIM Update event - if (__HAL_TIM_GET_FLAG(&t6_handle, TIM_FLAG_UPDATE) != RESET) + if (__HAL_TIM_GET_FLAG(&tim_handle, TIM_FLAG_UPDATE) != RESET) { - if (__HAL_TIM_GET_IT_SOURCE(&t6_handle, TIM_IT_UPDATE) != RESET) + if (__HAL_TIM_GET_IT_SOURCE(&tim_handle, TIM_IT_UPDATE) != RESET) { - __HAL_TIM_CLEAR_IT(&t6_handle, TIM_IT_UPDATE); + __HAL_TIM_CLEAR_IT(&tim_handle, TIM_IT_UPDATE); overflow_count++; } } } -static void pulsein_handler(uint8_t num) { +static void pulsein_exti_event_handler(uint8_t num) { // Grab the current time first. uint32_t current_overflow = overflow_count; - uint32_t current_count = 0; - #if HAS_BASIC_TIM - current_count = TIM6->CNT; - #endif + uint32_t current_count = tim_handle.Instance->CNT; // Interrupt register must be cleared manually EXTI->PR = 1 << num; @@ -105,17 +103,14 @@ void pulsein_reset(void) { } memset(_objs, 0, sizeof(_objs)); - #if HAS_BASIC_TIM - __HAL_RCC_TIM6_CLK_DISABLE(); + HAL_TIM_Base_DeInit(&tim_handle); + tim_clock_disable(stm_peripherals_timer_get_index(tim_handle.Instance)); + memset(&tim_handle, 0, sizeof(tim_handle)); refcount = 0; - #endif } void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t* self, const mcu_pin_obj_t* pin, uint16_t maxlen, bool idle_state) { -#if !(HAS_BASIC_TIM) - mp_raise_NotImplementedError(translate("PulseIn not supported on this chip")); -#else // STM32 has one shared EXTI for each pin number, 0-15 uint8_t p_num = pin->number; if(_objs[p_num]) { @@ -141,24 +136,34 @@ void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t* self, const mcu self->last_count = 0; self->last_overflow = 0; - if (HAL_TIM_Base_GetState(&t6_handle) == HAL_TIM_STATE_RESET) { - // Set the new period - t6_handle.Instance = TIM6; - t6_handle.Init.Prescaler = 168; // HCLK is 168 mhz so divide down to 1mhz - t6_handle.Init.Period = 0xffff; - HAL_TIM_Base_Init(&t6_handle); + if (HAL_TIM_Base_GetState(&tim_handle) == HAL_TIM_STATE_RESET) { + // Find a suitable timer + TIM_TypeDef * tim_instance = stm_peripherals_find_timer(); + stm_peripherals_timer_reserve(tim_instance); + + // Set ticks to 1us + uint32_t source = stm_peripherals_timer_get_source_freq(tim_instance); + uint32_t prescaler = source/1000000; + + // Enable clocks and IRQ, set callback + stm_peripherals_timer_preinit(tim_instance, 4, pulsein_timer_event_handler); - // TIM6 has limited HAL support, set registers manually - t6_handle.Instance->SR = 0; // Prevent the SR from triggering an interrupt - t6_handle.Instance->CR1 |= TIM_CR1_CEN; // Resume timer - t6_handle.Instance->CR1 |= TIM_CR1_URS; // Disable non-overflow interrupts - __HAL_TIM_ENABLE_IT(&t6_handle, TIM_IT_UPDATE); + // Set the new period + tim_handle.Instance = tim_instance; + tim_handle.Init.Prescaler = prescaler - 1; + tim_handle.Init.Period = 0x10000 - 1; //65 ms period (maximum) + HAL_TIM_Base_Init(&tim_handle); + + // Set registers manually + tim_handle.Instance->SR = 0; // Prevent the SR from triggering an interrupt + tim_handle.Instance->CR1 |= TIM_CR1_CEN; // Resume timer + tim_handle.Instance->CR1 |= TIM_CR1_URS; // Disable non-overflow interrupts + __HAL_TIM_ENABLE_IT(&tim_handle, TIM_IT_UPDATE); overflow_count = 0; } // Add to active PulseIns refcount++; -#endif // EXTI pins can also be read as an input GPIO_InitTypeDef GPIO_InitStruct = {0}; @@ -170,7 +175,7 @@ void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t* self, const mcu // Interrupt starts immediately assign_EXTI_Interrupt(self, pin->number); HAL_NVIC_EnableIRQ(self->irq); - claim_pin(pin); + common_hal_mcu_pin_claim(pin); } bool common_hal_pulseio_pulsein_deinited(pulseio_pulsein_obj_t* self) { @@ -182,16 +187,13 @@ void common_hal_pulseio_pulsein_deinit(pulseio_pulsein_obj_t* self) { return; } //Remove pulsein slot from shared array - HAL_NVIC_DisableIRQ(self->irq); _objs[self->pin->number] = NULL; reset_pin_number(self->pin->port, self->pin->number); self->pin = NULL; refcount--; if (refcount == 0) { - #if HAS_BASIC_TIM - __HAL_RCC_TIM6_CLK_DISABLE(); - #endif + stm_peripherals_timer_free(tim_handle.Instance); } } @@ -299,23 +301,23 @@ static void assign_EXTI_Interrupt(pulseio_pulsein_obj_t* self, uint8_t num) { void EXTI0_IRQHandler(void) { - pulsein_handler(0); + pulsein_exti_event_handler(0); } void EXTI1_IRQHandler(void) { - pulsein_handler(1); + pulsein_exti_event_handler(1); } void EXTI2_IRQHandler(void) { - pulsein_handler(2); + pulsein_exti_event_handler(2); } void EXTI3_IRQHandler(void) { - pulsein_handler(3); + pulsein_exti_event_handler(3); } void EXTI4_IRQHandler(void) { - pulsein_handler(4); + pulsein_exti_event_handler(4); } void EXTI9_5_IRQHandler(void) @@ -323,7 +325,7 @@ void EXTI9_5_IRQHandler(void) uint32_t pending = EXTI->PR; for (uint i = 5; i <= 9; i++) { if(pending & (1 << i)) { - pulsein_handler(i); + pulsein_exti_event_handler(i); } } } @@ -333,7 +335,7 @@ void EXTI15_10_IRQHandler(void) uint32_t pending = EXTI->PR; for (uint i = 10; i <= 15; i++) { if(pending & (1 << i)) { - pulsein_handler(i); + pulsein_exti_event_handler(i); } } } diff --git a/ports/stm/common-hal/pulseio/PulseOut.c b/ports/stm/common-hal/pulseio/PulseOut.c index c7c879c88..bcc25d817 100644 --- a/ports/stm/common-hal/pulseio/PulseOut.c +++ b/ports/stm/common-hal/pulseio/PulseOut.c @@ -36,20 +36,20 @@ #include "supervisor/shared/translate.h" #include STM32_HAL_H -#include "common-hal/microcontroller/Pin.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "timers.h" // A single timer is shared amongst all PulseOut objects under the assumption that // the code is single threaded. STATIC uint8_t refcount = 0; - STATIC uint16_t *pulse_array = NULL; STATIC volatile uint16_t pulse_array_index = 0; STATIC uint16_t pulse_array_length; - //Timer is shared, must be accessible by interrupt -STATIC TIM_HandleTypeDef t7_handle; +STATIC TIM_HandleTypeDef tim_handle; pulseio_pulseout_obj_t *curr_pulseout = NULL; + STATIC void turn_on(pulseio_pulseout_obj_t *pulseout) { // Turn on PWM HAL_TIM_PWM_Start(&(pulseout->pwmout->handle), pulseout->pwmout->channel); @@ -65,91 +65,78 @@ STATIC void turn_off(pulseio_pulseout_obj_t *pulseout) { STATIC void start_timer(void) { // Set the new period - t7_handle.Init.Period = pulse_array[pulse_array_index] - 1; - HAL_TIM_Base_Init(&t7_handle); + tim_handle.Init.Period = pulse_array[pulse_array_index] - 1; + HAL_TIM_Base_Init(&tim_handle); // TIM7 has limited HAL support, set registers manually - t7_handle.Instance->SR = 0; // Prevent the SR from triggering an interrupt - t7_handle.Instance->CR1 |= TIM_CR1_CEN; // Resume timer - t7_handle.Instance->CR1 |= TIM_CR1_URS; // Disable non-overflow interrupts - __HAL_TIM_ENABLE_IT(&t7_handle, TIM_IT_UPDATE); - + tim_handle.Instance->SR = 0; // Prevent the SR from triggering an interrupt + tim_handle.Instance->CR1 |= TIM_CR1_CEN; // Resume timer + tim_handle.Instance->CR1 |= TIM_CR1_URS; // Disable non-overflow interrupts + __HAL_TIM_ENABLE_IT(&tim_handle, TIM_IT_UPDATE); } STATIC void pulseout_event_handler(void) { - if (curr_pulseout->pwmout == NULL) { - return; //invalid interrupt - } - - HAL_GPIO_WritePin(pin_port(2),pin_mask(6), 1); - HAL_GPIO_WritePin(pin_port(2),pin_mask(6), 0); - - pulse_array_index++; - - // No more pulses. Turn off output and don't restart. - if (pulse_array_index >= pulse_array_length) { - turn_off(curr_pulseout); - return; - } - - // Alternate on and off, starting with on. - if (pulse_array_index % 2 == 0) { - turn_on(curr_pulseout); - } else { - turn_off(curr_pulseout); + // Detect TIM Update event + if (__HAL_TIM_GET_FLAG(&tim_handle, TIM_FLAG_UPDATE) != RESET) + { + if (__HAL_TIM_GET_IT_SOURCE(&tim_handle, TIM_IT_UPDATE) != RESET) + { + __HAL_TIM_CLEAR_IT(&tim_handle, TIM_IT_UPDATE); + if (curr_pulseout->pwmout == NULL) { + return; //invalid interrupt + } + + pulse_array_index++; + + // No more pulses. Turn off output and don't restart. + if (pulse_array_index >= pulse_array_length) { + turn_off(curr_pulseout); + return; + } + + // Alternate on and off, starting with on. + if (pulse_array_index % 2 == 0) { + turn_on(curr_pulseout); + } else { + turn_off(curr_pulseout); + } + + // Count up to the next given value. + start_timer(); + } } - - // Count up to the next given value. - start_timer(); } void pulseout_reset() { - #if HAS_BASIC_TIM - __HAL_RCC_TIM7_CLK_DISABLE(); + stm_peripherals_timer_free(tim_handle.Instance); refcount = 0; - #endif } void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t* self, const pulseio_pwmout_obj_t* carrier) { -#if !(HAS_BASIC_TIM) - mp_raise_NotImplementedError(translate("PulseOut not supported on this chip")); -#else // Add to active PulseOuts refcount++; + TIM_TypeDef * tim_instance = stm_peripherals_find_timer(); + stm_peripherals_timer_reserve(tim_instance); - // Calculate a 1 ms period - uint32_t source, clk_div; - source = HAL_RCC_GetPCLK1Freq(); // TIM7 is on APB1 - clk_div = RCC->CFGR & RCC_CFGR_PPRE1; - // APB quirk, see See DM00031020 Rev 4, page 115. - if (clk_div != 0) { - // APB prescaler for this timer is > 1 - source *= 2; - } - + //calculate a 1ms period + uint32_t source = stm_peripherals_timer_get_source_freq(tim_instance); uint32_t prescaler = source/1000000; //1us intervals - __HAL_RCC_TIM7_CLK_ENABLE(); - HAL_NVIC_SetPriority(TIM7_IRQn, 4, 0); - HAL_NVIC_EnableIRQ(TIM7_IRQn); - - // Timers 6 and 7 have no pins, so using them doesn't affect PWM availability - t7_handle.Instance = TIM7; - t7_handle.Init.Period = 100; //immediately replaced. - t7_handle.Init.Prescaler = prescaler - 1; - t7_handle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; - t7_handle.Init.CounterMode = TIM_COUNTERMODE_UP; - t7_handle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; + stm_peripherals_timer_preinit(tim_instance, 4, pulseout_event_handler); + tim_handle.Instance = tim_instance; + tim_handle.Init.Period = 100; //immediately replaced. + tim_handle.Init.Prescaler = prescaler - 1; + tim_handle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; + tim_handle.Init.CounterMode = TIM_COUNTERMODE_UP; + tim_handle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; - HAL_TIM_Base_Init(&t7_handle); - t7_handle.Instance->SR = 0; + HAL_TIM_Base_Init(&tim_handle); + tim_handle.Instance->SR = 0; // The HAL can't work with const, recast required. self->pwmout = (pulseio_pwmout_obj_t*)carrier; - turn_off(self); -#endif } bool common_hal_pulseio_pulseout_deinited(pulseio_pulseout_obj_t* self) { @@ -165,9 +152,7 @@ void common_hal_pulseio_pulseout_deinit(pulseio_pulseout_obj_t* self) { refcount--; if (refcount == 0) { - #if HAS_BASIC_TIM - __HAL_RCC_TIM7_CLK_DISABLE(); - #endif + stm_peripherals_timer_free(tim_handle.Instance); } } @@ -190,24 +175,11 @@ void common_hal_pulseio_pulseout_send(pulseio_pulseout_obj_t* self, uint16_t* pu // signal. RUN_BACKGROUND_TASKS; - // Use when debugging, or issues are irrecoverable + // // Use when debugging, or issues are irrecoverable // if ((supervisor_ticks_ms64() - starttime ) > timeout ) { // mp_raise_RuntimeError(translate("Error: Send Timeout")); // } } //turn off timer counter. - t7_handle.Instance->CR1 &= ~TIM_CR1_CEN; -} - -void TIM7_IRQHandler(void) -{ - // Detect TIM Update event - if (__HAL_TIM_GET_FLAG(&t7_handle, TIM_FLAG_UPDATE) != RESET) - { - if (__HAL_TIM_GET_IT_SOURCE(&t7_handle, TIM_IT_UPDATE) != RESET) - { - __HAL_TIM_CLEAR_IT(&t7_handle, TIM_IT_UPDATE); - pulseout_event_handler(); - } - } + tim_handle.Instance->CR1 &= ~TIM_CR1_CEN; } diff --git a/ports/stm/common-hal/rgbmatrix/RGBMatrix.c b/ports/stm/common-hal/rgbmatrix/RGBMatrix.c index 9e60cc3e6..3b42631ad 100644 --- a/ports/stm/common-hal/rgbmatrix/RGBMatrix.c +++ b/ports/stm/common-hal/rgbmatrix/RGBMatrix.c @@ -27,28 +27,30 @@ #include <stddef.h> #include "common-hal/rgbmatrix/RGBMatrix.h" +#include "timers.h" #include STM32_HAL_H extern void _PM_IRQ_HANDLER(void); void *common_hal_rgbmatrix_timer_allocate() { - // TODO(jepler) properly handle resource allocation including never-reset - return TIM6; + TIM_TypeDef * timer = stm_peripherals_find_timer(); + stm_peripherals_timer_reserve(timer); + return timer; } - void common_hal_rgbmatrix_timer_enable(void* ptr) { - HAL_NVIC_EnableIRQ(TIM6_DAC_IRQn); + TIM_TypeDef *tim = (TIM_TypeDef*)ptr; + HAL_NVIC_EnableIRQ(stm_peripherals_timer_get_irqnum(tim)); } void common_hal_rgbmatrix_timer_disable(void* ptr) { TIM_TypeDef *tim = (TIM_TypeDef*)ptr; tim->DIER &= ~TIM_DIER_UIE; - HAL_NVIC_DisableIRQ(TIM6_DAC_IRQn); } void common_hal_rgbmatrix_timer_free(void* ptr) { + TIM_TypeDef *tim = (TIM_TypeDef*)ptr; + stm_peripherals_timer_free(tim); common_hal_rgbmatrix_timer_disable(ptr); - // TODO(jepler) properly handle resource allocation including never-reset } |
