ysyx学习:移植rt-thread

news/2025/10/17 23:05:04/文章来源:https://www.cnblogs.com/yuweijie/p/19133994

ysyx学习:移植rt-thread

OS中的上下文切换

上一期我们搞懂了yield-os.c的原理如何,我们理解 玩上下文切换的核心细节之后,我们可以把这些原理迁移到RT-Thread这个更大的操作系统中。
RT-Thread中有两个抽象层, 一个是BSP(Board Support Package), 另一个是libcpu。

负责把 RT-Thread 的线程结构(PCB)和抽象机器(AM)的上下文切换接口连接起来:调用处把目标/来源上下文地址临时放到线程的 user_data,触发 yield(),AM 回调读出这些信息并完成实际的上下文切换;另外还准备线程首次运行时的栈/参数(通过 kcontext)。

对于上下文的创建,需要先实现rt_uint8_t *rt_hw_stack_init(void *tentry, void *parameter, rt_uint8_t *stack_addr, void *texit)函数。

rt_uint8_t* rt_hw_stack_init(void* tentry, void* parameter, rt_uint8_t* stack_addr, void* texit) {stack_addr = (rt_uint8_t*)(((uintptr_t)stack_addr + sizeof(uintptr_t) - 1) & ~(sizeof(uintptr_t) - 1));stack_addr -= sizeof(temp_args); temp_args* args = (temp_args*)stack_addr; // 在栈上保存 入口 参数 出口 等信息// 设置参数args->tentry = (void (*)(void*))tentry;   // tentry是“接受一个 void* 参数、返回 void 的函数指针”args->parameter = parameter;args->texit = (void (*)(void))texit;      // texit是“不接受参数、返回 void 的函数指针”rt_uint8_t* c = (rt_uint8_t*)kcontext((Area){ stack_addr - sizeof(Area) , stack_addr }, (void*)wrap, args);return c;
}

一开始先对齐,然后拉出栈的位置,在栈上保存 入口 参数 出口 等信息,然后使用kcontext函数(详情见之前的随笔),将控制状态寄存器mepc设置为函数的地址,当你执行mret指令的时候就会跳转到该函数中去,因此会跳转到wrap中,附带参数args。

这个wrap()函数如下,这个是包裹函数,讲义中提到让包裹函数来调用tentry, 并在tentry返回后调用texit,T-Thread会保证代码不会从texit中返回,因此我这个代码这么写。
执行入口函数,并附带上参数,执行完之后执行退出函数。

void wrap(temp_args* args) {args->tentry(args->parameter);args->texit();// 不应该执行于此,RT-Thread会保证代码不会从texit中返回while (1);
}

接下来来看main函数,main函数代码如下:

int main() {ioe_init();
#ifdef __ISA_NATIVE__// trigger the real initialization of IOE to// perform SDL initialization int this main thread with large stackio_read(AM_TIMER_CONFIG);
#endifextern void __am_cte_init();__am_cte_init();extern int entry(void);entry();return 0;
}

先初始化一下ioe外设,在调用__am_cte_init()函数初始化cte。

void __am_cte_init() {cte_init(ev_handler); 
} 

意思就是把__am_asm_trap赋值给mtvec,方便后面ecall的时候直接跳进去__am_asm_trap函数。
然后把ev_handler函数注册进回调函数中。

ev_handler函数如下:定义一个当前的线程,可以通过rt_thread_self()这个函数获取当前线程,再使用这个线程中的user_data,可以用current->user_data来使用他,为什么用这个呢,因为这个user_data它用于存放线程的私有数据, 这意味着RT-Thread中调度相关的代码必定不会使用这个成员, 因此它很适合我们用来传递fromto的信息,这里的from是当前线程,这个to是你要跳往的线程,这里的ev_handler是回调函数,当系统陷入yield的时候,执行完一些列操作(看以前的随笔)后会执行这个回调函数了。这个函数主要作用就是把当前上下文保存到from中然后利用to作为下一个上下文进行跳转。

static Context* ev_handler(Event e, Context* c) {rt_thread_t current;rt_ubase_t* para;switch (e.event) {case EVENT_YIELD:current = rt_thread_self();para = (rt_ubase_t*)current->user_data;rt_ubase_t from = para[0];rt_ubase_t to = para[1];if (from) {*((Context**)from) = c; //保存上下文到from中}c = *(Context**)to;  // 返回to作为下一个上下文break;case EVENT_IRQ_TIMER:return c;default:printf("Unhandled event ID = %d\n", e.event);assert(0);}return c;
}

具体怎么上下文的切换呢,看这两个函数void rt_hw_context_switch_to(rt_ubase_t to)//切换到to的上下文
void rt_hw_context_switch(rt_ubase_t from, rt_ubase_t to)//切换到to的上下文,又要保存当前上下文到from上。

void rt_hw_context_switch_to(rt_ubase_t to) {rt_ubase_t data[2];rt_thread_t current = rt_thread_self();rt_ubase_t temp_ud = current->user_data;   //保存原来的 from 和 todata[1] = to;current->user_data = (rt_ubase_t)data;yield();current->user_data = temp_ud;
}
void rt_hw_context_switch(rt_ubase_t from, rt_ubase_t to) {rt_ubase_t data[2];rt_thread_t current = rt_thread_self();rt_ubase_t temp_ud = current->user_data;   //保存原来的 from 和 todata[0] = from;data[1] = to;current->user_data = (rt_ubase_t)data;yield();current->user_data = temp_ud;
}

这两个函数实现起来基本差不多,使用刚刚的user_data保存完fromto之后将,切换线程,然后切换完之后再将原先的user_data数据还回去。

然后启动rt-thread,成功!!!

但是很奇怪,我每次输入完一行命令,下次那一行命令会多一个/>,之前貌似不会,不知道改了什么之后就会了。
image

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/939226.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

综合性题目

经典的项目可以在csdn或者博客园上面找到即可猜数字游戏 功能要求: 1. 计算机随机生成1-100的数字 2. 玩家有7次猜测机会 3. 每次猜测后提示"太大"或"太小" 4. 记录游戏历史并显示 5. 询问是否再…

实用指南:从入门到精通:Django的深度探索之旅

实用指南:从入门到精通:Django的深度探索之旅pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", &…

UML中9中数据流图总结

数据流图与9种UML图核心内容总结 在软件需求分析与系统设计领域,数据流图(Data Flow Diagram,DFD)和统一建模语言(Unified Modeling Language,UML)图是两类至关重要的建模工具。数据流图以直观的方式展现系统中…

两种树状数组

单点修改,区间查询树状数组,洛谷P3374 #include<bits/stdc++.h> using namespace std; const int N = 5e5 + 5; int n, m, a[N]; int chaxun(int n){int ans = 0;while(1){ans += a[n];int x = n & -n;n -…

斑马日记2025.10.17

​ 今天学习了const修饰成员函数和mutable关键字,还刷了一道关于看似简单的数学题,收获颇丰呢。 首先学习了const修饰成员函数部分,成员函数后放const,那么成员变量在里面就不能被改变, class Person { public: vo…

CF Global Round 29(#2147) 总结

CF Global Round 29(#2147) 总结 ​ A void solve() {int x,y;cin>>x>>y;if(x<y) return cout<<"2\n",void();--x;if(y<x&&y>1) return cout<<"3\n",vo…

详细介绍:C语言中#pragma的用法

详细介绍:C语言中#pragma的用法pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco&qu…

实用指南:Godot 城市模拟 – 003 根据不规则底面和高度,动态创建节点

实用指南:Godot 城市模拟 – 003 根据不规则底面和高度,动态创建节点2025-10-17 22:48 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: aut…

JAVA 中断处理

目录背景和价值一、什么时候需要发起中断?1. 用户主动取消操作2. 程序优雅关闭时终止后台线程3. 超时任务处理4. 协作式终止长期运行的任务二、中断异常(InterruptedException)的处理正确的处理方式:1. 如果线程可…

软件工程学习日志2025.10.17

今天深入复习了BP(Backpropagation)神经网络,作为深度学习的基础,其“前馈计算误差,反向传播梯度”的思想贯穿现代许多复杂模型。记录关键点以备回顾:核心思想:双向流动的信息• 前向传播:数据从输入层经隐藏层…

天黑了,睡觉

大家好,晚安啦,拜拜。

升鲜宝生鲜配送供应链管理系统---- 门店收银 POS 离线工作设计文档(支持线上线下一体化)---02

门店收银 POS 离线工作设计文档(支持线上线下一体化)📘 背景与目标 在门店运营中,POS 端(收银机/安卓终端)经常会遇到以下情况: • 网络中断(Wi-Fi、4G、服务器不可达); • 临时维护或总部系统升级; • 云…

2025.10.16NOIP模拟

T1.略 T2.略 T3.思路简单,细节出锅 注意:线段树左右端点有负数时,不要用(l+r)/2,应用(l+r)>>1 T4. n行m列的网格,每个格子有一个权值\(v_{i,j}\)(\(-1e9<=v_{i,j}<=1e9\))和一个指示方向,假设起点为\…

Python 基于Python开发的数据库同步检测工具

程序源码下载地址 https://gitee.com/ishouke/database-checker 数据库同步检测工具 适用环境 win11 Centos7 工具用途 同类型数据库比对,比较库,库表,库模式(针对opengauss)是否一致,比较库表记录数是否一致。 目…

Python 基于Python开发的数据库同步检测工具

程序源码下载地址 https://gitee.com/ishouke/database-checker 数据库同步检测工具 适用环境 win11 Centos7 工具用途 同类型数据库比对,比较库,库表,库模式(针对opengauss)是否一致,比较库表记录数是否一致。 目…

当AI学会进化:荣耀与用户的“共生式成长”新范式

「 在科技与人文的交汇处,荣耀始终坚信,真正的创新不应仅是参数的堆叠,更应是一场关于“人”的深刻对话。 」荣耀CEO李健反复提及“灵魂马车”哲学,将对人的关爱、智慧的激发与快乐的传递融为一体,这一理念正悄然…

VSCode的下载安装以及配置

一、下载VSCode 1. 打开VSCode官网 https://code.visualstudio.com2. download下载3.下载特别慢二. 解决VSCode下载速度特别慢 1. 单击右下角全部显示 我是用chrome浏览器,点击右下角的全部显示按钮,可以跳转到下载内…

2025年终极公众号排版神器排行榜 最新案例研究权威测评

2025年终极公众号排版神器排行榜 最新案例研究权威测评谁还在为公众号排版头疼?有一云AI直接让这个问题成为历史。这款被多家白皮书列为行业标杆的工具,正在重新定义内容创作的标准。看看那些头部自媒体账号的排版,…

NAS安装远程协作神器twake

Twake Twake是一款开源可自托管的团队协作平台,把聊天、任务、文档、会议四件套塞进一个工具箱模块 功能点 详细说明🗨️ 实时团队沟通 • 频道 / 私聊 / 群组聊天 • 全局消息搜索 • 文件拖拽上传(文档 / 图片…

把三门问题做成了"游戏"

代码:<html><head><meta charset="UTF-8"> <meta name="screen-orientation" content="landscape"> <meta name="viewport" content="widt…