Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: антипод модификатора __raw
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Cредства разработки для МК > IAR
ArtemKAD
Появилась тут мысля. У IAR-а для не сохранения контекста в прерывании служит __raw. А есть ли его "антипод" - модификатор заставляющий IAR сохранить контекст некоторой функции (не прерывания) в стеке? help.gif
Rst7
Используйте модификатор __interrupt и запретите лишние варнинги. При вызове не забудьте преобразовать тип функции, вообщем смотри тут, пост номер 30.
ArtemKAD
Цитата
вообщем смотри тут, пост номер 30

Ну собственно после той темы я и задался этим вопросом. Да и хотелось бы, чтобы сохранялись только используемые в функции регистры, а не все кроме возможных глобальных.
dxp
Цитата(ArtemKAD @ Jun 22 2007, 18:12) *
Появилась тут мысля. У IAR-а для не сохранения контекста в прерывании служит __raw. А есть ли его "антипод" - модификатор заставляющий IAR сохранить контекст некоторой функции (не прерывания) в стеке? help.gif

Так он ведь и так сохраняет нужный контекст - все ресурсы (регистры), которые могут быть порушены вызовом функции, но должны остаться целостными, сохраняются в прологе и восстанавливаются в эпилоге. Или что Вам нужно, задачу полнее обрисуйте?
Rst7
Цитата(ArtemKAD @ Jun 22 2007, 16:18) *
Ну собственно после той темы я и задался этим вопросом. Да и хотелось бы, чтобы сохранялись только используемые в функции регистры, а не все кроме возможных глобальных.


так в том примере вызывается функция 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
ArtemKAD
Цитата
Или что Вам нужно, задачу полнее обрисуйте?

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

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

Хм... А это Мысль! У меня там вызовов библиотечных функций нет, но два CALL-а там точно есть. Возможно при их наличие IAR-а сохраняет регистры "на полную катушку". В понедельник попробую без CALL-ов...
dxp
Цитата(ArtemKAD @ Jun 23 2007, 00:36) *
Есть ШИМ на нулевом таймере, каждые 4 цикла которого надо менять его значение. Тактовая таймера равна тактовой Меги. Т.е. каждые 256 тактов МК влетает в прерывание и 3 раза из 4-х должен сделать три действия (сложить, сохранить и проверить) и выйти. Любые лишние сохранения там кушают драгоценный ресурс процессора - его такты. На каждый регистр - 4 такта. А при сохранении всех 15-ти - 60 тактов из 256 улетает "в трубу".

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

Цитата(ArtemKAD @ Jun 23 2007, 00:36) *
Хм... А это Мысль! У меня там вызовов библиотечных функций нет, но два CALL-а там точно есть. Возможно при их наличие IAR-а сохраняет регистры "на полную катушку". В понедельник попробую без CALL-ов...

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

Не понял, а кому кроме него знать как он распределит регистры для этой функции? Не я же их распределяю...
dxp
Цитата(ArtemKAD @ Jun 25 2007, 14:03) *
Не понял, а кому кроме него знать как он распределит регистры для этой функции? Не я же их распределяю...

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

Что-то я не все понимаю. Компиляция раздельная - понимаю, но сохранение регистров ведь в части компиляции, когда сама функция компилируется, а не вызов ее. Или?
dxp
Цитата(Dog Pawlowa @ Jun 25 2007, 16:05) *
Что-то я не все понимаю. Компиляция раздельная - понимаю, но сохранение регистров ведь в части компиляции, когда сама функция компилируется, а не вызов ее. Или?

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

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