А как, к примеру, на СИ будет выглядеть типичный для ассемблера приём условного возврата из прерывания подстановкой адреса возврата в стеке?
Обычно никак, потому что типичный для ассма прием не обязан быть таковым для C/С++. Но в тех редких случаях когда это действительно нужно всегда можно на ассме и написать. Возьмите любую RTOS на С, там будут ассм вставки для того же переключения контекста.
ГЫММ.... А как, к примеру, на СИ будет выглядеть типичный для ассемблера приём условного возврата из прерывания подстановкой
Точно так же. Все РОНы имеют абсолютный адрес, включая TOS. Так в общем реализуется любая вытесняющая RTOS. На Си, есличо. Но можно и асм вставками. Не вижу проблемы. Тут не вставал вопрос такого рода. Тут товарисч утверждал глупые глупости про читаемость и объем исходников.
А без ассемблерных вставок аналогия по функционалу?
Даже пустой обработчик будет генерить пролог/эпилог, который для вашей задачи не нужен. Следовательно обработчик нужно делать naked и тогда внутри придется все писать на инлайн ассме.
Для прямой подмены адреса все равно минимум один регистр потребуется, да еще и х/з чего в sreg... Потом ведь все равно необходимо в исходную программу с ее значениями вернуться - так что пролог/эпилог должен быть ПОЛНЫМ.
BOB51, понятно, что раз есть обработчик прерывания плюс еще непонятно какая функция, то пролог/эпилог нужен, но не тот, что компилятор вам сгенерит по умолчанию. При входе в прерывание на стеке будет адрес возврата, затем, как минимум, в прологе сохранится пару регистров и теперь можно на стек кинуть адрес вашей функции, но RETI должна вызывать когда этот адрес на вершине, т.е. эпилог восстанавливающий пару регистров все поломает. Конечно можно сохраненные регистры сдвинуть и в освободившуюся дыру положить адрес функции, но тогда в самой функции придется некоторые регистры сохранять и восстанавливать повторно. И как вообще понять какие регистры этой функцией используются и требуют сохранения? Как вы их будет сохранять и восстанавливать без инлайн ассма? И в чем польза от подмены адреса возврата, нельзя просто включить прерывания в SREG без RETI?
УВЫ... При ассемблере таки выбор списка регистров, требующих сохранения в стеке и их возврат из стека в конце "вложенной программы" определяется программистом. В СИ это на усмотрение компилятора. Т.е. пролог/эпилог придется делать самому с учетом, что пролог выполняется при входе в прерывание, а эпилог при возврате из "вложенной программы" (удаляя пролог и эпилог от компилятора). Польза от такого приема для СИ относительна - можно просто поменять алгоритм для ухода от необходимости его применения. Но с точки зрения сравнения возможностей СИ и ассемблера это таки представляет интерес - "а вдруг есть то, чего я не знаю, но специалисты встречали?" и можно без инлайн асма обойтись.
Где то в архивах лежали. Однако ежли таковое есть, то и интерес имеется. Там рядышком ещё несколько забытых приемов, хош и более легко реализуемых стандартными СИшными функциями.
а можно, хотя бы, один пример реальной практической необходимости подмены адреса возврата из прерывания?
Так обсуждение идет как раз об этом практическом применении - РТОС. В обработчике расположен шедулер, который останавливает текущую задачу и реанимирует следующую в очереди. Для этого нужно сохранить контекст текущей, восстановить контекст рекомендуемой и подменить адрес возврата, что бы при выходе из шедулера программа ушла на эту задачу с точки ее прежнего останова.
Да и в случае, если у МК жесткая система приоритетов прерываний. Т. Е. даже при разрешении прерывания внутри текущего исполняемого не может быть выполнено прерывание более низкого уровня. (замена приоритетов проблематично/невозможна). Программу обслуживания пропустить/отложить нельзя, но и блокировка прерываний более низкого уровня не желательна. Иногда в mcs51 попадалось в давние времена.
КРАМ, что-то я не могу с тобой согласиться. текущая задача выполняется не в прерывании, чтобы в прерывании была необходимость подменить адрес на следующую задачу. шедулер просто для каждой задачи выделяет "квант" времени, и как я понимаю, это выделение времени для каждой задачи не связано с работой прерывания. я с РТОС не знаком, могу и ошибаться.
_________________ Мудрость приходит вместе с импотенцией... Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
..текущая задача выполняется не в прерывании, чтобы в прерывании была необходимость подменить адрес на следующую задачу...
именно так и происходит (вытесняющая логика работы): - прерывание шедуллера - внутри прерывания сохраняем регистры с которыми мы будем работать - меняем контекст (смена всех регистров, для продвинутых МК как правило это команды загрузка/выгрузка регистров в/из памяти) - восстанавливаем регистры которые использовали (уже в контексте другой задачи) - делаем возврат из прерывания (это общий схемотоз работы) явно тут не меняют в стеке команду возврата, а меняют сам стек (его адресацию)
кстати есть ещё перенос адреса возврата - это если стек чистит вызываемый. там перенос адреса возврата делается (выкидываются запушенные на стек параметры вызова).
К примеру для примитивного МК основная программа достаточно длинная. Обработчик прерывания (может и не один) тоже не десяток команд. Если делать обработку по флагу, выставляемому в прерывании, то нужно ждать завершения текущего участка основной программы. А надо таки побыстре "вне очереди" обслужить то "длинное прерывание"... Вот тут и приходиться делать подстановку с переходом на фрагмент обслуживания (сохраняя доступность остальных прерываний) и дальнейший возврат к основной программе. При нынешних МК с большим объёмом ресурсов и скоростями обработки вряд ли особо понадобится. Но лет 20-30 назад весьма полезно было.
Вот тут и приходиться делать подстановку с переходом на фрагмент обслуживания (сохраняя доступность остальных прерываний) и дальнейший возврат к основной программе.
В AVR же примитивный контроллер прерываний, насколько помню разрешать прерывания можно когда угодно потому я выше спрашивал зачем подменять адрес если можно просто прерывания разрешить и вызвать функцию прямо из обработчика, при этом компилятор будет видеть весь выполняемый в прерывании код и сможет вычислить какие регистры сохранять.
Так сказал же - а вдруг да прямая аналогия есть, но мне не ведома - интересна именно без ассемблерных вставок реализация/аналогия. Но не вариант с подменой содержимого указателей на функцию.
Бывает ДВА вида РТОС: кооперативная и вытесняющая. Кооперативная подразумевает наличие у каждой задачи права отдавать управление шедулеру по собственному разумению. Для этой РТОС вообще не нужны обязательные прерывания. Каждая задача в неактивном режиме знает где она завершила работу и где ее следует начать при ее вызове шедулером. Вытесняющая РТОС содержит задачи С БЕСКОНЕЧНЫМ ЦИКЛОМ. Каждая задача думает, что она одна и прервать ее можно только в прерывании. Поэтому тело шедулера обычно представляет собой колбэк в прерывании по систик-таймеру (любой таймер способный генерировать прерывания с каким то периодом - квантом времени РТОС). Так же прерывание может быть сгенерировано и иными событиями, в нем так же может быть вызван шедулер, который вне очереди поставит в исполнение задачу связанную с этим событием. В этой схеме есть только один способ менять задачи - подмена контекста, в который входит и текущий адрес исполнения задачи. Таким образом, заходим в шедулер с одной задачей, а выходим в другую.
Это зависит от сложности алгоритма. Помигать LED-ом или прочитать клаву - это суперпримитивные задачи. Макросы АСМа - это беспонтовый костыль. Чисто листинг сократить.
Вообще-то там не макрос, а Sub с параметрами. Дело не только в сокращении листинга. Написать и прочитать 6 строк гораздо проще, чем, например, 500 строк у ТС.
В том и дело, что простые. Текст понятен до уровня его исполнения. Алгоритм в нем вообще не читается. А под читабельностью понимается не код, а алгоритм.
Скорее всего, у нас разные алгоритмы, точнее, концепция программы. Пишу просто, МК большей частью последовательно выполняет текущие задачи. МК работает быстро, тем более на ассемблере, успевает. В свободном окне - обработка флагов прерываний, опрос кнопок. В эту концепцию предложенный код хорошо укладывается. Не нужно никаких операционных систем с их проблемами. У такого метода есть существенные преимущества.
Во первых, уже обсуждали как выглядит защита от дребезга. "Читать три раза подряд с заданным интервалом" - совершенно пустое мероприятие. Мало того, оно еще и блокирующее или требует специально выделенного таймера.
Почему пустое мероприятие? Много лет пользуюсь – никаких проблем. Если по условии задачи надо быстро выскочить, есть такая команда с флагом, по которому программа выскочит.
В третьих, AVR является RISC машиной, то есть вся математика возможна только с РОНами. А это значит, что регистр Keys - это РОН. Со всеми вытекающими последствиями для остального кода и его читабельности.
Keys может быть РОН, SRAM, РВВ и даже EEPROM. Выбор - на усмотрение разработчика.
Штобтызнал. Вот так выглядит функция подсчета CRC16 на Си. Абсолютно для любого контроллера любой разрядности.
Функции подсчета CRC16 у меня нет, сравнить не с чем. А при передаче пакета контрольная сумма считается. Сделано просто на основе простой суммы байтов. Этот метод вроде как стандартный для hex-файлов программатора. Вызвать передачу байта контрольной суммы просто. Например, в команде посылки пакета добавляется слово Check_Sum. Команда работает со всеми МК AVR. В принципе, одним словом можно вызвать и CRC16, но этого пока нет.
Сколько лет вы уже на свой современный ассемблер потратили? И не потому ли никому его не показываете, что вдруг именно он окажется хуже? )
Всё проще, пока не готово. Не проверены многие функции, не доработан отладчик, симулятор и т.д. Да ещё на форуме подбрасывают идеи. Та же команда чтения кнопок появилась из обсуждений на форуме.
Всё проще, пока не готово. Не проверены многие функции, не доработан отладчик, симулятор и т.д. Да ещё на форуме подбрасывают идеи. Та же команда чтения кнопок появилась из обсуждений на форуме.
Речь конкретно про ассемблер. У вас же, после стольких лет разработки, должен быть компилятор которому можно скормить исходник и получить hex, например?
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 18
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения