ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Пятница
3 мая
1322071 Топик полностью
vpv.vpv (20.06.2023 12:27, просмотров: 142) ответил il-2 на Могу предположить что __regvar и volatile не совместимы, но компилятор об этом скромно молчит. Проверить легко - попробуй убрать __regvar, чтобы была обычная volatile переменная.
Да, похоже на то. Исковырял всё, вдоль и поперек. Почему-то "атомарность" работы с парой регистров выводит компилятор из себя. Вот, переписал написал кусок без функций. Чтение без запрета прерываний (они закомментированы): 
void main(void)
  {
  uiCommonTimer = 1000;
  PORTA = 10;
  PORTB = 5;
   {
   unsigned int uitemp;
   // __disable_interrupt();
   uitemp = uiCommonTimer;
   // __enable_interrupt();
   eeTestTime = 1000 - uitemp;
   }


Результат:


315    {
316    unsigned int uitemp;
317 // __disable_interrupt();
318    uitemp = uiCommonTimer;
319 // __enable_interrupt();
320    eeTestTime = 1000 - uitemp;
\ 00000010 EE08   LDI R16, 232
\ 00000012 E013   LDI R17, 3
\ 00000014 1904   SUB R16, R4
\ 00000016 0915   SBC R17, R5
\ 00000018 E141   LDI R20, 17
\ 0000001A ....   RCALL __eeput16_8

321    }


Пестня! В R17:R16 грузится тыща, и прямо из них вычитаются R5:R4. Ничего лишнего, оптимум на 100%.

Теперь добавляем "атомарности" чтения регистрового счетчика. Просто запрещаем на время прерывания. И теперь получаем вот что:


315     {
316     unsigned int uitemp;
317     __disable_interrupt();

\ 00000010 94F8   CLI

318     uitemp = uiCommonTimer;

\ 00000012 0192   MOVW R19:R18, R5:R4

319    __enable_interrupt();

\ 00000014 9478   SEI

320     eeTestTime = 1000 - uitemp;

\ 00000016 E000   LDI R16, 0
\ 00000018 2711   CLR R17
\ 0000001A E141   LDI R20, 17
\ 0000001C ....   RCALL __eeput16_8

321     }


Здравствуй жопа новый год. Что не так-то?

Если счётчик организовать не в регистрах, а в ОЗУ, тогда компилятор не приходит в эррегированное состояние. Когда ОЗУ, тогда ему всё равно, запрещены прерывания, или нет:


315   {
316   unsigned int uitemp;
317   __disable_interrupt();

\ 00000012 94F8   CLI

318   uitemp = uiCommonTimer;

\ 00000014 8120   LD R18, Z
\ 00000016 8131   LDD R19, Z+1

319 __enable_interrupt();

\ 00000018 9478   SEI

320 eeTestTime = 1000 - uitemp;

\ 0000001A EE08   LDI R16, 232
\ 0000001C 1B02   SUB R16, R18
\ 0000001E 0B13   SBC R17, R19
\ 00000020 E141   LDI R20, 17
\ 00000022 ....   RCALL __eeput16_8

321 }

Похоже, действительно, есть какая-то недокуметнированная несовместимость между __regvar и volatile. А простой запрет прерываний каким тут боком? Вот это вобще не понятно... Очень жаль. Работа напрямую с регистрами гораздо быстрее. Ладно, предупреждён, значит вооружён. Может, кому-то эта информация будет полезна. :))