RTOS之二环境搭建初识RTOS

参考:https://blog.csdn.net/kouxi1/article/details/123650688

视频:https://www.bilibili.com/video/BV1b14y1c783/

RTOS本质就是切换线程栈,栈换了环境就换了,一个重要的结构tcb(linux叫PCB或thread_info)

struct tcb{

int32_t *sp; // 重要的sp指针,其它寄存器保存在栈中

struct tcb *next; // 下一个tcb

};

采用Valvano教授的RoundRobin_4C123源码一张图解释线程调度

两个重要文件os.c osasm.s

  1. os.c

void StartOS(void);

#define NUMTHREADS 3 // maximum number of threads

#define STACKSIZE 100 // number of 32-bit words in stack

void SetInitialStack(int i){

tcbs[i].sp = &Stacks[i][STACKSIZE-16]; // thread stack pointer

//r0-r3 r12,LR XPSR发生中断时自动压栈

Stacks[i][STACKSIZE-1] = 0x01000000; // thumb bit xPSR

Stacks[i][STACKSIZE-3] = 0x14141414; // R14 LR

Stacks[i][STACKSIZE-4] = 0x12121212; // R12 ip

Stacks[i][STACKSIZE-5] = 0x03030303; // R3

Stacks[i][STACKSIZE-6] = 0x02020202; // R2

Stacks[i][STACKSIZE-7] = 0x01010101; // R1

Stacks[i][STACKSIZE-8] = 0x00000000; // R0

//r4-r11要求程序处理

Stacks[i][STACKSIZE-9] = 0x11111111; // R11

Stacks[i][STACKSIZE-10] = 0x10101010; // R10

Stacks[i][STACKSIZE-11] = 0x09090909; // R9

Stacks[i][STACKSIZE-12] = 0x08080808; // R8

Stacks[i][STACKSIZE-13] = 0x07070707; // R7

Stacks[i][STACKSIZE-14] = 0x06060606; // R6

Stacks[i][STACKSIZE-15] = 0x05050505; // R5

Stacks[i][STACKSIZE-16] = 0x04040404; // R4

}

void OS_Launch(uint32_t theTimeSlice){

STCTRL = 0; // disable SysTick during setup

STCURRENT = 0; // any write to current clears it

SYSPRI3 =(SYSPRI3&0x00FFFFFF)|0xE0000000; // priority 7

STRELOAD = theTimeSlice - 1; // reload value

STCTRL = 0x00000007; // enable, core clock and interrupt arm

StartOS(); // 第一次启动一个线程

}

void Scheduler(void){

RunPt = RunPt->next; // Round Robin

}

  1. osasm.s

SysTick_Handler ; 自动保存 R0-R3,R12,LR,PC,PSR

CPSID I ; Prevent interrupt during switch

PUSH {R4-R11} ; 保存 r4-r11在马上成为旧线程的sp中

LDR R0, =RunPt ; R0=pointer to RunPt, old thread

LDR R1, [R0] ; R1 = 当前线程,也马上成为旧线程

STR SP, [R1] ; 保存马上成为旧线程的sp到TCB

PUSH {R0,LR} ; Scheduler会改变r0, LR,所以先保存(发生中断时LR=0xfffffff9,以 后要通过它触发中断返回)

BL Scheduler 找到下一个新线程

POP {R0,LR} 恢复r0, LR,

LDR R1, [R0] ; R1 = 新线程

LDR SP, [R1] ; 新的线程的 SP = RunPt->sp;

POP {R4-R11} ; 恢复r4-r11从新的线程的sp中

CPSIE I ; 9) tasks run with interrupts enabled

BX LR ; 10) LR=0xfffffff9触发中断返回,恢复 R0-R3,R12,LR,PC,PSR(注意这里恢复的PC,PSR是任务函数task()对应的地方,BX LR 后执行的就是恢复的PC所指的task里面地方,这样就继续从task里面执行)

StartOS

//R0=pointer to RunPt, old thread伪指令,调试时发现r0=0x0000044

//runPt=0x0000054 而且0x0000054中的内容为tcb[0]

LDR R0, =RunPt ; currently running thread

LDR R2, [R0] ; R2 = value of RunPt

LDR SP, [R2] ; new thread SP; SP = RunPt->stackPointer;

POP {R4-R11} ; 恢复 regs r4-11

POP {R0-R3} ; 恢复 regs r0-3

POP {R12}

ADD SP,SP,#4 ; 第一次,不需要返回,丢弃LR

POP {LR} ; 把task()函数地址推送给LR

ADD SP,SP,#4 ;第一次,丢弃 PSR

CPSIE I ; Enable interrupts at processor level

BX LR ; start first thread

ALIGN

END

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值