|
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