|
楼主 |
发表于 2015-5-13 20:31:29
|
显示全部楼层
本帖最后由 worldsing 于 2015-5-13 20:33 编辑
- /*!
- *************************************************************************************
- *\file switch.h
- *\brief 简易的调度器
- * 1、轮番调度
- * 2、可以主动释放CPU
- * 3、用户的栈大小可自定义
- * 4、任务数可自定义
- *
- *\author worldsing
- *\version V0.01
- *\date 2015/04/24
- *
- *\b 1、去除C文件, 实现单个头文件代码结构
- * 2、目前仅在ST系列的Cortex-M3平台测试过
- *\li 2015/04/24
- * SWITCH_EN 宏须在创建任务的文件里定义
- *************************************************************************************
- */
- #ifndef __SWITCH_H__
- #define __SWITCH_H__
- //------------------------------------------------------------------------------------
- // Include File
- //------------------------------------------------------------------------------------
- #include <stm32f10x.h>
- #include <core_cm3.h>
- #include <stdint.h>
- #include <stdbool.h>
- //------------------------------------------------------------------------------------
- // Function declare
- //------------------------------------------------------------------------------------
- void switchDelayMs(uint16_t nTick);
- //------------------------------------------------------------------------------------
- // Switch code
- //------------------------------------------------------------------------------------
- #ifdef SWITCH_EN
- __asm void setPSP(uint32_t topOfProcStack)
- {
- msr psp, r0
- bx lr
- }
-
- __asm void taskSwitch(void)
- {
- LDR R0, =0xE000ED22
- LDR R1, =0xFF
- STRB R1, [R0]
- LDR R0, =0xE000ED04
- LDR R1, =0x10000000
- STR R1, [R0]
- BX LR
- ALIGN
- }
- __asm void PendSV_Handler(void)
- {
- IMPORT taskRuning
- IMPORT taskNew
- CPSID I
- MRS R0, PSP
- CBZ R0, NoSave
- SUBS R0, R0, #0x20
- STM R0, {R4-R11}
- LDR R1, =taskRuning
- LDR R1, [R1]
- STR R0, [R1]
-
- NoSave
- LDR R0, =taskRuning
- LDR R1, =taskNew
- LDR R2, [R1]
- STR R2, [R0]
- LDR R0, [R2]
- LDM R0, {R4-R11}
- ADDS R0, R0, #0x20
- MSR PSP, R0
- ORR LR, LR, #0x04
- CPSIE I
- BX LR
- ALIGN
- }
- #define SWITCH_CONFIG(MAX_TASK, N_TICK_IN_SECOND, SYSTEM_CLK_NMHZ, \
- SYS_TICK_HOOK, IDLE_HOOK); \
- \
- typedef struct { \
- uint32_t *pTaskStack; \
- uint16_t delay; \
- }TCB; \
- \
- TCB taskTCB[MAX_TASK + 1] = {0}; \
- \
- TCB *taskNew, *taskRuning; \
- \
- uint8_t taskCnt = 0; \
- uint8_t nTask; \
- \
- void taskIdle(void) { \
- while(1){ \
- IDLE_HOOK(); \
- __nop(); \
- } \
- } \
- void SysTick_Handler (void) { \
- uint8_t i; \
- bool bOneSwitch; \
- SYS_TICK_HOOK(); \
- bOneSwitch = false; \
- for(i = 0; i < nTask; i++){ \
- if(taskTCB[i].delay != 0){ \
- taskTCB[i].delay--; \
- } \
- if(bOneSwitch == false){ \
- taskCnt %= nTask; \
- if(0 == taskTCB[taskCnt].delay){ \
- bOneSwitch = true; \
- taskNew = &taskTCB[taskCnt]; \
- } \
- taskCnt++; \
- } \
- } \
- if(bOneSwitch == false) \
- taskNew = &taskTCB[nTask]; \
- taskSwitch(); \
- } \
- \
- \
- void switchDelayMs(uint16_t nTick) { \
- uint8_t i; \
- if(0 == nTick) \
- return; \
- \
- taskRuning->delay = nTick; \
- for(i = 0; i < nTask; i++){ \
- \
- if(0 == taskTCB[taskCnt].delay){ \
- taskNew = &taskTCB[taskCnt++]; \
- break; \
- }else taskCnt++; \
- } \
- if(taskRuning == taskNew) \
- taskNew = &taskTCB[nTask]; \
- taskSwitch(); \
- } \
- \
- \
- void switchTaskInt(void (*task)(void), uint32_t *ptos) { \
- if(MAX_TASK + 1 <= taskCnt){ \
- taskCnt = 0; \
- return; \
- } \
- *(ptos) = (uint32_t)0x01000000L; \
- *(--ptos) = (uint32_t)task; \
- taskTCB[taskCnt++]. pTaskStack = ptos -14; \
- } \
- \
- \
- void switchStart(void){ \
- switchTaskCreate(taskIdle, 256); \
- if(taskCnt < (MAX_TASK + 1)) \
- nTask = taskCnt; \
- else \
- nTask = MAX_TASK; \
- setPSP(0); \
- SysTick_Config((SYSTEM_CLK_NMHZ / N_TICK_IN_SECOND) - 1); \
- while(1); \
- }
- #define switchTaskCreate(task, stackSize) {__align(8) static uint32_t task##Stack[stackSize / 4]; \
- switchTaskInt(task, &task##Stack[(stackSize/4)-1]); \
- }
- #endif
- //------------------------------------------------------------------------------------
- // Demo code
- //------------------------------------------------------------------------------------
- #if(0)
- #define SWITCH_EN
- #include "switch.h"
- void tickHook(void)
- {
- //不得放入阻塞\复杂\死循环代码
- }
-
- void idleHook(void)
- {
-
- }
- //配置参数:最大任务数 1秒Tick数 系统时钟 时钟钩子 空闲钩子
- SWITCH_CONFIG(2, 100, 72000000, tickHook, idleHook);
-
- void task0(void){ //任务0
- for(;;){
- //这放入您的代码
- switchDelayMs(200); //可用delay()释放CPU
- }
- }
-
- void task1(void){ //任务1
- for(;;){
- //这放入您的代码
- switchDelayMs(1); //可用delay()释放CPU
- }
- }
-
- int main(void){
- switchTaskCreate(task0, 60); //在调度前建立任务
- switchTaskCreate(task1, 30); //在调度前建立任务
- switchStart(); //开始调度
- }
- #endif
- #endif
- //------------------------------------------------------------------------------------
- // End of file
- //------------------------------------------------------------------------------------
-
复制代码 |
|