RTOS之二环境搭建初识RTOS
创始人
2024-05-25 09:37:14
0

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

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

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

相关内容

热门资讯

监控摄像头接入GB28181平... 流程简介将监控摄像头的视频在网站和APP中直播,要解决的几个问题是:1&...
Windows10添加群晖磁盘... 在使用群晖NAS时,我们需要通过本地映射的方式把NAS映射成本地的一块磁盘使用。 通过...
protocol buffer... 目录 目录 什么是protocol buffer 1.protobuf 1.1安装  1.2使用...
在Word、WPS中插入AxM... 引言 我最近需要写一些文章,在排版时发现AxMath插入的公式竟然会导致行间距异常&#...
修复 爱普生 EPSON L4... L4151 L4153 L4156 L4158 L4163 L4165 L4166 L4168 L4...
【PdgCntEditor】解... 一、问题背景 大部分的图书对应的PDF,目录中的页码并非PDF中直接索引的页码...
Fluent中创建监测点 1 概述某些仿真问题,需要创建监测点,用于获取空间定点的数据࿰...
educoder数据结构与算法...                                                   ...
MySQL下载和安装(Wind... 前言:刚换了一台电脑,里面所有东西都需要重新配置,习惯了所...
MFC文件操作  MFC提供了一个文件操作的基类CFile,这个类提供了一个没有缓存的二进制格式的磁盘...