a9d 0 11 ноября, 2012 Опубликовано 11 ноября, 2012 · Жалоба Прямая уже готова. Там четыре уровня прерываний. И возможно с ними будут проблемы, но я пока что их не заметил. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Артём__ 0 11 ноября, 2012 Опубликовано 11 ноября, 2012 · Жалоба Там четыре уровня прерываний. И возможно с ними будут проблемы, но я пока что их не заметил. Допустим в программе задействованны два прерывания с разными приоритетами Int0 и Int1. Приоритет Int0 выше приоритета Int1. В некоторый момент времени возникло прерывание Int1, процессор начал его отрабатывать. И затем возникает прерывание Int0, которое вытесняет прерывание Int1. В конце прерывания Int0 выполняется ISR_Exit и если прерывание Int1 не успело инкрементировать Kernel.ISR_NestCount, то начнётся выполнятся переключение контекста. Прерывание Int1 потеряется и возможно будет заблокировано. То есть Kernel.ISR_NestCount не может быть использован со схемой прямого переключения контекста, если контроллер прерываний поддерживает вложенные приоритетные прерывания. Или я не прав? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
a9d 0 11 ноября, 2012 Опубликовано 11 ноября, 2012 (изменено) · Жалоба Так крит. секция на выходе из обработчика разрешит прерывания. Значит прерывание не будет вытеснено. Понял проблему нужно посмотреть что будет. Это можно решить только запретом прерывания перед ISR_Enter и разрешением после. Изменено 11 ноября, 2012 пользователем a9d Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ReAl 0 11 ноября, 2012 Опубликовано 11 ноября, 2012 · Жалоба То есть Kernel.ISR_NestCount не может быть использован со схемой прямого переключения контекста, если контроллер прерываний поддерживает вложенные приоритетные прерывания. Или я не прав? Обязанность сделать это правильно лежит на авторе порта. TISRW определяется в OS_Target.h. Если вложенных прерываний нет, то INLINE void ISR_Enter() { Kernel.ISR_NestCount++; } Если есть, то INLINE void ISR_Enter() { // STM8 can (atomically) increment byte in memory, but IAR 1.20 and 1.30 - can't :-( TCritSect cs; Kernel.ISR_NestCount++; } В данном конкретном случае STM8 можно было бы даже со вложенными прерываниями обойтись без крит. секции, но конкретные версии компилятора не умели использовать атомарную инструкцию инкремента байта в памяти. Более свежий компилятор не проверял, да и STM8 Discovery вернул хозяину. Да и времени нет. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Артём__ 0 11 ноября, 2012 Опубликовано 11 ноября, 2012 · Жалоба Это можно решить только запретом прерывания перед ISR_Enter и разрешением после. Если возможно запретить - зависит от архитектуры и компилятора. В данном конкретном случае STM8 можно было бы даже со вложенными прерываниями обойтись без крит. секции, но конкретные версии компилятора не умели использовать атомарную инструкцию инкремента байта в памяти. Перед этим "атомарным инкрементом" нет никаких других инструкций (push-ей, jump-ов и др)? Тогда можно обойтись без критической секции (или запрета прерываний). Иначе и TCritSect не поможет. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
a9d 0 11 ноября, 2012 Опубликовано 11 ноября, 2012 · Жалоба Вариант с крит секцией не подходит да и работать он не будет как задумывалось. Ведь сначала будет сохраняться состояние и в этот момент может произойти вытеснение. С запретом прерывания тоже не работает. Даже если запрет стоит самым первым, то перед ним все равно есть код где в программный стек сохраняются регистры. Думаю как это исправить. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Артём__ 0 11 ноября, 2012 Опубликовано 11 ноября, 2012 · Жалоба С запретом прерывания тоже не работает. Даже если запрет стоит самым первым, то перед ним все равно есть код где в программный стек сохраняются регистры. Думаю как это исправить. Смотря где запрет поставить... Как у CC25 выглядит таблица векторов? Если как у классических 51-ых (на каждый вектор кажеется выделялось 8 байт, в которые можно было вставить короткий обработчик или переход на длинную функцию). Если так, то можно первой же командой сделать запрет а потом вызывать обработчик. Всё это на асме придётся делать, наверное. PS. Нет ли в CC25 чего-нибудь наподобие xmeg-овского PMIC.STATUS? Может можно задействовать? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
a9d 0 11 ноября, 2012 Опубликовано 11 ноября, 2012 (изменено) · Жалоба Я тоже подумал про таблицу векторов. Там 8байт дано. Сейчас думаю как перед джампами лочить глобальное прерывание. Исправил таблицу векторов. Теперь проблемы с вытеснением точно нет. Изменено 11 ноября, 2012 пользователем a9d Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ReAl 0 11 ноября, 2012 Опубликовано 11 ноября, 2012 · Жалоба Вариант с крит секцией не подходит да и работать он не будет как задумывалось. Ведь сначала будет сохраняться состояние и в этот момент может произойти вытеснение.Речь идёт об TISRW ? Самое худшее, что произойдёт, так это будет несколько большее использование стека. Но оно при вложенных прерываниях и так бывает. Ну ещё дважды вызовется перепланировщик. Так он и так дважды вызовется, если во время отработки какого-то прерывания в очередь встанет следующее. Пусть прерывания разрешены работает какой-то процесс прерывание push-push-push начало ISR_Enter. Тут может быть сохранение состояния прерываний от TCritSect, но ещё не запретили, инкрементировать вложенность не успели Хопа! пошло другое прерывание push-push ISR_Enter - инкремент счётчика вложенности 0->1 обработка прерывания ISR_Exit - декремент счётчика, 1->0, перепланировка, тут уже другие стек и PC, мы уже не из этого прерывания "возвращаемся". Может вообще не из прерывания, а из sleep() или event.wait(), а из этого прерывания "вернёмся", когда тот первый процесс будет самым приоритетным. pop-pop-pop-pop возврат продолжение прерванного ISR_Enter - инкремент счётчика вложенности 0->1 обработка прерывания ISR_Exit - декремент счётчика, 1->0, перепланировка pop-pop возврат работа какого-то другого процесса Пусть прерывания запрещены работает какой-то процесс прерывание push-push-push ISR_Enter - инкремент счётчика вложенности 0->1 обработка прерывания ISR_Exit - декремент счётчика, 1->0, перепланировка pop-pop где-то тут перед концом возврата всё равно разрешение прерываний пошло второе, ранее отложенное прерывание push-push ISR_Enter - инкремент счётчика вложенности 0->1 обработка прерывания ISR_Exit - декремент счётчика, 1->0, перепланировка pop-pop-pop-pop "возврат" работа Что так, что так -- при наложении прерываний может оказаться две перепланировки. Если бы в первом варианте второе прерывание пришло капельку позже, после инкремента счетчика вложенности, то перепланировка была бы одна. Но стек всё равно на два прерывания. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
a9d 0 11 ноября, 2012 Опубликовано 11 ноября, 2012 · Жалоба Произойдет все немного по другому. Вошли в первое прерывание. До ISR_Enter вытеснили. Произошла перепланировка и мы влетаем повторно в первое прерывание. Ведь мы не успели сбросить флаг прерывания. И того у нас произошел ложный вызов прерывания. Это уже аварийная ситуация. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ReAl 0 11 ноября, 2012 Опубликовано 11 ноября, 2012 · Жалоба Возможно я что-то забыл по 8051-ым. Прервать текущее прерывание может только прерывание более высокого приоритета. Такого же -- не может. reti в конце прерывания более высокого приоритета очищает тот уровень прерывания, данный не очищает. После возврата в данное прерывание флаг-то не сброшен, но и уровень этого прерывания не очищен, так что повторного входа не произойдет. Иначе бы без никаких ОС сразу после ljmp из вектора мы бы заново входили в данное прерывание. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
a9d 0 11 ноября, 2012 Опубликовано 11 ноября, 2012 (изменено) · Жалоба Провел эксперимент. Повысил прерывание WDT. В системном таймере до обвертки вызываю прерывание WDT. Таки да повторного прерывания не происходит. Но контекст восстанавливается неправильно. Если произвести вытеснение после обвертки. То контекст восстанавливается верно. Изменено 11 ноября, 2012 пользователем a9d Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Артём__ 0 11 ноября, 2012 Опубликовано 11 ноября, 2012 · Жалоба Пусть прерывания разрешены работает какой-то процесс прерывание push-push-push начало ISR_Enter. Тут может быть сохранение состояния прерываний от TCritSect, но ещё не запретили, инкрементировать вложенность не успели Хопа! пошло другое прерывание push-push ISR_Enter - инкремент счётчика вложенности 0->1 обработка прерывания ISR_Exit - декремент счётчика, 1->0, перепланировка, тут уже другие стек и PC, мы уже не из этого прерывания "возвращаемся". Может вообще не из прерывания, а из sleep() или event.wait(), а из этого прерывания "вернёмся", когда тот первый процесс будет самым приоритетным. pop-pop-pop-pop возврат продолжение прерванного ISR_Enter - инкремент счётчика вложенности 0->1 обработка прерывания ISR_Exit - декремент счётчика, 1->0, перепланировка pop-pop возврат работа какого-то другого процесса Звучит логично. Возможно я был частично или совсем неправ, говоря о возможных проблемах. Пока сам не понял. а из этого прерывания "вернёмся", когда тот первый процесс будет самым приоритетным. То есть прерывание отложится на неизестное время и может вообще навсегда? А уровень так и будет заблокированным? Тагда это аварийная ситуация. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ReAl 0 11 ноября, 2012 Опубликовано 11 ноября, 2012 · Жалоба То есть прерывание отложится на неизестное время и может вообще навсегда? А уровень так и будет заблокированным? Тагда это аварийная ситуация.Возврат из прерывания. Само-то прерывание отработали и нужные флаги сбросило. А вот дальше... У STM8 уровень (всё запрещено и три уровня разрешённости) записан в двух битах статусного регистра. Для MCS51 с аппаратным отслеживанием по reti тут, похоже, таки бяка. Для рассмотрения и вложенные прерывания не нужны. Разблокировать может только выход по reti из любого переключения контекста. Но переключение может быть на возврат из some_event.wait() (и прерывание этот event и подняло), а там по дороге только ret. Хотя почему только ret? Собственно переключатель-то на асме написан, там можно и reti написать. Или делать переключение свободным отложенным прерыванием. Тогда из всех тех прерыываний вышли, все уровни очистили и только потом пойдёт прерывание переключения, кторое тоже за собой почистит. В системном таймере до обвертки вызываю прерывание WDT. Таки да повторного прерывания не происходит. Но контекст восстанавливается неправильно. Если произвести вытеснение после обвертки. То контекст восстанавливается верно. Ну тут помочь не могу. Это нужно бы копаться с живой платой и компилятором, а у меня нет ни времени, ни желания ни ещё одну версию IAR в виртуалбоксе ставить, ни с 51-ыми играться. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
a9d 0 11 ноября, 2012 Опубликовано 11 ноября, 2012 · Жалоба Определил причину. Из-за лишних переключений контекста происходило переполнение софтварного стека процесса Idle. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться