前言:2013年,时间有点富裕,就学习,查看CortexM3权威指南,并参照某些操作系统,
实现了最简单的时间片轮转和线程休眠一定时间(osDelayMS())。最近突然有想完善一下,增加了Mutex 和 进程间信息传递类似mailbox(协作式调度,以实现信息传递的快速)。并优化了任务调度。整个内核非常小巧,STM32F030F4P6 4K 内存,跑三个任务,还有将近2K内存,估计还可以跑3-4任务(TASK)应该没问题,而之前测试FreeRTOS,最多只能跑两个任务。闲话少说,开始正题:
基本知识:
cortex -M0,M3,M4 有16个寄存器,R0-R15,xPSR
你些的C代码,编译器会试用这些寄存器来进行各种运算,当有中断来的时候,ARM内核会自动依次将xPSR,PC,LR,R12,R0-R3压入堆栈,这就有意思了,操作系统每1ms来一次中断,这些寄存器不用管,只需要把R4-R11压入栈,然后指向新的TAS环境,从新的TASK栈里,把寄存器回复,于是,实现了任务的调度,每1ms(通常)来切换一下。当然,怎么切换,就是操作系统最核心的算法,那么,我们简单处理,来个时间片轮换调度,说干就干:
cortex里有个著名的sysTick中断,SysTick_Handler()CPU我先先用手头上的STM32F407VET6,
CUBEMX配置,
建立文件cpu.s
实现两个函数
PendSV_Handler (将中断文件里的此函数注释掉)
CPSID I ; Prevent interruption during context switch
; LDR R1,=TCBRunning ; @1 if here use R3,@2 can remove
; LDR R1,[R1] ; R1 == running tcb
LDR R3,=TCBRunning ; @1 if here use R3,@2 can remove
LDR R1,[R3] ; R1 == running tcb
LDR R2,=TCBNext
LDR R2,[R2] ; R2 == next tcb
CMP R1,R2
BEQ exitPendSV
MRS R0, PSP ; Get PSP point (can not use PUSH,in ISR,SP is MSP )
STMDB R0!,{R4-R11} ; Store r4-r11,r0 -= regCnt * 4,r0 is new stack
; top point (addr h->l r11,r10,...,r5,r4)
IF :DEF:M4FPU ;#if CFG_CHIP_TYPE == 3
VSTMDB R0!, {S16-S31} ;// store remaining FPU registers
ENDIF ;#endif // CFG_FPU_ENABLE
STR R0,[R1] ; Save orig PSP
popStk
;LDR R3,=TCBRunning ; @2
STR R2, [R3] ; TCBRunning = TCBNext;
LDR R0, [R2] ; Get SP of task that be switch into.
IF :DEF:M4FPU ;#if CFG_CHIP_TYPE == 3
VLDMIA R0!, {S16-S31} ;// load remaining FPU registers