王朝网络
分享
 
 
 

学习ARM开发(21)

王朝other·作者佚名  2006-03-10
宽屏版  字体: |||超大  

OS任务切换源程序分析

先要声明任务指针,因为后面需要使用。

//任务指针.

volatile TASK_TCB* volatile g_pCurrentTask = NULL;

volatile TASK_TCB* volatile g_pCurrentTask1 = NULL;

volatile TASK_TCB* volatile g_pCurrentTask2 = NULL;

接着就需要初始化这些任务栈,用下面的代码进行初始化,为了简单,全部使用内存地址操作的方式,当然后面会改成动态地分配内存的方式。代码如下:

///////////////////////////////////////////////////////////////////////////////

//函数名称: TaskInitStack

//函数功能: 分配任务的栈。

//输入参数:

//输出参数:

//返 回 值:

//开发人员: 蔡军生

//时 间: 2006/02/26

//修改说明:

//

///////////////////////////////////////////////////////////////////////////////

void TaskInitStack(void)

{

g_pCurrentTask1 = (PTASK_TCB)0x0c700000;

g_pCurrentTask1->pStackStart = (UINT*)(0x0c700000+0x200);

g_pCurrentTask1->pStackTop = g_pCurrentTask1->pStackStart + 0x100;

g_pCurrentTask2 = (PTASK_TCB)(0x0c700000 + 0x400);

g_pCurrentTask2->pStackStart = (UINT*)(0x0c700000+0x400 + 0x200);

g_pCurrentTask2->pStackTop = g_pCurrentTask2->pStackStart + 0x100;

}

接着再创建两个简单的任务,它们都是输出一行字符串,就等待一会,代码如下:

//

void TaskTest1(void)

{

for(;;)

{

Lock();

puts("TaskTest1\n");

UnLock();

SoftDelay(100);

}

}

//

void TaskTest2(void)

{

for(;;)

{

Lock();

puts("TaskTest2\n");

UnLock();

SoftDelay(100);

}

}

然后再初始化任务栈,代码如下:

void TaskStart(void)

{

//

UINT* pTemp = g_pCurrentTask1->pStackTop;

//

*g_pCurrentTask1->pStackTop = (UINT)TaskTest1;

g_pCurrentTask1->pStackTop--;

*g_pCurrentTask1->pStackTop = (UINT)0x14141414; /* R14 */

g_pCurrentTask1->pStackTop--;

// *g_pCurrentTask1->pStackTop = (UINT)pTemp; /* R13 */

// g_pCurrentTask1->pStackTop--;

*g_pCurrentTask1->pStackTop = (UINT)0x12121212; /* R12 */

g_pCurrentTask1->pStackTop--;

*g_pCurrentTask1->pStackTop = (UINT)0x11111111; /* R11 */

g_pCurrentTask1->pStackTop--;

*g_pCurrentTask1->pStackTop = (UINT)0x10101010; /* R10 */

g_pCurrentTask1->pStackTop--;

*g_pCurrentTask1->pStackTop = (UINT)0x09090909; /* R9 */

g_pCurrentTask1->pStackTop--;

*g_pCurrentTask1->pStackTop = (UINT)0x08080808; /* R8 */

g_pCurrentTask1->pStackTop--;

*g_pCurrentTask1->pStackTop = (UINT)0x07070707; /* R7 */

g_pCurrentTask1->pStackTop--;

*g_pCurrentTask1->pStackTop = (UINT)0x06060606; /* R6 */

g_pCurrentTask1->pStackTop--;

*g_pCurrentTask1->pStackTop = (UINT)0x05050505; /* R5 */

g_pCurrentTask1->pStackTop--;

*g_pCurrentTask1->pStackTop = (UINT)0x04040404; /* R4 */

g_pCurrentTask1->pStackTop--;

*g_pCurrentTask1->pStackTop = (UINT)0x03030303; /* R3 */

g_pCurrentTask1->pStackTop--;

*g_pCurrentTask1->pStackTop = (UINT)0x02020202; /* R2 */

g_pCurrentTask1->pStackTop--;

*g_pCurrentTask1->pStackTop = (UINT)0x01010101; /* R1 */

g_pCurrentTask1->pStackTop--;

*g_pCurrentTask1->pStackTop = (UINT)0; /* R0 */

g_pCurrentTask1->pStackTop--;

*g_pCurrentTask1->pStackTop = (UINT)0x13; /* SPSR */

//

//

//

pTemp = g_pCurrentTask2->pStackTop;

//

*g_pCurrentTask2->pStackTop = (UINT)TaskTest2;

g_pCurrentTask2->pStackTop--;

*g_pCurrentTask2->pStackTop = (UINT)0x14141414; /* R14 */

g_pCurrentTask2->pStackTop--;

// *g_pCurrentTask2->pStackTop = (UINT)pTemp; /* R13 */

// g_pCurrentTask2->pStackTop--;

*g_pCurrentTask2->pStackTop = (UINT)0x12121212; /* R12 */

g_pCurrentTask2->pStackTop--;

*g_pCurrentTask2->pStackTop = (UINT)0x11111111; /* R11 */

g_pCurrentTask2->pStackTop--;

*g_pCurrentTask2->pStackTop = (UINT)0x10101010; /* R10 */

g_pCurrentTask2->pStackTop--;

*g_pCurrentTask2->pStackTop = (UINT)0x09090909; /* R9 */

g_pCurrentTask2->pStackTop--;

*g_pCurrentTask2->pStackTop = (UINT)0x08080808; /* R8 */

g_pCurrentTask2->pStackTop--;

*g_pCurrentTask2->pStackTop = (UINT)0x07070707; /* R7 */

g_pCurrentTask2->pStackTop--;

*g_pCurrentTask2->pStackTop = (UINT)0x06060606; /* R6 */

g_pCurrentTask2->pStackTop--;

*g_pCurrentTask2->pStackTop = (UINT)0x05050505; /* R5 */

g_pCurrentTask2->pStackTop--;

*g_pCurrentTask2->pStackTop = (UINT)0x04040404; /* R4 */

g_pCurrentTask2->pStackTop--;

*g_pCurrentTask2->pStackTop = (UINT)0x03030303; /* R3 */

g_pCurrentTask2->pStackTop--;

*g_pCurrentTask2->pStackTop = (UINT)0x02020202; /* R2 */

g_pCurrentTask2->pStackTop--;

*g_pCurrentTask2->pStackTop = (UINT)0x01010101; /* R1 */

g_pCurrentTask2->pStackTop--;

*g_pCurrentTask2->pStackTop = (UINT)0; /* R0 */

g_pCurrentTask2->pStackTop--;

*g_pCurrentTask2->pStackTop = (UINT)0x13; /* SPSR */

//设置首先运行的任务是1.

g_pCurrentTask = g_pCurrentTask1;

}

代码初始化了两个任务栈后,接着设置第一个任务为优先运行的任务。

最后就需要进行中断任务调度任务进行运行了,代码如下:

///////////////////////////////////////////////////////////////////////////////

//函数名称: EIntTickIsr

//函数功能: 时钟中断函数。

//输入参数:

//输出参数:

//返 回 值:

//开发人员: 蔡军生

//时 间: 2006/02/26

//修改说明:

//

///////////////////////////////////////////////////////////////////////////////

void EIntTickIsr(void) __attribute__((naked));

void EIntTickIsr(void)

{

//保存R0-R12寄存器到栈里.

asm volatile(" STMDB SP!, {R0-R12} ");

//关闭TICK中断.

INTMSK |= BIT_GLOBAL|BIT_TICK;

//取得保存IRQ的LR地址,并保存LR.

asm volatile (" LDR R0,=g_dwIRQLR" );

asm volatile (" SUBS LR,LR,#4 ");

asm volatile (" STR LR,[R0] ");

//取回前面保存的R0-R12寄存的值.

asm volatile (" LDMIA SP!, {R0-R12} ");

//取得最后返回的SPSR,就是SVC模式下的CPSR.

//从IRQ模式切换回到SVC模式.

asm volatile (" MRS LR,SPSR ");

asm volatile (" ORR LR,#0xc0 ");

asm volatile (" MSR CPSR,LR ");

//现在已经转换回到SVC模式,取回IRQ模式下保存的LR.

//把R0的值保存到栈中第二个位置.

asm volatile (" STR R0,[SP,#-8] ");

//从保存位置取回IRQ模式下保存的LR值.

asm volatile (" LDR R0,=g_dwIRQLR" );

asm volatile (" LDR R0,[R0] ");

//把IRQ模式下的LR保存到栈里,就是出栈时的PC值.

asm volatile (" STMDB SP!,{R0} ");

//从栈里第二个位置取回先前保存的R0值.

asm volatile (" SUBS SP,SP,#4 ");

asm volatile (" LDMIA SP!,{R0} ");

//保存R0-R12,LR到栈里,入栈顺序是刚好相反的.

asm volatile (" STMDB SP!,{R0-R12,LR} ");

//保存CPSR的值到栈里,就是SPSR的位置.

asm volatile (" MRS R4,CPSR ");

asm volatile (" BIC R4,#0xc0 ");

asm volatile (" STMDB SP!,{R4} ");

//保存栈顶到任务指针里.

asm volatile ( "LDR R0, %0" : : "m" (g_pCurrentTask) );

asm volatile ( "STR SP, [R0]" );

//增加时钟计数.

g_dwTickCount++;

//

printf("g_dwTickCount = (%d)\n",g_dwTickCount);

//

//清除屏蔽位.

I_ISPC = BIT_TICK;

INTMSK &= ~(BIT_GLOBAL|BIT_TICK);

//

if (g_dwTickCount < 3)

{

g_pCurrentTask = g_pCurrentTask1;

}

else if (g_dwTickCount < 4)

{

g_pCurrentTask = g_pCurrentTask2;

}

else

{

g_dwTickCount = 0;

}

//取得新任务指针

asm volatile ( "LDR R0, %0" : : "m" (g_pCurrentTask) );

asm volatile ( "LDR SP, [R0]" );

//取回SPSR值.

asm volatile ( "LDMIA SP!, {R0}" );

asm volatile ( "MSR SPSR, R0" );

//取回R0-R12,LR,PC值,并运行最后的任务.

asm volatile ( "LDMIA SP!, {R0-R12,LR,PC}^" );

}

写完上面的代码,就可以真正地实现了任务调度了。有了以上的代码,写其它复杂的任务调试都变得很容易了,这些代码得来是不太容易的,我经历了好几个星期的调试才通过的。

这些都是在我的S3C44B0开发板上调试通过的,如果你没有开发板,可以跟我购买。联系方法ccaimouse#gmail.com(请把#换成@)。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
>>返回首页<<
推荐阅读
 
 
频道精选
 
静静地坐在废墟上,四周的荒凉一望无际,忽然觉得,凄凉也很美
© 2005- 王朝网络 版权所有