artemkad 69 22 июня, 2007 Опубликовано 22 июня, 2007 · Жалоба Появилась тут мысля. У IAR-а для не сохранения контекста в прерывании служит __raw. А есть ли его "антипод" - модификатор заставляющий IAR сохранить контекст некоторой функции (не прерывания) в стеке? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Rst7 5 22 июня, 2007 Опубликовано 22 июня, 2007 · Жалоба Используйте модификатор __interrupt и запретите лишние варнинги. При вызове не забудьте преобразовать тип функции, вообщем смотри тут, пост номер 30. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
artemkad 69 22 июня, 2007 Опубликовано 22 июня, 2007 (изменено) · Жалоба вообщем смотри тут, пост номер 30 Ну собственно после той темы я и задался этим вопросом. Да и хотелось бы, чтобы сохранялись только используемые в функции регистры, а не все кроме возможных глобальных. Изменено 22 июня, 2007 пользователем ArtemKAD Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 56 22 июня, 2007 Опубликовано 22 июня, 2007 · Жалоба Появилась тут мысля. У IAR-а для не сохранения контекста в прерывании служит __raw. А есть ли его "антипод" - модификатор заставляющий IAR сохранить контекст некоторой функции (не прерывания) в стеке? Так он ведь и так сохраняет нужный контекст - все ресурсы (регистры), которые могут быть порушены вызовом функции, но должны остаться целостными, сохраняются в прологе и восстанавливаются в эпилоге. Или что Вам нужно, задачу полнее обрисуйте? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Rst7 5 22 июня, 2007 Опубликовано 22 июня, 2007 · Жалоба Ну собственно после той темы я и задался этим вопросом. Да и хотелось бы, чтобы сохранялись только используемые в функции регистры, а не все кроме возможных глобальных. так в том примере вызывается функция 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 69 22 июня, 2007 Опубликовано 22 июня, 2007 · Жалоба Или что Вам нужно, задачу полнее обрисуйте? Есть ШИМ на нулевом таймере, каждые 4 цикла которого надо менять его значение. Тактовая таймера равна тактовой Меги. Т.е. каждые 256 тактов МК влетает в прерывание и 3 раза из 4-х должен сделать три действия (сложить, сохранить и проверить) и выйти. Любые лишние сохранения там кушают драгоценный ресурс процессора - его такты. На каждый регистр - 4 такта. А при сохранении всех 15-ти - 60 тактов из 256 улетает "в трубу". так в том примере вызывается функция strcmp, а если все сделать руками, то сохранит только нужные регистры Хм... А это Мысль! У меня там вызовов библиотечных функций нет, но два CALL-а там точно есть. Возможно при их наличие IAR-а сохраняет регистры "на полную катушку". В понедельник попробую без CALL-ов... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 56 23 июня, 2007 Опубликовано 23 июня, 2007 · Жалоба Есть ШИМ на нулевом таймере, каждые 4 цикла которого надо менять его значение. Тактовая таймера равна тактовой Меги. Т.е. каждые 256 тактов МК влетает в прерывание и 3 раза из 4-х должен сделать три действия (сложить, сохранить и проверить) и выйти. Любые лишние сохранения там кушают драгоценный ресурс процессора - его такты. На каждый регистр - 4 такта. А при сохранении всех 15-ти - 60 тактов из 256 улетает "в трубу". Все ясно. Вы вызываете из прерывания другую функцию и поэтому компилятор просто обязан сохранить все scratch регистры - он ведь не знает, какие из них используются вызываемой функции, поэтому для обеспечения целостности работы программы он должен их все сохранить. Количество этих регистров у EWAVR достаточно велико - почти половина регистрового файла. Выход тут простой - не надо из обработчика прерываний вызывать функций, либо можно вызывать только встраиваемые (inline) - тело встраиваемой функции видно комплятору, он в этом случае "знает" какие регистры используются и сохраняет только их. Когда комплятор видит весь код обработчика прерываний, он сохраняет только то, что надо. Хм... А это Мысль! У меня там вызовов библиотечных функций нет, но два CALL-а там точно есть. Возможно при их наличие IAR-а сохраняет регистры "на полную катушку". В понедельник попробую без CALL-ов... Именно! Не вызывайте функции - чтобы не было call, и все будет в лучшем виде. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
artemkad 69 25 июня, 2007 Опубликовано 25 июня, 2007 · Жалоба он ведь не знает, какие из них используются вызываемой функции, Не понял, а кому кроме него знать как он распределит регистры для этой функции? Не я же их распределяю... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 56 25 июня, 2007 Опубликовано 25 июня, 2007 · Жалоба Не понял, а кому кроме него знать как он распределит регистры для этой функции? Не я же их распределяю... А как же принцип раздельной компиляции? Функция-то может вообще в библиотеке лежать, и компилятор к ней доступа не имеет - ее потом уже линкер подлинкует. Компилятор обрабатывает один текущий файл и видит только код этого файла. Если используется встраиваемая фукнция, т.е. тело которой непосредственно встраивается в точку вызова, то тут да, комплятор все видит и сохраняет только то, что используется. А если фукнция вызываемая, то тут он не видит конкретного кода этой вызываемой фуникции, не знает, какие конкретно регистры в ней используются, поэтому сохраняет весь набор scratch регистров. Это для него единственный способ обеспечить целостность программы. Вывод: для эффективности не использовать вызовов функции в ISR либо использовать только встраиваемые фукнции. Для пущей уверенности - чтобы компилятор точно встроил тело функции (иногда он "умничает" и делает вызов), использовать для этой функции прагму принудительного встраивания (#pragma inline=forced). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DogPawlowa 0 25 июня, 2007 Опубликовано 25 июня, 2007 · Жалоба ... А если фукнция вызываемая, то тут он не видит конкретного кода этой вызываемой фуникции, не знает, какие конкретно регистры в ней используются, поэтому сохраняет весь набор scratch регистров. ... Что-то я не все понимаю. Компиляция раздельная - понимаю, но сохранение регистров ведь в части компиляции, когда сама функция компилируется, а не вызов ее. Или? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 56 25 июня, 2007 Опубликовано 25 июня, 2007 · Жалоба Что-то я не все понимаю. Компиляция раздельная - понимаю, но сохранение регистров ведь в части компиляции, когда сама функция компилируется, а не вызов ее. Или? Представьте, что вы компилятор. У вас есть соглашения о сохраняемых регистрах - конкретно у EWAVR примерно половина регистров при вызове фукнции предоставляется в использование вызываемой фукнции без сохранения - бери и юзай, как хошь, в этих регистрах вызывающая функция ничего не хранит - это так называемые scratch регистры, а вторая половина регистров, если вызываемая фукнция "хочет" их поиспользовать, должна быть сохранена - это так называемые local или preserved регистры. Вот вам предлагается сгенерить код для ISR. В этом коде присутствует вызов функции. Вы на него генерируете инструкцию call. НО! Поскольку ISR - это не обычная функция и получает управление асинхронно по отношению к потоку управления остальной программы, то в нем должны быть сохранены ВСЕ регистры, которые могут быть использованы. Здесь про local регистры нам волноваться не надо - если вызываемаая фукнция (потроха которой мы не видим) будет их использовать - она сама их сохранит, столько, сколько ей надо. Но вот scratch регистры она сохранять не будет (по вышеописанному соглашению). Поэтому мы просто обязаны их сохранить сами. Поскольку мы не знаем, какие именно регистры вызываемая фукнция будет использовать, мы должны сохранить их все. Отсюда и неэффективность. Если же фукнцию сделать встраиваемой, т.е. когда ее тело видно нам на момент кодогенерации, то мы, видя, что в ней используется, сохраняем только используемые регистры. Все логично. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться