|
29 | 29 | #include "us_ticker_api.h"
|
30 | 30 | #include "PeripheralNames.h"
|
31 | 31 |
|
32 |
| -// Timer selection: |
33 |
| -#define TIM_MST TIM9 |
34 |
| -#define TIM_MST_IRQ TIM9_IRQn |
35 |
| -#define TIM_MST_RCC RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM9, ENABLE) |
| 32 | +// 32-bit timer selection |
| 33 | +#define TIM_MST TIM5 |
| 34 | +#define TIM_MST_IRQ TIM5_IRQn |
| 35 | +#define TIM_MST_RCC RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE) |
36 | 36 |
|
37 |
| -static int us_ticker_inited = 0; |
38 |
| -static volatile uint32_t SlaveCounter = 0; |
39 |
| -static volatile uint32_t oc_int_part = 0; |
40 |
| -static volatile uint16_t oc_rem_part = 0; |
41 |
| - |
42 |
| -void set_compare(uint16_t count) { |
43 |
| - // Set new output compare value |
44 |
| - TIM_SetCompare1(TIM_MST, count); |
45 |
| - // Enable IT |
46 |
| - TIM_ITConfig(TIM_MST, TIM_IT_CC1, ENABLE); |
47 |
| -} |
48 |
| - |
49 |
| -static void tim_update_oc_irq_handler(void) { |
50 |
| - uint16_t cval = TIM_MST->CNT; |
51 |
| - |
52 |
| - // Update interrupt: increment the slave counter |
53 |
| - if (TIM_GetITStatus(TIM_MST, TIM_IT_Update) == SET) { |
54 |
| - TIM_ClearITPendingBit(TIM_MST, TIM_IT_Update); |
55 |
| - SlaveCounter++; |
56 |
| - } |
57 |
| - |
58 |
| - // Output compare interrupt: used by interrupt system |
59 |
| - if (TIM_GetITStatus(TIM_MST, TIM_IT_CC1) == SET) { |
60 |
| - TIM_ClearITPendingBit(TIM_MST, TIM_IT_CC1); |
61 |
| - if (oc_rem_part > 0) { |
62 |
| - set_compare(oc_rem_part); // Finish the remaining time left |
63 |
| - oc_rem_part = 0; |
64 |
| - } |
65 |
| - else { |
66 |
| - if (oc_int_part > 0) { |
67 |
| - set_compare(0xFFFF); |
68 |
| - oc_rem_part = cval; // To finish the counter loop the next time |
69 |
| - oc_int_part--; |
70 |
| - } |
71 |
| - else { |
72 |
| - us_ticker_irq_handler(); |
73 |
| - } |
74 |
| - } |
75 |
| - } |
76 |
| -} |
| 37 | +static int us_ticker_inited = 0; |
77 | 38 |
|
78 | 39 | void us_ticker_init(void) {
|
79 | 40 | TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
|
80 | 41 |
|
81 | 42 | if (us_ticker_inited) return;
|
82 | 43 | us_ticker_inited = 1;
|
83 | 44 |
|
84 |
| - // Enable Timer clock |
| 45 | + // Enable timer clock |
85 | 46 | TIM_MST_RCC;
|
86 | 47 |
|
87 | 48 | // Configure time base
|
88 | 49 | TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
|
89 |
| - TIM_TimeBaseStructure.TIM_Period = 0xFFFF; |
| 50 | + TIM_TimeBaseStructure.TIM_Period = 0xFFFFFFFF; |
90 | 51 | TIM_TimeBaseStructure.TIM_Prescaler = (uint16_t)(SystemCoreClock / 1000000) - 1; // 1 µs tick
|
91 | 52 | TIM_TimeBaseStructure.TIM_ClockDivision = 0;
|
92 | 53 | TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
|
93 | 54 | TIM_TimeBaseInit(TIM_MST, &TIM_TimeBaseStructure);
|
94 |
| - |
95 |
| - // Configure interrupts |
96 |
| - TIM_ITConfig(TIM_MST, TIM_IT_Update, ENABLE); |
97 |
| - |
98 |
| - // For 32-bit counter and output compare |
99 |
| - NVIC_SetVector(TIM_MST_IRQ, (uint32_t)tim_update_oc_irq_handler); |
| 55 | + |
| 56 | + NVIC_SetVector(TIM_MST_IRQ, (uint32_t)us_ticker_irq_handler); |
100 | 57 | NVIC_EnableIRQ(TIM_MST_IRQ);
|
101 | 58 |
|
102 | 59 | // Enable timer
|
103 | 60 | TIM_Cmd(TIM_MST, ENABLE);
|
104 | 61 | }
|
105 | 62 |
|
106 | 63 | uint32_t us_ticker_read() {
|
107 |
| - uint32_t counter, counter2; |
108 | 64 | if (!us_ticker_inited) us_ticker_init();
|
109 |
| - // A situation might appear when Master overflows right after Slave is read and before the |
110 |
| - // new (overflowed) value of Master is read. Which would make the code below consider the |
111 |
| - // previous (incorrect) value of Slave and the new value of Master, which would return a |
112 |
| - // value in the past. Avoid this by computing consecutive values of the timer until they |
113 |
| - // are properly ordered. |
114 |
| - counter = (uint32_t)(SlaveCounter << 16); |
115 |
| - counter += TIM_MST->CNT; |
116 |
| - while (1) { |
117 |
| - counter2 = (uint32_t)(SlaveCounter << 16); |
118 |
| - counter2 += TIM_MST->CNT; |
119 |
| - if (counter2 > counter) { |
120 |
| - break; |
121 |
| - } |
122 |
| - counter = counter2; |
123 |
| - } |
124 |
| - return counter2; |
| 65 | + return TIM_MST->CNT; |
125 | 66 | }
|
126 | 67 |
|
127 | 68 | void us_ticker_set_interrupt(unsigned int timestamp) {
|
128 |
| - int delta = (int)(timestamp - us_ticker_read()); |
129 |
| - uint16_t cval = TIM_MST->CNT; |
130 |
| - |
131 |
| - if (delta <= 0) { // This event was in the past |
132 |
| - us_ticker_irq_handler(); |
133 |
| - } |
134 |
| - else { |
135 |
| - oc_int_part = (uint32_t)(delta >> 16); |
136 |
| - oc_rem_part = (uint16_t)(delta & 0xFFFF); |
137 |
| - if (oc_rem_part <= (0xFFFF - cval)) { |
138 |
| - set_compare(cval + oc_rem_part); |
139 |
| - oc_rem_part = 0; |
140 |
| - } else { |
141 |
| - set_compare(0xFFFF); |
142 |
| - oc_rem_part = oc_rem_part - (0xFFFF - cval); |
143 |
| - } |
144 |
| - } |
| 69 | + // Set new output compare value |
| 70 | + TIM_SetCompare1(TIM_MST, timestamp); |
| 71 | + // Enable IT |
| 72 | + TIM_ITConfig(TIM_MST, TIM_IT_CC1, ENABLE); |
145 | 73 | }
|
146 | 74 |
|
147 | 75 | void us_ticker_disable_interrupt(void) {
|
148 | 76 | TIM_ITConfig(TIM_MST, TIM_IT_CC1, DISABLE);
|
149 | 77 | }
|
150 | 78 |
|
151 | 79 | void us_ticker_clear_interrupt(void) {
|
152 |
| - if (TIM_GetITStatus(TIM_MST, TIM_IT_CC1) == SET) { |
153 |
| - TIM_ClearITPendingBit(TIM_MST, TIM_IT_CC1); |
154 |
| - } |
| 80 | + TIM_ClearITPendingBit(TIM_MST, TIM_IT_CC1); |
155 | 81 | }
|
0 commit comments