当前位置:网站首页>RTT学习笔记8-RTT内核移植
RTT学习笔记8-RTT内核移植
2022-08-07 14:55:00 【Car12】
RTT 内核移植接口

CortexM系列的内核移植
1.关闭中断
;/*
; * rt_base_t rt_hw_interrupt_disable(void);
; */
rt_hw_interrupt_disable PROC ;PROC 伪指令定义函数
EXPORT rt_hw_interrupt_disable ;EXPORT 输出定义的函数,类似于 C 语言 extern
MRS r0, PRIMASK ; 读取 PRIMASK 寄存器的值到 r0 寄存器
CPSID I ; 关闭全局中断
BX LR ; 函数返回
ENDP ;ENDP 函数结束
2.打开中断
;/* ; * void rt_hw_interrupt_enable(rt_base_t level); ; */
rt_hw_interrupt_enable PROC ; PROC 伪指令定义函数
EXPORT rt_hw_interrupt_enable ; EXPORT 输出定义的函数,类似于 C 语言 extern
MSR PRIMASK, r0 ; 将 r0 寄存器的值写入到 PRIMASK 寄存器
BX LR ; 函数返回
ENDP ; ENDP 函数结束
3.线程栈初始化
rt_uint8_t *rt_hw_stack_init(void *tentry,
void *parameter,
rt_uint8_t *stack_addr,
void *texit)
{
struct stack_frame *stack_frame;
rt_uint8_t *stk;
unsigned long i;
/* 对传入的栈指针做对齐处理 */
stk = stack_addr + sizeof(rt_uint32_t);
stk = (rt_uint8_t *)RT_ALIGN_DOWN((rt_uint32_t)stk, 8);
stk -= sizeof(struct stack_frame);
/* 得到上下文的栈帧的指针 */
stack_frame = (struct stack_frame *)stk;
/* 把所有寄存器的默认值设置为 0xdeadbeef */
for (i = 0; i < sizeof(struct stack_frame) / sizeof(rt_uint32_t); i ++)
{
((rt_uint32_t *)stack_frame)[i] = 0xdeadbeef;
}
/* 根据 ARM APCS 调用标准,将第一个参数保存在 r0 寄存器 */
stack_frame->exception_stack_frame.r0 = (unsigned long)parameter;
/* 将剩下的参数寄存器都设置为 0 */
stack_frame->exception_stack_frame.r1 = 0; /* r1 寄存器 */
stack_frame->exception_stack_frame.r2 = 0; /* r2 寄存器 */
stack_frame->exception_stack_frame.r3 = 0; /* r3 寄存器 */
/* 将 IP(Intra-Procedure-call scratch register.) 设置为 0 */
stack_frame->exception_stack_frame.r12 = 0; /* r12 寄存器 */
/* 将线程退出函数的地址保存在 lr 寄存器 */
stack_frame->exception_stack_frame.lr = (unsigned long)texit;
/* 将线程入口函数的地址保存在 pc 寄存器 */
stack_frame->exception_stack_frame.pc = (unsigned long)tentry;
/* 设置 psr 的值为 0x01000000L,表示默认切换过去是 Thumb 模式 */
stack_frame->exception_stack_frame.psr = 0x01000000L;
/* 返回当前线程的栈地址 */
return stk;
}
3. 实现上下文切换
1) rt_hw_context_switch_to():没有来源线程,切换到目标线程,在调度器启动第一个线程的时候被调用。
2) rt_hw_context_switch():在线程环境下,从当前线程切换到目标线程。
3) rt_hw_context_switch_interrupt ():在中断环境下,从当前线程切换到目标线程。
- 在线程环境下,可以马上进行上下文切换;
- 而在中断环境下,需要等待中断处理函数完成之后才能进行切换。
3.1在 Cortex-M 上下文切换
线程A运行过程中产生PendSV中断,进入中断函数之前硬件保存当前线程的 PSR、PC、LR、R12、R3-R0 ,进入中断函数后软件/手动保存 R11~R4 寄存器,接下来恢复线程B的R11~R4 寄存器,退出中断,硬件完成线程B的 R0~R3、R12、LR、PC、PSR 寄存器
3.2只有目标线程,没有来源线程的线程切换
rt_hw_context_switch_to()
;/* ; * void rt_hw_context_switch_to(rt_uint32_t to); ; * r0 --> to ; * this fucntion is used to perform the first thread switch ; */
rt_hw_context_switch_to PROC
EXPORT rt_hw_context_switch_to
; r0 的值是一个指针,该指针指向 to 线程的线程控制块的 SP 成员
; 将 r0 寄存器的值保存到 rt_interrupt_to_thread 变量里
LDR r1, =rt_interrupt_to_thread
STR r0, [r1]
; 设置 from 线程为空,表示不需要从保存 from 的上下文
LDR r1, =rt_interrupt_from_thread
MOV r0, #0x0
STR r0, [r1]
; 设置标志为 1,表示需要切换,这个变量将在 PendSV 异常处理函数里切换的时被清零
LDR r1, =rt_thread_switch_interrupt_flag
MOV r0, #1
STR r0, [r1]
; 设置 PendSV 异常优先级为最低优先级
LDR r0, =NVIC_SYSPRI2
LDR r1, =NVIC_PENDSV_PRI
LDR.W r2, [r0,#0x00] ; read
ORR r1,r1,r2 ; modify
STR r1, [r0] ; write-back
; 触发 PendSV 异常 (将执行 PendSV 异常处理程序)
LDR r0, =NVIC_INT_CTRL
LDR r1, =NVIC_PENDSVSET
STR r1, [r0]
; 放弃芯片启动到第一次上下文切换之前的栈内容,将 MSP 设置启动时的值
LDR r0, =SCB_VTOR
LDR r0, [r0]
LDR r0, [r0]
MSR msp, r0
; 使能全局中断和全局异常,使能之后将进入 PendSV 异常处理函数
CPSIE F
CPSIE I
; 不会执行到这里
ENDP
3.2 从一个线程到另外一个线程的切换和中断内部的线程切换
rt_hw_context_switch()/ rt_hw_context_switch_interrupt()
;/* ; * void rt_hw_context_switch(rt_uint32_t from, rt_uint32_t to); ; * r0 --> from ; * r1 --> to ; */
rt_hw_context_switch_interrupt
EXPORT rt_hw_context_switch_interrupt
rt_hw_context_switch PROC
EXPORT rt_hw_context_switch
; 检查 rt_thread_switch_interrupt_flag 变量是否为 1
; 如果变量为 1 就跳过更新 from 线程的内容
LDR r2, =rt_thread_switch_interrupt_flag
LDR r3, [r2]
CMP r3, #1
BEQ _reswitch
; 设置 rt_thread_switch_interrupt_flag 变量为 1
MOV r3, #1
STR r3, [r2]
; 从参数 r0 里更新 rt_interrupt_from_thread 变量
LDR r2, =rt_interrupt_from_thread
STR r0, [r2]
_reswitch
; 从参数 r1 里更新 rt_interrupt_to_thread 变量
LDR r2, =rt_interrupt_to_thread
STR r1, [r2]
; 触发 PendSV 异常,将进入 PendSV 异常处理函数里完成上下文切换
LDR r0, =NVIC_INT_CTRL
LDR r1, =NVIC_PENDSVSET
STR r1, [r0]
BX LR
4.实现时钟节拍
void SysTick_Handler(void)
{
/* enter interrupt */
rt_interrupt_enter();
rt_tick_increase();
/* leave interrupt */
rt_interrupt_leave();
}
边栏推荐
- 哈希表 | 三数之和、四数之和 | 用`双指针法`最合适 | leecode刷题笔记
- [Principle of Database System] Chapter 3 BC Normal Form, Third Normal Form and Fourth Normal Form
- 【通信原理】第三章 -- 随机过程[下]
- 微信自动发卡机器人说明
- 【IROS 2019】RangeNet++: 快速准确的LiDAR语义分割
- php源码随机输出某个目录下的图片API
- Programming Experts in C Chapter 8 Why Programmers Can't Tell the Difference Between Halloween and Christmas 8.8 Software is more difficult than hardware
- C专家编程 第7章 对内存的思考 7.8 轻松一下---“Thing King”和“页面游戏”
- Summary of the open surface
- LeetCode 热题 HOT 100(5.最长回文子串)
猜你喜欢

Summary of the open surface

(imdb数据集)电影评论分类实战:二分类问题

小程序基础——全局配置_pages
![【Verilog】时序逻辑电路 -- 有限同步状态机[补充]](/img/fc/c0b2cef16cf9acdb8be3e838ba474b.png)
【Verilog】时序逻辑电路 -- 有限同步状态机[补充]
![[Principle of Database System] Chapter 4 Advanced Database Model: E/R Model and Its Design Rules and Constraints](/img/67/c6ee5068487bb812c8092fce7ad81c.png)
[Principle of Database System] Chapter 4 Advanced Database Model: E/R Model and Its Design Rules and Constraints

001_微服务框架学习分类总结

【通信原理】第四章 -- 信道

Based on RTL8201F Ethernet port 100M debugging notes in RK3566

俩日总结(【20】【21】)

【Verilog】组合逻辑电路 -- 程序设计及应用
随机推荐
AQS synchronization component - Semaphore (semaphore) analysis and case
win10 uwp 圆角按钮
03 【常用类型(下)】
03 "commonly used types (below)"
LeetCode 热题 HOT 100(8.三数之和)
微信小程序——video视频全屏展示
【数据库系统原理】第四章 高级数据库模型:E/R模型及其设计规则、约束
【通信原理】第三章 -- 随机过程[补充]
【PTA】L2-002 Deduplication of linked list (25 points)
The two day summary ([18], [19])
Browser working principle and practical study notes (1) Browser from a macro perspective
Chapter 8 C programming expert why programmers cannot distinguish where Halloween and Christmas 8.5 prototype fail
LeetCode HOT HOT 100 (5. Back to the longest text string)
[21天学习挑战赛——内核笔记](三)——Pinctrl介绍
【电工学(下)】部分基础概念整理
自动化测试、测试左移、精准测试,一次性说透
Hash table | The sum of three numbers, the sum of four numbers | The most suitable `double pointer method` | leecode brush notes
C专家编程 第8章 为什么程序员无法分清万圣节和圣诞节 8.9 如何进行强制类型转换,为何要进行类型强制转换
微信小程序——动态绑定多个class
哈希表 | 三数之和、四数之和 | 用`双指针法`最合适 | leecode刷题笔记