diff --git a/Core/Src/main.c b/Core/Src/main.c
index 4cd0029..7efecd7 100644
--- a/Core/Src/main.c
+++ b/Core/Src/main.c
@@ -52,17 +52,35 @@ void Error_Handler(void)
}
}
-void prosee(void *data)
+void prosee1(void *data)
{
- printf("prosee1\r\n");
+ tcb_t *self = (tcb_t *)data;
while(1)
- {
+ {
+ __disable_irq();
+ printf("prosee_%d\r\n", self->task_id);
+ __enable_irq();
+ HAL_Delay(1000);
}
}
+void prosee2(void *data)
+{
+ tcb_t *self = (tcb_t *)data;
+ while(1)
+ {
+ __disable_irq();
+ printf("prosee_%d\r\n", self->task_id);
+ __enable_irq();
+ HAL_Delay(1000);
+ }
+}
+
+tcb_t tcb1;
+tcb_t tcb2;
+uint8_t statck[STACK_SIZE];
+uint8_t statck2[STACK_SIZE];
-tcb_t tcb;
-uint32_t statck[128];
int main(void)
{
__disable_irq();
@@ -70,16 +88,15 @@ int main(void)
SystemClock_Config();
MX_USART1_UART_Init();
printf("Init tasks\r\n");
- tcb.stack_ptr = statck;
- tcb.task_id = 1;
- init_task(&tcb,prosee, 0);
-
+ init_task(&tcb1, prosee1, statck, (void *)&tcb1);
+ init_task(&tcb2, prosee2, statck2, (void *)&tcb2);
+
/* run the first task */
start_first_task();
__enable_irq();
while(1)
{
- __NOP();
+ printf("idle\r\n");
};
}
diff --git a/Core/Src/stm32f1xx_it.c b/Core/Src/stm32f1xx_it.c
index 23788e5..89d376e 100644
--- a/Core/Src/stm32f1xx_it.c
+++ b/Core/Src/stm32f1xx_it.c
@@ -176,6 +176,7 @@ void SysTick_Handler(void)
/* USER CODE END SysTick_IRQn 0 */
HAL_IncTick();
+ tcb_scheduler();
/* USER CODE BEGIN SysTick_IRQn 1 */
/* USER CODE END SysTick_IRQn 1 */
diff --git a/MDK-ARM/TEST1.uvprojx b/MDK-ARM/TEST1.uvprojx
index e8cc8ca..61c28b6 100644
--- a/MDK-ARM/TEST1.uvprojx
+++ b/MDK-ARM/TEST1.uvprojx
@@ -10,7 +10,8 @@
TEST1
0x4
ARM-ADS
- 6140000::V6.14::ARMCLANG
+ 6220000::V6.22::ARMCLANG
+ 6220000::V6.22::ARMCLANG
1
@@ -137,7 +138,7 @@
4101
1
- BIN\UL2V8M.DLL
+ BIN\UL2CM3.DLL
"" ()
@@ -186,6 +187,7 @@
0
0
0
+ 0
0
0
8
@@ -669,11 +671,6 @@
<Project Info>
-
-
-
-
-
0
1
diff --git a/MDK-ARM/startup_stm32f103xb.s b/MDK-ARM/startup_stm32f103xb.s
index b2cdba8..db1fec6 100644
--- a/MDK-ARM/startup_stm32f103xb.s
+++ b/MDK-ARM/startup_stm32f103xb.s
@@ -30,7 +30,7 @@
; Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
;
-Stack_Size EQU 0x1000
+Stack_Size EQU 0x300
AREA STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem SPACE Stack_Size
@@ -41,7 +41,7 @@ __initial_sp
; Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
;
-Heap_Size EQU 0x1000
+Heap_Size EQU 0x300
AREA HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base
diff --git a/thead/inc/thread.h b/thead/inc/thread.h
index be7c47c..73f118b 100644
--- a/thead/inc/thread.h
+++ b/thead/inc/thread.h
@@ -3,14 +3,16 @@
#define __THREAD_H
#include
-typedef struct
+#define STACK_SIZE 512 // 每个任务的栈大小(按需调整)
+
+typedef struct tcb
{
uint32_t *stack_ptr; // 任务栈指针
uint32_t task_id; // 任务 ID
- // 其他成员:优先级、状态、等待事件等...
+ struct tcb * next;
} tcb_t;
-void init_task(tcb_t *tcb, void (*task_entry)(void *), void *arg);
+void init_task(tcb_t *tcb, void (*task_entry)(void *), uint8_t *start_stack, void *arg);
void start_first_task(void);
-
+void tcb_scheduler(void);
#endif
\ No newline at end of file
diff --git a/thead/src/context_switch.s b/thead/src/context_switch.s
index 4443729..42de634 100644
--- a/thead/src/context_switch.s
+++ b/thead/src/context_switch.s
@@ -17,22 +17,21 @@ PendSV_Handler PROC
;--------------------------------------------------
CPSID I ; 禁用中断 (PRIMASK=1)
CPSID F ; 禁用快速中断 (FAULTMASK=1)
-
+
+ ;--------------------------------------------------
+ ; 2. 更新当前任务的栈指针到 TCB
+ ;--------------------------------------------------
+ LDR R1, = current_task ; 加载 current_task 的地址到 R1
+ LDR R1, [R1] ; 获取 current_task 指针的值(TCB地址)
+ CBZ R1, switch_nosave ; 如果是系统的第一个运行任务,不需要保存
;--------------------------------------------------
- ; 2. 保存当前任务上下文(R4-R11 手动保存)
+ ; 3. 保存当前任务上下文(R4-R11 手动保存)
; 硬件自动保存: R0-R3, R12, LR, PC, PSR (通过 PSP)
;--------------------------------------------------
MRS R0, PSP ; 获取当前任务的栈指针 PSP
- SUBS R0, R0, #0x20 ; 预留空间保存 R4-R11 (8寄存器 * 4字节 = 0x20)
- STMIA R0!, {R4-R11} ; 将 R4-R11 压入任务栈(地址递增)
-
- ;--------------------------------------------------
- ; 3. 更新当前任务的栈指针到 TCB
- ;--------------------------------------------------
- LDR R1, =current_task ; 加载 current_task 的地址到 R1
- LDR R2, [R1] ; 获取 current_task 指针的值(TCB地址)
- STR R0, [R2] ; 将更新后的 PSP 保存到 TCB 的 stack_ptr 成员
-
+ STMFD R0!, {R4-R11} ; 将 R4-R11 压入任务栈(地址递增)
+ STR R0, [R1]
+switch_nosave
;--------------------------------------------------
; 4. 切换当前任务和下一个任务(调用 C 函数)
;--------------------------------------------------
@@ -41,7 +40,7 @@ PendSV_Handler PROC
;--------------------------------------------------
; 5. 加载下一个任务的上下文
;--------------------------------------------------
- LDR R1, =current_task ; 重新加载 current_task(此时已切换为新任务)
+ LDR R1, = current_task ; 重新加载 current_task(此时已切换为新任务)
LDR R2, [R1] ; 获取新任务的 TCB 地址
LDR R0, [R2] ; 从 TCB 中获取新任务的栈指针 PSP
diff --git a/thead/src/thread.c b/thead/src/thread.c
index dfacf2e..fd1b96e 100644
--- a/thead/src/thread.c
+++ b/thead/src/thread.c
@@ -25,318 +25,55 @@ void start_first_task(void)
__ISB();
}
-#define STACK_SIZE 512 // 每个任务的栈大小(按需调整)
+tcb_t *task[2];
-void init_task(tcb_t *tcb, void (*task_entry)(void *), void *arg)
+uint8_t tcb_cunt = 0;
+void tcb_scheduler(void)
{
- // 栈顶对齐到 8 字节(硬件要求)
- uint32_t *stack_top = (uint32_t*)((uint8_t*)tcb->stack_ptr + STACK_SIZE);
- stack_top = (uint32_t*)((uint32_t)stack_top & ~0x07);
-
- // 构造初始栈帧(模拟异常退出时的上下文)
- *(--stack_top) = 0x01000000; // xPSR (Thumb 模式)
- *(--stack_top) = (uint32_t)task_entry; // PC (任务入口)
- *(--stack_top) = 0xDEADBEEF; // LR (通常无意义,但需占位)
- *(--stack_top) = 0x0000000C; // R12
- *(--stack_top) = 0x00000003; // R3
- *(--stack_top) = 0x00000002; // R2
- *(--stack_top) = (uint32_t)arg;// R1 (参数)
- *(--stack_top) = 0x00000000; // R0
-
- // 手动保存的寄存器(R4-R11)初始值(通常为0)
- for (int i = 0; i < 8; i++)
+ if(tcb_cunt >= 1)
{
- *(--stack_top) = 0x00000000; // R4-R11
- }
-
- // 保存栈顶到 TCB
- tcb->stack_ptr = stack_top;
-}
-
-#if 0
-void trigger_context_switch(void)
-{
- SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk; // ?? PendSV ???
- __DSB(); // ??????
- __ISB(); // ??????
-}
-
-#define STACK_SIZE 32
-
-
-struct exception_stack_frame
-{
- uint32_t r0;
- uint32_t r1;
- uint32_t r2;
- uint32_t r3;
- uint32_t r12;
- uint32_t lr;
- uint32_t pc;
- uint32_t psr;
-};
-
-typedef struct
-{
- /* r4 ~ r11 register */
- uint32_t r4;
- uint32_t r5;
- uint32_t r6;
- uint32_t r7;
- uint32_t r8;
- uint32_t r9;
- uint32_t r10;
- uint32_t r11;
- struct exception_stack_frame exception_stack_frame;
-}stack_frame_t;
-
-
-struct Thread {
- unsigned long ip;
- unsigned int *sp;
-};
-
-typedef struct PCB {
- struct Thread thread;
- int pid;
- volatile long state; /* -1 idle, 0 runnable */
- uint32_t stack[STACK_SIZE];
- struct PCB *next;
-} tPCB;
-
-static tPCB task[MAX_TASK_NUM];
-static tPCB *current_task = NULL;
-static uint32_t *current_task_sp = NULL;
-static uint32_t *next_task_sp = NULL;
-
-
-void tTaskRunFirst(void);
-void tTaskSwitch(void);
-void tTask_schedule(void);
-
-void my_process(void)
-{
- uint32_t i = 0;
- while (1) {
- i++;
- if (i % 1000000 == 0) {
- printf("this is process %d - \r\n", current_task->pid);
- }
+ tcb_cunt = -1;
}
-}
-
-#define RT_ALIGN_DOWN(size, align) ((size) & ~((align) - 1))
-void StackInit(tPCB * task, void (*entry)(void), unsigned int * stack_addr)
-{
- stack_frame_t * stack_frame;
- uint32_t *stk;
- unsigned long i;
-
- stk = stack_addr + sizeof(uint32_t);
- stk = (uint32_t *)RT_ALIGN_DOWN((uint32_t)stk, 8);
- stk -= sizeof(stack_frame_t);
- stack_frame = (stack_frame_t *)stk;
-
- /* init all register */
- for (i = 0; i < sizeof(stack_frame_t) / sizeof(uint32_t); i ++)
- {
- ((uint32_t *)stack_frame)[i] = 0xdeadbeef;
- }
-
- stack_frame->exception_stack_frame.r0 = 0; /* r0 : argument */
- stack_frame->exception_stack_frame.r1 = 0; /* r1 */
- stack_frame->exception_stack_frame.r2 = 0; /* r2 */
- stack_frame->exception_stack_frame.r3 = 0; /* r3 */
- stack_frame->exception_stack_frame.r12 = 0; /* r12 */
- stack_frame->exception_stack_frame.lr = 0; /* lr */
- stack_frame->exception_stack_frame.pc = (unsigned long)entry; /* entry point, pc */
- stack_frame->exception_stack_frame.psr = 0x01000000L; /* PSR */
-
-}
-
-void tTaskInit(int task_num)
-{
- int i = 0;
-
- task[i].pid = i;
- task[i].state = 0;
- task[i].thread.ip = (unsigned long)my_process;
- task[i].thread.sp = &task[i].stack[STACK_SIZE - 1];
- task[i].next = &task[i];
- for (i = 1; i < task_num; i++) {
- task[i].pid = i;
- task[i].state = 0;
- task[i].thread.ip = (unsigned long)my_process;
- task[i].thread.sp = &task[i].stack[STACK_SIZE - 1];
- task[i].next = task[i - 1].next;
- task[i - 1].next = &task[i];
- StackInit(&task[i], my_process, task[i].stack);
- }
- current_task = &task[0];
- current_task_sp = (uint32_t *)__get_MSP();
-}
-
-
-void tTask_schedule(void)
-{
- current_task_sp = current_task->thread.sp;
- current_task = current_task->next;
- next_task_sp = current_task->thread.sp;
+ tcb_cunt++;
+ next_task = task[tcb_cunt];
SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk;
__DSB();
__ISB();
- return;
}
-void tTaskRunFirst(void)
-{
- tTask_schedule();
- __enable_irq();
- while(1);
-}
-// PendSV 쳣
-void PendSV_Handler(void)
+void init_task(tcb_t *tcb, void (*task_entry)(void *), uint8_t *start_stack, void *arg)
{
-
- extern unsigned int *next_task_sp;
- extern unsigned int *current_task_sp;
- __asm volatile (
- // жϣȷԭӲ
- "CPSID I\n"
-
- // current_task ĵַ R
- "LDR R0, = current_task_sp\n"
- "STR R0, [R0]\n"
-
- // 浱ǰ
- "MRS R1, MSP\n" // ջָ루MSP浽 R0
- "STMDB R1!, {R4-R11}\n" // ֶ R4-R11
-
-
-
-
- // лһ
- "LDR R1, = next_task_sp\n"
- "LDR R0, [R1]\n"
-
- // ָһ
- "LDMIA R0!, {R4-R11}\n" // ֶָ R4-R11
- "MSR MSP, R0\n" // ָջָд PSP
-
- // ж
- "CPSIE I\n"
-
- // 쳣
- "BX LR\n"
- );
-}
-
-/*
-void tTaskSwitch(void)
-{
- extern tPCB *current_task;
- extern tPCB *next_task;
-
- __asm volatile (
- "CPSID I\n"
- // R0 = current_task->thread.ip
- "LDR r0, =current_task\n" // current_task ĵַ r0
- "LDR r0, [r0]\n" // current_task ֵ r0
- "LDR r0, [r0, #4]\n" // current_task->thread.ip r0
-
- // PUSH {LR}
- "STMDB r0!, {lr}\n" // LRR14ѹջ r0
-
- // ˢ current_task->thread.ip
- "LDR r1, =current_task\n" // current_task ĵַ r1
- "LDR r1, [r1]\n" // current_task ֵ r1
- "STR r0, [r1, #4]\n" // º r0 洢 current_task->thread.ip
-
- // current_task = next_task
- "LDR r0, =current_task\n" // current_task ĵַ r0
- "LDR r1, =next_task\n" // next_task ĵַ r1
- "LDR r1, [r1]\n" // next_task ֵ r1
- "STR r1, [r0]\n" // next_task ֵ洢 current_task
-
- // R0 = next_task->thread.ip
- "LDR r0, =next_task\n" // next_task ĵַ r0
- "LDR r0, [r0]\n" // next_task ֵ r0
- "LDR r0, [r0, #4]\n" // next_task->thread.ip r0
-
- // POP {LR}
- "LDMIA r0!, {lr}\n" // r0 ָĵַ LRR14 r0
-
- // ˢ next_task->thread.ip
- "LDR r1, =next_task\n" // next_task ĵַ r1
- "LDR r1, [r1]\n" // next_task ֵ r1
- "STR r0, [r1, #4]\n" // º r0 洢 next_task->thread.ip
-
- // ת LR ָĵַ
- "BX lr\n" // ת LR ָĵַ
- );
-}
-
+ // 栈顶对齐到 8 字节(硬件要求)
+ static uint8_t tcb_id = 0;
+ task[tcb_id] = tcb;
+ tcb_id++;
+ tcb->task_id = tcb_id;
+ tcb->stack_ptr = (uint32_t *)start_stack;
+ uint32_t *stack_top = (uint32_t*)((uint8_t*)tcb->stack_ptr + STACK_SIZE);
+ stack_top = (uint32_t*)((uint32_t)stack_top & ~0x07);
-__asm void tTaskRunFirst(void)
-{
- IMPORT current_task
+ *(--stack_top) = 0x01000000; // xPSR (Thumb 模式)
+ *(--stack_top) = (uint32_t)task_entry; // PC
+ *(--stack_top) = 0xDEADBEEF; // LR
+ *(--stack_top) = 0x0000000C; // R12
+ *(--stack_top) = 0x00000003; // R3
+ *(--stack_top) = 0x00000002; // R2
+ *(--stack_top) = 0x00000000; // R1 (参数)
+ *(--stack_top) = (uint32_t)arg; // R0
- // R0 = current_task->thread.ip
- LDR R0, =current_task
- LDR R0, [R0]
- LDR R0, [R0, #4]
-
- // POP
- LDMIA R0!,{R14};
-
- // refresh current_task->thread.ip
- LDR R1, =current_task
- LDR R1, [R1]
- STR R0, [R1, #4]
+ for (int i = 0; i < 8; i++)
+ {
+ *(--stack_top) = 0x12345678; // R4-R11
+ }
+ tcb->stack_ptr = stack_top;
- BX R14
+ printf("init_tch:%d\r\n", tcb_id);
+ if(tcb_id == 1)
+ {
+ printf("start_tch:%d\r\n", tcb_id);
+ next_task = tcb;
+ }
}
-__asm void tTaskSwitch(void)
-{
- IMPORT current_task
- IMPORT next_task
-
- // R0 = current_task->thread.ip
- LDR R0, =current_task
- LDR R0, [R0]
- LDR R0, [R0, #4]
-
- // PUSH
- STMDB R0!, {R14};
-
- // refresh current_task->thread.ip
- LDR R1, =current_task
- LDR R1, [R1]
- STR R0, [R1, #4]
-
- // current_task = next_task;
- LDR R0, =current_task
- LDR R1, =next_task
- LDR R1, [R1]
- STR R1, [R0]
-
- // R0 = next_task->thread.ip
- LDR R0, =next_task
- LDR R0, [R0]
- LDR R0, [R0, #4]
-
- // POP
- LDMIA R0!,{R14};
-
- // refresh next_task->thread.ip
- LDR R1, =next_task
- LDR R1, [R1]
- STR R0, [R1, #4]
-
- BX R14
-}
-*/
-#endif