UPD:Любителям загадок WINAVR(решение связано с volatile)
Добавлено: Вт янв 05, 2010 00:26:19
Конечно можно было и в ветку winavr записать это, но случай мне кажется,интересный. Захотел я себе в winavr uart с буферами чтоб можно было в буфер складывать данные а они пусть там через прерывания выводятся. Такой механизм генерит визард CodeVision если ставить там RX или TX прерывние. Вот я выдернул оттуда исходники, запихал их в библиотеку и... приём не работает. Весь проект я сложил в архив а тут приведу важные участки кода. Собственно проблема в таком вот моменте
Ничего волшебного - ждём пока rx_counter перестанеть быть равным 0.
И затыкается отладчик в месте помеченном звёздочкой.
Т.е. стрелочка становится там и никуда не двигается. При нажатии F10 студия запускает ход программы но долго останавливает. Смотрим в дизассемблер(для не знающих - в меню AvrStudio View->Dissassembler) и видем там вот такой код
Что-же происходит? А вот что - если R25 равен 0 то выполнится breq PC+0x0016 а именно выполнение перейдёт в 0x000001C1+0x00000016=000001D7. И останется там до второго прешествия потому что rjmp PC-0x0000. На этом чудеса не заканчиваются. Меняю вот так
А нефига. Опять смотрим в отладчик - там
Это кусочек си кода приведённого выше. Опять лажа. До NOP дойдёт но второй раз проверку не сделает. команда RJMP PC-0x0001 приведёт на NOP а не на проверку.
Так тоже до проверки не доходит
Точнее проверка есть но содержимое к25 не обновляется. Вобщем пока наверно напишу вставку на асме, но как же так? Все остальные while прекрасно работают... вроде...
Код: Выделить всё
while (rx_counter==0);
И затыкается отладчик в месте помеченном звёздочкой.
Код: Выделить всё
char getchar_u(void)
{
char data;
while (rx_counter==0);
data=rx_buffer[rx_rd_index];
if (++rx_rd_index == RX_BUFFER_SIZE) rx_rd_index=0;
asm("cli");
--rx_counter;
asm("sei");
return data;
}*
Код: Выделить всё
@000001BE: getchar_u
38: while (rx_counter==0);
+000001BE: 91900073 LDS R25,0x0073 Load direct from data space
+000001C0: 2399 TST R25 Test for Zero or Minus
+000001C1: F0A9 BREQ PC+0x16 Branch if equal
39: data=rx_buffer[rx_rd_index];
+000001C2: 91800074 LDS R24,0x0074 Load direct from data space
+000001C4: 2FE8 MOV R30,R24 Copy register
+000001C5: E0F0 LDI R31,0x00 Load immediate
+000001C6: 59ED SUBI R30,0x9D Subtract immediate
+000001C7: 4FFF SBCI R31,0xFF Subtract immediate with carry
+000001C8: 81E0 LDD R30,Z+0 Load indirect with displacement
40: if (++rx_rd_index == RX_BUFFER_SIZE) rx_rd_index=0;
+000001C9: 5F8F SUBI R24,0xFF Subtract immediate
+000001CA: 93800074 STS 0x0074,R24 Store direct to data space
+000001CC: 3088 CPI R24,0x08 Compare with immediate
+000001CD: F411 BRNE PC+0x03 Branch if not equal
+000001CE: 92100074 STS 0x0074,R1 Store direct to data space
41: asm("cli");
+000001D0: 94F8 CLI Global Interrupt Disable
42: --rx_counter;
+000001D1: 5091 SUBI R25,0x01 Subtract immediate
+000001D2: 93900073 STS 0x0073,R25 Store direct to data space
43: asm("sei");
+000001D4: 9478 SEI Global Interrupt Enable
45: }
+000001D5: 2F8E MOV R24,R30 Copy register
+000001D6: 9508 RET Subroutine return
+000001D7: CFFF RJMP PC-0x0000 Relative jump
Код: Выделить всё
while (rx_counter==0)
{
asm("nop");
};
Код: Выделить всё
@000001BE: getchar_u
38: while (rx_counter==0)
+000001BE: 91900073 LDS R25,0x0073 Load direct from data space
+000001C0: 2399 TST R25 Test for Zero or Minus
+000001C1: F411 BRNE PC+0x03 Branch if not equal
40: asm("nop");
+000001C2: 0000 NOP No operation
+000001C3: CFFE RJMP PC-0x0001 Relative jump
Так тоже до проверки не доходит
Код: Выделить всё
while (!(rx_counter|=0));
Код: Выделить всё
@000001BE: getchar_u
36: {
+000001BE: 91900073 LDS R25,0x0073 Load direct from data space
38: while (!(rx_counter|=0));
+000001C0: 2399 TST R25 Test for Zero or Minus
+000001C1: F3F1 BREQ PC-0x01 Branch if equal