AndreyS 0 30 августа, 2012 Опубликовано 30 августа, 2012 · Жалоба Добрый день. Подскажите пожалуйста, как заставить Keil (проект на Си) не укладывать сохранение в стек регистров и соответственно не восстанавливать их из стека? Пояснение: Объявляю функцию с параметром interrupt 0 и в теле ее вызываю проверку с битовой переменной, если переменная возведена, то делаю прямой переход (через #pragma asm) на требуемый внешний обработчик. Если нет, то хочу отсюда выйти. В конце внешнего обработчика конечно стоит RETI (средствами Си, потому что этот внешний обработчик есть другая прошивка) и по нему прерывание нормально завершится. Но вот при такой конструкции Кеил упорно обрамляет вызов прерывания сохранением полного набора регистров в стек и соответственно его полного восставноления. Как это обрамление отключить?? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
kolobok0 0 30 августа, 2012 Опубликовано 30 августа, 2012 · Жалоба ...Как это обрамление отключить?? уровень оптимизации проверьте. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
barabek 0 30 августа, 2012 Опубликовано 30 августа, 2012 · Жалоба Как это обрамление отключить?? void ISRsome(void)interrupt 0 using 1 Так? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Edit2007 3 31 августа, 2012 Опубликовано 31 августа, 2012 · Жалоба Для interrupt функций ВСЕГДА сохраняются регистры, опция usng 1 (2,3,0) лишь уменьшает их количество, поскольку сохраняет в стек регистр статуса и меняет банк, при выходе из функции банк восстанавливается. Остальные регистры сохраняются-восстанавливаются при необходимости. Выход из Interrupt функции осуществляется командой RETI. Все это делается для того, что бы при возвращении в основную программу оставить неизменными регистры, используемые в обработчике прерываний. Для Interrupt функций компилятор делает следующее. По указанному вектору располагает команду перехода на функцию. В функции сохраняет используемые регистры (ACC, DPTR и т.д), переключает банк рабочих регистров (если есть опция USING) и выполняет тело функции. По завершении функции все регистры восстанавливаются и выход осуществляется командой RETI. поэтому ваш подход Объявляю функцию с параметром interrupt 0 и в теле ее вызываю проверку с битовой переменной, если переменная возведена, то делаю прямой переход (через #pragma asm) на требуемый внешний обработчик в принципе не верен. Функцию надо объявлять без параметра interrupt. А если вы в функции проверяете именно флаг этого прерывания, то вообще непонятно зачем все так сложно. При возникновении прерывания, если оно разрешено, управление автоматически передается на соответствующий вектор. Если хотите работать по опросу, то после проверки флага надо вызывать обычную функцию. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
barabek 0 31 августа, 2012 Опубликовано 31 августа, 2012 · Жалоба поэтому ваш подход в принципе не верен. Функцию надо объявлять без параметра interrupt. Хм. Я ТС понял несколько иначе. Думаю, что битовая переменная у него имеется ввиду другая. И регистры, думаю, он имеет ввиду те, что не используются в прерывании, но все равно сохраняются. В общем, пусть он сам прокоментирует. А вот про вызов внешней функции из прерывания Вы не зря сказали. Я и забыл про это, хотя ловился на этих граблях. При использованиии using настоятельно не рекомендую вызывать из прерывания другие функции. Можно нарваться. И если используются прерывания с разными приоритетами, то для них обязательно использовать using с разными банками. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AndreyS 0 31 августа, 2012 Опубликовано 31 августа, 2012 · Жалоба Добрый день. Поясняю. Решил написать бузагрузчик с максимальным использованием Си. Для этого выбрал следующий путь для себя: 1. Удобнее всего объявить прерывания в Си и все в одном файле, тогда всегда легко можно обработчик найти (спустя время) и подкорректировать. 2. Для того что бы прерывания передавались внешней прошивке зафиксировал в битовой области флаг состояния бутзагрузчика (внешняя/бут) и это определение также дал коду внешней прошивки (что бы она его не меняла). 3. В обработчике прерывания, всех прерываний проца, (который на си объявлен) хотел поставить простую конструкцию if (IN_BOOT) { процедура бутзагрузчика, если она есть } else { #pragma asm JMP OFFSET_EXT_PROGRAM+"адрес вектора прерывания" #endasm } Что получилось. Компилятор на пустое объявление прерывания тут же вставляет PUSH ACC и POP ACC На объявление прерывания с using еще и PSW На мою конструкцию вставляет полный набор всех регистров и DPTR (даже в случае отсутствия процедуры обработки прерывания в бутзагрузчике (ну просто if и else с asmовой вставкой). Решил пока переписать все объявления прерываний на ассемблере в стартапе и там на каждый обработчик поставил свой макрос Interrupt MACRO COUNTER,VECTOR_BOOT_INT JNB BOOT_in_boot_f,$+4 LCALL VECTOR_BOOT_INT RETI LJMP BASE_ADR_EXT_PROG+COUNTER COUNTER SET COUNTER+8 ENDM Ни и пришлось описать заранее названия всех обработчик прерываний на Си (которые теперь в Си стали просто процедурами) и в стартап файл их EXTRN"ить :) Но это мне не нравится, потому как идея была изначально делать на асме все по минимуму ибо видимо лень мне нажимать на клавиатуру (хотелось больше сделать все средствами компилятора). Я правильно понимаю что нет (пока я не нашел об этом информации) возможности в Keil x51 для прерываний (и видимо для функций) запретить автоматическое сохранение регистров в стек (понятно что это рукоблудство может развалить всю прогу, но я надеялся что можно настройкой или прагмой для определенной области это сделать). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Edit2007 3 3 сентября, 2012 Опубликовано 3 сентября, 2012 · Жалоба В Keil отключить сохранение регистров в функциях прерывания нельзя. Другие компиляторы скорее всего тоже этого не допускают (прерывание все таки). Реализовать вашу конструкцию можно только через AMS. Либо в режиме загрузчика использовать пулинг (опрос). Вот как я это делал. младшие адреса (1-2 Кб) - приложение загрузчика. Зашивается прграмматором. При подаче питания стартует всегда. При отсутствии кода (или ошибке) может зациклить управление внутри себя в ожидании команд. в загрузчике в стартапе по всем векторам ставлю переход на величину смещения кода основного приложения. Сам загрузчик использует только пулинг для работы с перефирией. старшие адреса - основное приложение. Сюда управление передается от загрузчика после проверки кода. Прерывания обрабатываются штатно, хоть и с задержкой на выполнение команды перехода. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Артём__ 0 3 сентября, 2012 Опубликовано 3 сентября, 2012 · Жалоба В Keil отключить сохранение регистров в функциях прерывания нельзя. Другие компиляторы скорее всего тоже этого не допускают (прерывание все таки). В GCC делается так: void IsrHandler(void) __attribute__ ( ( naked ) ) { } Может и в Кейле есть подобное... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Палыч 6 3 сентября, 2012 Опубликовано 3 сентября, 2012 · Жалоба Может и в Кейле есть подобное... Увы! Нет ничего подобного... Обработчик прерывания не будет сохранять регистры, если его тело - пусто. В противном случае, используемые в обработчике регистры (или все регистры) сохраняются. The interrupt attribute affects the object code of the function as follows: - When required, the contents of ACC, B, DPH, DPL, and PSW are saved on the stack at function invocation time. - All working registers used in the interrupt function are stored on the stack if a register bank is not specified with the using attribute. - The working registers and special registers that were saved on the stack are restored before exiting the function. - The function is terminated by the 8051 RETI instruction. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AndreyS 0 4 сентября, 2012 Опубликовано 4 сентября, 2012 · Жалоба Добрый день всем. Спасибо Всем за ответы. Значит оставлю все определения в стартапе на асме. Вот только как заставить Кеил для процедур сохранить используемые регистры в стек? А то он в моих процедурах (которые на самом деле прерывания) не сохранил в стек ничего. Видимо думает что процедура не вызывается под другой (и время жизни регистра A и R7 маленькое). Пробовал вызвать процедуру через указатель, в надежде что Кеил вставит сохранение регистров. Ничего подобного не произошло. Пока добавил в макрос определения прерывания полное сохранение в стек регистров и их восстановление. Просто таблица прерываний бутзагрузчика стала большой. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Палыч 6 4 сентября, 2012 Опубликовано 4 сентября, 2012 · Жалоба Вот только как заставить Кеил для процедур сохранить используемые регистры в стек? Вероятно, никак, поскольку: Assembler functions may change all register contents in the currently selected register bank as well as the contents of the ACC, B, DPTR, and PSW registers. When invoking a C function from assembly, assume that these registers are destroyed by the C function that is called. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Edit2007 3 5 сентября, 2012 Опубликовано 5 сентября, 2012 · Жалоба Можно обмануть всех. Допустим в МК используется 5 аппаратных векторов прерывания (IRQ0...IRQ4) Тогда можно объявить функцию обработки прерывания по вектору IRQ5 void IRQ_FUNC(void) interrupt 5 // using N при необходимости {...} Причем аппаратно на этот вектор никогда перехода не будет. В ассемблере передавать управление ей. Только учесть - по адресу данного вектора (0x3 + IRQ_N * 7 (в нашем случа IRQ_N это 5)) будет располагаться команда перехода. Keil сформирует сохранение и восстановление ИСПОЛЬЗУЕМЫХ ДАННОЙ ФУНКЦИЕЙ РЕГИСТРОВ. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AndreyS 0 5 сентября, 2012 Опубликовано 5 сентября, 2012 (изменено) · Жалоба Можно обмануть всех. Допустим в МК используется 5 аппаратных векторов прерывания (IRQ0...IRQ4) Тогда можно объявить функцию обработки прерывания по вектору IRQ5 Хорошая мысль. Правда в кейле заложено 32 прерывание для 51 контроллера (вернее 32 вектора), не знаю что будет с ним если указать номер больше чем 31. А так было бы хорошо. В контроллере с 21 вектором прерываний продублировать их в старшие от 21 и до 42. И вот старшие - это прерывания бутзагрузчика. Тогда стартап файл будет короче. Попробовал сделать более 32 вектора. Ругается кейл А мысль хорошая. Главное потом в бутзагрузчике не забыть что вектор номер 10, скажем, это на самом деле вектор номер 0 :) Изменено 5 сентября, 2012 пользователем AndreyS Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться