Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
arm
内核
从裸机到rtt任务切换有感
发布于 2023-01-13 16:07:16 浏览:1063
订阅该版
闲来无事,作为第一次使用实时操作系统的小白想看看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
rt-thread的学习疑惑
6
基于stm32的RTT在RTT Studio IDE环境中的启动顺序求解
7
关于 rt_object_detach 脱离内核对象函数的作用求解
8
RT-Thread内核什么时候考虑加入MPU功能?
9
rt_hw_board_init中开中断后,触发SysTick_Handler
10
Cortex-M0在bootloader环境下的上下文切换问题?
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
机器人操作系统 (ROS2) 和 RT-Thread 通信
4
国产MCU移植系列教程汇总,欢迎查看!
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
串口
LWIP
SPI
Env
Bootloader
AT
ART-Pi
Hardfault
CAN总线
FinSH
USB
文件系统
DMA
RT-Thread
SCons
线程
RT-Thread Nano
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
ota在线升级
WIZnet_W5500
I2C_IIC
UART
flash
cubemx
packages_软件包
freemodbus
PWM
潘多拉开发板_Pandora
定时器
ADC
BSP
中断
编译报错
socket
keil_MDK
GD32
MicroPython
msh
Debug
ulog
SFUD
flashDB
SDIO总线
rt_mq_消息队列_msg_queue
本月问答贡献
用户名由3_15位
18
个答案
3
次被采纳
xiaorui
7
个答案
3
次被采纳
sakumisu
4
个答案
3
次被采纳
踩姑娘的小蘑菇
15
个答案
2
次被采纳
三世执戟
32
个答案
1
次被采纳
本月文章贡献
比特饼干
3
篇文章
8
次点赞
Z_Y
2
篇文章
5
次点赞
Alipay
2
篇文章
3
次点赞
xusiwei1236
2
篇文章
3
次点赞
yinxiangxv
2
篇文章
3
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部