历史上的今天
返回首页

历史上的今天

今天是:2025年01月12日(星期日)

2021年01月12日 | 一步步写STM32 OS【一】 序言

2021-01-12 来源:eefocus

  一直想写个类似uCOS的OS,近段时间考研复习之余忙里偷闲,总算有点成果了。言归正传,我觉得OS最难的部分首先便是上下文切换的问题,他和MCU的架构有关,所以对于不同的MCU,这部分需要移植。一旦这个问题解决了,整个OS算是成功了一半了,当然,是对于简单的OS。


  好了,要写一个OS,首先需要一个开发板和仿真器。我的开发板是STM32F4DISCOVERY,自带ST-LINK V2仿真器,板载MCU为STM32F407VGT6,支持FPU,32位ARM Cortex-M4F核,1024KB FLASH,192 KB RAM,总之很强大。对STM32其他系列,本OS几乎不需修改修改就可使用。开发环境为IAR for ARM 6.5,如果是MDK的话,也是大同小异,汇编部分需要修改。


  研究了一下UCOS-II的Cortex-M4的Port部分,觉得很好,就直接拿来用了,修改的很少。首先我们来看一下这一部分几个比较重要的函数,打开os_cpu_a.asm文件,定位到下面的地方,注释我改成中文了。当OS初始化完毕后,执行OSStart,OSStart最后调用OSStartHighRdy函数,注意在此之前的线程模式和异常模式的堆栈都是MSP,在此之后线程模式的堆栈是PSP,异常模式的堆栈仍是MSP。


OSStartHighRdy

    LDR     R0, =NVIC_SYSPRI14         ; 设置PendSV的异常中断优先级

    LDR     R1, =NVIC_PENDSV_PRI

    STRB    R1, [R0]


    MOVS    R0, #0                     ; 初始化PSP=0

    MSR     PSP, R0


    LDR     R0, =OS_CPU_ExceptStkBase  ; 初始化异常堆栈MSP地址

    LDR     R1, [R0]

    MSR     MSP, R1    


    LDR     R0, =OSRunning             ; 置OSRunning = TRUE

    MOVS    R1, #1

    STRB    R1, [R0]


    LDR     R0, =NVIC_INT_CTRL         ; 触发PendSV异常 (引起上下文切换)

    LDR     R1, =NVIC_PENDSVSET

    STR     R1, [R0]


    CPSIE   I                          ; 开启中断,于是进入PendSV异常


OSStartHang

    B       OSStartHang                ; 正常情况下,不应运行到这


  其中最核心的函数应该是OS_CPU_PendSVHandler了,它处理PendSV中断,完成上下文切换。


OS_CPU_PendSVHandler

    CPSID   I                              ; 关中断

    MRS     R0, PSP                        ; 获得PSP

    CBZ     R0, OS_CPU_PendSVHandler_nosave; PSP为0跳到OS_CPU_PendSVHandler_nosave,即不保存上文,直接进入下文。

                                           ; 问什么呢,因为首次调用,是没有上文的。

                                           ; 保存上文

    SUBS    R0, R0, #0x20                  ; 因为寄存器是32位的,4字节对齐,自动压栈的寄存器有8个,所以偏移为8*0x04=0x20

    STM     R0, {R4-R11}                   ; 除去自动压栈的寄存器外,需手动将R4-R11压栈


    LDR     R1, =OSTCBCur                  ; 保存上文的SP指针 OSTCBCur->OSTCBStkPtr = SP;

    LDR     R1, [R1]

    STR     R0, [R1]                                            


                                                                

OS_CPU_PendSVHandler_nosave                ; 切换下文

    PUSH    {R14}                          ; LR压栈,下面要调用C函数

    LDR     R0, =OSTaskSwHook              ; 调用OSTaskSwHook();

    BLX     R0

    POP     {R14}


    LDR     R0, =OSPrioCur                 ; 置OSPrioCur = OSPrioHighRdy;

    LDR     R1, =OSPrioHighRdy

    LDRB    R2, [R1]

    STRB    R2, [R0]


    LDR     R0, =OSTCBCur                  ; 置OSTCBCur  = OSTCBHighRdy;

    LDR     R1, =OSTCBHighRdy

    LDR     R2, [R1]

    STR     R2, [R0]


    LDR     R0, [R2]                       ; R0中的值为新任务的SP; SP = OSTCBHighRdy->OSTCBStkPtr;

    LDM     R0, {R4-R11}                   ; 手动弹出 R4-R11

    ADDS    R0, R0, #0x20

   

        

    MSR     PSP, R0                        ; PSP = 新任务SP

    ORR     LR, LR, #0x04                  ; 确保异常返回后使用PSP

    CPSIE   I

    BX      LR                             ; 退出异常,从PSP弹出xPSR,PC,LR,R0-R3,进入新任务运行    


  之后我们在此基础上构建自己的OS,首先完成两个任务互相调用,然后是加入SysTick的任务调度,最后加入信号量,邮箱等功能。


推荐阅读

史海拾趣

High Tech Chips Inc公司的发展小趣事

机顶盒,全称为数字视频变换盒,是连接电视机与外部信号源的重要设备,具有高度的专业性和广泛的应用性。它不仅能接收来自有线电缆、卫星天线、宽带网络及地面广播的数字电视信号,还能将这些信号转换成适合在电视机上播放的格式,极大地丰富了用户的观看体验。

机顶盒分为数字机顶盒和网络机顶盒两大类。数字机顶盒主要实现数模转换功能,使用户能用原有的模拟电视机观看数字电视,包括有线电视、卫星电视和地面广播电视的数字机顶盒。而网络机顶盒则进一步扩展了功能,能接入互联网,提供如IPTV、视频点播、在线游戏、网页浏览等多元化服务,使电视机转变为一个智能互动终端。

机顶盒的工作原理涵盖接收、解码和显示三个关键步骤。通过内置的调谐器接收信号,解调器将信号从载波中提取,解码器再将信号转换为电视可识别的视频和音频流,最终通过电视机呈现给用户。随着技术的不断进步,机顶盒的功能也在不断升级,如支持4K、8K超高清视频播放,搭载智能推荐算法提供个性化内容推荐,以及通过语音识别技术实现便捷操作等。

综上所述,机顶盒作为连接电视与互联网的重要桥梁,其专业性和科普性不言而喻。它不仅为用户提供了丰富多彩的电视节目和娱乐选择,还推动了电视产业的智能化发展,成为现代家庭不可或缺的一部分。

Gentron Corp公司的发展小趣事
检查LED、计数器、定时器等元件的连接是否正确,有无短路或断路现象。
Amphenol RF公司的发展小趣事
如果某个LED不亮或闪烁异常,可能是LED本身损坏,需要更换新的LED。
国芯佳品公司的发展小趣事
在广告牌或指示牌上使用顺序闪光的LED灯,吸引注意力并传递信息。
BOT公司的发展小趣事

广西来宾电厂是中国第一个国家正式批准的BOT试点项目。该项目由法国电力国际和通用电气阿尔斯通公司作为项目公司的主要股东,总投资为6.16亿美元。这个电厂的装机规模为72万千瓦,安装了两台36万千瓦的进口燃煤机组。在长达18年的特许经营期内,该项目为广西地区提供了稳定的电力供应,同时也为项目公司带来了可观的投资回报。随着时间的推移,该项目成为了BOT模式在中国成功应用的典范,为后来的类似项目提供了宝贵的经验。

Elpakco Inc公司的发展小趣事

Elpakco Inc公司的创立,源于创始人对电子行业未来趋势的敏锐洞察。在电子科技日新月异的时代,创始人凭借在半导体封装领域的丰富经验和深厚技术积累,决定创立一家专注于高精度电子元件封装的公司。初创时期,资金紧张、技术难度大、市场竞争激烈,但创始人带领团队夜以继日地研发,不断突破技术瓶颈,终于成功研制出第一款高精度、高可靠性的电子封装产品,为公司的发展奠定了坚实的基础。

问答坊 | AI 解惑

女工程师在各大名企求职80天的经历(一)

作者:从11月初回到深圳,就开始着手找工作,拖到05年1月,80天的奔波和忐忑不安的心理终于告一段落。期间面试了好几家公司,有惊喜有失望有抱怨甚至对自己的怀疑,但是我顽固的执着终于有了回报,得到了想要的工作。其中的甘苦与大家分享、共勉, ...…

查看全部问答>

电子设计 (遥控车)

本帖最后由 paulhyde 于 2014-9-15 08:54 编辑 有人猜测会有遥控车的题目 就跟大家分享一下  …

查看全部问答>

求指导

本帖最后由 paulhyde 于 2014-9-15 09:40 编辑 有人知道ad811芯片怎么搭建才能实现功能吗,datasheet上的电路好像不行  …

查看全部问答>

摇摇棒制作

网上这些东西都比较多了,今天也把我做的东东跟大家共享一下,前些日子就送给女朋友了。所以没有照片,真不好意思,这里有原理图,源程序(c语言),和去摸软件,可以自由更换源代码,对于初学单片机的人来说无疑是个不错的选择,而且可以把作品送 ...…

查看全部问答>

生成NK.nb0的大小(CE6.0)

能否让Nk.Nb0的大小自动变化? 现在我的NK.NB0大小都一定会等于config.bib文件中定义的大小。 里边的ROMSIZE等于多大,NK.NB0就一定是多大。 请教…

查看全部问答>

关于对数据总线操作的问题

最近写了个应用程序对数据总线上的数据进行操作,关于物理地址和虚拟地址的映射我知道 假设*vi_adress为映射好的虚拟地址 先是写操作 *vi_adress=tmp  (tmp是数据) 这个操作是成功的 现在我想读取外面从过来的数据 tmp=*vi_adress& ...…

查看全部问答>

Wince 5.0 如何实现 AlphaBlend?

Wince 5.0 如何实现 AlphaBlend? Requirements OS Versions: Microsoft? Windows CE? 5.0 and later. Header: Windows.h. Link Library: Coredll.lib. 加入以上 lib后,编译仍出错。 应如何处理,找了些算法来代替,但速度太慢。 谢谢。…

查看全部问答>

问一个比较傻子的问题!硬件中断如何跳转到软件代码

偶菜鸟, 问一个傻子问题,硬件中断如何跳转到软件代码 例如,我有一个键盘,按一下, CPU是如何通过中断服务程序跳转到程序中的代码中? …

查看全部问答>

像迷一样的问题

想控制驱动程序,使用 CreateFile 取驱动句柄, 为什么有些驱动程序能够取到,有些取不到?驱动名称和路径是肯定正确的。 比较了代码,也没找出什么区别。 关键在哪里? 请高手帮助一下。 谢谢 。…

查看全部问答>

wince 图形绘制问题

不知道wince 支持 DirectX么? 支持 gdi+么? 各位大虾:不知道wince上,你们是怎么绘制图形?…

查看全部问答>