1
6
7
12
13
15
16
17
18
23
24
25
26
27
28
29
33
34
35
36
43
44
45
46
47
48
49
50
51
52
53
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
81
82
86
87
88
89
90
96
97
98
99
100
101
102
103
104
105
113
114
118
119
120
126
127
128
129
130
131
132
133
134
135
152
153
154
155
156
157
158
159
162
163
169
170
171
172
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
216
217
237
238
239
240
245
246
/* ... */
#include "sdkconfig.h"
#include <stdint.h>
#include <stdlib.h>
#include "FreeRTOS.h"
#include "task.h"5 includes
#if ( !CONFIG_FREERTOS_SMP && ( configNUM_CORES > 1 ) )
#include "esp_private/freertos_idf_additions_priv.h"/* ... */
#endif
#if CONFIG_FREERTOS_SYSTICK_USES_CCOUNT
#if CONFIG_FREERTOS_CORETIMER_0
#define SYSTICK_INTR_ID (ETS_INTERNAL_TIMER0_INTR_SOURCE + ETS_INTERNAL_INTR_SOURCE_OFF)
#else
#define SYSTICK_INTR_ID (ETS_INTERNAL_TIMER1_INTR_SOURCE + ETS_INTERNAL_INTR_SOURCE_OFF)
#endif/* ... */
#else
#define SYSTICK_INTR_ID (ETS_SYSTIMER_TARGET0_INTR_SOURCE)
#endif
BaseType_t xPortSysTickHandler(void);
/* ... */
#if CONFIG_FREERTOS_SYSTICK_USES_SYSTIMER
#include "soc/periph_defs.h"
#include "hal/systimer_hal.h"
#include "hal/systimer_ll.h"
#include "esp_err.h"
#include "esp_intr_alloc.h"
#include "esp_private/systimer.h"
#include "esp_private/periph_ctrl.h"7 includes
#ifdef CONFIG_PM_TRACE
#include "esp_private/pm_trace.h"
#endif
_Static_assert(SOC_CPU_CORES_NUM <= SOC_SYSTIMER_ALARM_NUM - 1, "the number of cores must match the number of core alarms in SYSTIMER");
void SysTickIsrHandler(void *arg);
static uint32_t s_handled_systicks[configNUM_CORES] = { 0 };
/* ... */
void vSystimerSetup(void)
{
unsigned cpuid = xPortGetCoreID();
#ifdef CONFIG_FREERTOS_CORETIMER_SYSTIMER_LVL3
const unsigned level = ESP_INTR_FLAG_LEVEL3;
#else
const unsigned level = ESP_INTR_FLAG_LEVEL1;
#endif
static systimer_hal_context_t systimer_hal;
ESP_ERROR_CHECK(esp_intr_alloc(ETS_SYSTIMER_TARGET0_INTR_SOURCE + cpuid, ESP_INTR_FLAG_IRAM | level, SysTickIsrHandler, &systimer_hal, NULL));
if (cpuid == 0) {
PERIPH_RCC_ACQUIRE_ATOMIC(PERIPH_SYSTIMER_MODULE, ref_count) {
if (ref_count == 0) {
systimer_ll_enable_bus_clock(true);
systimer_ll_reset_register();
}{...}
}{...}
systimer_hal_init(&systimer_hal);
systimer_hal_tick_rate_ops_t ops = {
.ticks_to_us = systimer_ticks_to_us,
.us_to_ticks = systimer_us_to_ticks,
}{...};
systimer_hal_set_tick_rate_ops(&systimer_hal, &ops);
systimer_ll_set_counter_value(systimer_hal.dev, SYSTIMER_COUNTER_OS_TICK, 0);
systimer_ll_apply_counter_value(systimer_hal.dev, SYSTIMER_COUNTER_OS_TICK);
for (cpuid = 0; cpuid < SOC_CPU_CORES_NUM; cpuid++) {
systimer_hal_counter_can_stall_by_cpu(&systimer_hal, SYSTIMER_COUNTER_OS_TICK, cpuid, false);
uint32_t alarm_id = SYSTIMER_ALARM_OS_TICK_CORE0 + cpuid;
systimer_hal_select_alarm_mode(&systimer_hal, alarm_id, SYSTIMER_ALARM_MODE_ONESHOT);
}{...}
for (cpuid = 0; cpuid < configNUM_CORES; ++cpuid) {
uint32_t alarm_id = SYSTIMER_ALARM_OS_TICK_CORE0 + cpuid;
systimer_hal_connect_alarm_counter(&systimer_hal, alarm_id, SYSTIMER_COUNTER_OS_TICK);
systimer_hal_set_alarm_period(&systimer_hal, alarm_id, 1000000UL / CONFIG_FREERTOS_HZ);
systimer_hal_select_alarm_mode(&systimer_hal, alarm_id, SYSTIMER_ALARM_MODE_PERIOD);
systimer_hal_counter_can_stall_by_cpu(&systimer_hal, SYSTIMER_COUNTER_OS_TICK, cpuid, true);
if (cpuid == 0) {
systimer_hal_enable_alarm_int(&systimer_hal, alarm_id);
systimer_hal_enable_counter(&systimer_hal, SYSTIMER_COUNTER_OS_TICK);
#ifndef CONFIG_FREERTOS_UNICORE
systimer_hal_counter_value_advance(&systimer_hal, SYSTIMER_COUNTER_OS_TICK, 1000000UL / CONFIG_FREERTOS_HZ / 2);/* ... */
#endif
}{...}
}{...}
}{...} else {
uint32_t alarm_id = SYSTIMER_ALARM_OS_TICK_CORE0 + cpuid;
systimer_hal_enable_alarm_int(&systimer_hal, alarm_id);
}{...}
}{...}
/* ... */
void SysTickIsrHandler(void *arg)
{
uint32_t cpuid = xPortGetCoreID();
systimer_hal_context_t *systimer_hal = (systimer_hal_context_t *)arg;
#ifdef CONFIG_PM_TRACE
ESP_PM_TRACE_ENTER(TICK, cpuid);
#endif
uint32_t alarm_id = SYSTIMER_ALARM_OS_TICK_CORE0 + cpuid;
do {
systimer_ll_clear_alarm_int(systimer_hal->dev, alarm_id);
uint32_t diff = systimer_hal_get_counter_value(systimer_hal, SYSTIMER_COUNTER_OS_TICK) / systimer_ll_get_alarm_period(systimer_hal->dev, alarm_id) - s_handled_systicks[cpuid];
if (diff > 0) {
if (s_handled_systicks[cpuid] == 0) {
s_handled_systicks[cpuid] = diff;
diff = 1;
}{...} else {
s_handled_systicks[cpuid] += diff;
}{...}
do {
xPortSysTickHandler();
}{...} while (--diff);
}{...}
}{...} while (systimer_ll_is_alarm_int_fired(systimer_hal->dev, alarm_id));
#ifdef CONFIG_PM_TRACE
ESP_PM_TRACE_EXIT(TICK, cpuid);
#endif
}{...}
/* ... */#endif
/* ... */
/* ... */
void vPortSetupTimer(void)
{
#if CONFIG_FREERTOS_SYSTICK_USES_CCOUNT
extern void _frxt_tick_timer_init(void);
extern void _xt_tick_divisor_init(void);
_xt_tick_divisor_init();
_frxt_tick_timer_init();/* ... */
#else
vSystimerSetup();
#endif
}{ ... }
/* ... */
BaseType_t xPortSysTickHandler(void)
{
#if configBENCHMARK
portbenchmarkIntLatency();
#endif
traceISR_ENTER(SYSTICK_INTR_ID);
extern void esp_vApplicationTickHook(void);
esp_vApplicationTickHook();
BaseType_t xSwitchRequired;
#if CONFIG_FREERTOS_SMP
UBaseType_t uxSavedStatus = taskENTER_CRITICAL_FROM_ISR();
#if ( configNUM_CORES > 1 )
if (portGET_CORE_ID() == 0) {
xSwitchRequired = xTaskIncrementTick();
}{...} else {
xSwitchRequired = pdFALSE;
}{...}
#else/* ... */
xSwitchRequired = xTaskIncrementTick();
#endif
taskEXIT_CRITICAL_FROM_ISR(uxSavedStatus);/* ... */
#else
#if ( configNUM_CORES > 1 )
/* ... */
if (xPortGetCoreID() == 0) {
xSwitchRequired = xTaskIncrementTick();
}{...} else {
xSwitchRequired = xTaskIncrementTickOtherCores();
}{...}
#else/* ... */
/* ... */
UBaseType_t uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
xSwitchRequired = xTaskIncrementTick();
portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus);/* ... */
#endif /* ... */
#endif
if (xSwitchRequired != pdFALSE) {
portYIELD_FROM_ISR();
}{...} else {
traceISR_EXIT();
}{...}
return xSwitchRequired;
}{ ... }