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 TIM1
34
+ #define TIM_MST_UP_IRQ TIM1_UP_IRQn
35
+ #define TIM_MST_OC_IRQ TIM1_CC_IRQn
36
+ #define TIM_MST_RCC RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE)
34
37
35
- #define TIM_MST TIM1
36
- #define TIM_MST_IRQ TIM1_CC_IRQn
37
- #define TIM_MST_RCC RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE)
38
+ static int us_ticker_inited = 0 ;
39
+ static uint32_t SlaveCounter = 0 ;
40
+ static uint32_t us_ticker_int_counter = 0 ;
41
+ static uint16_t us_ticker_int_remainder = 0 ;
38
42
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_ITR0
44
-
45
- int us_ticker_inited = 0 ;
43
+ // Used to increment the slave counter
44
+ static void tim_update_irq_handler ( void ) {
45
+ SlaveCounter ++ ;
46
+ if ( TIM_GetITStatus ( TIM_MST , TIM_IT_Update ) == SET ) {
47
+ TIM_ClearITPendingBit ( TIM_MST , TIM_IT_Update );
48
+ }
49
+ }
46
50
47
- void us_ticker_init (void ) {
51
+ // Used by interrupt system
52
+ static void tim_oc_irq_handler (void ) {
53
+ // Clear interrupt flag
54
+ if (TIM_GetITStatus (TIM_MST , TIM_IT_CC1 ) == SET ) {
55
+ TIM_ClearITPendingBit (TIM_MST , TIM_IT_CC1 );
56
+ }
48
57
49
- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure ;
50
- TIM_OCInitTypeDef TIM_OCInitStructure ;
58
+ if (us_ticker_int_counter > 0 ) {
59
+ TIM_SetCompare1 (TIM_MST , 0xFFFF );
60
+ us_ticker_int_counter -- ;
61
+ } else {
62
+ if (us_ticker_int_remainder > 0 ) {
63
+ TIM_SetCompare1 (TIM_MST , us_ticker_int_remainder );
64
+ us_ticker_int_remainder = 0 ;
65
+ } else {
66
+ // This function is going to disable the interrupts if there are
67
+ // no other events in the queue
68
+ us_ticker_irq_handler ();
69
+ }
70
+ }
71
+ }
51
72
73
+ void us_ticker_init (void ) {
74
+ TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure ;
75
+
52
76
if (us_ticker_inited ) return ;
53
77
us_ticker_inited = 1 ;
54
78
55
- // Enable Timers clock
79
+ // Enable Timer clock
56
80
TIM_MST_RCC ;
57
- TIM_SLV_RCC ;
58
81
59
- // Master and Slave timers time base configuration
82
+ // Configure time base
60
83
TIM_TimeBaseStructInit (& TIM_TimeBaseStructure );
61
84
TIM_TimeBaseStructure .TIM_Period = 0xFFFF ;
62
85
TIM_TimeBaseStructure .TIM_Prescaler = (uint16_t )(SystemCoreClock / 1000000 ) - 1 ; // 1 µs tick
63
86
TIM_TimeBaseStructure .TIM_ClockDivision = 0 ;
64
87
TIM_TimeBaseStructure .TIM_CounterMode = TIM_CounterMode_Up ;
65
88
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
89
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 );
90
+ // Configure interrupts
91
+ TIM_ITConfig (TIM_MST , TIM_IT_Update , ENABLE );
92
+ TIM_ITConfig (TIM_MST , TIM_IT_CC1 , ENABLE );
93
+
94
+ // For 32-bit counter
95
+ NVIC_SetVector (TIM_MST_UP_IRQ , (uint32_t )tim_update_irq_handler );
96
+ NVIC_EnableIRQ (TIM_MST_UP_IRQ );
97
+
98
+ // For ouput compare
99
+ NVIC_SetVector (TIM_MST_OC_IRQ , (uint32_t )tim_oc_irq_handler );
100
+ NVIC_EnableIRQ (TIM_MST_OC_IRQ );
83
101
84
- // Enable timers
85
- TIM_Cmd (TIM_SLV , ENABLE );
102
+ // Enable timer
86
103
TIM_Cmd (TIM_MST , ENABLE );
87
104
}
88
105
@@ -94,10 +111,10 @@ uint32_t us_ticker_read() {
94
111
// previous (incorrect) value of Slave and the new value of Master, which would return a
95
112
// value in the past. Avoid this by computing consecutive values of the timer until they
96
113
// are properly ordered.
97
- counter = (uint32_t )(( uint32_t ) TIM_GetCounter ( TIM_SLV ) << 16 );
114
+ counter = (uint32_t )(SlaveCounter << 16 );
98
115
counter += (uint32_t )TIM_GetCounter (TIM_MST );
99
116
while (1 ) {
100
- counter2 = (uint32_t )(( uint32_t ) TIM_GetCounter ( TIM_SLV ) << 16 );
117
+ counter2 = (uint32_t )(SlaveCounter << 16 );
101
118
counter2 += (uint32_t )TIM_GetCounter (TIM_MST );
102
119
if (counter2 > counter ) {
103
120
break ;
@@ -108,26 +125,31 @@ uint32_t us_ticker_read() {
108
125
}
109
126
110
127
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 );
128
+ int delta = ( int )( timestamp - us_ticker_read ());
129
+
130
+ if ( delta <= 0 ) { // This event was in the past
131
+ us_ticker_irq_handler ( );
132
+ return ;
116
133
}
117
134
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 );
135
+ us_ticker_int_counter = (uint32_t )(delta >> 16 );
136
+ us_ticker_int_remainder = (uint16_t )(delta & 0xFFFF );
137
+ if (us_ticker_int_counter > 0 ) { // means delta > 0xFFFF
138
+ TIM_SetCompare1 (TIM_MST , 0xFFFF );
139
+ us_ticker_int_counter -- ;
140
+ } else {
141
+ TIM_SetCompare1 (TIM_MST , us_ticker_int_remainder );
142
+ us_ticker_int_remainder = 0 ;
143
+ }
122
144
}
123
145
}
124
146
125
147
void us_ticker_disable_interrupt (void ) {
126
148
TIM_ITConfig (TIM_MST , TIM_IT_CC1 , DISABLE );
127
- TIM_ITConfig (TIM_SLV , TIM_IT_CC1 , DISABLE );
128
149
}
129
150
130
151
void us_ticker_clear_interrupt (void ) {
131
- TIM_ClearITPendingBit (TIM_MST , TIM_IT_CC1 );
132
- TIM_ClearITPendingBit (TIM_SLV , TIM_IT_CC1 );
152
+ if (TIM_GetITStatus (TIM_MST , TIM_IT_CC1 ) == SET ) {
153
+ TIM_ClearITPendingBit (TIM_MST , TIM_IT_CC1 );
154
+ }
133
155
}
0 commit comments