jeka 0 4 ноября, 2020 Опубликовано 4 ноября, 2020 · Жалоба Когда rtos ставить не хочется, а state машину внутри IRQ городить некрасиво, родилась мысль сделать механизм, который работает как yield(), но внутри IRQ. Т.е. выходит из IRQ, а при следующем вызове возобновляет исполнение с этого же места и сохраненным контекстом. exec_task: push {r0-r11,lr} mov32 r1,#core_task_sp str sp,[r1] ldr sp, [r0] ; sp=inline task stack pop {r0-r11,lr} bx lr task_yield: push {r0-r11,lr} ; save inline task state mov r12,sp mov32 r0,#core_task_sp ldr sp,[r0] ; sp=core stack pop {r0-r11,lr} str r12,[r0] bx lr end int init_task(uint32_t* task_stack_top, void* routine) { task_stack_top[-1]=(int)routine; return (int)(task_stack_top-13); } И простейший пример использования: init: task_common_sp=init_task_fpu(TASK_COMMON_STACK_TOP, (void*)&thread_in_irq); int result; TransferComplete_IRQHandler() { result=DGRAM_SENT; // timeout irq cancel exec_task_fpu(&task_common_sp); } Timeout_IRQHandler() {// во всех IRQ, которые вызывают один и тот же процесс, должен быть одинаковый приоритет result=TIMEOUT; // tx dma cancel exec_task_fpu(&task_common_sp); } int send_dgram(char* dgram) { // ... запускаем отправку через DMA, устанавливаем irq таймаута task_yield();// ждём окончания отправки return result; } int wait(int time) { // start_timeout_timer... task_yield(); } void thread_in_irq() { while (1) { int res=send_dgram("init"); if (res==TIMEOUT) ...; wait(100); res=send_dgram("bbb"); if (res==TIMEOUT) ...; wait(100); } } Сделал реализацию, всё работает, но есть одно но. Стек для каждого такого процесса приходится выделять с учетом того, что могут вызываться вложенные IRQ. А RAM порой хочется поэкономить. Поэтому хочется во время вызова потока внутри IRQ использовать стек процесса (PSP). Но в handler mode можно пользоваться только MSP. Думаю, как лучше сделать. Мысли такие: - внутри IRQ переключаться в THREAD MODE и на стек PSP, а IRQ маскировать с помощью BASEPRI. Но тут вырисовывается проблемка в совместимости с RTOS: RTOS для маскировки IRQ тоже использует BASEPRI (при некоторых вызовах callFromIRQ), но при выходе он BASEPRI сбрасывает в ноль (и ставит топорно, не проверяя что быдо до вызова), а не в то значение, которое было при вызове. Поэтому во всех IRQ нельзя будет пользоватся этим механизмом freertos на приоритетах >=процессного IRQ, либо сделать доработку для freertos, либо что-то еще придумать. Пока вырисовывается дополнительная опция freertos, добавляющая проверку и восстановление BASEPRI. p.s. Предвидя сообщения в стиле "так никто не делает и вообще это не правильно", просьба воздержаться от этого и писать по существу. Ибо инструмент в работе показал себя очень хорошо (красивые реализации получаются если делать тайм-ауты и несколько источников возобновления исполнения), только хочется подружить его со RTOS. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 17 4 ноября, 2020 Опубликовано 4 ноября, 2020 · Жалоба 3 minutes ago, jeka said: Когда rtos ставить не хочется, ... а очень хочется головняка на ровном месте Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jeka 0 4 ноября, 2020 Опубликовано 4 ноября, 2020 · Жалоба Как раз наоборот. Когда начал им пользоваться, сам удивился насколько им приятно пользоваться. Ибо крайне компактный и быстрый, позволяющий в большинстве случаев обойтись без дерганья контекстов, сообщений, вейкапа процессов, очередей, как это бы делалось в RTOS (отсюда простота и выше скорость). И при этом код вполне понятный. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 131 4 ноября, 2020 Опубликовано 4 ноября, 2020 · Жалоба 1 час назад, jeka сказал: - внутри IRQ переключаться в THREAD MODE и на стек PSP, а IRQ маскировать с помощью BASEPRI. Это еще как? Это делается только выходом из исключения/прерывания. И, если честно, не догоняю в плюсы и удобства всего этого чудо-механизма. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jeka 0 4 ноября, 2020 Опубликовано 4 ноября, 2020 · Жалоба Just now, Arlleex said: Это делается только выходом из исключения/прерывания. Почему только? PSR почему бы не подправить если очень хочется Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 131 4 ноября, 2020 Опубликовано 4 ноября, 2020 · Жалоба 27 минут назад, jeka сказал: Почему только? PSR почему бы не подправить если очень хочется А что конкретно Вы там подправить хотите, ну конечно, при условии, что очень хочется? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 17 4 ноября, 2020 Опубликовано 4 ноября, 2020 · Жалоба 1 hour ago, jeka said: Как раз наоборот. Когда начал им пользоваться, сам удивился насколько им приятно пользоваться. Ибо крайне компактный и быстрый, позволяющий в большинстве случаев обойтись без дерганья контекстов, сообщений, вейкапа процессов, очередей, как это бы делалось в RTOS (отсюда простота и выше скорость). И при этом код вполне понятный. Пример задачи, где происходит моргание светодиода яркостью, пропорционально загрузке ядра. Чего тут сложного? Какие "дерганья контекста", "вейкапы", "очереди процессов"? Все просто как два пальца. void ServiceLib::Thread::body() { auto ledFlashPulseWidthMs = OS::getCoreUsage() * (ledFlashPediodMs / 100); // 100% - led is on allways if (ledFlashPulseWidthMs < 10) ledFlashPulseWidthMs = 10; pinLED.setToLow(); sleep(ledFlashPulseWidthMs); pinLED.setToHigh(); sleep(ledFlashPediodMs-ledFlashPulseWidthMs); } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jeka 0 4 ноября, 2020 Опубликовано 4 ноября, 2020 · Жалоба 18 minutes ago, Arlleex said: А что конкретно Вы там подправить хотите IPSR bit definitions Bits 8:0 ISR_NUMBER: This is the number of the current exception: 0: Thread mode, все что не 0 - по логике handler mode т.е. если ISR_NUMBER сбросить в 0, как я понимаю, процессор перейдет в thread mode и можно стек переключить на PSP. (в handler mode опытка переключения стека вызывает hardfault, а так бы было то что надо). Но нужно предварительно замаскировать более низкие прерывания, чтоб не нарушить логику работы контроллера прерываний. Как я понял, при изменении ISR_NUMBER NVIC сразу доступные для вызова приоритеты обновит. (может и ошибаюсь, поправьте меня кто знает) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 131 4 ноября, 2020 Опубликовано 4 ноября, 2020 · Жалоба 1 минуту назад, jeka сказал: т.е. если ISR_NUMBER сбросить в 0... Ну я так и понял. Не получится. CPU игнорирует записи в это битовое поле. 4 минуты назад, jeka сказал: в handler mode опытка переключения стека вызывает hardfault... Не помню точно, но вроде никаких HF не будет. Процессор также игнорирует прямую смену стека в Handler Mode. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jeka 0 4 ноября, 2020 Опубликовано 4 ноября, 2020 · Жалоба Just now, Arlleex said: CPU игнорирует записи в это битовое поле. жаль. (хотя я софт-ребут из IRQ делал и вроде всё сбрасывалось, но могу и ошибаться). Значит стек на возврат настроить и выполнить возврат, сразу в нужное место. А вот с восстановлением вопрос. Видимо так же. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 131 4 ноября, 2020 Опубликовано 4 ноября, 2020 · Жалоба 6 минут назад, jeka сказал: жаль. (хотя я софт-ребут из IRQ делал и вроде всё сбрасывалось, но могу и ошибаться)... Софт-ребут делается совсем по-другому, посему не зависит от места, откуда его можно вызвать... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jeka 0 4 ноября, 2020 Опубликовано 4 ноября, 2020 · Жалоба нет, я про софт-ресет чисто программный, а не про ресет установкой бита ресета Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 131 4 ноября, 2020 Опубликовано 4 ноября, 2020 · Жалоба Софт-ресет можно эмулировать по-разному с разным аппаратным окружением при уйме разных условий. Например, тупым зацикливанием программы с активным внутренним или внешним watchdog-ом. Например, сбросом всех регистров CPU и периферии в их дефолтные значения и переходом по адресу ResetHandler(). Битами SYSRESETREQ и VECTRESET (в последнем случае подходить с головой и понимать, что происходит в системе). Записью в GPIO, подключенного к RST МК... Да сколько всего можно придумать. Но никак не записью в IPSR. Скорее всего, Вы что-то путаете P.S. Единственное, где я еще могу оправдать посыл Ваших идей с идеологией контекстного вытеснения в ISR - энергосберегающие девайсы. Пришло прерывание - отработали что-то по FSM, заснули. Но тут все от алгоритма работы зависит - не везде такой механизм удобен и оправдан. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jeka 0 4 ноября, 2020 Опубликовано 4 ноября, 2020 · Жалоба 17 minutes ago, Arlleex said: Скорее всего, Вы что-то путаете Всё верно. Я про ресет с помощью простой передачи управления по адресу. Запускал так бутлоадер прямо из irq. Ибо надо было не ресетить коммуникацию, иначе связь порвётся. 2 hours ago, Arlleex said: если честно, не догоняю в плюсы и удобства всего этого чудо-механизма. получается очень легкий механизм заточеный на событийную коммуникацию. Замена RTOS в части многопоточности и сигнализирования обслуживающих коммуникацию потоков. заменяя цепочку irq периферии->сообщение RTOS->wakeup процесса->IRQ планировщика->переключение контекста->обработка, на irq->переключение контекста->обработа Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 184 4 ноября, 2020 Опубликовано 4 ноября, 2020 · Жалоба 5 часов назад, jeka сказал: Когда rtos ставить не хочется, а state машину внутри IRQ городить некрасиво, родилась мысль сделать механизм, который работает как yield(), но внутри IRQ. Т.е. выходит из IRQ, а при следующем вызове возобновляет исполнение с этого же места и сохраненным контекстом. Ничего нового Вы не изобрели. Делали такое и работает давно уже в серийных устройствах (псевдозадача внутри IRQ со своим стеком и контекстом). И даже где-то на форуме я уже описывал такой способ как альтернативу машине состояний. Только переключать режим процессора здесь - пустая затея. Если даже и возможная. Никаких бонусов не даёт. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться