summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLucian Copeland <hierophect@gmail.com>2020-07-01 10:07:45 -0400
committerLucian Copeland <hierophect@gmail.com>2020-07-01 10:35:49 -0400
commitab9a64eafa7f2e5892e13053c5e9490437548263 (patch)
treeb9320fbe9f12ce439412ce6ae655440d7fb92b35
parent6c91af7d5601c0577e9f1909968bbb5aa2bf7b25 (diff)
Add timer allocator, adjust pulsio to use general purpose timers
-rwxr-xr-xports/stm/Makefile1
-rw-r--r--ports/stm/common-hal/pulseio/PWMOut.c176
-rw-r--r--ports/stm/common-hal/pulseio/PulseIn.c77
-rw-r--r--ports/stm/common-hal/pulseio/PulseOut.c132
-rw-r--r--ports/stm/mpconfigport.mk4
-rw-r--r--ports/stm/peripherals/timers.c136
-rw-r--r--ports/stm/peripherals/timers.h27
-rw-r--r--ports/stm/supervisor/port.c2
8 files changed, 252 insertions, 303 deletions
diff --git a/ports/stm/Makefile b/ports/stm/Makefile
index 08cb36ddf..0db0775e2 100755
--- a/ports/stm/Makefile
+++ b/ports/stm/Makefile
@@ -207,6 +207,7 @@ SRC_C += \
mphalport.c \
boards/$(BOARD)/board.c \
boards/$(BOARD)/pins.c \
+ peripherals/timers.c \
peripherals/stm32$(MCU_SERIES_LOWER)/clocks.c \
peripherals/stm32$(MCU_SERIES_LOWER)/$(MCU_VARIANT_LOWER)/pins.c \
peripherals/stm32$(MCU_SERIES_LOWER)/$(MCU_VARIANT_LOWER)/gpio.c \
diff --git a/ports/stm/common-hal/pulseio/PWMOut.c b/ports/stm/common-hal/pulseio/PWMOut.c
index 304a1539c..a3c21330e 100644
--- a/ports/stm/common-hal/pulseio/PWMOut.c
+++ b/ports/stm/common-hal/pulseio/PWMOut.c
@@ -35,38 +35,14 @@
#include STM32_HAL_H
#include "common-hal/microcontroller/Pin.h"
+#include "timers.h"
+
#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);
-
-// 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;
@@ -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..8b93e52f2 100644
--- a/ports/stm/common-hal/pulseio/PulseIn.c
+++ b/ports/stm/common-hal/pulseio/PulseIn.c
@@ -32,39 +32,36 @@
#include "py/runtime.h"
#include "shared-bindings/microcontroller/__init__.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 +102,12 @@ void pulsein_reset(void) {
}
memset(_objs, 0, sizeof(_objs));
- #if HAS_BASIC_TIM
- __HAL_RCC_TIM6_CLK_DISABLE();
+ tim_clock_disable(stm_peripherals_timer_get_index(tim_handle.Instance));
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 +133,33 @@ 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);
+
+ // Calculate a 1ms period
+ uint32_t source = stm_peripherals_timer_get_source_freq(tim_instance);
+ uint32_t prescaler = source/1000000; // 1us intervals
+
+ stm_peripherals_timer_preinit(tim_instance, 4, pulsein_timer_event_handler);
+
+ // Set the new period
+ tim_handle.Instance = tim_instance;
+ tim_handle.Init.Prescaler = prescaler; // divide down to 1mhz
+ tim_handle.Init.Period = 0xffff;
+ HAL_TIM_Base_Init(&tim_handle);
- // 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 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};
@@ -189,9 +190,7 @@ void common_hal_pulseio_pulsein_deinit(pulseio_pulsein_obj_t* self) {
refcount--;
if (refcount == 0) {
- #if HAS_BASIC_TIM
- __HAL_RCC_TIM6_CLK_DISABLE();
- #endif
+ tim_clock_disable(1<< stm_peripherals_timer_get_index(tim_handle.Instance));
}
}
@@ -299,23 +298,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 +322,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 +332,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 c31b23830..ba817ae26 100644
--- a/ports/stm/common-hal/pulseio/PulseOut.c
+++ b/ports/stm/common-hal/pulseio/PulseOut.c
@@ -37,19 +37,19 @@
#include STM32_HAL_H
#include "common-hal/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,88 +65,79 @@ 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
- }
-
- 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);
+ 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;
- // 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;
-
- 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) {
@@ -162,9 +153,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
+ tim_clock_disable(1<< stm_peripherals_timer_get_index(tim_handle.Instance));
}
}
@@ -187,24 +176,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/mpconfigport.mk b/ports/stm/mpconfigport.mk
index 7b720d156..3b3a21bd2 100644
--- a/ports/stm/mpconfigport.mk
+++ b/ports/stm/mpconfigport.mk
@@ -4,8 +4,8 @@ INTERNAL_LIBM ?= 1
USB_SERIAL_NUMBER_LENGTH ?= 24
ifeq ($(MCU_VARIANT),STM32F405xx)
- CIRCUITPY_FRAMEBUFFERIO ?= 1
- CIRCUITPY_RGBMATRIX ?= 1
+ CIRCUITPY_FRAMEBUFFERIO ?= 0
+ CIRCUITPY_RGBMATRIX ?= 0
endif
ifeq ($(MCU_SERIES),F4)
diff --git a/ports/stm/peripherals/timers.c b/ports/stm/peripherals/timers.c
index 81242f34b..f28b36eec 100644
--- a/ports/stm/peripherals/timers.c
+++ b/ports/stm/peripherals/timers.c
@@ -23,20 +23,51 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
+#include "timers.h"
+
+#include "py/mpconfig.h"
+#include "py/gc.h"
+#include "py/obj.h"
+#include "py/runtime.h"
+#include "supervisor/shared/translate.h"
+
+#include "shared-bindings/microcontroller/__init__.h"
+#include "shared-bindings/microcontroller/Pin.h"
+
+#define ALL_CLOCKS 0xFFFF
static bool stm_timer_reserved[MP_ARRAY_SIZE(mcu_tim_banks)];
static bool stm_timer_never_reset[MP_ARRAY_SIZE(mcu_tim_banks)];
-static void *stm_timer_callback[MP_ARRAY_SIZE(mcu_tim_banks)](void);
-
-STATIC void tim_clock_enable(uint16_t mask);
-STATIC void tim_clock_disable(uint16_t mask);
+static void (*stm_timer_callback[MP_ARRAY_SIZE(mcu_tim_banks)])(void);
+static size_t irq_map[] = {
+ TIM1_CC_IRQn,
+ TIM2_IRQn,
+ TIM3_IRQn,
+ TIM4_IRQn,
+ TIM5_IRQn,
+ TIM6_DAC_IRQn,
+ TIM7_IRQn,
+ TIM8_CC_IRQn,
+ TIM1_BRK_TIM9_IRQn,
+ TIM1_UP_TIM10_IRQn,
+ TIM1_TRG_COM_TIM11_IRQn,
+ TIM8_BRK_TIM12_IRQn,
+ TIM8_UP_TIM13_IRQn,
+ TIM8_TRG_COM_TIM14_IRQn,
+#if (CPY_STM32H7)
+ TIM15_IRQn,
+ TIM16_IRQn,
+ TIM17_IRQn,
+#endif
+};
// 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 stm_peripherals_timer_get_source_freq(TIM_TypeDef * timer) {
+ size_t tim_id = stm_peripherals_timer_get_index(timer);
uint32_t source, clk_div;
if (tim_id == 1 || (8 <= tim_id && tim_id <= 11)) {
// TIM{1,8,9,10,11} are on APB2
@@ -54,11 +85,44 @@ STATIC uint32_t timer_get_source_freq(uint32_t tim_id) {
return source;
}
+void timers_reset(void) {
+ uint16_t never_reset_mask = 0x00;
+ for (size_t i = 0; i < MP_ARRAY_SIZE(mcu_tim_banks); i++) {
+ if (!stm_timer_never_reset[i]) {
+ stm_timer_reserved[i] = false;
+ } else {
+ never_reset_mask |= 1 << i;
+ }
+ }
+ tim_clock_disable(ALL_CLOCKS & ~(never_reset_mask));
+}
+
TIM_TypeDef * stm_peripherals_find_timer(void) {
- // TODO: check for unreserved timers from already claimed pins
+ // Check for timers on pins outside the package size
+ // for (size_t i = 0; i < MP_ARRAY_SIZE(mcu_tim_banks); i++) {
+ // bool timer_in_package = false;
+ // // Find each timer instance on the given bank
+ // for (size_t j = 0; j < MP_ARRAY_SIZE(mcu_tim_pin_list); j++) {
+ // // If a pin is claimed, we skip it
+ // if ( (mcu_tim_pin_list[j].tim_index == i)
+ // && (common_hal_mcu_pin_is_free(mcu_tim_pin_list[j].pin) == true) ) {
+ // // Search whether any pins in the package array match it
+ // for (size_t k = 0; k < mcu_pin_globals.map.alloc; k++) {
+ // if ( (mcu_tim_pin_list[j].pin == (mcu_pin_obj_t*)(mcu_pin_globals.map.table[k].value)) ) {
+ // timer_in_package = true;
+ // }
+ // }
+ // }
+ // }
+ // // If no results are found, no unclaimed pins with this timer are in this package,
+ // // and it is safe to pick
+ // if (timer_in_package == false && mcu_tim_banks[i] != NULL) {
+ // return mcu_tim_banks[i];
+ // }
+ // }
// Work backwards - higher index timers have fewer pin allocations
- for (size_t i = MP_ARRAY_SIZE(stm_timer_reserved); i>=0; i--) {
+ for (size_t i = (MP_ARRAY_SIZE(mcu_tim_banks) - 1); i>=0; i--) {
if ((!stm_timer_reserved[i]) && (mcu_tim_banks[i] != NULL)) {
return mcu_tim_banks[i];
}
@@ -67,20 +131,58 @@ TIM_TypeDef * stm_peripherals_find_timer(void) {
return NULL;
}
+void stm_peripherals_timer_preinit(TIM_TypeDef * instance, uint8_t prio, void (*callback)(void)) {
+ size_t tim_idx = stm_peripherals_timer_get_index(instance);
+ stm_timer_callback[tim_idx] = callback;
+ tim_clock_enable(1 << tim_idx);
+ HAL_NVIC_SetPriority(irq_map[tim_idx], prio, 0);
+ HAL_NVIC_EnableIRQ(irq_map[tim_idx]);
+}
+
+void stm_peripherals_timer_reserve(TIM_TypeDef * instance) {
+ size_t tim_idx = stm_peripherals_timer_get_index(instance);
+ stm_timer_reserved[tim_idx] = true;
+}
+
void stm_peripherals_timer_set_callback(void(*callback)(void), TIM_TypeDef * timer) {
- stm_timer_callback[stm_peripherals_timer_get_index]
+ stm_timer_callback[stm_peripherals_timer_get_index(timer)] = callback;
}
void stm_peripherals_timer_free(TIM_TypeDef * instance) {
+ size_t tim_idx = stm_peripherals_timer_get_index(instance);
+ stm_timer_callback[tim_idx] = NULL;
+ tim_clock_disable(1 << tim_idx);
+ stm_timer_reserved[tim_idx] = false;
+ stm_timer_never_reset[tim_idx] = false;
+}
+void stm_peripherals_timer_never_reset(TIM_TypeDef * instance) {
+ size_t tim_idx = stm_peripherals_timer_get_index(instance);
+ stm_timer_never_reset[tim_idx] = true;
+}
+void stm_peripherals_timer_reset_ok(TIM_TypeDef * instance) {
+ size_t tim_idx = stm_peripherals_timer_get_index(instance);
+ stm_timer_never_reset[tim_idx] = false;
+}
+bool stm_peripherals_timer_is_never_reset(TIM_TypeDef * instance){
+ size_t tim_idx = stm_peripherals_timer_get_index(instance);
+ return stm_timer_never_reset[tim_idx];
+}
+bool stm_peripherals_timer_is_reserved(TIM_TypeDef * instance) {
+ size_t tim_idx = stm_peripherals_timer_get_index(instance);
+ return stm_timer_reserved[tim_idx];
+}
+
+size_t stm_peripherals_timer_get_index(TIM_TypeDef * instance) {
+ for (size_t i = 0; i < MP_ARRAY_SIZE(mcu_tim_banks); i++) {
+ if (instance == mcu_tim_banks[i]) {
+ return i;
+ }
+ }
+ return ~(size_t)0;
}
-void stm_peripherals_timer_never_reset(TIM_TypeDef * instance);
-void stm_peripherals_timer_reset_ok(TIM_TypeDef * instance);
-void stm_peripherals_timer_is_never_reset(TIM_TypeDef * instance);
-void stm_peripherals_timer_is_reserved(TIM_TypeDef * instance);
-size_t stm_peripherals_timer_get_index(TIM_TypeDef * instance);
-STATIC void tim_clock_enable(uint16_t mask) {
+void tim_clock_enable(uint16_t mask) {
#ifdef TIM1
if (mask & (1 << 0)) {
__HAL_RCC_TIM1_CLK_ENABLE();
@@ -144,7 +246,7 @@ STATIC void tim_clock_enable(uint16_t mask) {
#endif
}
-STATIC void tim_clock_disable(uint16_t mask) {
+void tim_clock_disable(uint16_t mask) {
#ifdef TIM1
if (mask & (1 << 0)) {
__HAL_RCC_TIM1_CLK_DISABLE();
@@ -209,8 +311,8 @@ STATIC void tim_clock_disable(uint16_t mask) {
}
STATIC void callback_router(size_t index) {
- if (stm_timer_callback[index]) {
- (*stm_timer_callback[index])();
+ if (stm_timer_callback[index - 1]) {
+ (*stm_timer_callback[index - 1])();
}
}
diff --git a/ports/stm/peripherals/timers.h b/ports/stm/peripherals/timers.h
index b0f594b77..8c8a80d53 100644
--- a/ports/stm/peripherals/timers.h
+++ b/ports/stm/peripherals/timers.h
@@ -24,17 +24,30 @@
* THE SOFTWARE.
*/
-typedef struct {
- TIM_TypeDef * p_reg;
- uint8_t instance_id;
- uint8_t cc_channel_count;
-} nrfx_timer_t;
+// typedef struct {
+// TIM_TypeDef * timer;
+// bool reserved;
+// bool never_reset;
+// void (*stm_timer_callback)(void);
+// size_t irq;
+// } stm_timer_t;
+#include <stdint.h>
+#include "py/mphal.h"
+#include "peripherals/periph.h"
+
+#include STM32_HAL_H
+
+void tim_clock_enable(uint16_t mask);
+void tim_clock_disable(uint16_t mask);
+uint32_t stm_peripherals_timer_get_source_freq(TIM_TypeDef * timer);
void timers_reset(void);
TIM_TypeDef * stm_peripherals_find_timer(void);
+void stm_peripherals_timer_preinit(TIM_TypeDef * instance, uint8_t prio, void (*callback)(void));
+void stm_peripherals_timer_reserve(TIM_TypeDef * instance);
void stm_peripherals_timer_free(TIM_TypeDef * instance);
void stm_peripherals_timer_never_reset(TIM_TypeDef * instance);
void stm_peripherals_timer_reset_ok(TIM_TypeDef * instance);
-void stm_peripherals_timer_is_never_reset(TIM_TypeDef * instance);
-void stm_peripherals_timer_is_reserved(TIM_TypeDef * instance);
+bool stm_peripherals_timer_is_never_reset(TIM_TypeDef * instance);
+bool stm_peripherals_timer_is_reserved(TIM_TypeDef * instance);
size_t stm_peripherals_timer_get_index(TIM_TypeDef * instance);
diff --git a/ports/stm/supervisor/port.c b/ports/stm/supervisor/port.c
index 07a93c025..7c9fcf750 100644
--- a/ports/stm/supervisor/port.c
+++ b/ports/stm/supervisor/port.c
@@ -41,6 +41,7 @@
#include "common-hal/pulseio/PWMOut.h"
#include "common-hal/pulseio/PulseOut.h"
#include "common-hal/pulseio/PulseIn.h"
+#include "timers.h"
#endif
#include "clocks.h"
@@ -224,6 +225,7 @@ void reset_port(void) {
uart_reset();
#endif
#if CIRCUITPY_PULSEIO
+ timers_reset();
pwmout_reset();
pulseout_reset();
pulsein_reset();