Перейти к содержанию
    

антипод модификатора __raw

Появилась тут мысля. У IAR-а для не сохранения контекста в прерывании служит __raw. А есть ли его "антипод" - модификатор заставляющий IAR сохранить контекст некоторой функции (не прерывания) в стеке? :help:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Используйте модификатор __interrupt и запретите лишние варнинги. При вызове не забудьте преобразовать тип функции, вообщем смотри тут, пост номер 30.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

вообщем смотри тут, пост номер 30

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

Изменено пользователем ArtemKAD

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Появилась тут мысля. У IAR-а для не сохранения контекста в прерывании служит __raw. А есть ли его "антипод" - модификатор заставляющий IAR сохранить контекст некоторой функции (не прерывания) в стеке? :help:

Так он ведь и так сохраняет нужный контекст - все ресурсы (регистры), которые могут быть порушены вызовом функции, но должны остаться целостными, сохраняются в прологе и восстанавливаются в эпилоге. Или что Вам нужно, задачу полнее обрисуйте?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

так в том примере вызывается функция strcmp, а если все сделать руками, то сохранит только нужные регистры

      6          //Также линкеру запретить w22
      7          #pragma diag_suppress=Ta006

   \                                 In segment CODE, align 2, keep-with-next
      8          __interrupt void IntLong(void)
   \                     IntLong:
      9          {
   \   00000000   93BA               ST      -Y, R27
   \   00000002   93AA               ST      -Y, R26
   \   00000004   93FA               ST      -Y, R31
   \   00000006   93EA               ST      -Y, R30
   \   00000008   931A               ST      -Y, R17
   \   0000000A   930A               ST      -Y, R16
   \   0000000C   B71F               IN      R17, 0x3F
     10            char *a=(char *)0x1234;
   \   0000000E   E3E4               LDI     R30, 52
   \   00000010   E1F2               LDI     R31, 18
     11            char *b=(char *)0x3456;
   \   00000012   E5A6               LDI     R26, 86
   \   00000014   E3B4               LDI     R27, 52
     12            while((*a++=*b++));
   \                     ??IntLong_0:
   \   00000016   910D               LD      R16, X+
   \   00000018   9301               ST      Z+, R16
   \   0000001A   2300               TST     R16
   \   0000001C   F7E1               BRNE    ??IntLong_0
     13          }
   \   0000001E   BF1F               OUT     0x3F, R17
   \   00000020   9109               LD      R16, Y+
   \   00000022   9119               LD      R17, Y+
   \   00000024   91E9               LD      R30, Y+
   \   00000026   91F9               LD      R31, Y+
   \   00000028   91A9               LD      R26, Y+
   \   0000002A   91B9               LD      R27, Y+
   \   0000002C   9518               RETI
     14          #pragma diag_default=Ta006

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Или что Вам нужно, задачу полнее обрисуйте?

Есть ШИМ на нулевом таймере, каждые 4 цикла которого надо менять его значение. Тактовая таймера равна тактовой Меги. Т.е. каждые 256 тактов МК влетает в прерывание и 3 раза из 4-х должен сделать три действия (сложить, сохранить и проверить) и выйти. Любые лишние сохранения там кушают драгоценный ресурс процессора - его такты. На каждый регистр - 4 такта. А при сохранении всех 15-ти - 60 тактов из 256 улетает "в трубу".

 

так в том примере вызывается функция strcmp, а если все сделать руками, то сохранит только нужные регистры

Хм... А это Мысль! У меня там вызовов библиотечных функций нет, но два CALL-а там точно есть. Возможно при их наличие IAR-а сохраняет регистры "на полную катушку". В понедельник попробую без CALL-ов...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Есть ШИМ на нулевом таймере, каждые 4 цикла которого надо менять его значение. Тактовая таймера равна тактовой Меги. Т.е. каждые 256 тактов МК влетает в прерывание и 3 раза из 4-х должен сделать три действия (сложить, сохранить и проверить) и выйти. Любые лишние сохранения там кушают драгоценный ресурс процессора - его такты. На каждый регистр - 4 такта. А при сохранении всех 15-ти - 60 тактов из 256 улетает "в трубу".

Все ясно. Вы вызываете из прерывания другую функцию и поэтому компилятор просто обязан сохранить все scratch регистры - он ведь не знает, какие из них используются вызываемой функции, поэтому для обеспечения целостности работы программы он должен их все сохранить. Количество этих регистров у EWAVR достаточно велико - почти половина регистрового файла. Выход тут простой - не надо из обработчика прерываний вызывать функций, либо можно вызывать только встраиваемые (inline) - тело встраиваемой функции видно комплятору, он в этом случае "знает" какие регистры используются и сохраняет только их. Когда комплятор видит весь код обработчика прерываний, он сохраняет только то, что надо.

 

Хм... А это Мысль! У меня там вызовов библиотечных функций нет, но два CALL-а там точно есть. Возможно при их наличие IAR-а сохраняет регистры "на полную катушку". В понедельник попробую без CALL-ов...

Именно! Не вызывайте функции - чтобы не было call, и все будет в лучшем виде.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

он ведь не знает, какие из них используются вызываемой функции,

Не понял, а кому кроме него знать как он распределит регистры для этой функции? Не я же их распределяю...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Не понял, а кому кроме него знать как он распределит регистры для этой функции? Не я же их распределяю...

А как же принцип раздельной компиляции? Функция-то может вообще в библиотеке лежать, и компилятор к ней доступа не имеет - ее потом уже линкер подлинкует. Компилятор обрабатывает один текущий файл и видит только код этого файла. Если используется встраиваемая фукнция, т.е. тело которой непосредственно встраивается в точку вызова, то тут да, комплятор все видит и сохраняет только то, что используется. А если фукнция вызываемая, то тут он не видит конкретного кода этой вызываемой фуникции, не знает, какие конкретно регистры в ней используются, поэтому сохраняет весь набор scratch регистров. Это для него единственный способ обеспечить целостность программы. Вывод: для эффективности не использовать вызовов функции в ISR либо использовать только встраиваемые фукнции. Для пущей уверенности - чтобы компилятор точно встроил тело функции (иногда он "умничает" и делает вызов), использовать для этой функции прагму принудительного встраивания (#pragma inline=forced).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

... А если фукнция вызываемая, то тут он не видит конкретного кода этой вызываемой фуникции, не знает, какие конкретно регистры в ней используются, поэтому сохраняет весь набор scratch регистров. ...

Что-то я не все понимаю. Компиляция раздельная - понимаю, но сохранение регистров ведь в части компиляции, когда сама функция компилируется, а не вызов ее. Или?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Что-то я не все понимаю. Компиляция раздельная - понимаю, но сохранение регистров ведь в части компиляции, когда сама функция компилируется, а не вызов ее. Или?

Представьте, что вы компилятор. У вас есть соглашения о сохраняемых регистрах - конкретно у EWAVR примерно половина регистров при вызове фукнции предоставляется в использование вызываемой фукнции без сохранения - бери и юзай, как хошь, в этих регистрах вызывающая функция ничего не хранит - это так называемые scratch регистры, а вторая половина регистров, если вызываемая фукнция "хочет" их поиспользовать, должна быть сохранена - это так называемые local или preserved регистры.

 

Вот вам предлагается сгенерить код для ISR. В этом коде присутствует вызов функции. Вы на него генерируете инструкцию call. НО! Поскольку ISR - это не обычная функция и получает управление асинхронно по отношению к потоку управления остальной программы, то в нем должны быть сохранены ВСЕ регистры, которые могут быть использованы. Здесь про local регистры нам волноваться не надо - если вызываемаая фукнция (потроха которой мы не видим) будет их использовать - она сама их сохранит, столько, сколько ей надо. Но вот scratch регистры она сохранять не будет (по вышеописанному соглашению). Поэтому мы просто обязаны их сохранить сами. Поскольку мы не знаем, какие именно регистры вызываемая фукнция будет использовать, мы должны сохранить их все. Отсюда и неэффективность. Если же фукнцию сделать встраиваемой, т.е. когда ее тело видно нам на момент кодогенерации, то мы, видя, что в ней используется, сохраняем только используемые регистры. Все логично.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...