Add code comments #2

Merged
xzb merged 1 commits from feature/mutil_thread into master 2 years ago
  1. 4
      Core/Src/main.c
  2. 2
      thead/inc/thread.h
  3. 19
      thead/src/context_switch.s
  4. 30
      thead/src/thread.c

4
Core/Src/main.c

@ -58,7 +58,7 @@ void prosee1(void *data)
while(1) while(1)
{ {
__disable_irq(); __disable_irq();
printf("prosee_%d\r\n", self->task_id); printf("prosee_%d, stack_ptr:%#x\r\n", self->task_id, self->stack_ptr);
__enable_irq(); __enable_irq();
HAL_Delay(1000); HAL_Delay(1000);
} }
@ -70,7 +70,7 @@ void prosee2(void *data)
while(1) while(1)
{ {
__disable_irq(); __disable_irq();
printf("prosee_%d\r\n", self->task_id); printf("prosee_%d, stack_ptr:%#x\r\n", self->task_id, self->stack_ptr);
__enable_irq(); __enable_irq();
HAL_Delay(1000); HAL_Delay(1000);
} }

2
thead/inc/thread.h

@ -9,7 +9,7 @@ typedef struct tcb
{ {
uint32_t *stack_ptr; // 任务栈指针 uint32_t *stack_ptr; // 任务栈指针
uint32_t task_id; // 任务 ID uint32_t task_id; // 任务 ID
struct tcb * next; struct tcb * next; // 需要采用链表的方式记录任务栈
} tcb_t; } tcb_t;
void init_task(tcb_t *tcb, void (*task_entry)(void *), uint8_t *start_stack, void *arg); void init_task(tcb_t *tcb, void (*task_entry)(void *), uint8_t *start_stack, void *arg);

19
thead/src/context_switch.s

@ -1,10 +1,6 @@
; 文件名: context_switch.s
; 目标平台: ARM Cortex-M3/M4 (STM32)
; 工具链: ARM Compiler 6 (Keil MDK/ARMCLANG)
; 描述: 通过 PendSV 异常实现 RTOS 上下文切换
PRESERVE8 ; 强制栈按 8 字节对齐 (Cortex-M 硬件要求) PRESERVE8 ; 8 字节对齐
THUMB ; 使用 Thumb-2 指令集 THUMB ; 使用 Thumb 指令集
AREA |.text|, CODE, READONLY ; 定义代码段 AREA |.text|, CODE, READONLY ; 定义代码段
EXPORT PendSV_Handler ; 导出 PendSV_Handler 符号 EXPORT PendSV_Handler ; 导出 PendSV_Handler 符号
@ -12,8 +8,9 @@
IMPORT next_task ; 从 C 代码导入 next_task 指针 IMPORT next_task ; 从 C 代码导入 next_task 指针
IMPORT switch_to_next_task ; 从 C 代码导入 switch_to_next_task 函数 IMPORT switch_to_next_task ; 从 C 代码导入 switch_to_next_task 函数
PendSV_Handler PROC PendSV_Handler PROC
;-------------------------------------------------- ;--------------------------------------------------
; 1. 关闭中断(确保上下文切换原子性) ; 1. 关闭中断(确保不会被更高优先级任务打断)
;-------------------------------------------------- ;--------------------------------------------------
CPSID I ; 禁用中断 (PRIMASK=1) CPSID I ; 禁用中断 (PRIMASK=1)
CPSID F ; 禁用快速中断 (FAULTMASK=1) CPSID F ; 禁用快速中断 (FAULTMASK=1)
@ -23,19 +20,21 @@ PendSV_Handler PROC
;-------------------------------------------------- ;--------------------------------------------------
LDR R1, = current_task ; 加载 current_task 的地址到 R1 LDR R1, = current_task ; 加载 current_task 的地址到 R1
LDR R1, [R1] ; 获取 current_task 指针的值(TCB地址) LDR R1, [R1] ; 获取 current_task 指针的值(TCB地址)
CBZ R1, switch_nosave ; 如果是系统的第一个运行任务,不需要保存 CBZ R1, switch_nosave ; 如果获取到底SP为空就不需要保存,并且跳转到switch_nosave函数
;-------------------------------------------------- ;--------------------------------------------------
; 3. 保存当前任务上下文(R4-R11 手动保存) ; 3. 保存当前任务上下文(R4-R11 手动保存)
; 硬件自动保存: R0-R3, R12, LR, PC, PSR (通过 PSP) ; 硬件自动保存: R0-R3, R12, LR, PC, PSR (通过 PSP)
;-------------------------------------------------- ;--------------------------------------------------
MRS R0, PSP ; 获取当前任务的栈指针 PSP MRS R0, PSP ; 获取当前任务的栈指针 PSP
STMFD R0!, {R4-R11} ; 将 R4-R11 压入任务栈(地址递增) STMFD R0!, {R4-R11} ; 将 R4-R11 压入任务栈(地址递增)
STR R0, [R1] STR R0, [R1] ; 将PSP保存进TCB的SP
switch_nosave switch_nosave
;-------------------------------------------------- ;--------------------------------------------------
; 4. 切换当前任务和下一个任务(调用 C 函数) ; 4. 切换当前任务和下一个任务(调用 C 函数)
;-------------------------------------------------- ;--------------------------------------------------
BL switch_to_next_task ; 调用 C 函数切换 current_task 和 next_task BL switch_to_next_task ; 调用 C 函数witch_to_next_task 获取下一个TCB
;-------------------------------------------------- ;--------------------------------------------------
; 5. 加载下一个任务的上下文 ; 5. 加载下一个任务的上下文

30
thead/src/thread.c

@ -5,12 +5,15 @@
#include "thread.h" #include "thread.h"
/***
// 声明任务指针(需在汇编中导入) 上下文切换的指针,如果触发了上下文切换,则next_task为下一个执行目标。
***/
tcb_t *current_task; tcb_t *current_task;
tcb_t *next_task; tcb_t *next_task;
// 切换任务的函数 /***
切换任务的函数,进行上下文切换的时候,会获取一下最新的任务指针。
***/
void switch_to_next_task(void) void switch_to_next_task(void)
{ {
tcb_t *temp = current_task; tcb_t *temp = current_task;
@ -18,6 +21,9 @@ void switch_to_next_task(void)
next_task = temp; next_task = temp;
} }
/***
启动切换,芯片上电默认执行的是main函数,需要切换到第一个任务上。
***/
void start_first_task(void) void start_first_task(void)
{ {
SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk; SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk;
@ -25,9 +31,15 @@ void start_first_task(void)
__ISB(); __ISB();
} }
/***
任务调度器,目前简单描写。采用循环执行任务策略, 后续优化方向:
1.采用任务优先级策略进行调度。
2.采用时间片调度。
3.采用信号量调度。
***/
tcb_t *task[2]; tcb_t *task[2];
uint8_t tcb_cunt = 0; uint8_t tcb_cunt = 0;
static uint8_t max_tcb = 0;
void tcb_scheduler(void) void tcb_scheduler(void)
{ {
if(tcb_cunt >= 1) if(tcb_cunt >= 1)
@ -41,7 +53,9 @@ void tcb_scheduler(void)
__ISB(); __ISB();
} }
/***
初始化任务,需要对栈初始化
***/
void init_task(tcb_t *tcb, void (*task_entry)(void *), uint8_t *start_stack, void *arg) void init_task(tcb_t *tcb, void (*task_entry)(void *), uint8_t *start_stack, void *arg)
{ {
// 栈顶对齐到 8 字节(硬件要求) // 栈顶对齐到 8 字节(硬件要求)
@ -53,14 +67,14 @@ void init_task(tcb_t *tcb, void (*task_entry)(void *), uint8_t *start_stack, voi
uint32_t *stack_top = (uint32_t*)((uint8_t*)tcb->stack_ptr + STACK_SIZE); uint32_t *stack_top = (uint32_t*)((uint8_t*)tcb->stack_ptr + STACK_SIZE);
stack_top = (uint32_t*)((uint32_t)stack_top & ~0x07); stack_top = (uint32_t*)((uint32_t)stack_top & ~0x07);
*(--stack_top) = 0x01000000; // xPSR (Thumb 模式) *(--stack_top) = 0x01000000; // xPSR
*(--stack_top) = (uint32_t)task_entry; // PC *(--stack_top) = (uint32_t)task_entry; // PC
*(--stack_top) = 0xDEADBEEF; // LR *(--stack_top) = 0xDEADBEEF; // LR
*(--stack_top) = 0x0000000C; // R12 *(--stack_top) = 0x0000000C; // R12
*(--stack_top) = 0x00000003; // R3 *(--stack_top) = 0x00000003; // R3
*(--stack_top) = 0x00000002; // R2 *(--stack_top) = 0x00000002; // R2
*(--stack_top) = 0x00000000; // R1 (参数) *(--stack_top) = 0x00000000; // R1
*(--stack_top) = (uint32_t)arg; // R0 *(--stack_top) = (uint32_t)arg; // R0 (参数)
for (int i = 0; i < 8; i++) for (int i = 0; i < 8; i++)
{ {

Loading…
Cancel
Save