AHTOXA 25 February 20, 2020 Posted February 20, 2020 · Report post В IdleProc нельзя вызывать ни sleep(), ни другие сервисы оси, на то она и IdleProc :-) Ну чудес-то не бывает. Простым изменением участка кода программы нельзя запретить/разрешить прерывания. Где-то вы их запрещаете. При переключении процесса происходит сохранение контекста одного процесса, и восстановление другого. Раз в одном процессе прерывания работают, а в другом - нет, то запрет происходит именно при переключении контекста. Вот и всё. Quote Share this post Link to post Share on other sites More sharing options...
abi 0 February 25, 2020 Posted February 25, 2020 · Report post 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. Quote Share this post Link to post Share on other sites More sharing options...
AHTOXA 25 February 25, 2020 Posted February 25, 2020 · Report post Хм. Очень интересно. Неужели это косяк в порте под AVR? Или всё же это особенность работы XMEGA... К сожалению, я не знаком с АВР-ками, поэтому не знаю, что посоветовать. Возможно, @dxp что-то подскажет. Если вспомнит, конечно :-) Quote Share this post Link to post Share on other sites More sharing options...
dxp 211 February 26, 2020 Posted February 26, 2020 · Report post 9 часов назад, AHTOXA сказал: Возможно, @dxp что-то подскажет. Если вспомнит, конечно :-) Почти всё забыл (17 лет уж тому), но насколько ещё что-то помню, в тех AVR не было никиких PMIC и система прерываний была одноуровневая. Потом портом под AVR занимался другой человек, может он бы что-то мог сказать, но, к сожалению, он давно не выходит на связь. Я даже не в курсе, что включает поддержку XMEGA и есть ли она там. P.S. Насколько помню, прямую передачу управления использовать не рекомендуется, этот способ только если по-другому уже никак. Неужели в xmega нельзя найти свободное прерывание? В примерах даже обычные AVR через прерывание передают управление. Quote Share this post Link to post Share on other sites More sharing options...
AlexG 3 March 11, 2020 Posted March 11, 2020 · Report post У меня есть стабильно работающий порт ScmRTOS 4.0 на Xmega/IAR и нестабильный порт ScmRTOS 5.1 (бросил разбирательства когда проект с 4.0 заработал). Также, если поискать, были чужие порты на Xmega/GCC. Могу выложить, если кому-то нужно. Отличий от портов на обычные AVR там много. Quote Share this post Link to post Share on other sites More sharing options...
AHTOXA 25 March 11, 2020 Posted March 11, 2020 · Report post Конечно выкладывайте, думаю, кому-нибудь непременно пригодится. Quote Share this post Link to post Share on other sites More sharing options...
AlexG 3 March 14, 2020 Posted March 14, 2020 · Report post Выкладываю фрагмент из одного из текущих проектов. Внутри 4.00 рабочая и 5.1.0 - не очень. scmrtos4xmega.zip Quote Share this post Link to post Share on other sites More sharing options...