29
29
#include "us_ticker_api.h"
30
30
#include "PeripheralNames.h"
31
31
32
- // Timers selection:
33
- // The Master timer clocks the Slave timer
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)
34
36
35
- #define TIM_MST TIM9
36
- #define TIM_MST_IRQ TIM9_IRQn
37
- #define TIM_MST_RCC RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM9, ENABLE)
37
+ static int us_ticker_inited = 0 ;
38
+ static uint32_t SlaveCounter = 0 ;
39
+ static uint32_t us_ticker_int_counter = 0 ;
40
+ static uint16_t us_ticker_int_remainder = 0 ;
38
41
39
- #define TIM_SLV TIM4
40
- #define TIM_SLV_IRQ TIM4_IRQn
41
- #define TIM_SLV_RCC RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE)
42
-
43
- #define MST_SLV_ITR TIM_TS_ITR3
42
+ static void tim_update_oc_irq_handler (void ) {
43
+ // Update interrupt: increment the slave counter
44
+ if (TIM_GetITStatus (TIM_MST , TIM_IT_Update ) == SET ) {
45
+ TIM_ClearITPendingBit (TIM_MST , TIM_IT_Update );
46
+ SlaveCounter ++ ;
47
+ }
44
48
45
- int us_ticker_inited = 0 ;
49
+ // Output compare interrupt: used by interrupt system
50
+ if (TIM_GetITStatus (TIM_MST , TIM_IT_CC1 ) == SET ) {
51
+ TIM_ClearITPendingBit (TIM_MST , TIM_IT_CC1 );
52
+ if (us_ticker_int_counter > 0 ) {
53
+ TIM_SetCompare1 (TIM_MST , 0xFFFF );
54
+ us_ticker_int_counter -- ;
55
+ } else {
56
+ if (us_ticker_int_remainder > 0 ) {
57
+ TIM_SetCompare1 (TIM_MST , us_ticker_int_remainder );
58
+ us_ticker_int_remainder = 0 ;
59
+ } else {
60
+ // This function is going to disable the interrupts if there are
61
+ // no other events in the queue
62
+ us_ticker_irq_handler ();
63
+ }
64
+ }
65
+ }
66
+ }
46
67
47
- void us_ticker_init (void ) {
48
-
68
+ void us_ticker_init (void ) {
49
69
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure ;
50
- TIM_OCInitTypeDef TIM_OCInitStructure ;
51
-
70
+
52
71
if (us_ticker_inited ) return ;
53
72
us_ticker_inited = 1 ;
54
73
55
- // Enable Timers clock
74
+ // Enable Timer clock
56
75
TIM_MST_RCC ;
57
- TIM_SLV_RCC ;
58
76
59
- // Master and Slave timers time base configuration
77
+ // Configure time base
60
78
TIM_TimeBaseStructInit (& TIM_TimeBaseStructure );
61
79
TIM_TimeBaseStructure .TIM_Period = 0xFFFF ;
62
80
TIM_TimeBaseStructure .TIM_Prescaler = (uint16_t )(SystemCoreClock / 1000000 ) - 1 ; // 1 µs tick
63
81
TIM_TimeBaseStructure .TIM_ClockDivision = 0 ;
64
82
TIM_TimeBaseStructure .TIM_CounterMode = TIM_CounterMode_Up ;
65
83
TIM_TimeBaseInit (TIM_MST , & TIM_TimeBaseStructure );
66
- TIM_TimeBaseStructure .TIM_Prescaler = 0 ;
67
- TIM_TimeBaseInit (TIM_SLV , & TIM_TimeBaseStructure );
68
-
69
- // Master timer configuration
70
- TIM_OCStructInit (& TIM_OCInitStructure );
71
- TIM_OCInitStructure .TIM_OCMode = TIM_OCMode_Toggle ;
72
- TIM_OCInitStructure .TIM_OutputState = TIM_OutputState_Enable ;
73
- TIM_OCInitStructure .TIM_Pulse = 0 ;
74
- TIM_OCInitStructure .TIM_OCPolarity = TIM_OCPolarity_High ;
75
- TIM_OC1Init (TIM_MST , & TIM_OCInitStructure );
76
- TIM_SelectMasterSlaveMode (TIM_MST , TIM_MasterSlaveMode_Enable );
77
- TIM_SelectOutputTrigger (TIM_MST , TIM_TRGOSource_Update );
78
84
79
- // Slave timer configuration
80
- TIM_SelectSlaveMode (TIM_SLV , TIM_SlaveMode_External1 );
81
- // The connection between Master and Slave is done here
82
- TIM_SelectInputTrigger (TIM_SLV , MST_SLV_ITR );
85
+ // Configure interrupts
86
+ TIM_ITConfig (TIM_MST , TIM_IT_Update , ENABLE );
87
+ TIM_ITConfig (TIM_MST , TIM_IT_CC1 , ENABLE );
88
+
89
+ // For 32-bit counter and output compare
90
+ NVIC_SetVector (TIM_MST_IRQ , (uint32_t )tim_update_oc_irq_handler );
91
+ NVIC_EnableIRQ (TIM_MST_IRQ );
83
92
84
- // Enable timers
85
- TIM_Cmd (TIM_SLV , ENABLE );
93
+ // Enable timer
86
94
TIM_Cmd (TIM_MST , ENABLE );
87
95
}
88
96
@@ -94,10 +102,10 @@ uint32_t us_ticker_read() {
94
102
// previous (incorrect) value of Slave and the new value of Master, which would return a
95
103
// value in the past. Avoid this by computing consecutive values of the timer until they
96
104
// are properly ordered.
97
- counter = (uint32_t )(( uint32_t ) TIM_GetCounter ( TIM_SLV ) << 16 );
105
+ counter = (uint32_t )(SlaveCounter << 16 );
98
106
counter += (uint32_t )TIM_GetCounter (TIM_MST );
99
107
while (1 ) {
100
- counter2 = (uint32_t )(( uint32_t ) TIM_GetCounter ( TIM_SLV ) << 16 );
108
+ counter2 = (uint32_t )(SlaveCounter << 16 );
101
109
counter2 += (uint32_t )TIM_GetCounter (TIM_MST );
102
110
if (counter2 > counter ) {
103
111
break ;
@@ -108,26 +116,31 @@ uint32_t us_ticker_read() {
108
116
}
109
117
110
118
void us_ticker_set_interrupt (unsigned int timestamp ) {
111
- if ( timestamp > 0xFFFF ) {
112
- TIM_SetCompare1 ( TIM_SLV , ( uint16_t )(( timestamp >> 16 ) & 0xFFFF ));
113
- TIM_ITConfig ( TIM_SLV , TIM_IT_CC1 , ENABLE );
114
- NVIC_SetVector ( TIM_SLV_IRQ , ( uint32_t ) us_ticker_irq_handler );
115
- NVIC_EnableIRQ ( TIM_SLV_IRQ );
119
+ int delta = ( int )( timestamp - us_ticker_read ());
120
+
121
+ if ( delta <= 0 ) { // This event was in the past
122
+ us_ticker_irq_handler ( );
123
+ return ;
116
124
}
117
125
else {
118
- TIM_SetCompare1 (TIM_MST , (uint16_t )timestamp );
119
- TIM_ITConfig (TIM_MST , TIM_IT_CC1 , ENABLE );
120
- NVIC_SetVector (TIM_MST_IRQ , (uint32_t )us_ticker_irq_handler );
121
- NVIC_EnableIRQ (TIM_MST_IRQ );
126
+ us_ticker_int_counter = (uint32_t )(delta >> 16 );
127
+ us_ticker_int_remainder = (uint16_t )(delta & 0xFFFF );
128
+ if (us_ticker_int_counter > 0 ) { // means delta > 0xFFFF
129
+ TIM_SetCompare1 (TIM_MST , 0xFFFF );
130
+ us_ticker_int_counter -- ;
131
+ } else {
132
+ TIM_SetCompare1 (TIM_MST , us_ticker_int_remainder );
133
+ us_ticker_int_remainder = 0 ;
134
+ }
122
135
}
123
136
}
124
137
125
138
void us_ticker_disable_interrupt (void ) {
126
139
TIM_ITConfig (TIM_MST , TIM_IT_CC1 , DISABLE );
127
- TIM_ITConfig (TIM_SLV , TIM_IT_CC1 , DISABLE );
128
140
}
129
141
130
142
void us_ticker_clear_interrupt (void ) {
131
- TIM_ClearITPendingBit (TIM_MST , TIM_IT_CC1 );
132
- TIM_ClearITPendingBit (TIM_SLV , TIM_IT_CC1 );
143
+ if (TIM_GetITStatus (TIM_MST , TIM_IT_CC1 ) == SET ) {
144
+ TIM_ClearITPendingBit (TIM_MST , TIM_IT_CC1 );
145
+ }
133
146
}
0 commit comments