28
28
#include " ticker_api_test_freq.h"
29
29
#include " hal/us_ticker_api.h"
30
30
#include " hal/lp_ticker_api.h"
31
+ #include " hal/mbed_lp_ticker_wrapper.h"
31
32
32
33
#if !DEVICE_USTICKER
33
34
#error [NOT_SUPPORTED] test not supported
38
39
using namespace utest ::v1;
39
40
40
41
const ticker_interface_t *intf;
41
-
42
- static volatile unsigned int overflowCounter;
42
+ uint32_t intf_mask;
43
+ uint32_t intf_last_tick;
44
+ uint32_t intf_elapsed_ticks;
45
+ ticker_irq_handler_type prev_handler;
43
46
44
47
uint32_t ticks_to_us (uint32_t ticks, uint32_t freq)
45
48
{
46
49
return (uint32_t )((uint64_t )ticks * US_PER_S / freq);
47
50
}
48
51
49
- void ticker_event_handler_stub ( const ticker_data_t * const ticker )
52
+ void elapsed_ticks_reset ( )
50
53
{
51
- if (ticker == get_us_ticker_data ()) {
52
- us_ticker_clear_interrupt ();
53
- } else {
54
- #if DEVICE_LPTICKER
55
- lp_ticker_clear_interrupt ();
56
- #endif
57
- }
54
+ core_util_critical_section_enter ();
55
+
56
+ const uint32_t ticker_bits = intf->get_info ()->bits ;
57
+
58
+ intf_mask = (1 << ticker_bits) - 1 ;
59
+ intf_last_tick = intf->read ();
60
+ intf_elapsed_ticks = 0 ;
61
+
62
+ core_util_critical_section_exit ();
63
+ }
58
64
59
- overflowCounter++;
65
+ uint32_t elapsed_ticks_update ()
66
+ {
67
+ core_util_critical_section_enter ();
68
+
69
+ const uint32_t current_tick = intf->read ();
70
+ intf_elapsed_ticks += (current_tick - intf_last_tick) & intf_mask;
71
+ intf_last_tick = current_tick;
72
+
73
+ /* Schedule next interrupt half way to overflow */
74
+ uint32_t next = (current_tick + intf_mask / 2 ) & intf_mask;
75
+ intf->set_interrupt (next);
76
+
77
+ uint32_t elapsed = intf_elapsed_ticks;
78
+
79
+ core_util_critical_section_exit ();
80
+ return elapsed;
81
+ }
82
+
83
+ void ticker_event_handler_stub (const ticker_data_t *const ticker)
84
+ {
85
+ intf->clear_interrupt ();
86
+ elapsed_ticks_update ();
60
87
}
61
88
62
89
/* Test that the ticker is operating at the frequency it specifies. */
@@ -66,13 +93,13 @@ void ticker_frequency_test()
66
93
char _value[128 ] = { };
67
94
int expected_key = 1 ;
68
95
const uint32_t ticker_freq = intf->get_info ()->frequency ;
69
- const uint32_t ticker_bits = intf->get_info ()->bits ;
70
- const uint32_t ticker_max = (1 << ticker_bits) - 1 ;
71
96
72
97
intf->init ();
73
98
99
+ elapsed_ticks_reset ();
100
+
74
101
/* Detect overflow for tickers with lower counters width. */
75
- intf-> set_interrupt ( 0 );
102
+ elapsed_ticks_update ( );
76
103
77
104
greentea_send_kv (" timing_drift_check_start" , 0 );
78
105
@@ -82,19 +109,17 @@ void ticker_frequency_test()
82
109
expected_key = strcmp (_key, " base_time" );
83
110
} while (expected_key);
84
111
85
- overflowCounter = 0 ;
86
-
87
- const uint32_t begin_ticks = intf->read ();
112
+ const uint32_t begin_ticks = elapsed_ticks_update ();
88
113
89
114
/* Assume that there was no overflow at this point - we are just after init. */
90
115
greentea_send_kv (_key, ticks_to_us (begin_ticks, ticker_freq));
91
116
92
117
/* Wait for 2nd signal from host. */
93
118
greentea_parse_kv (_key, _value, sizeof (_key), sizeof (_value));
94
119
95
- const uint32_t end_ticks = intf-> read ();
120
+ const uint32_t end_ticks = elapsed_ticks_update ();
96
121
97
- greentea_send_kv (_key, ticks_to_us (end_ticks + overflowCounter * ticker_max , ticker_freq));
122
+ greentea_send_kv (_key, ticks_to_us (end_ticks, ticker_freq));
98
123
99
124
/* Get the results from host. */
100
125
greentea_parse_kv (_key, _value, sizeof (_key), sizeof (_value));
@@ -106,43 +131,74 @@ void ticker_frequency_test()
106
131
107
132
utest::v1::status_t us_ticker_case_setup_handler_t (const Case *const source, const size_t index_of_case)
108
133
{
134
+ #if DEVICE_LPTICKER && (LPTICKER_DELAY_TICKS > 0)
135
+ /* Suspend the lp ticker wrapper since it makes use of the us ticker */
136
+ ticker_suspend (get_lp_ticker_data ());
137
+ lp_ticker_wrapper_suspend ();
138
+ #endif
139
+ ticker_suspend (get_us_ticker_data ());
109
140
intf = get_us_ticker_data ()->interface ;
110
- set_us_ticker_irq_handler (ticker_event_handler_stub);
141
+ prev_handler = set_us_ticker_irq_handler (ticker_event_handler_stub);
111
142
return greentea_case_setup_handler (source, index_of_case);
112
143
}
113
144
145
+ utest::v1::status_t us_ticker_case_teardown_handler_t (const Case *const source, const size_t passed, const size_t failed,
146
+ const failure_t reason)
147
+ {
148
+ set_us_ticker_irq_handler (prev_handler);
149
+ ticker_resume (get_us_ticker_data ());
150
+ #if DEVICE_LPTICKER && (LPTICKER_DELAY_TICKS > 0)
151
+ lp_ticker_wrapper_resume ();
152
+ ticker_resume (get_lp_ticker_data ());
153
+ #endif
154
+ return greentea_case_teardown_handler (source, passed, failed, reason);
155
+ }
156
+
114
157
#if DEVICE_LPTICKER
115
158
utest::v1::status_t lp_ticker_case_setup_handler_t (const Case *const source, const size_t index_of_case)
116
159
{
160
+ ticker_suspend (get_lp_ticker_data ());
117
161
intf = get_lp_ticker_data ()->interface ;
118
- set_lp_ticker_irq_handler (ticker_event_handler_stub);
162
+ prev_handler = set_lp_ticker_irq_handler (ticker_event_handler_stub);
119
163
return greentea_case_setup_handler (source, index_of_case);
120
164
}
121
- #endif
122
165
123
- utest::v1::status_t ticker_case_teardown_handler_t (const Case *const source, const size_t passed, const size_t failed,
124
- const failure_t reason)
166
+ utest::v1::status_t lp_ticker_case_teardown_handler_t (const Case *const source, const size_t passed, const size_t failed,
167
+ const failure_t reason)
125
168
{
169
+ set_lp_ticker_irq_handler (prev_handler);
170
+ ticker_resume (get_lp_ticker_data ());
126
171
return greentea_case_teardown_handler (source, passed, failed, reason);
127
172
}
173
+ #endif
128
174
129
175
// Test cases
130
176
Case cases[] = {
131
177
Case (" Microsecond ticker frequency test" , us_ticker_case_setup_handler_t , ticker_frequency_test,
132
- ticker_case_teardown_handler_t ),
178
+ us_ticker_case_teardown_handler_t ),
133
179
#if DEVICE_LPTICKER
134
180
Case (" Low power ticker frequency test" , lp_ticker_case_setup_handler_t , ticker_frequency_test,
135
- ticker_case_teardown_handler_t ),
181
+ lp_ticker_case_teardown_handler_t ),
136
182
#endif
137
183
};
138
184
139
185
utest::v1::status_t greentea_test_setup (const size_t number_of_cases)
140
186
{
187
+ /* Suspend RTOS Kernel so the timers are not in use. */
188
+ osKernelSuspend ();
189
+
141
190
GREENTEA_SETUP (120 , " timing_drift_auto" );
142
191
return greentea_test_setup_handler (number_of_cases);
143
192
}
144
193
145
- Specification specification (greentea_test_setup, cases, greentea_test_teardown_handler);
194
+ void greentea_test_teardown (const size_t passed, const size_t failed, const failure_t failure)
195
+ {
196
+ osKernelResume (0 );
197
+
198
+ greentea_test_teardown_handler (passed, failed, failure);
199
+ }
200
+
201
+ Specification specification (greentea_test_setup, cases, greentea_test_teardown);
146
202
147
203
int main ()
148
204
{
0 commit comments