完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
1、滴答定时器SysTick
滴答定时器是一个24位的倒计数定时器,当计到0时,将从RELOAD寄存器中自动重装载定时器初值,只要不把它在systick控制以及状态寄存器中的使能位清零,就将永久不息。systick的最大使命,就是定期地产生异常请求作为系统的时基。OS都需要这种“滴答”来推动任务和时间的管理。 我们在移植UCOSII的过程中就要使用滴答定时器来作为系统时钟,首先就是对滴答定时器的设置,主要是设置它的定时周期,在delay_init()函数中完成滴答定时器设置,delay_init()函数代码如下。 其中红色代码部分就是在使用UCOSII时配置systick的代码,如果SYSTEM_SUPPORT_UCOS被定义了就说明使用了UCOS操作系统,那么我们就需要配置systick。首先要根据UCOSII中的定义的OS_TICKS_PER_SEC来计算出systick的装载值reload,开启systick中断,将reload值写进systick的LOAD寄存器中,最后开启systick。 开启systick后还要编写systick的中断服务函数SysTick_Handler(),函数代码如下,同样也采用了条件编译。 2、os_cpu.a.asm文件详解 上面代码分为两部分,上半部分使用IMPORT来定义,下半部分使用EXPORT来定义。IMPORT定义表示这是一个外部变量的标号,不是在本程序定义的(可以理解为导入);EXPORT定义表示这些函数是在本文件中定义的,供其他文件调用(可以理解为导出)。 EQU和C语言中的#define一样,定义一个宏。NVIC_INT_CTRL为中断控制寄存器,地址为0xE000ED04;NVIC_SYSPRI2为系统优先级寄存器,地址为0xE000ED22;NVIC_PENDSV_PRI为PendSv和systick的中断优先级,这里为0xFFFF,都为最低优先级;NVIC_PENDSVSET可以触发软件中断,通过给中断控制寄存器(NVIC_INT_CTRL)的bit28写1来触发软件中断,因此NVIC_PENDSVSET为0x10000000. OS_CPU_SR_Save和OS_CPU_SR_Restore是开关中断的汇编代码,通过给PRIMASK写1来关中断,写0来打开中断。这里也可以使用CPS指令来快速的开关中断,我们在OS_CPU_SR_Save中就使用了CPSID I来关中断。 OSStartHighRdy是由OSStart()调用,用来开启多任务的,如果多任务开启失败的话就会进入OSStartHang。 OSCtxSw和OSIntCtxSw这两个是用来做任务切换的,这两个看起来都是一样的,其实他们都只是触发一个PendSv中断,具体的切换过程在PendSv中断服务函数里面进行。这两个函数看起来一样,但他们的意义是不同的,OSCtxSw是任务级切换,比如从任务A切换到任务B,OSIntCtxSw是中断级切换,是从中断退出时切换到一个任务中,从中断切换到任务时,CPU的寄存器入栈工作已经完成,无需做第二次。 上面的汇编代码才是真正的任务切换程序,在每行代码后面都有详细的注释,为了更好的理解我们对代码打标号的地方重点讲解一下。 ① 如果PSP为0的话说明是第一次做任务切换,而任务创建的时候会调用堆栈初始化函数OSTaskStkInit()来初始化堆栈,在初始化的过程中做了入栈处理,所以这里就不需要在做入栈处理,直接跳转到PendSv_Handler_Nosave. ② 此时SP指向的就是要运行的最高优先级的任务。 ③ 因为进入中断使用的是MSP,而退出中断的时候使用的是PSP,因此这里需要将LR的位2置1. 在UCOSII移植的时候说过要屏蔽stm32f10x.it.c文件中的PendSv_Handler()中断服务函数,原因就是我们在os_cpu_a.asm中重新定义了PendSv_Handler()函数,我们有时候在移植的时候可能会发现有OS_CPU_PendSVHandler这样的函数,其实就是官方移植使用到的,具体作用和PendSv_Handler一样都是PendSv的中断服务函数,不过ST官方启动文件startup_stm32f10x.hd.s中定义的PendSv中断服务函数为PendSv_Handler,所以说如果要使用OS_CPU_PendSVHandler作为PendSv的中断服务函数就需要修改启动文件startup_stm32f10x_hd.s中的中断向量表。 3、os_cpu.h文件详解 上面代码主要是定义了一些数据类型,在这里我们一定要注意OS_STK这个数据类型,我们在定义任务堆栈的时候就是定义OS_STK类型的,这是一个32的数据类型,按字节来算的话实际堆栈大小是我们定义的4倍。 上面代码中我们定义了堆栈的增长方向,任务级切换的宏定义OS_TASK_SW。如果OS_CRITICAL_METHOD被定义为3的话那么进出临界段的宏定义分别为OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL(),他们都是由汇编编写的。 4、os_cpu_c.c文件详解 os_cpu_c.c文件里面主要定义了几个钩子函数,这里我们就不具体讲解这些钩子函数了,我们主要来看一下OSTaskStkInit()这个函数,OSTaskStkInit()是堆栈初始化函数,该函数代码如下。 堆栈初始化函数OSTaskStkInit()是由任务创建函数OSTaskCreate()和OSTaskCreateExt()这两个函数调用的,用于在创建任务的时候初始化堆栈,从上面的代码中可以看出就是在任务堆栈中保存寄存器的值。 这里一定要注意入栈的顺序,硬件会自动将FPSCR, xPSR, PC, LR, R12, R0-R3这些寄存器入栈,这几个寄存器的入栈顺序我们在讲Stack frame的时候已经讲了。剩下的R4-R11就需要我们手动入栈了。 关于这几个文件的详细内容,参考源码。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1617 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1543 浏览 1 评论
977 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
683 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1595 浏览 2 评论
1863浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
644浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
515浏览 3评论
531浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
504浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-22 08:36 , Processed in 0.812365 second(s), Total 79, Slave 62 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号