Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
arm
内核
从裸机到rtt任务切换有感
发布于 2023-01-13 16:07:16 浏览:1379
订阅该版
闲来无事,作为第一次使用实时操作系统的小白想看看rtthread的调度方式。 总结: 主要调度使用scheduler.c和context——gcc.s。 ```c void rt_system_scheduler_start(void) { register struct rt_thread *to_thread; rt_ubase_t highest_ready_priority; to_thread = _get_highest_priority_thread(&highest_ready_priority); rt_current_thread = to_thread; rt_schedule_remove_thread(to_thread); to_thread->stat = RT_THREAD_RUNNING; rt_hw_context_switch_to((rt_ubase_t)&to_thread->sp);//跳转至.s文件执行 } ```第一次会调用此函数用来执行一个.s文件 ```c rt_hw_context_switch_to: LDR r1, =rt_interrupt_to_thread STR r0, [r1] /*将rt_interrupt_to_thread写入一个sp指针待会会用到*/ /* set interrupt flag to 1 */ LDR r1, =rt_thread_switch_interrupt_flag MOV r0, #1 STR r0, [r1] ... LDR r0, =NVIC_INT_CTRL /* trigger the PendSV exception (causes context switch) */ LDR r1, =NVIC_PENDSVSET STR r1, [r0] /*NVIC_INT_CTRL为ICSR寄存器将28位置1会导致一个sv异常,任务切 换也在sv中进行*/ /* restore MSP */ LDR r0, =SCB_VTOR /*VTOR保存着内存地址偏移,取出偏移值赋值给msp寄存器*/ LDR r0, [r0] LDR r0, [r0] NOP MSR msp, r0 ... ``` 第一次触发的sv异常 ```c PendSV_Handler: /* disable interrupt to protect context switch */ MRS r2, PRIMASK CPSID I /* get rt_thread_switch_interrupt_flag */ LDR r0, =rt_thread_switch_interrupt_flag LDR r1, [r0] CBZ r1, pendsv_exit /* pendsv already handled */ /* clear rt_thread_switch_interrupt_flag to 0 */ MOV r1, #0x00 STR r1, [r0] LDR r0, =rt_interrupt_from_thread /* 第一次执行所以此函数我们并没有赋值所以会执行跳转 */ LDR r1, [r0] CBZ r1, switch_to_thread /* skip register save at the first time */ MRS r1, psp /* get from thread stack pointer */ STMFD r1!, {r4 - r11} /* push r4 - r11 register */ LDR r0, [r0] STR r1, [r0] /* update from thread stack pointer */ switch_to_thread: LDR r1, =rt_interrupt_to_thread /* 获取需要切换的任务的sp指针 */ LDR r1, [r1] LDR r1, [r1] /* load thread stack pointer */ LDMFD r1!, {r4 - r11} /* pop r4 - r11 register */ MSR psp, r1 /* update stack pointer */ /* 此时psp寄存器已指向我们目标任务的sp */ pendsv_exit: /* restore interrupt */ MSR PRIMASK, r2 ORR lr, lr, #0x04 BX lr ``` 在后续的轮转中我们会调用 ```c void rt_schedule(void) { rt_base_t level; struct rt_thread *to_thread; struct rt_thread *from_thread; /* disable interrupt */ level = rt_hw_interrupt_disable(); /* check the scheduler is enabled or not */ if (rt_scheduler_lock_nest == 0) { rt_ubase_t highest_ready_priority; if (rt_thread_ready_priority_group != 0) { /* need_insert_from_thread: need to insert from_thread to ready queue */ int need_insert_from_thread = 0; /*获取任务列表中优先级最高的我们假设有比当前任务更高的优先级执行39行,此时目标任务为高优先级任务*/ to_thread = _get_highest_priority_thread(&highest_ready_priority); ... if (to_thread != rt_current_thread) { /* if the destination thread is not the same as current thread */ /* 开始进行转换,首先将源任务设置为当前任务,再将当前任务设置为目标任务 */ rt_current_priority = (rt_uint8_t)highest_ready_priority; from_thread = rt_current_thread; rt_current_thread = to_thread; ... #ifdef RT_USING_OVERFLOW_CHECK _rt_scheduler_stack_check(to_thread); #endif if (rt_interrupt_nest == 0) { extern void rt_thread_handle_sig(rt_bool_t clean_state); /* 这句进行任务切换 */ rt_hw_context_switch((rt_ubase_t)&from_thread->sp, (rt_ubase_t)&to_thread->sp); /* enable interrupt */ rt_hw_interrupt_enable(level); goto __exit; } else { RT_DEBUG_LOG(RT_DEBUG_SCHEDULER, ("switch in interrupt\n")); rt_hw_context_switch_interrupt((rt_ubase_t)&from_thread->sp, (rt_ubase_t)&to_thread->sp); } } else { rt_schedule_remove_thread(rt_current_thread); rt_current_thread->stat = RT_THREAD_RUNNING | (rt_current_thread->stat & ~RT_THREAD_STAT_MASK); } } } /* enable interrupt */ rt_hw_interrupt_enable(level); __exit: return; } ``` ```c rt_hw_context_switch: /* set rt_thread_switch_interrupt_flag to 1 */ LDR r2, =rt_thread_switch_interrupt_flag LDR r3, [r2] CMP r3, #1 /* 没有设置interrupt_flag跳过执行 */ BEQ _reswitch /* 再次置1用于sv异常 */ MOV r3, #1 STR r3, [r2] /* 将源任务sp赋值给rt_interrupt_from_thread,此时from是有值的*/ LDR r2, =rt_interrupt_from_thread /* set rt_interrupt_from_thread */ STR r0, [r2] _reswitch: /* 将目标任务sp赋值给rt_interrupt_to_thread*/ LDR r2, =rt_interrupt_to_thread /* set rt_interrupt_to_thread */ STR r1, [r2] /* 再次进入sv异常处理 */ LDR r0, =NVIC_INT_CTRL /* trigger the PendSV exception (causes context switch) */ LDR r1, =NVIC_PENDSVSET STR r1, [r0] BX LR ``` 此时sv处理与上次相比多了一个源任务的r4-r11的压栈处理其他相同
2
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
陈再松
这家伙很懒,什么也没写!
文章
1
回答
0
被采纳
0
关注TA
发私信
相关文章
1
关于dlmodule的relocation问题
2
复旦微Z7芯片支持问题
3
RTT Cortex R5的移植有谁弄过没?
4
RT-Thread/S3C4510
5
【求助】app能否调用bootloader中的部分文件
6
RT thread支持Arm China Star-SE架构?
7
rt-thread的学习疑惑
8
基于stm32的RTT在RTT Studio IDE环境中的启动顺序求解
9
关于 rt_object_detach 脱离内核对象函数的作用求解
10
RT-Thread内核什么时候考虑加入MPU功能?
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
UART
WIZnet_W5500
ota在线升级
PWM
cubemx
flash
freemodbus
BSP
packages_软件包
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
编译报错
Debug
rt_mq_消息队列_msg_queue
SFUD
keil_MDK
msh
ulog
MicroPython
C++_cpp
本月问答贡献
出出啊
1517
个答案
342
次被采纳
小小李sunny
1444
个答案
290
次被采纳
张世争
812
个答案
177
次被采纳
crystal266
547
个答案
161
次被采纳
whj467467222
1222
个答案
148
次被采纳
本月文章贡献
出出啊
1
篇文章
1
次点赞
小小李sunny
1
篇文章
1
次点赞
张世争
1
篇文章
2
次点赞
crystal266
2
篇文章
2
次点赞
whj467467222
2
篇文章
2
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部