2812移植ucos2经验-中断中完成任务切换,消息发送【转】


2812移植ucos2经验-中断中完成任务切换,消息发送
转自 http://www.hellodsp.com/bbs/forum.php?mod=viewthread&tid=17754&fromuid=365745

最近做了ucos2在2812的移植,之前在网上查资料时发现很多朋友说在2812上跑ucos时中断中无法进行任务切换, 或者是中断中无法发信号或消息。经过一段时间的调试,我解决了这个问题,发个经验贴,希望能对大家有帮助。

说到底这个问题是2812堆栈结构的问题,先看看2812CPU介绍中对中断堆栈保护的介绍吧。
Table 3−3. Register Pairs Saved and SP Positions for Context Saves 

                                               1 --SP position before step8
1st                ST0                    0                                 0  --SP position before step 8
                         T                    1                                1
2nd                AL                      0                                0
                      AH                     1                                 1
3rd                 PL                     0                                 0
                      PH                     1                                 1
4th                 AR                      0                                 0 
                      AR                      1                                 1 
5th              ST1                       0                                 0
                     DP                       1                                 1
6th               IER                       0                                 0
                    DBGSTAT              1                                  1
7th                 Return address
                   (low half)
                                                0                                   0
                   Return address
                  ( high half)
                                                 1                                   1
                                                 0 ← SP position after save      0
                                                 1                                  1 ← SP position after save
这是2812进入中断处理时cpu自动完成工作的一部分,从上面可以看出,在进入中断时,CPU自动按顺序保存ST0—---Return address等寄存器的值。要特别注意的是2812在保存寄存器时是按照32位寻址的,看这段话
These registers are saved in pairs; each pair is saved in a single 32-bit operation. 
At the end of each 32-bit save operation, the SP is incremented by 2. 
The CPU expects all 32-bit saves to be even-word aligned by the memory wrapper.
这三句话告诉我们在CPU存这些寄存器的时候,是成对存储的;每存一对寄存器,SP+2;最重要的是2812要求所有成对存储的寄存器从偶地址开始。于是有了上面两种情况。
        SP position before step8 这里的step8指得是SP加1的操作,0和1分别表示偶和奇地址。
第一种情况sp最初指向奇地址(表中左边一列):
1)sp+1 ,现在sp指向偶地址 
2)开始存储寄存器,因为sp指向偶地址,于是寄存器存在sp和sp+1的地方
3) sp<-sp+2 现在sp还是指向偶地址,继续重复1)
结束后sp指向偶地址。

第二种情况sp最初指向偶地址(表中右边一列)
1)        sp<-sp+1,现在sp指向奇地址。
2)        开始存储寄存器,由于sp指向奇地址,所以储存在sp和sp-1(不是sp+1!)的位置。从这里也可以看出为什么2812要在加上sp<-sp+1的操作。否则的话,如果sp最初指向奇地址,那么寄存器就存在sp和sp-1的位置了,这时sp-1里面是原来存的内容,这个内容就会被覆盖了。如下图:
原来的内容   0                               ST0            0(ST0已经把原内容覆盖!!)
空的         1 --SP before save       T                1
空的          0        (而后sp+2)   空的        0 
空的         1                               空的        1—sp after save

        费了一大堆话解释这个,就是要说明,在32位存储时寄存器对是从偶地址开始的。为了在中断中发送信号或消息就要在中断中调用函数OSMboxPost (MBOX, (void *)&event),这时要注意SP的指向问题。中断程序不要用interrupt关键字来写,最好用汇编,在汇编中完成出栈入栈的工作,而后在汇编中调用C函数完成中断服务,结构如下
.page
.text
_SAMPLE:
        .ref _SAMPLE_service
    .ref _OSIntNesting
    .ref _OSIntExit
        .global _SAMPLE        

        PUSH RPC
        
        MOVW      DP,#_OSIntNesting     ;提示uc/OS-II 进入中断
    INC       @_OSIntNesting        ; |168|     
     
    LCR _SAMPLE_service        
    LCR _OSIntExit
        POP  RPC
   
IRET
        .end
SAMPLE是用汇编写的中断函数,实际上不用担心汇编很难写,我们要做的大部分事情都是在那个汇编中调用的C函数SAMPLE_service来完成的,汇编只用来完成进入和退出中断的工作。 
        在SAMPLE_service中我们要发送消息,于是要调用OSMboxPost (MBOX, (void *)&event)
Void SAMPLE_service(void)
{
…..
OSMboxPost (MBOX, (void *)&event);
…..
}
问题就在汇编中调用C函数的时候,如果进入C函数之前SP不是指向偶地址的,那么在进入和退出C函数的时候就有可能发生前面所说的堆栈内容被覆盖的问题。最保险的办法,就是在进入C函数之前将SP调整到偶地址,而后在C函数中不再定义变量(在定义局部变量的话又会使用堆栈了。。)。为了解决这个问题,2812指令集中提供了ASP和NASP两个指令。ASP能够将sp调整到偶地址
if(SP = odd)
SP = SP + 1;
SPA = 1;else
SPA = 0;
NASP能够将SP退回到原来的位置。所以在上面的汇编中断处理程序中每调用C函数之前就先执行ASP指令,之后在执行NASP指令,同时在C函数中不定义局部变量,就能保证中断中任务切换或者信号,消息发送的成功。如下所示:
.page
.text
_SAMPLE:
        .ref _SAMPLE_service
    .ref _OSIntNesting
    .ref _OSIntExit
        .global _SAMPLE        

        PUSH RPC
        
        MOVW      DP,#_OSIntNesting     ;提示uc/OS-II 进入中断
    INC       @_OSIntNesting        ; |168|     
    
ASP   ;调用C函数之前 先执行ASP指令将SP调整到偶地址
    LCR _SAMPLE_service        
NASP  ;返回之后在调用NASP指令将SP调整回去

LCR _OSIntExit  ;这个函数是用汇编写的,不用先执行ASP指令。 
        POP  RPC
   
IRET
        .end
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值