Add timer allocator, adjust pulsio to use general purpose timers
This commit is contained in:
parent
6c91af7d56
commit
ab9a64eafa
@ -207,6 +207,7 @@ SRC_C += \
|
|||||||
mphalport.c \
|
mphalport.c \
|
||||||
boards/$(BOARD)/board.c \
|
boards/$(BOARD)/board.c \
|
||||||
boards/$(BOARD)/pins.c \
|
boards/$(BOARD)/pins.c \
|
||||||
|
peripherals/timers.c \
|
||||||
peripherals/stm32$(MCU_SERIES_LOWER)/clocks.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)/pins.c \
|
||||||
peripherals/stm32$(MCU_SERIES_LOWER)/$(MCU_VARIANT_LOWER)/gpio.c \
|
peripherals/stm32$(MCU_SERIES_LOWER)/$(MCU_VARIANT_LOWER)/gpio.c \
|
||||||
|
@ -35,38 +35,14 @@
|
|||||||
#include STM32_HAL_H
|
#include STM32_HAL_H
|
||||||
#include "common-hal/microcontroller/Pin.h"
|
#include "common-hal/microcontroller/Pin.h"
|
||||||
|
|
||||||
|
#include "timers.h"
|
||||||
|
|
||||||
#define ALL_CLOCKS 0xFFFF
|
#define ALL_CLOCKS 0xFFFF
|
||||||
|
|
||||||
STATIC uint8_t reserved_tim[TIM_BANK_ARRAY_LEN];
|
STATIC uint8_t reserved_tim[TIM_BANK_ARRAY_LEN];
|
||||||
STATIC uint32_t tim_frequencies[TIM_BANK_ARRAY_LEN];
|
STATIC uint32_t tim_frequencies[TIM_BANK_ARRAY_LEN];
|
||||||
STATIC bool never_reset_tim[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) {
|
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)
|
//duty cycle is duty/0xFFFF fraction x (number of pulses per period)
|
||||||
return (duty*period) / ((1 << 16) - 1);
|
return (duty*period) / ((1 << 16) - 1);
|
||||||
@ -97,7 +73,6 @@ void pwmout_reset(void) {
|
|||||||
never_reset_mask |= 1 << i;
|
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,
|
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) {
|
bool variable_frequency) {
|
||||||
TIM_TypeDef * TIMx;
|
TIM_TypeDef * TIMx;
|
||||||
uint8_t tim_num = MP_ARRAY_SIZE(mcu_tim_pin_list);
|
uint8_t tim_num = MP_ARRAY_SIZE(mcu_tim_pin_list);
|
||||||
|
bool tim_taken_internal = false;
|
||||||
bool tim_chan_taken = false;
|
bool tim_chan_taken = false;
|
||||||
bool tim_taken_f_mismatch = false;
|
bool tim_taken_f_mismatch = false;
|
||||||
bool var_freq_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 pin is same
|
||||||
if (l_tim->pin == pin) {
|
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) {
|
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)
|
//is it the same channel? (or all channels reserved by a var-freq)
|
||||||
if (reserved_tim[l_tim_index] & 1 << (l_tim_channel)) {
|
if (reserved_tim[l_tim_index] & 1 << (l_tim_channel)) {
|
||||||
tim_chan_taken = true;
|
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);
|
reserved_tim[self->tim->tim_index - 1] |= 1 << (self->tim->channel_index - 1);
|
||||||
}
|
}
|
||||||
tim_frequencies[self->tim->tim_index - 1] = frequency;
|
tim_frequencies[self->tim->tim_index - 1] = frequency;
|
||||||
|
stm_peripherals_timer_reserve(TIMx);
|
||||||
} else { //no match found
|
} else { //no match found
|
||||||
if (tim_chan_taken) {
|
if (tim_chan_taken) {
|
||||||
mp_raise_ValueError(translate("No more timers available on this pin."));
|
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) {
|
} else if (tim_taken_f_mismatch) {
|
||||||
mp_raise_ValueError(translate("Frequency must match existing PWMOut using this timer"));
|
mp_raise_ValueError(translate("Frequency must match existing PWMOut using this timer"));
|
||||||
} else if (var_freq_mismatch) {
|
} 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 prescaler = 0; //prescaler is 15 bit
|
||||||
uint32_t period = 0; //period is 16 bit
|
uint32_t period = 0; //period is 16 bit
|
||||||
timer_get_optimal_divisors(&period, &prescaler, frequency,
|
uint32_t source_freq = stm_peripherals_timer_get_source_freq(TIMx);
|
||||||
timer_get_source_freq(self->tim->tim_index));
|
timer_get_optimal_divisors(&period, &prescaler, frequency, source_freq);
|
||||||
|
|
||||||
//Timer init
|
//Timer init
|
||||||
self->handle.Instance = TIMx;
|
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 prescaler = 0;
|
||||||
uint32_t period = 0;
|
uint32_t period = 0;
|
||||||
timer_get_optimal_divisors(&period, &prescaler, frequency,
|
uint32_t source_freq = stm_peripherals_timer_get_source_freq(self->handle.Instance);
|
||||||
timer_get_source_freq(self->tim->tim_index));
|
timer_get_optimal_divisors(&period, &prescaler, frequency, source_freq);
|
||||||
|
|
||||||
//shut down
|
//shut down
|
||||||
HAL_TIM_PWM_Stop(&self->handle, self->channel);
|
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) {
|
bool common_hal_pulseio_pwmout_get_variable_frequency(pulseio_pwmout_obj_t* self) {
|
||||||
return self->variable_frequency;
|
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
|
|
||||||
}
|
|
||||||
|
@ -32,39 +32,36 @@
|
|||||||
#include "py/runtime.h"
|
#include "py/runtime.h"
|
||||||
#include "shared-bindings/microcontroller/__init__.h"
|
#include "shared-bindings/microcontroller/__init__.h"
|
||||||
#include "shared-bindings/pulseio/PulseIn.h"
|
#include "shared-bindings/pulseio/PulseIn.h"
|
||||||
|
#include "timers.h"
|
||||||
|
|
||||||
#include STM32_HAL_H
|
#include STM32_HAL_H
|
||||||
|
|
||||||
#define STM32_GPIO_PORT_SIZE 16
|
#define STM32_GPIO_PORT_SIZE 16
|
||||||
|
|
||||||
static pulseio_pulsein_obj_t* _objs[STM32_GPIO_PORT_SIZE];
|
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 uint32_t overflow_count = 0;
|
||||||
STATIC uint8_t refcount = 0;
|
STATIC uint8_t refcount = 0;
|
||||||
|
|
||||||
static void assign_EXTI_Interrupt(pulseio_pulsein_obj_t* self, uint8_t num);
|
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
|
// 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++;
|
overflow_count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pulsein_handler(uint8_t num) {
|
static void pulsein_exti_event_handler(uint8_t num) {
|
||||||
// Grab the current time first.
|
// Grab the current time first.
|
||||||
uint32_t current_overflow = overflow_count;
|
uint32_t current_overflow = overflow_count;
|
||||||
uint32_t current_count = 0;
|
uint32_t current_count = tim_handle.Instance->CNT;
|
||||||
#if HAS_BASIC_TIM
|
|
||||||
current_count = TIM6->CNT;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Interrupt register must be cleared manually
|
// Interrupt register must be cleared manually
|
||||||
EXTI->PR = 1 << num;
|
EXTI->PR = 1 << num;
|
||||||
@ -105,17 +102,12 @@ void pulsein_reset(void) {
|
|||||||
}
|
}
|
||||||
memset(_objs, 0, sizeof(_objs));
|
memset(_objs, 0, sizeof(_objs));
|
||||||
|
|
||||||
#if HAS_BASIC_TIM
|
tim_clock_disable(stm_peripherals_timer_get_index(tim_handle.Instance));
|
||||||
__HAL_RCC_TIM6_CLK_DISABLE();
|
|
||||||
refcount = 0;
|
refcount = 0;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t* self, const mcu_pin_obj_t* pin,
|
void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t* self, const mcu_pin_obj_t* pin,
|
||||||
uint16_t maxlen, bool idle_state) {
|
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
|
// STM32 has one shared EXTI for each pin number, 0-15
|
||||||
uint8_t p_num = pin->number;
|
uint8_t p_num = pin->number;
|
||||||
if(_objs[p_num]) {
|
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_count = 0;
|
||||||
self->last_overflow = 0;
|
self->last_overflow = 0;
|
||||||
|
|
||||||
if (HAL_TIM_Base_GetState(&t6_handle) == HAL_TIM_STATE_RESET) {
|
if (HAL_TIM_Base_GetState(&tim_handle) == HAL_TIM_STATE_RESET) {
|
||||||
// Set the new period
|
// Find a suitable timer
|
||||||
t6_handle.Instance = TIM6;
|
TIM_TypeDef * tim_instance = stm_peripherals_find_timer();
|
||||||
t6_handle.Init.Prescaler = 168; // HCLK is 168 mhz so divide down to 1mhz
|
stm_peripherals_timer_reserve(tim_instance);
|
||||||
t6_handle.Init.Period = 0xffff;
|
|
||||||
HAL_TIM_Base_Init(&t6_handle);
|
|
||||||
|
|
||||||
// TIM6 has limited HAL support, set registers manually
|
// Calculate a 1ms period
|
||||||
t6_handle.Instance->SR = 0; // Prevent the SR from triggering an interrupt
|
uint32_t source = stm_peripherals_timer_get_source_freq(tim_instance);
|
||||||
t6_handle.Instance->CR1 |= TIM_CR1_CEN; // Resume timer
|
uint32_t prescaler = source/1000000; // 1us intervals
|
||||||
t6_handle.Instance->CR1 |= TIM_CR1_URS; // Disable non-overflow interrupts
|
|
||||||
__HAL_TIM_ENABLE_IT(&t6_handle, TIM_IT_UPDATE);
|
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);
|
||||||
|
|
||||||
|
// 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;
|
overflow_count = 0;
|
||||||
}
|
}
|
||||||
// Add to active PulseIns
|
// Add to active PulseIns
|
||||||
refcount++;
|
refcount++;
|
||||||
#endif
|
|
||||||
|
|
||||||
// EXTI pins can also be read as an input
|
// EXTI pins can also be read as an input
|
||||||
GPIO_InitTypeDef GPIO_InitStruct = {0};
|
GPIO_InitTypeDef GPIO_InitStruct = {0};
|
||||||
@ -189,9 +190,7 @@ void common_hal_pulseio_pulsein_deinit(pulseio_pulsein_obj_t* self) {
|
|||||||
|
|
||||||
refcount--;
|
refcount--;
|
||||||
if (refcount == 0) {
|
if (refcount == 0) {
|
||||||
#if HAS_BASIC_TIM
|
tim_clock_disable(1<< stm_peripherals_timer_get_index(tim_handle.Instance));
|
||||||
__HAL_RCC_TIM6_CLK_DISABLE();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -299,23 +298,23 @@ static void assign_EXTI_Interrupt(pulseio_pulsein_obj_t* self, uint8_t num) {
|
|||||||
|
|
||||||
void EXTI0_IRQHandler(void)
|
void EXTI0_IRQHandler(void)
|
||||||
{
|
{
|
||||||
pulsein_handler(0);
|
pulsein_exti_event_handler(0);
|
||||||
}
|
}
|
||||||
void EXTI1_IRQHandler(void)
|
void EXTI1_IRQHandler(void)
|
||||||
{
|
{
|
||||||
pulsein_handler(1);
|
pulsein_exti_event_handler(1);
|
||||||
}
|
}
|
||||||
void EXTI2_IRQHandler(void)
|
void EXTI2_IRQHandler(void)
|
||||||
{
|
{
|
||||||
pulsein_handler(2);
|
pulsein_exti_event_handler(2);
|
||||||
}
|
}
|
||||||
void EXTI3_IRQHandler(void)
|
void EXTI3_IRQHandler(void)
|
||||||
{
|
{
|
||||||
pulsein_handler(3);
|
pulsein_exti_event_handler(3);
|
||||||
}
|
}
|
||||||
void EXTI4_IRQHandler(void)
|
void EXTI4_IRQHandler(void)
|
||||||
{
|
{
|
||||||
pulsein_handler(4);
|
pulsein_exti_event_handler(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EXTI9_5_IRQHandler(void)
|
void EXTI9_5_IRQHandler(void)
|
||||||
@ -323,7 +322,7 @@ void EXTI9_5_IRQHandler(void)
|
|||||||
uint32_t pending = EXTI->PR;
|
uint32_t pending = EXTI->PR;
|
||||||
for (uint i = 5; i <= 9; i++) {
|
for (uint i = 5; i <= 9; i++) {
|
||||||
if(pending & (1 << 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;
|
uint32_t pending = EXTI->PR;
|
||||||
for (uint i = 10; i <= 15; i++) {
|
for (uint i = 10; i <= 15; i++) {
|
||||||
if(pending & (1 << i)) {
|
if(pending & (1 << i)) {
|
||||||
pulsein_handler(i);
|
pulsein_exti_event_handler(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,19 +37,19 @@
|
|||||||
|
|
||||||
#include STM32_HAL_H
|
#include STM32_HAL_H
|
||||||
#include "common-hal/microcontroller/Pin.h"
|
#include "common-hal/microcontroller/Pin.h"
|
||||||
|
#include "timers.h"
|
||||||
|
|
||||||
// A single timer is shared amongst all PulseOut objects under the assumption that
|
// A single timer is shared amongst all PulseOut objects under the assumption that
|
||||||
// the code is single threaded.
|
// the code is single threaded.
|
||||||
STATIC uint8_t refcount = 0;
|
STATIC uint8_t refcount = 0;
|
||||||
|
|
||||||
STATIC uint16_t *pulse_array = NULL;
|
STATIC uint16_t *pulse_array = NULL;
|
||||||
STATIC volatile uint16_t pulse_array_index = 0;
|
STATIC volatile uint16_t pulse_array_index = 0;
|
||||||
STATIC uint16_t pulse_array_length;
|
STATIC uint16_t pulse_array_length;
|
||||||
|
|
||||||
//Timer is shared, must be accessible by interrupt
|
//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;
|
pulseio_pulseout_obj_t *curr_pulseout = NULL;
|
||||||
|
|
||||||
|
|
||||||
STATIC void turn_on(pulseio_pulseout_obj_t *pulseout) {
|
STATIC void turn_on(pulseio_pulseout_obj_t *pulseout) {
|
||||||
// Turn on PWM
|
// Turn on PWM
|
||||||
HAL_TIM_PWM_Start(&(pulseout->pwmout->handle), pulseout->pwmout->channel);
|
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) {
|
STATIC void start_timer(void) {
|
||||||
// Set the new period
|
// Set the new period
|
||||||
t7_handle.Init.Period = pulse_array[pulse_array_index] - 1;
|
tim_handle.Init.Period = pulse_array[pulse_array_index] - 1;
|
||||||
HAL_TIM_Base_Init(&t7_handle);
|
HAL_TIM_Base_Init(&tim_handle);
|
||||||
|
|
||||||
// TIM7 has limited HAL support, set registers manually
|
// TIM7 has limited HAL support, set registers manually
|
||||||
t7_handle.Instance->SR = 0; // Prevent the SR from triggering an interrupt
|
tim_handle.Instance->SR = 0; // Prevent the SR from triggering an interrupt
|
||||||
t7_handle.Instance->CR1 |= TIM_CR1_CEN; // Resume timer
|
tim_handle.Instance->CR1 |= TIM_CR1_CEN; // Resume timer
|
||||||
t7_handle.Instance->CR1 |= TIM_CR1_URS; // Disable non-overflow interrupts
|
tim_handle.Instance->CR1 |= TIM_CR1_URS; // Disable non-overflow interrupts
|
||||||
__HAL_TIM_ENABLE_IT(&t7_handle, TIM_IT_UPDATE);
|
__HAL_TIM_ENABLE_IT(&tim_handle, TIM_IT_UPDATE);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC void pulseout_event_handler(void) {
|
STATIC void pulseout_event_handler(void) {
|
||||||
if (curr_pulseout->pwmout == NULL) {
|
// Detect TIM Update event
|
||||||
return; //invalid interrupt
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void pulseout_reset() {
|
void pulseout_reset() {
|
||||||
#if HAS_BASIC_TIM
|
stm_peripherals_timer_free(tim_handle.Instance);
|
||||||
__HAL_RCC_TIM7_CLK_DISABLE();
|
|
||||||
refcount = 0;
|
refcount = 0;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t* self,
|
void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t* self,
|
||||||
const pulseio_pwmout_obj_t* carrier) {
|
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
|
// Add to active PulseOuts
|
||||||
refcount++;
|
refcount++;
|
||||||
|
TIM_TypeDef * tim_instance = stm_peripherals_find_timer();
|
||||||
|
stm_peripherals_timer_reserve(tim_instance);
|
||||||
|
|
||||||
// Calculate a 1 ms period
|
//calculate a 1ms period
|
||||||
uint32_t source, clk_div;
|
uint32_t source = stm_peripherals_timer_get_source_freq(tim_instance);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t prescaler = source/1000000; //1us intervals
|
uint32_t prescaler = source/1000000; //1us intervals
|
||||||
|
|
||||||
__HAL_RCC_TIM7_CLK_ENABLE();
|
stm_peripherals_timer_preinit(tim_instance, 4, pulseout_event_handler);
|
||||||
HAL_NVIC_SetPriority(TIM7_IRQn, 4, 0);
|
tim_handle.Instance = tim_instance;
|
||||||
HAL_NVIC_EnableIRQ(TIM7_IRQn);
|
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
|
HAL_TIM_Base_Init(&tim_handle);
|
||||||
t7_handle.Instance = TIM7;
|
tim_handle.Instance->SR = 0;
|
||||||
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;
|
|
||||||
|
|
||||||
// The HAL can't work with const, recast required.
|
// The HAL can't work with const, recast required.
|
||||||
self->pwmout = (pulseio_pwmout_obj_t*)carrier;
|
self->pwmout = (pulseio_pwmout_obj_t*)carrier;
|
||||||
|
|
||||||
turn_off(self);
|
turn_off(self);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool common_hal_pulseio_pulseout_deinited(pulseio_pulseout_obj_t* self) {
|
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--;
|
refcount--;
|
||||||
if (refcount == 0) {
|
if (refcount == 0) {
|
||||||
#if HAS_BASIC_TIM
|
tim_clock_disable(1<< stm_peripherals_timer_get_index(tim_handle.Instance));
|
||||||
__HAL_RCC_TIM7_CLK_DISABLE();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -187,24 +176,11 @@ void common_hal_pulseio_pulseout_send(pulseio_pulseout_obj_t* self, uint16_t* pu
|
|||||||
// signal.
|
// signal.
|
||||||
RUN_BACKGROUND_TASKS;
|
RUN_BACKGROUND_TASKS;
|
||||||
|
|
||||||
// Use when debugging, or issues are irrecoverable
|
// // Use when debugging, or issues are irrecoverable
|
||||||
// if ((supervisor_ticks_ms64() - starttime ) > timeout ) {
|
// if ((supervisor_ticks_ms64() - starttime ) > timeout ) {
|
||||||
// mp_raise_RuntimeError(translate("Error: Send Timeout"));
|
// mp_raise_RuntimeError(translate("Error: Send Timeout"));
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
//turn off timer counter.
|
//turn off timer counter.
|
||||||
t7_handle.Instance->CR1 &= ~TIM_CR1_CEN;
|
tim_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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,8 @@ INTERNAL_LIBM ?= 1
|
|||||||
USB_SERIAL_NUMBER_LENGTH ?= 24
|
USB_SERIAL_NUMBER_LENGTH ?= 24
|
||||||
|
|
||||||
ifeq ($(MCU_VARIANT),STM32F405xx)
|
ifeq ($(MCU_VARIANT),STM32F405xx)
|
||||||
CIRCUITPY_FRAMEBUFFERIO ?= 1
|
CIRCUITPY_FRAMEBUFFERIO ?= 0
|
||||||
CIRCUITPY_RGBMATRIX ?= 1
|
CIRCUITPY_RGBMATRIX ?= 0
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(MCU_SERIES),F4)
|
ifeq ($(MCU_SERIES),F4)
|
||||||
|
@ -23,20 +23,51 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* 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_reserved[MP_ARRAY_SIZE(mcu_tim_banks)];
|
||||||
static bool stm_timer_never_reset[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 (*stm_timer_callback[MP_ARRAY_SIZE(mcu_tim_banks)])(void);
|
||||||
|
static size_t irq_map[] = {
|
||||||
STATIC void tim_clock_enable(uint16_t mask);
|
TIM1_CC_IRQn,
|
||||||
STATIC void tim_clock_disable(uint16_t mask);
|
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.
|
// 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.
|
// 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
|
// 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
|
// APB clock. Otherwise (APB prescaler > 1) the timer clock is twice its
|
||||||
// respective APB clock. See DM00031020 Rev 4, page 115.
|
// 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;
|
uint32_t source, clk_div;
|
||||||
if (tim_id == 1 || (8 <= tim_id && tim_id <= 11)) {
|
if (tim_id == 1 || (8 <= tim_id && tim_id <= 11)) {
|
||||||
// TIM{1,8,9,10,11} are on APB2
|
// 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;
|
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) {
|
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
|
// 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)) {
|
if ((!stm_timer_reserved[i]) && (mcu_tim_banks[i] != NULL)) {
|
||||||
return mcu_tim_banks[i];
|
return mcu_tim_banks[i];
|
||||||
}
|
}
|
||||||
@ -67,20 +131,58 @@ TIM_TypeDef * stm_peripherals_find_timer(void) {
|
|||||||
return NULL;
|
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) {
|
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) {
|
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);
|
|
||||||
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 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 tim_clock_enable(uint16_t mask) {
|
||||||
#ifdef TIM1
|
#ifdef TIM1
|
||||||
if (mask & (1 << 0)) {
|
if (mask & (1 << 0)) {
|
||||||
__HAL_RCC_TIM1_CLK_ENABLE();
|
__HAL_RCC_TIM1_CLK_ENABLE();
|
||||||
@ -144,7 +246,7 @@ STATIC void tim_clock_enable(uint16_t mask) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC void tim_clock_disable(uint16_t mask) {
|
void tim_clock_disable(uint16_t mask) {
|
||||||
#ifdef TIM1
|
#ifdef TIM1
|
||||||
if (mask & (1 << 0)) {
|
if (mask & (1 << 0)) {
|
||||||
__HAL_RCC_TIM1_CLK_DISABLE();
|
__HAL_RCC_TIM1_CLK_DISABLE();
|
||||||
@ -209,8 +311,8 @@ STATIC void tim_clock_disable(uint16_t mask) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
STATIC void callback_router(size_t index) {
|
STATIC void callback_router(size_t index) {
|
||||||
if (stm_timer_callback[index]) {
|
if (stm_timer_callback[index - 1]) {
|
||||||
(*stm_timer_callback[index])();
|
(*stm_timer_callback[index - 1])();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,17 +24,30 @@
|
|||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef struct {
|
// typedef struct {
|
||||||
TIM_TypeDef * p_reg;
|
// TIM_TypeDef * timer;
|
||||||
uint8_t instance_id;
|
// bool reserved;
|
||||||
uint8_t cc_channel_count;
|
// bool never_reset;
|
||||||
} nrfx_timer_t;
|
// 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);
|
void timers_reset(void);
|
||||||
TIM_TypeDef * stm_peripherals_find_timer(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_free(TIM_TypeDef * instance);
|
||||||
void stm_peripherals_timer_never_reset(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_reset_ok(TIM_TypeDef * instance);
|
||||||
void stm_peripherals_timer_is_never_reset(TIM_TypeDef * instance);
|
bool stm_peripherals_timer_is_never_reset(TIM_TypeDef * instance);
|
||||||
void stm_peripherals_timer_is_reserved(TIM_TypeDef * instance);
|
bool stm_peripherals_timer_is_reserved(TIM_TypeDef * instance);
|
||||||
size_t stm_peripherals_timer_get_index(TIM_TypeDef * instance);
|
size_t stm_peripherals_timer_get_index(TIM_TypeDef * instance);
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
#include "common-hal/pulseio/PWMOut.h"
|
#include "common-hal/pulseio/PWMOut.h"
|
||||||
#include "common-hal/pulseio/PulseOut.h"
|
#include "common-hal/pulseio/PulseOut.h"
|
||||||
#include "common-hal/pulseio/PulseIn.h"
|
#include "common-hal/pulseio/PulseIn.h"
|
||||||
|
#include "timers.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "clocks.h"
|
#include "clocks.h"
|
||||||
@ -224,6 +225,7 @@ void reset_port(void) {
|
|||||||
uart_reset();
|
uart_reset();
|
||||||
#endif
|
#endif
|
||||||
#if CIRCUITPY_PULSEIO
|
#if CIRCUITPY_PULSEIO
|
||||||
|
timers_reset();
|
||||||
pwmout_reset();
|
pwmout_reset();
|
||||||
pulseout_reset();
|
pulseout_reset();
|
||||||
pulsein_reset();
|
pulsein_reset();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user