R0 нарушается после возврата функции - PullRequest
0 голосов
/ 03 мая 2011

Я реализую очередь uart в s3c44b0x (ARM7TDMI), ISR uart0 будет ставить в очередь символ, в то время как основной цикл удалит его из очереди. однако во время удаления из очереди возвращаемое значение (в R0) может быть не тем, которое было исключено из очереди, и я обнаружил, что R0 нарушается после возврата из функции удаления из очереди (ввод 'v', продолжение, и 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 голосов
/ 06 мая 2011

вот код сборки: для теста ():

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

для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 (перемещено в R0 до B) 4) Я использую J-LINK, но без J-LINK (запускается из флэш-памяти),это все еще существует.

0 голосов
/ 04 мая 2011

У нас недостаточно информации / контекста, чтобы ответить окончательно. Также было бы полезно, если бы вы опубликовали соответствующий ассемблерный код, чтобы мы могли видеть, как / когда вещи перемещаются и выходят из R0. Безотносительно, несколько вещей сразу приходят на ум из вашего опубликованного кода C.

(0) Переменные, совместно используемые между прерываниями и основным циклом, объявлены как volatile?

(1) В CliDequeue вы получаете доступ к массиву, который используется совместно с ISR. Похоже, это конструкция с одним читателем / одним писателем, так что это автоматически не плохо, но ваша домашняя работа не герметична.

Например, один инвариант, который вы должны обязательно выполнить, состоит в том, что размер очереди и указатель хвоста синхронизированы. Тем не менее, если эта процедура не вызывается с отключенными прерываниями, ваш хвостовой указатель и размер очереди не корректируются как одна транзакция.

(2) Кроме того, я бы предположил, что gwCliQSize также корректируется в прерывании (увеличивается в ISR, уменьшается в приложении). Другое состояние гонки. Для выполнения gwCliQSize-- за кадром вы, вероятно, читаете из памяти в регистр, уменьшаете регистр, а затем записываете его обратно. Что произойдет, если вы прочитаете 5 из памяти в R1, затем прерывание сработает и увеличит его до 6, затем вы выйдете из ISR, а также уменьшите регистр и произведете обратную запись (со значением 4).

(3) И, наконец, возможно (хотя и не слишком вероятно), что bTmpCh или bTestCh хранятся в стеке, и что ваш стек поврежден / захлопнут из-за другой задачи / прерывания / и т.д. думая, что R0 поврежден, но на самом деле это может быть то, что значение, перемещенное в R0 перед возвратом, или значение, перемещенное из R0 в переменную стека, становится засоренным.

Я достаточно болтала. Существуют и другие возможности, но из того, что вы опубликовали (а не опубликовали), невозможно сказать наверняка.

P.S. Если вы использовали отладчик, и это действительно и буквально искажает значение R0, а не только значение символа в очереди, это указывает на проблему в вашем планировщике / переключателе контекста / ISR до или после преобразования и т. Д. ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...