-
Notifications
You must be signed in to change notification settings - Fork 6.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
timer: cortex_m_systick: uptime drifting in tickless mode #35073
Labels
Milestone
Comments
He are the logs (STM32F070 MCU, external oscillator, tickless mode) of the test application with the patch proposed in PR #35062 applied:
After 10 minutes the Zephyr uptime is now 1 second behind the host machine clock (against 4.5 seconds without the patch). |
Hi, I made some tests on an stm32g4.
Code: /*
* Copyright (c) 2020 Alexander Wachter
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr.h>
#include <soc.h>
#include <device.h>
#include <devicetree.h>
#include <irq.h>
#include <stm32_ll_rcc.h>
#include <stm32_ll_tim.h>
#include <drivers/clock_control/stm32_clock_control.h>
#include <drivers/clock_control.h>
#include <logging/log.h>
LOG_MODULE_REGISTER(main);
static uint32_t timer_cnt;
void timer_isr(void* unused)
{
if(LL_TIM_IsActiveFlag_UPDATE(TIM2)==SET) //Overflow interrupt
{
const uint32_t uptime = k_uptime_get_32();
LOG_INF("Timer ISR %d Timer: %d",timer_cnt, uptime);
timer_cnt += 1;
}
LL_TIM_ClearFlag_UPDATE(TIM2); //Clear interrupt flag
}
void sys_timer_isr(struct k_timer* unused)
{
const uint32_t uptime = k_uptime_get_32();
uint32_t time = (uint32_t)(((uint64_t)timer_cnt * 1000000ULL + (uint64_t)LL_TIM_GetCounter(TIM2)) / 1000ULL);
LOG_INF("Sys Timer ISR. Timer: %d Uptime: %d", time ,uptime);
}
void main(void)
{
const uint32_t tim_clk = DT_PROP(DT_NODELABEL(rcc), clock_frequency);
LL_TIM_InitTypeDef init = {
.Prescaler = __LL_TIM_CALC_PSC(tim_clk, 1000000U),
.CounterMode = LL_TIM_COUNTERMODE_UP,
.Autoreload = 1000000U,
.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1
};
const struct stm32_pclken pclken = {
.enr = DT_CLOCKS_CELL(DT_NODELABEL(timers2), bits),
.bus = DT_CLOCKS_CELL(DT_NODELABEL(timers2), bus),
};
const struct device *clock = DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE);
struct k_timer timer;
int ret;
ret = clock_control_on(clock, (clock_control_subsys_t *)&pclken);
if (ret < 0) {
LOG_ERR("Could not initialize clock [%d]", ret);
return;
}
if (LL_TIM_Init(TIM2, &init) != SUCCESS) {
LOG_ERR("Timer Init failed");
}
IRQ_CONNECT(DT_IRQN(DT_NODELABEL(timers2)),
DT_IRQ(DT_NODELABEL(timers2), priority),
timer_isr, NULL, 0);
LL_TIM_EnableIT_UPDATE(TIM2);
LL_TIM_EnableARRPreload(TIM2);
LL_TIM_EnableCounter(TIM2);
LOG_INF("Init done");
irq_enable(DT_IRQN(DT_NODELABEL(timers2)));
k_timer_init(&timer, sys_timer_isr, NULL);
k_timer_start(&timer, K_NO_WAIT, K_MSEC(1000));
while(1) {
k_msleep(10);
}
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Labels
Abnormal uptime drifting can been observed in Zephyr when using the cortex_m_systick driver in tickless mode.
The following application code can be used to reproduce and highlight the issue. It runs a "no op" timer at 1000 Hz and writes the system uptime on console every 10 seconds. By printing the console messages (and some timestamps) on a host machine connected through serial, then it is possible to compare the Zephyr uptime with the host machine's clock. Although unreliable, this method is good enough to observe the drifting.
Here are the logs when running this application on a board embedding a STM32F070 MCU and an external oscillator / crystal. The console messages are sent over UART. And on the host machine side the minicom program (with the extended timestamps enabled) is used to print them.
After 10 minutes, the Zephyr uptime is approximately 4.5 seconds behind the host machine clock, which is too much given the accuracy of the external oscillator (less than 150 PPM at 24 MHz).
And if I run the same application in the same conditions but with the TICKLESS_KERNEL option disabled and SYS_CLOCK_TICKS_PER_SEC set to 1000, then I get the following output:
This time, after 10 minutes, the Zephyr uptime is looking much better. We can't conclude to any drifting.
The text was updated successfully, but these errors were encountered: