0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看威廉希尔官方网站 视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

FreeRTOS中Systick的问题

撞上电子 2023-12-15 08:00 次阅读

在Cortex-M内核中,系统节拍由Systick时钟提供,当配置好系统滴答时钟后,每次时钟中断就会触发中断处理数xPortSysTickHandler()。

void xPortSysTickHandler( void ){ /* The SysTick runs at the lowest interrupt priority, so when this interrupt * executes all interrupts must be unmasked. There is therefore no need to * save and then restore the interrupt mask value as its value is already * known - therefore the slightly faster vPortRaiseBASEPRI() function is used * in place of portSET_INTERRUPT_MASK_FROM_ISR(). */ vPortRaiseBASEPRI();//屏蔽归属FreeRTOS的中断优先级 { /* Increment the RTOS tick. */ if( xTaskIncrementTick() != pdFALSE )//时钟计数处理 { /* A context switch is required. Context switching is performed in * the PendSV interrupt. Pend the PendSV interrupt. */ portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;//如果需要切换上下文操作,PendSV标记置位 } }

vPortClearBASEPRIFromISR();}

这部分主要是依靠 xTaskIncrementTick(),来判断任务切换是否在此次系统时钟中断时被需要。如果是,则PendSV标记置位,等待触发PendSV中断。来看看 xTaskIncrementTick()。

BaseType_t xTaskIncrementTick( void ){ TCB_t * pxTCB; TickType_t xItemValue; BaseType_t xSwitchRequired = pdFALSE;

/* Called by the portable layer each time a tick interrupt occurs. * Increments the tick then checks to see if the new tick value will cause any * tasks to be unblocked. */ traceTASK_INCREMENT_TICK( xTickCount );

if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE ) //调度是否被挂起,默认为否 { /* Minor optimisation. The tick count cannot change in this * block. */ const TickType_t xConstTickCount = xTickCount + ( TickType_t ) 1;

/* Increment the RTOS tick, switching the delayed and overflowed * delayed lists if it wraps to 0. */ xTickCount = xConstTickCount;

if( xConstTickCount == ( TickType_t ) 0U ) /*lint !e774 'if' does not always evaluate to false as it is looking for an overflow. 如果xConstTickCount为0,说明溢出了*/ { taskSWITCH_DELAYED_LISTS();/*切换延迟列表*/ } else { mtCOVERAGE_TEST_MARKER(); }

/* See if this tick has made a timeout expire. Tasks are stored in * the queue in the order of their wake time - meaning once one task * has been found whose block time has not expired there is no need to * look any further down the list. */ if( xConstTickCount >= xNextTaskUnblockTime ) { for( ; ; ) { if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE ) { /* The delayed list is empty. Set xNextTaskUnblockTime * to the maximum possible value so it is extremely * unlikely that the * if( xTickCount >= xNextTaskUnblockTime ) test will pass * next time through. */ xNextTaskUnblockTime = portMAX_DELAY; /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ break; } else { /* The delayed list is not empty, get the value of the * item at the head of the delayed list. This is the time * at which the task at the head of the delayed list must * be removed from the Blocked state. */ pxTCB = listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */ xItemValue = listGET_LIST_ITEM_VALUE( &( pxTCB->xStateListItem ) );

关键问题是,这个函数使用到了pxDelayedTaskList, 这定义在本文件

PRIVILEGED_DATA static List_t * volatile pxDelayedTaskList;

该变量初始化为0,该变量正常初始化位置在创建 Task 对象等的函数中, 也就是说,如果在Tick中断到来时,如果还没有任务被创建,就会导致不可预期的结果,中断服务函数会使用这个野指针,执行任务切换。这会导致触发栈溢出钩子函数,或者是直接Hardfault。有些硬件初始化需要借助delay功能,不得不在初始化之前配置SysTick。而又不希望在硬件初始化阶段触发这个Bug。所以在配置SysTick之前,先创建一个初始化任务,初始化 pxDelayedTaskList 这个指针,在初始化任务里配置SysTick,和其他初始化,这样能够避免此类问题。或者是在配置SysTick的时候屏蔽中断,一切准备就绪后,开启中断。执行vTaskStartScheduler()默认创建一个空闲任务。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 内核
    +关注

    关注

    3

    文章

    1372

    浏览量

    40282
  • FreeRTOS
    +关注

    关注

    12

    文章

    484

    浏览量

    62151
  • Systick
    +关注

    关注

    0

    文章

    62

    浏览量

    13074
收藏 人收藏

    评论

    相关推荐

    FreeRTOS内核默认会初始化systick是必须的吗?

    FreeRTOS内核默认会初始化systick;原子哥的视频教程里的例程也会使用delay_init初始化systick。请问是否是必须,有无影响?
    发表于 07-20 08:03

    使用FreeRTOSSystick时钟的配置分享

    FreeRTOS按照教程移植好之后就可以使用了。需要注意的是从官网下载的针对keil环境下STM32F103的FreeRTOS文件,使用systick时钟作为rtos的时钟,而这个systic
    发表于 07-30 11:39

    SysTicK的函数重复定义

    ).原因使用KEIL时在Manage Run-Time Environment勾选的HAL库,然后添加FreeRTOS操作系统时,工程会出现问题首先是下图SysTicK的函数重复定义,是因为添加的
    发表于 08-04 07:55

    使用CubeMX 6为freeRTOS生成代码的问题如何解决?

    我认为在使用 freeRTOS 生成代码时,新的 CubeMX 6.0 存在错误。可能只是从旧的 CubeMX 项目迁移到新的项目时,我不确定。我将使用 CubeMX 5.3 构建的项目更新为
    发表于 01-31 08:56

    系统节拍定时(SysTick)

    SysTick 是一个简单的系统时钟节拍计数器,它属于 ARM Cortex-M3 内核嵌套向量中断 控制器 NVIC 里的一个功能单元,而非片内外设。SysTick 常用于操作系统(如:µC/OS-II、 FreeRTOS
    发表于 01-13 16:34 8次下载

    如何使用STM32实现systick的精确延时

    SYSTICK寄存器初始化 void SysTick_Configuration(void) { if (SysTick_Config(SystemCoreClock / 100
    发表于 11-21 15:54 5941次阅读

    STM32SysTick时钟源来自哪里?

    STM32的SysTick时钟源来自哪里?
    的头像 发表于 03-03 14:32 7860次阅读

    如何使用STM32单片机systick来实现延时定时功能

    SysTick 控制及状态寄存器的使能位清除,就永不停息。这样可以用systick来实现延时定时功能,不用再占用系统定时器。systick也多用做系统的时钟节拍,如
    的头像 发表于 02-14 06:25 6797次阅读
    如何使用STM32单片机<b class='flag-5'>systick</b>来实现延时定时功能

    STM32—关于SYSTICK系统时钟的详解及学习笔记

    /*配置SYSTICK很简单,只需在SySTick_Config写入一个不大于2^24次方的数,就可以产生systick中断1.无需对NVIC进行配置,在
    发表于 11-30 15:51 15次下载
    STM32—关于<b class='flag-5'>SYSTICK</b>系统时钟的详解及学习笔记

    STM32_SysTick—系统定时器

    SysTick 的简介和寄存器的详细描述。因为 SysTick 是属于CM3 内核的外设,有关寄存器的定义和部分库函数都在 core_CM3.h 这个头文件实现。所以学习 SysTick
    发表于 12-23 19:56 2次下载
    STM32_<b class='flag-5'>SysTick</b>—系统定时器

    systick定时器 延时计时

    是cortex M内核的单片机,都拥有这个24位的systick定时器。systick定时器是一个24位递减计时器,用户至于要掌握CMSIS包SysTick_Config 函数进行
    发表于 01-18 10:28 7次下载
    <b class='flag-5'>systick</b>定时器 延时计时

    STM32单片机systick使用注意事项

    寄存器自动重装载定时初值。只要不把它在SysTick 控制及状态寄存器的使能位清除,就永不停息。这样可以用systick来实现延时定时功能,不用再占用系统定时器。
    发表于 01-18 10:35 1次下载
    STM32单片机<b class='flag-5'>systick</b>使用注意事项

    什么是FreeRTOS的延时

    FreeRTOS的时钟节拍通常由**SysTick**提供,它周期性的产生定时中断,所谓的时钟节拍管理的核心就是这个定时中断的服务程序。**FreeRTOS**的时钟节拍isr核心的
    的头像 发表于 02-14 09:45 3487次阅读
    什么是<b class='flag-5'>FreeRTOS</b>的延时

    SysTick时钟

    Cortex-M3内核的处理器,内部包含了一个SysTick定时器,SysTick是一个24位的倒计数定时器,当计数到0时,将从ReLoad寄存器自动重装载定时初值,开始新一轮计数。只要不把它在
    的头像 发表于 03-01 17:40 838次阅读
    <b class='flag-5'>SysTick</b>时钟

    systick_handler无法进入怎么解决

    在嵌入式系统SysTick是一个用于定时器和延时的模块,通常用于处理实时任务、中断和延时等。然而,在某些情况下,SysTick中断处理函数(systick_handler)可能无法
    的头像 发表于 12-01 15:36 4954次阅读