• 【freertos】002-posix模拟器设计与cortex m3异常处理


    前言

    如果对硬件任务内核切换不感兴趣的同学可以跳过。

    由于任务源码分析开始涉及到接口层,所以在学习源码前,先了解下posix接口层的设计。

    本系列接口层会讲解两个:

    1. posix标准接口。因为本教程demo在linux上跑freertos时实际使用的就是这个接口。
    2. cortex m3/m4架构接口。因为这才是真正设计到ARM架构硬件的接口。且,这个网上资料较多,看不懂本作者的笔记也可以找度娘辅助分析。

    强烈建议:

    1. 涉及到接口,建议找到对应的架构权威指南学习,掌握底层原理。
    2. 对于指向学习系统应用的同学,快速移植,直接在freertos原生代码中找到结构层进行替换即可。

    参考:

    posix 标准接口层设计

    模拟器不涉及到CPU寄存器组。

    模拟器的系统心跳

    RTOS系统周期是使用ITIMER生成的,并且信号仅被传递给当前执行的pthread。

    RTPS系统滴答信号处理器增加滴答计数,并选择下一个RTOS任务上下文。

    它恢复该线程,并向自己发送一个信号来暂停。

    挂起仅在系统滴答信号处理程序退出时进行处理,因为信号已排队。

    模拟器的task底层实质

    FreeRTOS模拟器的实现是简单地包装平台本地线程,所有切换任务上下文的调用将调用OS挂起和恢复线程API。

    这个模拟器使用Posix条件变量和Signals来控制底层Posix线程的执行。

    信号可以异步地传递给线程,这样它们就会中断目标线程的执行,而挂起的线程则会等待条件变量恢复。

    模拟器的任务切换原理

    当一个新的Task被创建时,一个pthread被创建为Task的执行上下文。

    pthread立即挂起自己,并将执行返回给创建者。

    当一个pthread挂起时,它正在pthread_cond_wait调用中等待,这个调用被阻塞,直到它收到一个恢复信号pthread_cond_signal。

    任务可以通过协作调用taskYIELD()或RTOS系统Tick调度两种方式。

    在这个模拟器中,通过恢复下一个任务上下文(由FreeRTOS Scheduler决定)和挂起当前上下文(两者之间进行简短的握手)来切换Task上下文。

    cortex M3/M4异常处理

    参考:《The Definitive Guide to Arm Cortex-M3 and Cortex-M4 Processors_c.pdf》

    读者可以翻看cortex m3/m4的权威指南查看更多细节即可,本教程只粗略说明下异常时栈帧的动态过程。

    CPU寄存器组可自行百度。

    双堆栈指针

    Cortex-M3内核有两个堆栈指针:

    • MSP:主堆栈指针,是给系统栈空间使用的。
    • PSP:进程堆栈指针,是给任务栈使用的。

    在FreeRTOS任务中,所有栈空间的使用都是通过PSP指针进行指向的。

    一旦进入了中断函数以及可能发生的中断嵌套都是用的MSP指针。

    双操作模式

    Cortex-M3支持两种操作模式(handler模式和thread模式),这两种模式是为了区别正在执行代码的类型:

    • handler模式为异常处理程序的代码。
    • 线程模式为普通应用程序的代码。

    栈帧

    异常后硬件压栈部分:

    • 下图描述的是启用或需要双字栈对齐调整时,Cortex-M3或Cortex-M4处理器(不带浮点)的栈帧。
    • 双字栈对齐这个特性是AAPCS规则的一个要求,意思是栈指针的数值在函数入口或出口处应该是双字对齐,若未对齐,异常硬件压栈时会自动插入一个字来保证双字对齐。(了解即可)

    注意,异常时硬件压栈的LR值和函数调用时的函数栈帧中的LR值是不一样的,具体可以了解下EXC_RETURN

    EXC_RETURN

    进入异常服务程序以后,LR的值被自动更新为特殊的EXC_RETURN(只有[3:0]位有意义,其他位都为1)。如图说明:

    位段 意义
    3 0:返回后进入Handler模式
    1:返回后进入线程模式
    2 0:从主堆栈中执行出栈操作,返回后使用MSP
    1:从进程栈中执行出栈操作,返回后使用PSP
    1 保留,必须为0
    0 0:返回ARM状态
    1:返回Thumb状态(在CM3中必须为1)

    有效值如下:

    如主程序在线程模式下运行,并且在使用PSP时被中断,则在服务程序中LR=0xFFFFFFFD(主程序被打断前LR已被自动入栈)。

    异常及异常嵌套时LR动态及栈指针使用过程:下图是线程模式使用进程栈为基础:


    __EOF__

  • 本文作者: 李柱明
  • 本文链接: https://www.cnblogs.com/lizhuming/p/16062486.html
  • 关于博主: 嵌入式从业者。RTOS、Linux ...
  • 版权声明: 版权归博主所有
  • 声援博主: 学习笔记分享
  • 相关阅读:
    消息队列延时聚合通知的重要性
    Windows调试技巧&工具
    在 PostgreSQL 中,解决图片二进制数据,由于bytea_output参数问题导致显示不正常的问题。
    VS配置libtorch,torchvision(vision)的一些问题记录
    通过高分辨照片中激光图形对应的hsv值对图形进行提取
    MySQL增删改查语句练习(grade表,student表,subjects表,result表)
    【考研】数据结构——线索二叉树
    OpenCV入门8:区域分割和区域生长
    @设计模式-工厂模式
    使用Python语言制作贪吃蛇游戏,并制作成为exe可执行文件
  • 原文地址:https://www.cnblogs.com/lizhuming/p/16062486.html