OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 24073|回复: 10

UC/OS II临界段理解

[复制链接]

51

主题

214

帖子

0

精华

高级会员

Rank: 4

积分
561
金钱
561
注册时间
2011-4-11
在线时间
43 小时
发表于 2011-4-13 21:13:07 | 显示全部楼层 |阅读模式
最近在学UC/OS II, 对于里面有一个临界段不是很理解。
OS_ENTER_CRITICAL(); (1)
            .
            .
            (2)
OS_EXIT_CRITICAL();(3)
书上说(1)是关中断  (3)是开中断。
我的问题是:UC/OS II里面是软中断来切换任务,那意思就是说(2)里面不能切换任务吗???  还是(2)里面可以切换任务,那关的中断是硬件中断,而非所以中断????
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165352
金钱
165352
注册时间
2010-12-1
在线时间
2108 小时
发表于 2011-4-13 22:42:10 | 显示全部楼层
我的理解.
(1)的作用是让ucos无法再执行任务调度,也就是执行1之后,ucos处于关闭状态.
(2)区域用于处理比较连续的事情,不希望被ucos打断.
(3)用于恢复ucos的任务调度功能.重新开启ucos.

至于硬中断能否打断(2)的执行,就要看(1)里面是怎么做的 了.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

98

主题

408

帖子

3

精华

金牌会员

Rank: 6Rank: 6

积分
1280
金钱
1280
注册时间
2010-12-14
在线时间
0 小时
发表于 2011-4-13 22:43:41 | 显示全部楼层
OS_cpu_a.asm文件中:

OS_ENTER_CRITICAL
 
        CPSID   I                       ; Disable all the interrupts
                                                                       
        PUSH     {R1,R2}     

        LDR     R1, =OSInterrputSum        ; OSInterrputSum++
        LDRB     R2, [R1]
        ADD       R2, R2, #1
        STRB     R2, [R1]
        POP     {R1,R2}
          BX LR

;/***************************************************************************************
;* 函数名称: OS_EXIT_CRITICAL
;*
;* 功能描述: 退出临界区
;*           
;* 参    数: None
;*
;* 返 回 值: None
;*****************************************************************************************/

OS_EXIT_CRITICAL
        PUSH    {R1, R2}
        LDR     R1, =OSInterrputSum     ; OSInterrputSum--
        LDRB    R2, [R1]
        SUB     R2, R2, #1
        STRB    R2, [R1]
        MOV     R1,  #0         
        CMP     R2,  #0                    ; if OSInterrputSum=0,enable
                                        ; interrupts如果OSInterrputSum=0,
        MSREQ  PRIMASK, R1  
        POP       {R1, R2}
        BX LR





--------------------------------------
我的理解是硬中断+软中断,




我写过一段测试代码测试OS_ENTER_CRITICAL(),OS_EXIT_CRITICAL();
#include "sys.h"
#include "usart.h"       
#include "delay.h"   
#include "led.h"
#include "key.h"   
#include "includes.h"     
//Mini STM32开发板扩展实例 8
//ucos 实验
//正点原子@ALIENTEK
//2010.12.25

 
//设置任务堆栈大小
#define LED_STK_SIZE     64
#define LED1_STK_SIZE    64
#define START_STK_SIZE   128
#define USART_STK_SIZE   64

//设置任务优先级
#define LED_TASK_Prio       5
#define LED1_TASK_Prio      9
#define USART_TASK_Prio     8
#define START_TASK_Prio     10 //这个任务的优先级应该是最高的

//任务堆栈
OS_STK  TASK_LED1_STK[LED_STK_SIZE];
OS_STK  TASK_LED_STK[LED_STK_SIZE];
OS_STK  TASK_START_STK[START_STK_SIZE];
OS_STK  TASK_USART_STK[USART_STK_SIZE];
//任务申明
void TaskStart(void *pdata);
void TaskLed(void *pdata);
void TaskLed1(void *pdata);
void TaskUsart(void *pdata);
//系统时钟配置函数
void SysTick_Configuration(void);

INT32U time1=0;
INT32U time2=0;
     
//Mini STM32开发板ucos范例
//基于ucos2.52内核.
//张洋@ALIENTEK
//www.openedv.com
//2010.12.15

/**
* OS_ENTER_CRITICAL(),OS_EXIT_CRITICAL()之间的代码段构成临界段,此段代码不能被中断打断,
*也就是说,在执行此段代码的过程中不进行任务调度,那么期间即使有高优先级的任务等待时间到达,那么也不能立即获得cpu的控制权
**/
void _delay(INT32U times){
while(times--);
}             
int main(void)
{    INT8U state;               
    Stm32_Clock_Init(9); //系统时钟设置
    delay_init(72);         //延时初始化
    uart_init(72,9600);     //串口初始化为9600
    LED_Init();               //初始化与LED连接的硬件接口 
    SysTick_Configuration();
    OSInit();
   
    state=OSTaskCreate( TaskStart,    //task pointer
                    (void *)0,    //parameter
                    (OS_STK *)&TASK_START_STK[START_STK_SIZE-1],    //task stack top pointer
                    START_TASK_Prio );    //task priority
                   
    if(state==OS_PRIO_EXIST){}
   
    OSStart();       //开始调度
    return 0;
 
}
//开始任务
void TaskStart(void * pdata)
{          
    pdata = pdata;     //防止某些编译器报错

    OS_ENTER_CRITICAL();  
    OSTaskCreate(TaskLed, (void *)0,  &TASK_LED_STK[LED_STK_SIZE-1], LED_TASK_Prio);
    OSTaskCreate(TaskLed1, (void *)0,  &TASK_LED1_STK[LED1_STK_SIZE-1], LED1_TASK_Prio);
//    OSTaskCreate(TaskUsart,(void *)0, &TASK_USART_STK[USART_STK_SIZE-1],USART_TASK_Prio);
    OSTaskSuspend(START_TASK_Prio);    //suspend but not delete
    OS_EXIT_CRITICAL();
     
}
//任务1
//控制DS0的亮灭.
void TaskLed(void *pdata)
{
    while(1)
    {
        LED0=!LED0;
         printf("TaskLED0...LED0=%d\n",LED0);
        OSTimeDlyHMSM(0,0,0,100);//500ms   
    }
}
//任务2
//控制DS1的亮灭.
void TaskLed1(void *pdata)
{
    while(1)
    {
        LED1=!LED1;
        printf("TaskLED1...LED1=%d\n",LED1);
       
        OS_ENTER_CRITICAL();
         printf("enter Critical...\n");
        _delay(1000000);
        printf("exit Critical...\n");
        OS_EXIT_CRITICAL();
        printf("enter Active...\n");
        _delay(1000000);
        printf("exist Active...\n");
        OSTimeDlyHMSM(0,0,0,200);//500ms   
    }
}   

 




















 
希望openedv能给大家提供一个友好的技术交流平台!
回复 支持 反对

使用道具 举报

98

主题

408

帖子

3

精华

金牌会员

Rank: 6Rank: 6

积分
1280
金钱
1280
注册时间
2010-12-14
在线时间
0 小时
发表于 2011-4-13 22:46:34 | 显示全部楼层
 这个地方我理解也不透,楼主如果找到相关资料理解了,麻烦分享,谢谢!
希望openedv能给大家提供一个友好的技术交流平台!
回复 支持 反对

使用道具 举报

51

主题

214

帖子

0

精华

高级会员

Rank: 4

积分
561
金钱
561
注册时间
2011-4-11
在线时间
43 小时
 楼主| 发表于 2011-4-14 07:08:58 | 显示全部楼层
回复【3楼】张洋:
-------------------------------
我也测了一下,
OS_ENTER_CRITICAL(); (1)
         .
            .
            (2)
OS_EXIT_CRITICAL();(3)
(2)里面会出现任务调度的情况,在OS_ENTER_CRITICAL()里面用的了SPID I,关掉所有的中断,但是还会出现任务调度,真是不可理解。书上说任务调度也是用的中断来的,所有这样结果说明 SPID I不能把OSPendSV 中断禁止。
回复 支持 反对

使用道具 举报

51

主题

214

帖子

0

精华

高级会员

Rank: 4

积分
561
金钱
561
注册时间
2011-4-11
在线时间
43 小时
 楼主| 发表于 2011-4-14 07:27:10 | 显示全部楼层
回复【3楼】张洋:
-------------------------------
#include "includes.h"  
//UC/OS II 信号量实验
//Julius
//13/04/2011

//声明信号量
INT8U err;
OS_EVENT *Fun_Semp;

//设置任务堆栈大小
#define LED_STK_SIZE     64
#define LED1_STK_SIZE    64
#define START_STK_SIZE   128

//设置任务优先级
#define LED_TASK_Prio       9
#define LED1_TASK_Prio      5
#define START_TASK_Prio     10

//任务堆栈
OS_STK  TASK_LED1_STK[LED_STK_SIZE];
OS_STK  TASK_LED_STK[LED_STK_SIZE];
OS_STK  TASK_START_STK[START_STK_SIZE];
//任务申明
void TaskStart(void *pdata);
void TaskLed(void *pdata);
void TaskLed1(void *pdata);
   
int main(void)
{
    Wait_ms(1); //Ensure I/O is ready      
OSInit();

    Fun_Semp = OSSemCreate(1);     //定义信号量

OSTaskCreate( TaskStart, //task pointer
(void *)0, //parameter
(OS_STK *)&TASK_START_STK[START_STK_SIZE-1], //task stack top pointer
START_TASK_Prio ); //task priority

OSStart();    //开始调度
return 0;    
}
//开始任务
void TaskStart(void * pdata)
{
pdata = pdata; 

CPU_Init();
Wait_ms(5);
LED0=LED1=1;

//OSStatInit(); 
OS_ENTER_CRITICAL();   //关掉了中断   可以切换任务 就是不能进入一般的中断  内核中断可以
OSTaskCreate(TaskLed, (void * )0, (OS_STK *)&TASK_LED_STK[LED_STK_SIZE-1], LED_TASK_Prio);//先会执行以下这个任务然后才建立后面的任务
OSTaskCreate(TaskLed1, (void * )0, (OS_STK *)&TASK_LED1_STK[LED1_STK_SIZE-1],LED1_TASK_Prio);
OSTaskSuspend(START_TASK_Prio); //suspend but not delete
OS_EXIT_CRITICAL();   //开中断 
}
//任务1
//控制led0 led1 全亮.
void TaskLed(void *pdata)
{
    pdata=pdata;
while(1)
{
    OSSemPend(Fun_Semp,0,&err);  //请求信号量
printf("task0");
LED0=!LED0;
OSSemPost(Fun_Semp);
OSTimeDlyHMSM(0,0,2,0);
}
}
//任务2
//控制led0 led1的全灭.
void TaskLed1(void *pdata)
{
   pdata=pdata;
while(1)
{
OSSemPend(Fun_Semp,0,&err);  //请求信号量
printf("task1");
LED1=!LED1;
OSSemPost(Fun_Semp);
OSTimeDlyHMSM(0,0,4,0);
}
}   

这段串口的输出结果是:task0task1task0task0task1task0task1task0task0task1task0task0task1task0task0task1task0task0task1task0
如果临界段里不出现切换任务的话,应该是task1 先输出的,因为一开中断优先级是TaskLed1高于TaskLed的,你的“#define START_TASK_Prio     10 //这个任务的优先级应该是最高的”这里应该错了,书上说越小优先级越高的。  所有对于这个关中断很迷惑。
















回复 支持 反对

使用道具 举报

38

主题

248

帖子

0

精华

版主

Rank: 7Rank: 7Rank: 7

积分
463
金钱
463
注册时间
2011-2-11
在线时间
12 小时
发表于 2011-4-14 09:47:20 | 显示全部楼层
引用自 1楼 ???????????? 的回复: 我的理解.
(1)的作用是让ucos无法再执行任务调度,也就是执行1之后,ucos处于关闭状态.
(2)区域用于处理比较连续的事情,不希望被ucos打断.
(3)用于恢复ucos的任务调度功能.重新开启ucos.

至于硬中断能否打断(2)的执行,就要看(1)里面是怎么做的 了.


(1)和(3)中间确实不能进行调度,但是能够向中断控制器申请一个特殊的中断,此时(2)该中断产生但是不能响应,因为此时全局中断是关闭的。等(3)之后,全局中断打开,那么core自动响应在(2)时刻的中断。

你应该知道(2)那时候申请的是什么中断吧







Openedv大力支持的开源RTOS  --Trochili RTOS(飞鸟)
回复 支持 反对

使用道具 举报

38

主题

248

帖子

0

精华

版主

Rank: 7Rank: 7Rank: 7

积分
463
金钱
463
注册时间
2011-2-11
在线时间
12 小时
发表于 2011-4-14 09:51:32 | 显示全部楼层
引用自 4楼 Julius007 的回复: 回复【3楼】张洋:
-------------------------------
我也测了一下,
OS_ENTER_CRITICAL(); (1)
         .
            .
            (2)
OS_EXIT_CRITICAL();(3)
(2)里面会出现任务调度的情况,在OS_ENTER_CRITICAL()里面用的了SPID I,关掉所有的中断,但是还会出现任务调度,真是不可理解。书上说任务调度也是用的中断来的,所有这样结果说明 SPID I不能把OSPendSV 中断禁止。


SPID I已经把OSPendSV 中断禁止了,所以在(2)只能申请这个OSPendSV ,但是core不会相应的。等打开全局中断后,core才会响应OSPendSV 中断。才会进一步调度任务。这点正是m3的精妙所在,任务级别的调度转化成中断级别的调度,所以ucosii才只需要一个调度处理函数,i


Openedv大力支持的开源RTOS  --Trochili RTOS(飞鸟)
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165352
金钱
165352
注册时间
2010-12-1
在线时间
2108 小时
发表于 2011-4-14 10:57:16 | 显示全部楼层
回复【7楼】trochili:
-------------------------------
还真不知道.呵呵.请指点.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

38

主题

248

帖子

0

精华

版主

Rank: 7Rank: 7Rank: 7

积分
463
金钱
463
注册时间
2011-2-11
在线时间
12 小时
发表于 2011-4-14 11:07:34 | 显示全部楼层
在关闭全局中断的时候,基本都是内核在做关键操作,随后要申请任务调度。此时只需要作次OSPendSV申请 ,然后再打开
全局中断。再然后,core响应OSPendSV 中断请求。在OSPendSV 的isr中完成任务调度。
Openedv大力支持的开源RTOS  --Trochili RTOS(飞鸟)
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165352
金钱
165352
注册时间
2010-12-1
在线时间
2108 小时
发表于 2011-4-14 12:25:23 | 显示全部楼层
回复【10楼】trochili:
-------------------------------
哦,多谢指点.呵呵.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-24 16:28

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表