Jump to content
    

XMEGA прерывания

В IdleProc нельзя вызывать ни sleep(), ни другие сервисы оси, на то она и IdleProc :-)

Ну чудес-то не бывает. Простым изменением участка кода программы нельзя запретить/разрешить прерывания. Где-то вы их запрещаете. При переключении процесса происходит сохранение контекста одного процесса, и восстановление другого. Раз в одном процессе прерывания работают, а в другом - нет, то запрет происходит именно при переключении контекста. Вот и всё.

 

Share this post


Link to post
Share on other sites

On 2/20/2020 at 1:23 PM, AHTOXA said:

Раз в одном процессе прерывания работают, а в другом - нет, то запрет происходит именно при переключении контекста.

Нашел причину. Попробую объяснить. Проект настроен на прямую передачу управления, т.е. #define scmRTOS_CONTEXT_SWITCH_SCHEME 0. Для примера запускаем проект с одним процессом.

template<> void TProc1::exec()
{
  for(;;)
  {
    sleep(10);
    delay_ms(500);
  }
}

1. Заходим в sleep(10), выставляем timeout, сбрасываем флаг готовности процесса и выполняем перепланировку Kernel.scheduler(), т.к. рабочий процесс один и он ушел в спячку, система переключится на процесс IdleProc.

2. Периодически через заданный интервал времени от системного таймера возникают прерывания, в обработчике функция Kernel.system_timer() проверяет флаг готовности процесса Proc1. Если готовности нет, прерывание завершается без перепланировки и система продолжает оставаться в IdleProc. Тут отмечу, что выход из обработчика прерывания без перепланировки выполняется командой RETI, контроллер прерываний при этом сбрасывает флаг в PMIC.STATUS. Далее контроллер готов к выполнению других прерываний, если они есть в очереди или когда возникнут новые.

3. Если флаг готовности процесса Proc1 установлен, в обработчике прерывания системного таймера произойдет перепланировка процессов в функции os_context_switcher. Тут немного подробнее, при вызове этой функции в RStаck процесса IdleProc запишется адрес возврата, в CStack сохранится SP, сохранятся состояние регистров, далее для выполнения Proc1, из стека Proc1 восстановится SP и регистры, т.е. все готово для продолжения выполнения этого процесса. В конце функции os_context_switcher выполняется команда RET, в результате которой попадаем сразу в Proc1 и продолжаем его выполнение. В итоге получается, что обработка прерывания осталась не завершена, команды RETI не было, флаг в PMIC.STATUS = 1, прерывания одного уровня работать не будут даже при SREG = 0x80. 

4. Далее по коду в Proc1, функция delay_ms(500) отработает без прерываний, зайдет в sleep(10), в которой произойдет перепланировка, восстановится процесс IdleProc, а т.к. он был ранее сохранен в обработчике прерывания, завершит его код с командой выхода RETI, и прерывания снова будут выполняться.

Подскажите, пожалуйста, может есть какие мысли? Пока думаю над таким вариантом: в конце функции os_context_switcher сделать проверку флага PMIC.STATUS, если флаг установлен, то выполнять выход командой RETI, если нет, то RET. Но тут есть один момент, IdleProc при возобновлении в обработчике прерывания будет завершать его командой RETI, т.е. прерывание уже было завершено ранее командой RETI, и тут снова RETI. 

Share this post


Link to post
Share on other sites

Хм. Очень интересно. Неужели это косяк в порте под AVR? Или всё же это особенность работы XMEGA...

К сожалению, я не знаком с АВР-ками, поэтому не знаю, что посоветовать. Возможно, @dxp что-то подскажет. Если вспомнит, конечно :-)

 

Share this post


Link to post
Share on other sites

9 часов назад, AHTOXA сказал:

Возможно, @dxp что-то подскажет. Если вспомнит, конечно :-)

Почти всё забыл (17 лет уж тому), но насколько ещё что-то помню, в тех AVR не было никиких PMIC и система прерываний была одноуровневая. Потом портом под AVR занимался другой человек, может он бы что-то мог сказать, но, к сожалению, он давно не выходит на связь. Я даже не в курсе, что включает поддержку XMEGA и есть ли она там.

 

P.S. Насколько помню, прямую передачу управления использовать не рекомендуется, этот способ только если по-другому уже никак. Неужели в xmega нельзя найти свободное прерывание? В примерах даже обычные AVR через прерывание передают управление.

Share this post


Link to post
Share on other sites

У меня есть стабильно работающий порт ScmRTOS 4.0 на Xmega/IAR и нестабильный порт ScmRTOS 5.1 (бросил разбирательства когда проект с 4.0 заработал). Также, если поискать, были чужие порты на Xmega/GCC. Могу выложить, если кому-то нужно. Отличий от портов на обычные AVR там много.

Share this post


Link to post
Share on other sites

Конечно выкладывайте, думаю, кому-нибудь непременно пригодится.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...