完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
扫一扫,分享给好友
帮顶。。。。
|
|
|
|
不会。。。。
|
|
|
|
//task1任务函数
void task1_task(void *p_arg) { u16 i; u8 task1_num=0; OS_ERR err; CPU_SR_ALLOC(); p_arg = p_arg; POINT_COLOR = BLACK; OS_CRITICAL_ENTER(); LCD_DrawRectangle(5,110,115,314); //画一个矩形 LCD_DrawLine(5,130,115,130);//画线 POINT_COLOR = BLUE; LCD_ShowString(6,111,110,16,16,"Task1 Run:000"); OS_CRITICAL_EXIT(); while(1) { task1_num++;//任务执1行次数加1 注意task1_num1加到255的时候会清零!! LED0= ~LED0; printf("任务1已经执行:%d次rn",task1_num); //if(task1_num==5) //{ //OSTaskDel((OS_TCB*)&Task2_TaskTCB,&err);//任务1执行5此后删除掉任务2 //printf("任务1删除了任务2!rn"); //} for(i=0;i<100;i++) { LCD_Fill(6,131,114,313,lcd_discolor[task1_num%14]); //填充区域 LCD_ShowxNum(86,111,task1_num,3,16,0x80);//显示任务执行次数 OSTimeDlyHMSM(0,0,0,10,OS_OPT_TIME_HMSM_STRICT,&err); //延时1s } } } |
|
|
|
//task2任务函数
void task2_task(void *p_arg) { u16 i; u8 task2_num=0; OS_ERR err; CPU_SR_ALLOC(); p_arg = p_arg; POINT_COLOR = BLACK; OS_CRITICAL_ENTER(); LCD_DrawRectangle(125,110,234,314); //画一个矩形 LCD_DrawLine(125,130,234,130);//画线 POINT_COLOR = BLUE; LCD_ShowString(126,111,110,16,16,"Task2 Run:000"); OS_CRITICAL_EXIT(); while(1) { task2_num++;//任务2执行次数加1 注意task1_num2加到255的时候会清零!! LED1=~LED1; printf("任务2已经执行:%d次rn",task2_num); for(i=0;i<1000;i++) { LCD_ShowxNum(206,111,task2_num,3,16,0x80); //显示任务执行次数 LCD_Fill(126,131,233,313,lcd_discolor[13-task2_num%14]); //填充区域 OSTimeDlyHMSM(0,0,0,1,OS_OPT_TIME_HMSM_STRICT,&err); } } } |
|
|
|
//任务优先级
#define TASK1_TASK_PRIO4 //任务堆栈大小 #define TASK1_STK_SIZE 128 //任务控制块 OS_TCB Task1_TaskTCB; //任务堆栈 CPU_STK TASK1_TASK_STK[TASK1_STK_SIZE]; void task1_task(void *p_arg); //任务优先级 #define TASK2_TASK_PRIO5 //任务堆栈大小 #define TASK2_STK_SIZE 128 //任务控制块 OS_TCB Task2_TaskTCB; //任务堆栈 CPU_STK TASK2_TASK_STK[TASK2_STK_SIZE]; //任务函数 void task2_task(void *p_arg); |
|
|
|
不知道。
咱来谈谈理论, 纯靠想象的话: 我觉得不能这样搞,应该会有影响。 一个任务a操作硬件时,另一个任务b不能在a处理完之前去折腾这个硬件。 估计会被玩死的吧... |
|
|
|
结果是冲突的。见图片。
|
|
|
|
在2个任务中,涉及到同一个硬件,要小心! 怎样合理安排任务,非常重要。系统越复杂,失控可能性越大。
|
|
|
|
应该会有冲突,因为一个任务在操作硬件时应该不能被打断,它不像软件可以中断嵌套,可以保存现场,恢复现场,继续执行,硬件的打断也许是不允许发生的,是不可逆转的,应该最好加入临界区,使之不被任何中断打断,操作硬件时应该关闭所有中断,操作完成后再打开中断,否则,可能会出现一些不可预料的结果的。
|
|
|
|
//task1任务函数
void task1_task(void *p_arg) { u16 i; u8 task1_num=0; OS_ERR err; CPU_SR_ALLOC(); p_arg = p_arg; POINT_COLOR = BLACK; OS_CRITICAL_ENTER(); LCD_DrawRectangle(5,110,115,314); //画一个矩形 LCD_DrawLine(5,130,115,130);//画线 POINT_COLOR = BLUE; LCD_ShowString(6,111,110,16,16,"Task1 Run:000"); OS_CRITICAL_EXIT(); while(1) { task1_num++;//任务执1行次数加1 注意task1_num1加到255的时候会清零!! LED0= ~LED0; printf("任务1已经执行:%d次rn",task1_num); //if(task1_num==5) //{ //OSTaskDel((OS_TCB*)&Task2_TaskTCB,&err);//任务1执行5此后删除掉任务2 //printf("任务1删除了任务2!rn"); //} for(i=0;i<100;i++) { OS_CRITICAL_ENTER(); LCD_Fill(6,131,114,313,lcd_discolor[task1_num%14]); //填充区域 LCD_ShowxNum(86,111,task1_num,3,16,0x80);//显示任务执行次数 OS_CRITICAL_EXIT(); OSTimeDlyHMSM(0,0,0,10,OS_OPT_TIME_HMSM_STRICT,&err); //延时1s } } } //task2任务函数 void task2_task(void *p_arg) { u16 i; u8 task2_num=0; OS_ERR err; CPU_SR_ALLOC(); p_arg = p_arg; POINT_COLOR = BLACK; OS_CRITICAL_ENTER(); LCD_DrawRectangle(125,110,234,314); //画一个矩形 LCD_DrawLine(125,130,234,130);//画线 POINT_COLOR = BLUE; LCD_ShowString(126,111,110,16,16,"Task2 Run:000"); OS_CRITICAL_EXIT(); while(1) { task2_num++;//任务2执行次数加1 注意task1_num2加到255的时候会清零!! LED1=~LED1; printf("任务2已经执行:%d次rn",task2_num); for(i=0;i<1000;i++) { OS_CRITICAL_ENTER(); LCD_ShowxNum(206,111,task2_num,3,16,0x80); //显示任务执行次数 LCD_Fill(126,131,233,313,lcd_discolor[13-task2_num%14]); //填充区域 OS_CRITICAL_EXIT(); OSTimeDlyHMSM(0,0,0,1,OS_OPT_TIME_HMSM_STRICT,&err); } } } |
|
|
|
"加入临界区",有效果。显示正常了!
|
|
|
|
两个任务要操作同一个硬件外设这个问题就是典型的共享资源保护的问题!对于共享资源的保护你可以使用临界段代码保护的方式也可以使用信号量。
|
|
|
|
http://blog.csdn.net/liuhui_8989/article/details/8783323
|
|
|
|
"使用信号量"比较可靠!,“临界段代码保护”还有风险!同样是通过关中断来保护临界区,OS_ENTER_CRITICAL/OS_EXIT_CRITICAL一共实现了三种实现方式。 第一种方式,OS_ENTER_CRITICAL()简单地关中断,OS_EXIT_CRITICAL()简单地开中断。这种方式虽然简单高效,但无法满足嵌套的情况。如果有两层临界区保护,在退出内层临界区时就会开中断,使外层的临界区也失去保护。虽然ucos的内核写的足够好,没有明显嵌套临界区的情况,但谁也无法保证一定没有,无法保证今后没有,无法保证在附加的驱动或什么位置没有,所以基本上第一种方法是没有人用的。
第二种方式,OS_ENTER_CRITICAL()会在关中断前保存之前的标志寄存器内容到堆栈中,OS_EXIT_CRITICAL()从堆栈中恢复之前保存的状态。这样就允许了临界区嵌套的情况。但现在看来,这种方法还存在很大的问题,甚至会出现致命的漏洞。 |
|
|
|
在使用UCOSIII时,要确保理论上无问题,否则不敢用。
|
|
|
|
//任务优先级
#define START_TASK_PRIO3 //任务堆栈大小 #define START_STK_SIZE 128 //任务控制块 OS_TCB StartTaskTCB; //任务堆栈 CPU_STK START_TASK_STK[START_STK_SIZE]; //任务函数 void start_task(void *p_arg); //任务优先级 #define TASK1_TASK_PRIO4 //任务堆栈大小 #define TASK1_STK_SIZE 128 //任务控制块 OS_TCB Task1_TaskTCB; //任务堆栈 CPU_STK TASK1_TASK_STK[TASK1_STK_SIZE]; void task1_task(void *p_arg); //任务优先级 5 #define TASK2_TASK_PRIO5 //任务堆栈大小 #define TASK2_STK_SIZE 128 //任务控制块 OS_TCB Task2_TaskTCB; //任务堆栈 CPU_STK TASK2_TASK_STK[TASK2_STK_SIZE]; //任务函数 void task2_task(void *p_arg); //LCD刷屏时使用的颜色 int lcd_discolor[14]= { WHITE, BLACK, BLUE, BRED, GRED, GBLUE, RED, MAGENTA, GREEN, CYAN, YELLOW,BROWN, BRRED, GRAY }; u8 cnt; OS_MUTEXTEST_MUTEX;//定义一个互斥信号量 int main(void) { OS_ERR err; CPU_SR_ALLOC(); //临界代码保护开始 cnt=0; delay_init(168); //初始化延时函数 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断分组配置 uart_init(115200); //串口初始化 LED_Init(); //初始化LED端口 BEEP_Init(); //初始化蜂鸣器端口 LCD_Init(); POINT_COLOR = RED; LCD_ShowString(30,10,200,16,16,"Explorer STM32F4"); LCD_ShowString(30,30,200,16,16,"UCOSIII Examp 6-1"); LCD_ShowString(30,50,200,16,16,"Task Creat and Del"); LCD_ShowString(30,70,200,16,16,"ATOM@ALIENTEK"); LCD_ShowString(30,90,200,16,16,"2015/07/22"); OSInit(&err); //初始化UCOSIII OS_CRITICAL_ENTER();//进入临界区 //创建开始任务 OSTaskCreate((OS_TCB * )&StartTaskTCB,//任务控制块 (CPU_CHAR* )"start task", //任务名字 (OS_TASK_PTR )start_task, //任务函数 (void* )0,//传递给任务函数的参数 (OS_PRIO )START_TASK_PRIO, //任务优先级 (CPU_STK * )&START_TASK_STK[0],//任务堆栈基地址 (CPU_STK_SIZE)START_STK_SIZE/10,//任务堆栈深度限位 (CPU_STK_SIZE)START_STK_SIZE,//任务堆栈大小 (OS_MSG_QTY )0,//任务内部消息队列能够接收的最大消息数目,为0时禁止接收消息 (OS_TICK )0,//当使能时间片轮转时的时间片长度,为0时为默认长度, (void * )0,//用户补充的存储区 (OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, //任务选项 (OS_ERR * )&err);//存放该函数错误时的返回值 OS_CRITICAL_EXIT();//退出临界区 OSStart(&err); while(1); } //开始任务任务函数 void start_task(void *p_arg) { OS_ERR err; CPU_SR_ALLOC(); p_arg = p_arg; CPU_Init(); #if OS_CFG_STAT_TASK_EN > 0u OSStatTaskCPUUsageInit(&err); //统计任务 #endif #ifdef CPU_CFG_INT_DIS_MEAS_EN//如果使能了测量中断关闭时间 CPU_IntDisMeasMaxCurReset(); #endif #ifOS_CFG_SCHED_ROUND_ROBIN_EN //当使用时间片轮转的时候 //使能时间片轮转调度功能,时间片长度为1个系统时钟节拍,既1*5=5ms OSSchedRoundRobinCfg(DEF_ENABLED,1,&err); #endif OS_CRITICAL_ENTER();//进入临界区 //创建一个互斥信号量 OSMutexCreate((OS_MUTEX*)&TEST_MUTEX, (CPU_CHAR*)"TEST_MUTEX", (OS_ERR*)&err); //创建TASK2任务 OSTaskCreate((OS_TCB * )&Task2_TaskTCB, (CPU_CHAR* )"task2 task", (OS_TASK_PTR )task2_task, (void* )0, (OS_PRIO )TASK2_TASK_PRIO, (CPU_STK * )&TASK2_TASK_STK[0], (CPU_STK_SIZE)TASK2_STK_SIZE/10, (CPU_STK_SIZE)TASK2_STK_SIZE, (OS_MSG_QTY )0, (OS_TICK )0, (void * )0, (OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, (OS_ERR * )&err); //创建TASK1任务 OSTaskCreate((OS_TCB * )&Task1_TaskTCB, (CPU_CHAR* )"Task1 task", (OS_TASK_PTR )task1_task, (void* )0, (OS_PRIO )TASK1_TASK_PRIO, (CPU_STK * )&TASK1_TASK_STK[0], (CPU_STK_SIZE)TASK1_STK_SIZE/10, (CPU_STK_SIZE)TASK1_STK_SIZE, (OS_MSG_QTY )0, (OS_TICK )0, (void * )0, (OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, (OS_ERR * )&err); OS_CRITICAL_EXIT();//退出临界区 OSTaskDel((OS_TCB*)0,&err);//删除start_task任务自身, NULL删除自身 } //task1任务函数 void task1_task(void *p_arg) { u16 i; u8 task1_num=0; OS_ERR err; CPU_SR_ALLOC(); p_arg = p_arg; POINT_COLOR = BLACK; OS_CRITICAL_ENTER(); LCD_DrawRectangle(5,110,115,314); //画一个矩形 LCD_DrawLine(5,130,115,130);//画线 POINT_COLOR = BLUE; LCD_ShowString(6,111,110,16,16,"Task1 Run:000"); OS_CRITICAL_EXIT(); while(1) { task1_num++;//任务执1行次数加1 注意task1_num1加到255的时候会清零!! LED0= ~LED0; printf("任务1已经执行:%d次rn",task1_num); //if(task1_num==5) //{ //OSTaskDel((OS_TCB*)&Task2_TaskTCB,&err);//任务1执行5此后删除掉任务2 //printf("任务1删除了任务2!rn"); //} for(i=0;i<100;i++) { OSMutexPend (&TEST_MUTEX,0,OS_OPT_PEND_BLOCKING,0,&err);//请求互斥信号量 LCD_Fill(6,131,114,313,lcd_discolor[task1_num%14]); //填充区域 LCD_ShowxNum(86,111,task1_num,3,16,0x80);//显示任务执行次数 OSMutexPost(&TEST_MUTEX,OS_OPT_POST_NONE,&err);//释放互斥信号量 OSTimeDlyHMSM(0,0,0,10,OS_OPT_TIME_HMSM_STRICT,&err); //延时1s } } } //task2任务函数 void task2_task(void *p_arg) { u16 i; u8 task2_num=0; OS_ERR err; CPU_SR_ALLOC(); p_arg = p_arg; POINT_COLOR = BLACK; OS_CRITICAL_ENTER(); LCD_DrawRectangle(125,110,234,314); //画一个矩形 LCD_DrawLine(125,130,234,130);//画线 POINT_COLOR = BLUE; LCD_ShowString(126,111,110,16,16,"Task2 Run:000"); OS_CRITICAL_EXIT(); while(1) { task2_num++;//任务2执行次数加1 注意task1_num2加到255的时候会清零!! LED1=~LED1; printf("任务2已经执行:%d次rn",task2_num); for(i=0;i<1000;i++) { OSMutexPend (&TEST_MUTEX,0,OS_OPT_PEND_BLOCKING,0,&err);//请求互斥信号量 LCD_ShowxNum(206,111,task2_num,3,16,0x80); //显示任务执行次数 LCD_Fill(126,131,233,313,lcd_discolor[13-task2_num%14]); //填充区域 OSMutexPost(&TEST_MUTEX,OS_OPT_POST_NONE,&err);//释放互斥信号量 OSTimeDlyHMSM(0,0,0,1,OS_OPT_TIME_HMSM_STRICT,&err); } } } |
|
|
|
得定义互斥信号量吧,还没深入研究。。。
|
|
|
|
比如我有个两个任务要往nand flash里面不同page写数据,这时候该怎么办了
|
|
|
|
只有小组成员才能发言,加入小组>>
791 浏览 0 评论
1151 浏览 1 评论
2527 浏览 5 评论
2860 浏览 9 评论
移植了freeRTOS到STMf103之后显示没有定义的原因?
2710 浏览 6 评论
keil5中manage run-time environment怎么是灰色,不可以操作吗?
1071浏览 3评论
194浏览 2评论
456浏览 2评论
369浏览 2评论
M0518 PWM的电压输出只有2V左右,没有3.3V是怎么回事?
454浏览 1评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-22 17:27 , Processed in 1.623839 second(s), Total 113, Slave 93 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号