借傻孩子老师的地盘发个小小调度器
/*!*************************************************************************************
*\file switch.h
*\brief 简易的调度器
* 1、轮番调度
* 2、可以主动释放CPU
* 3、用户的栈大小可自定义
* 4、任务数可自定义
*
*\authorworldsing
*\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
//------------------------------------------------------------------------------------
#ifdefSWITCH_EN
__asm void setPSP(uint32_t topOfProcStack)
{
msr psp, r0
bx lr
}
__asm void taskSwitch(void)
{
LDR R0, =0xE000ED22
LDR R1, =0xFF
STRB R1,
LDR R0, =0xE000ED04
LDR R1, =0x10000000
STR R1,
BX LR
ALIGN
}
__asm void PendSV_Handler(void)
{
IMPORTtaskRuning
IMPORTtaskNew
CPSID I
MRS R0, PSP
CBZ R0, NoSave
SUBS R0, R0, #0x20
STM R0, {R4-R11}
LDR R1, =taskRuning
LDR R1,
STR R0,
NoSave
LDR R0, =taskRuning
LDR R1, =taskNew
LDR R2,
STR R2,
LDR R0,
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 = {0}; \
\
TCB *taskNew, *taskRuning; \
\
uint8_ttaskCnt = 0; \
uint8_tnTask; \
\
void taskIdle(void) { \
while(1){ \
IDLE_HOOK(); \
__nop(); \
} \
} \
voidSysTick_Handler (void) { \
uint8_t i; \
bool bOneSwitch; \
SYS_TICK_HOOK(); \
bOneSwitch = false; \
for(i = 0; i < nTask; i++){ \
if(taskTCB.delay != 0){ \
taskTCB.delay--; \
} \
if(bOneSwitch == false){ \
taskCnt %= nTask; \
if(0 == taskTCB.delay){ \
bOneSwitch = true; \
taskNew = &taskTCB; \
} \
taskCnt++; \
} \
} \
if(bOneSwitch == false) \
taskNew = &taskTCB; \
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.delay){ \
taskNew = &taskTCB; \
break; \
}else taskCnt++; \
} \
if(taskRuning == taskNew) \
taskNew = &taskTCB; \
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. 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; \
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
//------------------------------------------------------------------------------------
本帖最后由 worldsing 于 2015-5-13 20:33 编辑
/*!
*************************************************************************************
*\file switch.h
*\brief 简易的调度器
* 1、轮番调度
* 2、可以主动释放CPU
* 3、用户的栈大小可自定义
* 4、任务数可自定义
*
*\authorworldsing
*\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
//------------------------------------------------------------------------------------
#ifdefSWITCH_EN
__asm void setPSP(uint32_t topOfProcStack)
{
msr psp, r0
bx lr
}
__asm void taskSwitch(void)
{
LDR R0, =0xE000ED22
LDR R1, =0xFF
STRB R1,
LDR R0, =0xE000ED04
LDR R1, =0x10000000
STR R1,
BX LR
ALIGN
}
__asm void PendSV_Handler(void)
{
IMPORTtaskRuning
IMPORTtaskNew
CPSID I
MRS R0, PSP
CBZ R0, NoSave
SUBS R0, R0, #0x20
STM R0, {R4-R11}
LDR R1, =taskRuning
LDR R1,
STR R0,
NoSave
LDR R0, =taskRuning
LDR R1, =taskNew
LDR R2,
STR R2,
LDR R0,
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 = {0}; \
\
TCB *taskNew, *taskRuning; \
\
uint8_ttaskCnt = 0; \
uint8_tnTask; \
\
void taskIdle(void) { \
while(1){ \
IDLE_HOOK(); \
__nop(); \
} \
} \
voidSysTick_Handler (void) { \
uint8_t i; \
bool bOneSwitch; \
SYS_TICK_HOOK(); \
bOneSwitch = false; \
for(i = 0; i < nTask; i++){ \
if(taskTCB.delay != 0){ \
taskTCB.delay--; \
} \
if(bOneSwitch == false){ \
taskCnt %= nTask; \
if(0 == taskTCB.delay){ \
bOneSwitch = true; \
taskNew = &taskTCB; \
} \
taskCnt++; \
} \
} \
if(bOneSwitch == false) \
taskNew = &taskTCB; \
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.delay){ \
taskNew = &taskTCB; \
break; \
}else taskCnt++; \
} \
if(taskRuning == taskNew) \
taskNew = &taskTCB; \
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. 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; \
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
//------------------------------------------------------------------------------------
STM32可用? 码一个,改天试试 来个压缩文件分享一下,谢谢! MARK.看看。。。。
楼主把汇编部分讲解下吧,汇编看起来太累!{:biggrin:} MARK之。。。坐等傻孩子点评!!! 果断小白鼠一下,帮顶~ 有空仔细研究一下 mark试试看 有时间试试,貌似不错。 楼主汇编看不懂啊,{:sweat:} 沉默胜过白金 发表于 2015-5-13 10:48
STM32可用?
可用{:smile:} LZ是转过来的吗{:lol:} xad74 发表于 2015-5-13 20:34
LZ是转过来的吗
欢迎找原文,找到有奖励。哈哈 embeddev_1 发表于 2015-5-13 14:09
楼主把汇编部分讲解下吧,汇编看起来太累!
大概的意思就是产生个软件异常中断,再切换任务栈。 creep 发表于 2015-5-13 11:22
来个压缩文件分享一下,谢谢!
没有细看帖子啊,整个调度器就一个头文件,还带demo还有什么好说的? LZ高人!虽然不懂汇编,还是要拿来玩一下。
页:
[1]