函数返回后违反R0

时间:2011-05-03 08:14:21

标签: function arm return-value

我正在s3c44b0x(ARM7TDMI)中实现一个uart队列,uart0 ISR会将char排入队列,而主循环将使char出列队列。然而,当出列时,返回的值(在R0中)可能不是从队列中出队的值,并且我从出列函数返回后发现R0被违反(输入'v'cont。,并且test()在主要部分中环): 希望得到你的帮助。

CHAR cliDequeue(void)
{
    CHAR bTmpCh;

    if (gwCliQSize == 0)
    {
        return 0;
    }

    bTmpCh = gabCliQ[gwCliQTail];  /* char is enqueued in the Q in ISR */
    gwCliQTail++;
    gwCliQTail %= MAX_CLI_QUEUE_LEN;
    ASSERT(gwCliQSize > 0);
    gwCliQSize--;

    ASSERT(bTmpCh == 'v');   /* will not assert */
    //uartPutChar(bTmpCh);
    return bTmpCh;
}

void test(void)
{
    CHAR bTestCh;

    bTestCh = cliDequeue();


    if (bTestCh != 0)
    { 
        ASSERT(bTestCh == 'v');  /* assert here ! */
            uartPutChar(bTestCh);

    }
}

2 个答案:

答案 0 :(得分:0)

我们没有足够的信息/背景来明确回答。如果您发布了相应的汇编代码,以便我们可以看到事情是如何/何时被移动的,那么它也会很有帮助。超出R0。无论如何,您发布的C代码会立即想到一些事情。

(0)变量和中断之间是否共享变量主循环声明为volatile

(1)  在CliDequeue中,您正在访问与ISR共享的阵列。它似乎是一个单一的读者/单一作家构造,所以这不会自动坏,但你的家务管理不是密不透风。

例如,您必须确保满足的一个不变量是队列大小&尾指针同步。然而,除非在禁用中断的情况下调用此例程,否则您的尾部指针和队列大小不会作为单个事务进行调整。

(2) 此外,我猜测gwCliQSize也在中断中调整(在ISR中递增,在应用程序中递减)。另一种竞争条件。要执行gwCliQSize--,在幕后您可能正在从内存读取寄存器,递减寄存器,然后将其写回。如果从内存中读取5到R1,然后中断触发并将其递增到6,然后退出ISR,寄存器递减和写回(值为4),会发生什么。

(3) 最后,有可能(虽然不太可能)bTmpChbTestCh存储在堆栈中,并且您的堆栈被另一个任务/中断/等等损坏/破坏。所以当你的断言失败时,你认为它的R0已经被破坏了,但实际上它可能是在返回之前值移入R0,或者从R0移出到堆栈变量中的值被破坏了。

我已经吃饱了。还有其他可能性,但是从你发布的内容(而不是发布内容)来看,这是不可能肯定的。

P.S。如果您使用过调试器,它确实是&字面上R0的值被破坏,而不仅仅是队列中字符的值,它指向调度程序/上下文切换器/ ISR之前或后导码中的问题......

答案 1 :(得分:0)

这是汇编代码: 对于测试():

0x00001308  E92D4010  STMDB     R13!,{R4,R14}
    37:     bTestCh = cliDequeue(); 
    38:          
0x0000130C  EB000207  BL        cliDequeue(0x00001B30)
0x00001310  E1A04000  MOV       R4,R0
    39:     if (bTestCh != 0) 
    40:     {  
0x00001314  E3540000  CMP       R4,#pTest(0x00000000)
0x00001318  0A000007  BEQ       0x0000133C
    41:         ASSERT(bTestCh == 'v'); 
0x0000131C  E1A00000  NOP       
0x00001320  E3540076  CMP       R4,#0x00000076
0x00001324  0A000001  BEQ       0x00001330
0x00001328  E1A00000  NOP       
0x0000132C  EAFFFFFE  B         0x0000132C
0x00001330  E1A00000  NOP       
    42:         uartPutChar(bTestCh); 
    43:     } 
0x00001334  E1A00004  MOV       R0,R4
0x00001338  EB00014A  BL        uartPutChar(0x00001868)
    44: } 
    45:  
    46: int main(void) 
0x0000133C  E8BD4010  LDMIA     R13!,{R4,R14}
0x00001340  E12FFF1E  BX        R14

对于cliDequeu(),BTW,gwCliQSize定义为 UINT32 volatile gwCliQSize;

0x00001B30  E59F00D4  LDR       R0,[PC,#0x00D4]
0x00001B34  E5900000  LDR       R0,[R0]
0x00001B38  E3500000  CMP       R0,#pTest(0x00000000)
0x00001B3C  1A000001  BNE       0x00001B48
    78:         return 0; 
    79:     } 
    80:      
    81:     bTmpCh = gabCliQ[gwCliQTail]; 
    82:     gwCliQTail++; 
    83:     gwCliQTail %= MAX_CLI_QUEUE_LEN; 
    84:     ASSERT(gwCliQSize > 0); 
    85:     gwCliQSize--; 
    86:  
    87:     //chCheck(bTmpCh); 
    88:          ASSERT(bTmpCh == 'v');   /* will not assert */ 
    89:     //uartPutChar(bTmpCh); 
    90:      
    91:     return bTmpCh; 
0x00001B40  E3A00000  MOV       R0,#pTest(0x00000000)
    92: } 
    93:  
    94:  
    95: void cliQInit(void) 
0x00001B44  E12FFF1E  BX        R14
    81:     bTmpCh = gabCliQ[gwCliQTail]; 
0x00001B48  E59F00C0  LDR       R0,[PC,#0x00C0]
0x00001B4C  E59F20C4  LDR       R2,[PC,#0x00C4]
0x00001B50  E5922000  LDR       R2,[R2]
0x00001B54  E7D01002  LDRB      R1,[R0,R2]
    82:     gwCliQTail++; 
0x00001B58  E59F00B8  LDR       R0,[PC,#0x00B8]
0x00001B5C  E5900000  LDR       R0,[R0]
0x00001B60  E2800001  ADD       R0,R0,#0x00000001
0x00001B64  E59F20AC  LDR       R2,[PC,#0x00AC]
0x00001B68  E5820000  STR       R0,[R2]
    83:     gwCliQTail %= MAX_CLI_QUEUE_LEN; 
0x00001B6C  E2820000  ADD       R0,R2,#pTest(0x00000000)
0x00001B70  E5900000  LDR       R0,[R0]
0x00001B74  E20000FF  AND       R0,R0,#0x000000FF
0x00001B78  E5820000  STR       R0,[R2]
    84:     ASSERT(gwCliQSize > 0); 
0x00001B7C  E1A00000  NOP       
0x00001B80  E59F0084  LDR       R0,[PC,#0x0084]
0x00001B84  E5900000  LDR       R0,[R0]
0x00001B88  E3500000  CMP       R0,#pTest(0x00000000)
0x00001B8C  1A000001  BNE       0x00001B98
0x00001B90  E1A00000  NOP       
0x00001B94  EAFFFFFE  B         0x00001B94
0x00001B98  E1A00000  NOP       
    85:     gwCliQSize--; 
    86:  
    87:     //chCheck(bTmpCh); 
0x00001B9C  E59F0068  LDR       R0,[PC,#0x0068]
0x00001BA0  E5900000  LDR       R0,[R0]
0x00001BA4  E2400001  SUB       R0,R0,#0x00000001
0x00001BA8  E59F205C  LDR       R2,[PC,#0x005C]
0x00001BAC  E5820000  STR       R0,[R2]
    88:          ASSERT(bTmpCh == 'v');   /* will not assert */ 
    89:     //uartPutChar(bTmpCh); 
    90:      
0x00001BB0  E1A00000  NOP       
0x00001BB4  E3510076  CMP       R1,#0x00000076
0x00001BB8  0A000001  BEQ       0x00001BC4
0x00001BBC  E1A00000  NOP       
0x00001BC0  EAFFFFFE  B         0x00001BC0
0x00001BC4  E1A00000  NOP       
    91:     return bTmpCh; 
    92: } 
    93:  
    94:  
    95: void cliQInit(void) 
0x00001BC8  E1A00001  MOV       R0,R1
0x00001BCC  EAFFFFDC  B         0x00001B44

for cliEnqueue:

void cliEnqueue(CHAR bC)
{
    if (gwCliQSize == MAX_CLI_QUEUE_LEN)
    {
        ASSERT(0);
    }

    gabCliQ[gwCliQHeader] = bC;
    gwCliQHeader++;
    gwCliQHeader %= MAX_CLI_QUEUE_LEN;
    gwCliQSize++;
}

组件:

0x00001A5C  E59F11AC  LDR       R1,[PC,#0x01AC]
0x00001A60  E59F21AC  LDR       R2,[PC,#0x01AC]
0x00001A64  E5922000  LDR       R2,[R2]
0x00001A68  E7C10002  STRB      R0,[R1,R2]
    25:     gwCliQHeader++; 
0x00001A6C  E59F11A0  LDR       R1,[PC,#0x01A0]
0x00001A70  E5911000  LDR       R1,[R1]
0x00001A74  E2811001  ADD       R1,R1,#0x00000001
0x00001A78  E59F2194  LDR       R2,[PC,#0x0194]
0x00001A7C  E5821000  STR       R1,[R2]
    26:     gwCliQHeader %= MAX_CLI_QUEUE_LEN; 
0x00001A80  E2821000  ADD       R1,R2,#pTest(0x00000000)
0x00001A84  E5911000  LDR       R1,[R1]
0x00001A88  E20110FF  AND       R1,R1,#0x000000FF
0x00001A8C  E5821000  STR       R1,[R2]
    27:     gwCliQSize++; 
0x00001A90  E59F1174  LDR       R1,[PC,#0x0174]
0x00001A94  E5911000  LDR       R1,[R1]
0x00001A98  E2811001  ADD       R1,R1,#0x00000001
0x00001A9C  E59F2168  LDR       R2,[PC,#0x0168]
0x00001AA0  E5821000  STR       R1,[R2]
    28: } 
    29:  
    30:  
    31: static void chCheck(CHAR cTmpChar) 
    32: { 
0x00001AA4  E12FFF1E  BX        R14

0),1):gwCliQSize和数组在ISR和主循环之间共享。

2)gwCliQSize定义为volatile 3)从组件中,bTestCh是R4(从R0移动)而bTmpCh是R1(在B之前移到R0) 4)我正在使用J-LINK,但没有J-LINK(从闪存运行),它仍然存在。