Перейти к содержанию
    

Прямая уже готова.

 

Там четыре уровня прерываний. И возможно с ними будут проблемы, но я пока что их не заметил.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Там четыре уровня прерываний. И возможно с ними будут проблемы, но я пока что их не заметил.

 

Допустим в программе задействованны два прерывания с разными приоритетами Int0 и Int1. Приоритет Int0 выше приоритета Int1.

В некоторый момент времени возникло прерывание Int1, процессор начал его отрабатывать. И затем возникает прерывание Int0,

которое вытесняет прерывание Int1. В конце прерывания Int0 выполняется ISR_Exit и если прерывание Int1 не успело инкрементировать

Kernel.ISR_NestCount, то начнётся выполнятся переключение контекста.

Прерывание Int1 потеряется и возможно будет заблокировано.

То есть Kernel.ISR_NestCount не может быть использован со схемой прямого переключения контекста, если контроллер прерываний поддерживает вложенные приоритетные прерывания.

 

Или я не прав?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Так крит. секция на выходе из обработчика разрешит прерывания. Значит прерывание не будет вытеснено.

 

 

Понял проблему нужно посмотреть что будет.

 

 

Это можно решить только запретом прерывания перед ISR_Enter и разрешением после.

Изменено пользователем a9d

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

То есть 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 вернул хозяину. Да и времени нет.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Это можно решить только запретом прерывания перед ISR_Enter и разрешением после.

 

Если возможно запретить - зависит от архитектуры и компилятора.

 

В данном конкретном случае STM8 можно было бы даже со вложенными прерываниями обойтись без крит. секции, но конкретные версии компилятора не умели использовать атомарную инструкцию инкремента байта в памяти.

Перед этим "атомарным инкрементом" нет никаких других инструкций (push-ей, jump-ов и др)?

Тогда можно обойтись без критической секции (или запрета прерываний). Иначе и TCritSect не поможет.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вариант с крит секцией не подходит да и работать он не будет как задумывалось. Ведь сначала будет сохраняться состояние и в этот момент может произойти вытеснение.

 

С запретом прерывания тоже не работает. Даже если запрет стоит самым первым, то перед ним все равно есть код где в программный стек сохраняются регистры. Думаю как это исправить.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

С запретом прерывания тоже не работает. Даже если запрет стоит самым первым, то перед ним все равно есть код где в программный стек сохраняются регистры. Думаю как это исправить.

Смотря где запрет поставить...

Как у CC25 выглядит таблица векторов?

Если как у классических 51-ых (на каждый вектор кажеется выделялось 8 байт, в которые можно было вставить короткий обработчик или переход на длинную функцию). Если так, то можно первой же командой сделать запрет а потом вызывать обработчик. Всё это на асме придётся делать, наверное.

 

PS. Нет ли в CC25 чего-нибудь наподобие xmeg-овского PMIC.STATUS? Может можно задействовать?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я тоже подумал про таблицу векторов. Там 8байт дано. Сейчас думаю как перед джампами лочить глобальное прерывание.

 

Исправил таблицу векторов. Теперь проблемы с вытеснением точно нет.

Изменено пользователем a9d

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вариант с крит секцией не подходит да и работать он не будет как задумывалось. Ведь сначала будет сохраняться состояние и в этот момент может произойти вытеснение.
Речь идёт об 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
  • "возврат"
  • работа

 

Что так, что так -- при наложении прерываний может оказаться две перепланировки.

 

Если бы в первом варианте второе прерывание пришло капельку позже, после инкремента счетчика вложенности, то перепланировка была бы одна. Но стек всё равно на два прерывания.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Произойдет все немного по другому.

 

Вошли в первое прерывание.

До ISR_Enter вытеснили. Произошла перепланировка и мы влетаем повторно в первое прерывание. Ведь мы не успели сбросить флаг прерывания. И того у нас произошел ложный вызов прерывания. Это уже аварийная ситуация.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Возможно я что-то забыл по 8051-ым.

 

Прервать текущее прерывание может только прерывание более высокого приоритета. Такого же -- не может.

 

reti в конце прерывания более высокого приоритета очищает тот уровень прерывания, данный не очищает.

 

После возврата в данное прерывание флаг-то не сброшен, но и уровень этого прерывания не очищен, так что повторного входа не произойдет. Иначе бы без никаких ОС сразу после ljmp из вектора мы бы заново входили в данное прерывание.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Провел эксперимент.

 

 

Повысил прерывание WDT.

В системном таймере до обвертки вызываю прерывание WDT. Таки да повторного прерывания не происходит. Но контекст восстанавливается неправильно.

 

Если произвести вытеснение после обвертки. То контекст восстанавливается верно.

Изменено пользователем a9d

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Пусть прерывания разрешены

  • работает какой-то процесс
  • прерывание
  • 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
  • возврат
  • работа какого-то другого процесса

Звучит логично.

Возможно я был частично или совсем неправ, говоря о возможных проблемах. Пока сам не понял.

 

а из этого прерывания "вернёмся", когда тот первый процесс будет самым приоритетным.

То есть прерывание отложится на неизестное время и может вообще навсегда? А уровень так и будет заблокированным? Тагда это аварийная ситуация.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

То есть прерывание отложится на неизестное время и может вообще навсегда? А уровень так и будет заблокированным? Тагда это аварийная ситуация.
Возврат из прерывания. Само-то прерывание отработали и нужные флаги сбросило.

А вот дальше...

 

У STM8 уровень (всё запрещено и три уровня разрешённости) записан в двух битах статусного регистра.

 

Для MCS51 с аппаратным отслеживанием по reti тут, похоже, таки бяка. Для рассмотрения и вложенные прерывания не нужны.

Разблокировать может только выход по reti из любого переключения контекста.

Но переключение может быть на возврат из some_event.wait() (и прерывание этот event и подняло), а там по дороге только ret.

Хотя почему только ret? Собственно переключатель-то на асме написан, там можно и reti написать.

 

Или делать переключение свободным отложенным прерыванием. Тогда из всех тех прерыываний вышли, все уровни очистили и только потом пойдёт прерывание переключения, кторое тоже за собой почистит.

 

В системном таймере до обвертки вызываю прерывание WDT. Таки да повторного прерывания не происходит. Но контекст восстанавливается неправильно.

Если произвести вытеснение после обвертки. То контекст восстанавливается верно.

Ну тут помочь не могу. Это нужно бы копаться с живой платой и компилятором, а у меня нет ни времени, ни желания ни ещё одну версию IAR в виртуалбоксе ставить, ни с 51-ыми играться.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Определил причину. Из-за лишних переключений контекста происходило переполнение софтварного стека процесса Idle.

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...