36
36
37
37
#include "timers.h"
38
38
39
- #define ALL_CLOCKS 0xFFFF
40
-
41
- STATIC uint8_t reserved_tim [ TIM_BANK_ARRAY_LEN ];
39
+ // Bitmask of channels taken.
40
+ STATIC uint8_t tim_channels_taken [ TIM_BANK_ARRAY_LEN ];
41
+ // Initial frequency timer is set to.
42
42
STATIC uint32_t tim_frequencies [TIM_BANK_ARRAY_LEN ];
43
43
STATIC bool never_reset_tim [TIM_BANK_ARRAY_LEN ];
44
44
45
45
STATIC uint32_t timer_get_internal_duty (uint16_t duty , uint32_t period ) {
46
46
// duty cycle is duty/0xFFFF fraction x (number of pulses per period)
47
- return (duty * period ) / (( 1 << 16 ) - 1 ) ;
47
+ return (duty * period ) / 0xffff ;
48
48
}
49
49
50
50
STATIC bool timer_get_optimal_divisors (uint32_t * period , uint32_t * prescaler ,
51
51
uint32_t frequency , uint32_t source_freq ) {
52
52
// Find the largest possible period supported by this frequency
53
- for (int i = 0 ; i < (1 << 16 ); i ++ ) {
53
+ * prescaler = 0 ;
54
+ for (uint32_t i = 1 ; i <= 0xffff ; i ++ ) {
54
55
* period = source_freq / (i * frequency );
55
- if (* period < ( 1 << 16 ) && * period >= 2 ) {
56
+ if (* period <= 0xffff && * period >= 2 ) {
56
57
* prescaler = i ;
57
58
break ;
58
59
}
@@ -62,13 +63,10 @@ STATIC bool timer_get_optimal_divisors(uint32_t *period, uint32_t *prescaler,
62
63
}
63
64
64
65
void pwmout_reset (void ) {
65
- uint16_t never_reset_mask = 0x00 ;
66
66
for (int i = 0 ; i < TIM_BANK_ARRAY_LEN ; i ++ ) {
67
67
if (!never_reset_tim [i ]) {
68
- reserved_tim [i ] = 0x00 ;
69
- tim_frequencies [i ] = 0x00 ;
70
- } else {
71
- never_reset_mask |= 1 << i ;
68
+ tim_channels_taken [i ] = 0x00 ;
69
+ tim_frequencies [i ] = 0 ;
72
70
}
73
71
}
74
72
}
@@ -78,73 +76,69 @@ pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t *self,
78
76
uint16_t duty ,
79
77
uint32_t frequency ,
80
78
bool variable_frequency ) {
81
- TIM_TypeDef * TIMx ;
82
- uint8_t tim_num = MP_ARRAY_SIZE (mcu_tim_pin_list );
83
- bool tim_taken_internal = false;
84
- bool tim_chan_taken = false;
85
- bool tim_taken_f_mismatch = false;
86
- bool var_freq_mismatch = false;
79
+ // Default error is no timer at all on pin.
80
+ pwmout_result_t last_failure = PWMOUT_INVALID_PIN ;
87
81
bool first_time_setup = true;
88
82
89
- for (uint i = 0 ; i < tim_num ; i ++ ) {
90
- const mcu_tim_pin_obj_t * l_tim = & mcu_tim_pin_list [i ];
91
- uint8_t l_tim_index = l_tim -> tim_index ;
92
- uint8_t l_tim_channel = l_tim -> channel_index ;
83
+ uint8_t tim_index ;
84
+ uint8_t tim_channel_index ;
85
+
86
+ self -> tim = NULL ;
87
+ for (uint i = 0 ; i < MP_ARRAY_SIZE (mcu_tim_pin_list ); i ++ ) {
88
+ const mcu_tim_pin_obj_t * tim = & mcu_tim_pin_list [i ];
89
+ tim_index = tim -> tim_index ;
90
+ tim_channel_index = tim -> channel_index ;
93
91
94
92
// if pin is same
95
- if (l_tim -> pin == pin ) {
93
+ if (tim -> pin == pin ) {
96
94
// check if the timer has a channel active, or is reserved by main timer system
97
- if (l_tim_index < TIM_BANK_ARRAY_LEN && reserved_tim [ l_tim_index ] != 0 ) {
95
+ if (tim_index < TIM_BANK_ARRAY_LEN && tim_channels_taken [ tim_index ] != 0 ) {
98
96
// Timer has already been reserved by an internal module
99
- if (stm_peripherals_timer_is_reserved (mcu_tim_banks [l_tim_index ])) {
100
- tim_taken_internal = true ;
97
+ if (stm_peripherals_timer_is_reserved (mcu_tim_banks [tim_index ])) {
98
+ last_failure = PWMOUT_ALL_TIMERS_ON_PIN_IN_USE ;
101
99
continue ; // keep looking
102
100
}
103
101
// is it the same channel? (or all channels reserved by a var-freq)
104
- if (reserved_tim [ l_tim_index ] & 1 << ( l_tim_channel )) {
105
- tim_chan_taken = true ;
102
+ if (tim_channels_taken [ tim_index ] & ( 1 << tim_channel_index )) {
103
+ last_failure = PWMOUT_ALL_TIMERS_ON_PIN_IN_USE ;
106
104
continue ; // keep looking, might be another viable option
107
105
}
108
106
// If the frequencies are the same it's ok
109
- if (tim_frequencies [l_tim_index ] != frequency ) {
110
- tim_taken_f_mismatch = true ;
107
+ if (tim_frequencies [tim_index ] != frequency ) {
108
+ last_failure = PWMOUT_INVALID_FREQUENCY_ON_PIN ;
111
109
continue ; // keep looking
112
110
}
113
111
// you can't put a variable frequency on a partially reserved timer
114
112
if (variable_frequency ) {
115
- var_freq_mismatch = true ;
113
+ last_failure = PWMOUT_VARIABLE_FREQUENCY_NOT_AVAILABLE ;
116
114
continue ; // keep looking
117
115
}
118
116
first_time_setup = false; // skip setting up the timer
119
117
}
120
118
// No problems taken, so set it up
121
- self -> tim = l_tim ;
119
+ self -> tim = tim ;
122
120
break ;
123
121
}
124
122
}
125
123
124
+ TIM_TypeDef * TIMx ;
125
+
126
126
// handle valid/invalid timer instance
127
127
if (self -> tim != NULL ) {
128
128
// create instance
129
- TIMx = mcu_tim_banks [self -> tim -> tim_index ];
129
+ TIMx = mcu_tim_banks [tim_index ];
130
130
// reserve timer/channel
131
131
if (variable_frequency ) {
132
- reserved_tim [self -> tim -> tim_index ] = 0x0F ;
132
+ // Take all the channels.
133
+ tim_channels_taken [tim_index ] = 0x0F ;
133
134
} else {
134
- reserved_tim [ self -> tim -> tim_index ] |= 1 << self -> tim -> channel_index ;
135
+ tim_channels_taken [ tim_index ] |= 1 << tim_channel_index ;
135
136
}
136
- tim_frequencies [self -> tim -> tim_index ] = frequency ;
137
+ tim_frequencies [tim_index ] = frequency ;
137
138
stm_peripherals_timer_reserve (TIMx );
138
- } else { // no match found
139
- if (tim_chan_taken || tim_taken_internal ) {
140
- return PWMOUT_ALL_TIMERS_ON_PIN_IN_USE ;
141
- } else if (tim_taken_f_mismatch ) {
142
- return PWMOUT_INVALID_FREQUENCY_ON_PIN ;
143
- } else if (var_freq_mismatch ) {
144
- return PWMOUT_VARIABLE_FREQUENCY_NOT_AVAILABLE ;
145
- } else {
146
- return PWMOUT_INVALID_PIN ;
147
- }
139
+ } else {
140
+ // no match found
141
+ return last_failure ;
148
142
}
149
143
150
144
uint32_t prescaler = 0 ; // prescaler is 15 bit
@@ -163,10 +157,10 @@ pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t *self,
163
157
HAL_GPIO_Init (pin_port (pin -> port ), & GPIO_InitStruct );
164
158
self -> pin = pin ;
165
159
166
- tim_clock_enable (1 << ( self -> tim -> tim_index ) );
160
+ tim_clock_enable (1 << tim_index );
167
161
168
- // translate channel into handle value
169
- self -> channel = 4 * self -> tim -> channel_index ;
162
+ // translate channel into handle value: TIM_CHANNEL_1, _2, _3, _4.
163
+ self -> channel = 4 * tim_channel_index ;
170
164
171
165
// Timer init
172
166
self -> handle .Instance = TIMx ;
@@ -175,6 +169,7 @@ pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t *self,
175
169
self -> handle .Init .ClockDivision = TIM_CLOCKDIVISION_DIV1 ;
176
170
self -> handle .Init .CounterMode = TIM_COUNTERMODE_UP ;
177
171
self -> handle .Init .RepetitionCounter = 0 ;
172
+ self -> handle .Init .AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE ;
178
173
179
174
// only run init if this is the first instance of this timer
180
175
if (first_time_setup ) {
@@ -232,15 +227,15 @@ void common_hal_pwmio_pwmout_deinit(pwmio_pwmout_obj_t *self) {
232
227
}
233
228
// var freq shuts down entire timer, others just their channel
234
229
if (self -> variable_frequency ) {
235
- reserved_tim [self -> tim -> tim_index ] = 0x00 ;
230
+ tim_channels_taken [self -> tim -> tim_index ] = 0x00 ;
236
231
} else {
237
- reserved_tim [self -> tim -> tim_index ] &= ~(1 << self -> tim -> channel_index );
232
+ tim_channels_taken [self -> tim -> tim_index ] &= ~(1 << self -> tim -> channel_index );
238
233
HAL_TIM_PWM_Stop (& self -> handle , self -> channel );
239
234
}
240
235
common_hal_reset_pin (self -> pin );
241
236
242
237
// if reserved timer has no active channels, we can disable it
243
- if (reserved_tim [self -> tim -> tim_index ] == 0 ) {
238
+ if (tim_channels_taken [self -> tim -> tim_index ] == 0 ) {
244
239
tim_frequencies [self -> tim -> tim_index ] = 0x00 ;
245
240
stm_peripherals_timer_free (self -> handle .Instance );
246
241
}
0 commit comments