Skip to content

Commit ab9a64e

Browse files
committed
Add timer allocator, adjust pulsio to use general purpose timers
1 parent 6c91af7 commit ab9a64e

File tree

8 files changed

+252
-303
lines changed

8 files changed

+252
-303
lines changed

ports/stm/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@ SRC_C += \
207207
mphalport.c \
208208
boards/$(BOARD)/board.c \
209209
boards/$(BOARD)/pins.c \
210+
peripherals/timers.c \
210211
peripherals/stm32$(MCU_SERIES_LOWER)/clocks.c \
211212
peripherals/stm32$(MCU_SERIES_LOWER)/$(MCU_VARIANT_LOWER)/pins.c \
212213
peripherals/stm32$(MCU_SERIES_LOWER)/$(MCU_VARIANT_LOWER)/gpio.c \

ports/stm/common-hal/pulseio/PWMOut.c

Lines changed: 16 additions & 160 deletions
Original file line numberDiff line numberDiff line change
@@ -35,38 +35,14 @@
3535
#include STM32_HAL_H
3636
#include "common-hal/microcontroller/Pin.h"
3737

38+
#include "timers.h"
39+
3840
#define ALL_CLOCKS 0xFFFF
3941

4042
STATIC uint8_t reserved_tim[TIM_BANK_ARRAY_LEN];
4143
STATIC uint32_t tim_frequencies[TIM_BANK_ARRAY_LEN];
4244
STATIC bool never_reset_tim[TIM_BANK_ARRAY_LEN];
4345

44-
STATIC void tim_clock_enable(uint16_t mask);
45-
STATIC void tim_clock_disable(uint16_t mask);
46-
47-
// Get the frequency (in Hz) of the source clock for the given timer.
48-
// On STM32F405/407/415/417 there are 2 cases for how the clock freq is set.
49-
// If the APB prescaler is 1, then the timer clock is equal to its respective
50-
// APB clock. Otherwise (APB prescaler > 1) the timer clock is twice its
51-
// respective APB clock. See DM00031020 Rev 4, page 115.
52-
STATIC uint32_t timer_get_source_freq(uint32_t tim_id) {
53-
uint32_t source, clk_div;
54-
if (tim_id == 1 || (8 <= tim_id && tim_id <= 11)) {
55-
// TIM{1,8,9,10,11} are on APB2
56-
source = HAL_RCC_GetPCLK2Freq();
57-
clk_div = RCC->CFGR & RCC_CFGR_PPRE2;
58-
} else {
59-
// TIM{2,3,4,5,6,7,12,13,14} are on APB1
60-
source = HAL_RCC_GetPCLK1Freq();
61-
clk_div = RCC->CFGR & RCC_CFGR_PPRE1;
62-
}
63-
if (clk_div != 0) {
64-
// APB prescaler for this timer is > 1
65-
source *= 2;
66-
}
67-
return source;
68-
}
69-
7046
STATIC uint32_t timer_get_internal_duty(uint16_t duty, uint32_t period) {
7147
//duty cycle is duty/0xFFFF fraction x (number of pulses per period)
7248
return (duty*period) / ((1 << 16) - 1);
@@ -97,7 +73,6 @@ void pwmout_reset(void) {
9773
never_reset_mask |= 1 << i;
9874
}
9975
}
100-
tim_clock_disable(ALL_CLOCKS & ~(never_reset_mask));
10176
}
10277

10378
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,
10782
bool variable_frequency) {
10883
TIM_TypeDef * TIMx;
10984
uint8_t tim_num = MP_ARRAY_SIZE(mcu_tim_pin_list);
85+
bool tim_taken_internal = false;
11086
bool tim_chan_taken = false;
11187
bool tim_taken_f_mismatch = false;
11288
bool var_freq_mismatch = false;
@@ -119,8 +95,13 @@ pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self,
11995

12096
//if pin is same
12197
if (l_tim->pin == pin) {
122-
//check if the timer has a channel active
98+
//check if the timer has a channel active, or is reserved by main timer system
12399
if (reserved_tim[l_tim_index] != 0) {
100+
// Timer has already been reserved by an internal module
101+
if (stm_peripherals_timer_is_reserved(mcu_tim_banks[l_tim_index])) {
102+
tim_taken_internal = true;
103+
continue; //keep looking
104+
}
124105
//is it the same channel? (or all channels reserved by a var-freq)
125106
if (reserved_tim[l_tim_index] & 1 << (l_tim_channel)) {
126107
tim_chan_taken = true;
@@ -155,9 +136,12 @@ pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self,
155136
reserved_tim[self->tim->tim_index - 1] |= 1 << (self->tim->channel_index - 1);
156137
}
157138
tim_frequencies[self->tim->tim_index - 1] = frequency;
139+
stm_peripherals_timer_reserve(TIMx);
158140
} else { //no match found
159141
if (tim_chan_taken) {
160142
mp_raise_ValueError(translate("No more timers available on this pin."));
143+
} else if (tim_taken_internal) {
144+
mp_raise_ValueError(translate("Timer was reserved for internal use - declare PWM pins earlier in the program"));
161145
} else if (tim_taken_f_mismatch) {
162146
mp_raise_ValueError(translate("Frequency must match existing PWMOut using this timer"));
163147
} else if (var_freq_mismatch) {
@@ -182,8 +166,8 @@ pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self,
182166

183167
uint32_t prescaler = 0; //prescaler is 15 bit
184168
uint32_t period = 0; //period is 16 bit
185-
timer_get_optimal_divisors(&period, &prescaler, frequency,
186-
timer_get_source_freq(self->tim->tim_index));
169+
uint32_t source_freq = stm_peripherals_timer_get_source_freq(TIMx);
170+
timer_get_optimal_divisors(&period, &prescaler, frequency, source_freq);
187171

188172
//Timer init
189173
self->handle.Instance = TIMx;
@@ -282,8 +266,8 @@ void common_hal_pulseio_pwmout_set_frequency(pulseio_pwmout_obj_t* self, uint32_
282266

283267
uint32_t prescaler = 0;
284268
uint32_t period = 0;
285-
timer_get_optimal_divisors(&period, &prescaler, frequency,
286-
timer_get_source_freq(self->tim->tim_index));
269+
uint32_t source_freq = stm_peripherals_timer_get_source_freq(self->handle.Instance);
270+
timer_get_optimal_divisors(&period, &prescaler, frequency, source_freq);
287271

288272
//shut down
289273
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) {
318302
bool common_hal_pulseio_pwmout_get_variable_frequency(pulseio_pwmout_obj_t* self) {
319303
return self->variable_frequency;
320304
}
321-
322-
STATIC void tim_clock_enable(uint16_t mask) {
323-
#ifdef TIM1
324-
if (mask & (1 << 0)) {
325-
__HAL_RCC_TIM1_CLK_ENABLE();
326-
}
327-
#endif
328-
#ifdef TIM2
329-
if (mask & (1 << 1)) {
330-
__HAL_RCC_TIM2_CLK_ENABLE();
331-
}
332-
#endif
333-
#ifdef TIM3
334-
if (mask & (1 << 2)) {
335-
__HAL_RCC_TIM3_CLK_ENABLE();
336-
}
337-
#endif
338-
#ifdef TIM4
339-
if (mask & (1 << 3)) {
340-
__HAL_RCC_TIM4_CLK_ENABLE();
341-
}
342-
#endif
343-
#ifdef TIM5
344-
if (mask & (1 << 4)) {
345-
__HAL_RCC_TIM5_CLK_ENABLE();
346-
}
347-
#endif
348-
//6 and 7 are reserved ADC timers
349-
#ifdef TIM8
350-
if (mask & (1 << 7)) {
351-
__HAL_RCC_TIM8_CLK_ENABLE();
352-
}
353-
#endif
354-
#ifdef TIM9
355-
if (mask & (1 << 8)) {
356-
__HAL_RCC_TIM9_CLK_ENABLE();
357-
}
358-
#endif
359-
#ifdef TIM10
360-
if (mask & (1 << 9)) {
361-
__HAL_RCC_TIM10_CLK_ENABLE();
362-
}
363-
#endif
364-
#ifdef TIM11
365-
if (mask & (1 << 10)) {
366-
__HAL_RCC_TIM11_CLK_ENABLE();
367-
}
368-
#endif
369-
#ifdef TIM12
370-
if (mask & (1 << 11)) {
371-
__HAL_RCC_TIM12_CLK_ENABLE();
372-
}
373-
#endif
374-
#ifdef TIM13
375-
if (mask & (1 << 12)) {
376-
__HAL_RCC_TIM13_CLK_ENABLE();
377-
}
378-
#endif
379-
#ifdef TIM14
380-
if (mask & (1 << 13)) {
381-
__HAL_RCC_TIM14_CLK_ENABLE();
382-
}
383-
#endif
384-
}
385-
386-
STATIC void tim_clock_disable(uint16_t mask) {
387-
#ifdef TIM1
388-
if (mask & (1 << 0)) {
389-
__HAL_RCC_TIM1_CLK_DISABLE();
390-
}
391-
#endif
392-
#ifdef TIM2
393-
if (mask & (1 << 1)) {
394-
__HAL_RCC_TIM2_CLK_DISABLE();
395-
}
396-
#endif
397-
#ifdef TIM3
398-
if (mask & (1 << 2)) {
399-
__HAL_RCC_TIM3_CLK_DISABLE();
400-
}
401-
#endif
402-
#ifdef TIM4
403-
if (mask & (1 << 3)) {
404-
__HAL_RCC_TIM4_CLK_DISABLE();
405-
}
406-
#endif
407-
#ifdef TIM5
408-
if (mask & (1 << 4)) {
409-
__HAL_RCC_TIM5_CLK_DISABLE();
410-
}
411-
#endif
412-
//6 and 7 are reserved ADC timers
413-
#ifdef TIM8
414-
if (mask & (1 << 7)) {
415-
__HAL_RCC_TIM8_CLK_DISABLE();
416-
}
417-
#endif
418-
#ifdef TIM9
419-
if (mask & (1 << 8)) {
420-
__HAL_RCC_TIM9_CLK_DISABLE();
421-
}
422-
#endif
423-
#ifdef TIM10
424-
if (mask & (1 << 9)) {
425-
__HAL_RCC_TIM10_CLK_DISABLE();
426-
}
427-
#endif
428-
#ifdef TIM11
429-
if (mask & (1 << 10)) {
430-
__HAL_RCC_TIM11_CLK_DISABLE();
431-
}
432-
#endif
433-
#ifdef TIM12
434-
if (mask & (1 << 11)) {
435-
__HAL_RCC_TIM12_CLK_DISABLE();
436-
}
437-
#endif
438-
#ifdef TIM13
439-
if (mask & (1 << 12)) {
440-
__HAL_RCC_TIM13_CLK_DISABLE();
441-
}
442-
#endif
443-
#ifdef TIM14
444-
if (mask & (1 << 13)) {
445-
__HAL_RCC_TIM14_CLK_DISABLE();
446-
}
447-
#endif
448-
}

0 commit comments

Comments
 (0)