Forger 26 17 ноября, 2017 Опубликовано 17 ноября, 2017 · Жалоба что ARM не поддерживает reentrant прерывания Дык, это вполне логично, и касается не только для ARM )) и выполнение Step_1s() полностью блокирует прерывание и Step_10ms() при этом не исполняется. Нашел в инете, что народ играется ассемблером и пытается восстанавливать стек и прочие вещи, чтобы процессор опять мог заходить в это же прерывание, но хотелось бы узнать - есть ли простое решение, без RTOS, так В ARM (не во всех) реализована поддержка вложенных прерываний. Почитайте про PendSV и заодно про SVC вызовы. Про это уже давно исписаны все заборы интернеты. Это если желаете толстые фунции вызывать в фоне прерываний (кстати, за подобные "дела" в некоторых конторах очень сурово карают). как кроме этой функции RTOS будет не нужна. Это вы сейчас так говорите, в данный момент. А в перспективе? ;) Но, если же проект такой примитивный, то все можно сделать на паре/тройке аппаратных таймеров. В самом убогом ARM как минимум два-три штуки найдутся (помимо стандартного SysTimer). Такое решение простое, наглядное и железобетонное. Если правильно назначить приоритеты этим таймерам, то получится относительно работоспособный "шедулер" с поддержкой приоритетов. Еще еще вариант - простейший супер-луп, использующий лишь один таймер (systimer), где код из фона прерываний переносится в фон задач. Фактически пишете шедулер RTOS самостоятельно руками (со всеми вытекающими). зы. В любом проекте в фоне прерываний не должны вызываться никакие толстые функции! Иначе другие толстые функции поплывут и в итоге поплывет времянка всего проектика. Кто пытался писать сложные проекты в супер-лупе (продвинутые ардуинщики), то понимает, что я имею ввиду ))) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
scifi 1 17 ноября, 2017 Опубликовано 17 ноября, 2017 · Жалоба Каково же было мое удивление, когда оказалось, что ARM не поддерживает reentrant прерывания и выполнение Step_1s() полностью блокирует прерывание и Step_10ms() при этом не исполняется. Всё он поддерживает. Обработчик прерывания не будет вызван повторно, пока он выполняется. Вообще-то это разумно, не находите? Для того, чтобы он был прерван, должно произойти прерывание с более высоким приоритетом, а не с равным. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 26 17 ноября, 2017 Опубликовано 17 ноября, 2017 · Жалоба Всё он поддерживает. Здесь под словом reentrant имеется ввиду возможность обработчика прервать самого себя. Наподобие вызова функции внутри самой себя. А вытесняющие прерывания называются иначе - nesting interrupts, т.е. вложенные прерывания (в некоторой литературе может встречаться другое название - preemptive). Они подразумевают вытеснение одного обработчика прерываний ДРУГИМ обработчиком. Если же прерывание от того же самого источника произойдет в то время, пока обрабатывается прерывание от этого же источника (скажем, байты по USART сыпятся быстрее, чем успеваем их обрабатывать), то новое прерывание станет отложенным (pending) и вызовется сразу же после обработки текущего (если конечно никто более приоритетный его не прервет). Другими словами, встанет в очередь. Это если объяснять грубо и на пальцах, на деле там полно своих нюансов. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Timmy 1 17 ноября, 2017 Опубликовано 17 ноября, 2017 · Жалоба Каково же было мое удивление, когда оказалось, что ARM не поддерживает reentrant прерывания и выполнение Step_1s() полностью блокирует прерывание и Step_10ms() при этом не исполняется. Нашел в инете, что народ играется ассемблером и пытается восстанавливать стек и прочие вещи, чтобы процессор опять мог заходить в это же прерывание, но хотелось бы узнать - есть ли простое решение, без RTOS, так как кроме этой функции RTOS будет не нужна. Эта задача легко решается при помощи программных прерываний с различным приоритетом. Для программных прерываний можно использовать любые вектора неиспользуемых в проекте периферийных устройств. Для инициализации вызываем, как обычно, NVIC_SetPriority() и NVIC_EnableIRQ(), а чтобы позвать программное прерывание вызываем NVIC_SetPendingIRQ(). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
syoma 1 17 ноября, 2017 Опубликовано 17 ноября, 2017 · Жалоба Всё он поддерживает. Обработчик прерывания не будет вызван повторно, пока он выполняется. Вообще-то это разумно, не находите? Для того, чтобы он был прерван, должно произойти прерывание с более высоким приоритетом, а не с равным. Ну я нахожу разумным, если есть возможность выбора - так или этак. И мое представление об обработчике прерывания очень простое - произошло прерывание - процессор должен безусловно перейти на адрес обработчика. Если пользователь хочет - не снимает флаг, пока не обработает все прерывание и теряет возможность поимки следующего прерывания, пришедшего во время обработки. Если хочет - снимает, и не теряет. Насколько я помню 8051-ых так было реализовано. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 26 17 ноября, 2017 Опубликовано 17 ноября, 2017 · Жалоба И мое представление об обработчике прерывания очень простое - произошло прерывание - процессор должен безусловно перейти на адрес обработчика. Напишите свое видение этой "проблемы" в компанию ARM ;) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Obam 38 17 ноября, 2017 Опубликовано 17 ноября, 2017 · Жалоба …Если пользователь хочет - не снимает флаг, пока не обработает все прерывание и теряет возможность поимки следующего прерывания, пришедшего во время обработки. Если хочет - снимает, и не теряет. Насколько я помню 8051-ых так было реализовано. "Пешим по-конному" (; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AlexandrY 3 17 ноября, 2017 Опубликовано 17 ноября, 2017 · Жалоба Ну я нахожу разумным, если есть возможность выбора - так или этак. И мое представление об обработчике прерывания очень простое - произошло прерывание - процессор должен безусловно перейти на адрес обработчика. Если пользователь хочет - не снимает флаг, пока не обработает все прерывание и теряет возможность поимки следующего прерывания, пришедшего во время обработки. Если хочет - снимает, и не теряет. Насколько я помню 8051-ых так было реализовано. Т.е. любой хакер берет подает внешние сигналы для прерываний чуть быстрее и переполняет стек настолько насколько ему нужно. Это уже не программа будет, а настоящая диверсия. К счастью ARM это дело пресёк. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 244 17 ноября, 2017 Опубликовано 17 ноября, 2017 · Жалоба Насколько я помню 8051-ых так было реализовано. Видно что Вы со времён этого самого 8051 больше ничего другого не изучали. Почитайте мануал на ARM-ядро и узнаете, что на нём всё что нужно легко реализуется. А пока - рано вам ещё ISR-ы писать, не понимая как ядро работает. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
syoma 1 17 ноября, 2017 Опубликовано 17 ноября, 2017 (изменено) · Жалоба Знающие люди подсказали такой вариант. У них работает: __attribute__ ((naked)) void SysTick_Handler(void) { /* Multi tasking, enable re-entrancy to interrupt */ arm_cortex_m_call_thread_with_context_switch(SysTick_Isr); } /* Re-entrant function for multi-tasking: arm_cortex_m_call_thread_with_context_switch*/ __attribute__ ((naked)) void arm_cortex_m_call_thread_with_context_switch(void (* isr_routine_ptr)(void)) { #if (defined(__FPU_PRESENT) && (__FPU_PRESENT == 1)) && (defined(__FPU_USED) && (__FPU_USED == 1)) __asm volatile (" TST LR, #0x10"); __asm volatile (" IT EQ"); __asm volatile (" VMOVEQ S0, S0"); #endif __asm volatile (" PUSH {R0, R1}"); __asm volatile (" SUB SP, SP, #0x20"); __asm volatile (" ADR R0,Call_isr_routine_in_thread_mode"); __asm volatile (" STR R0,[sP, #24]"); __asm volatile (" MOV R0,#0x01000000"); __asm volatile (" STR R0,[sP, #28]"); __asm volatile (" MVNS R0,#0x6"); __asm volatile (" MOV LR, R0"); __asm volatile (" BX LR"); __asm volatile ("Call_isr_routine_in_thread_mode:"); __asm volatile (" POP {R0, R1}"); __asm volatile (" BLX R0"); __asm volatile (" ISB"); __asm volatile (" SVC #0"); __asm volatile ("Unknown_Execution:"); __asm volatile (" B Unknown_Execution"); } /* SVC Interrupt service routine to restore the context: SVC_Handler*/ __attribute__ ((naked)) void SVC_Handler(void) { #if (defined(__FPU_PRESENT) && (__FPU_PRESENT == 1)) && (defined(__FPU_USED) && (__FPU_USED == 1)) __asm volatile (" TST LR, #0x10"); __asm volatile (" IT EQ"); __asm volatile (" VMOVEQ S0, S0"); #endif __asm volatile (" TST LR, #0x4"); __asm volatile (" ITE EQ"); __asm volatile (" MRSEQ R0, MSP"); __asm volatile (" MRSNE R0, PSP"); __asm volatile (" LDR R1, [R0, #24]"); __asm volatile (" LDRB.W R0, [R1, #-2]"); __asm volatile (" CBZ R0, svc_service_0"); __asm volatile (" B Unknown_SVC_Request"); __asm volatile ("svc_service_0:"); #if (defined(__FPU_PRESENT) && (__FPU_PRESENT == 1)) && (defined(__FPU_USED) && (__FPU_USED == 1)) __asm volatile (" TST LR, #0x10"); __asm volatile (" ITE EQ"); __asm volatile (" ADDEQ SP, SP, #104"); __asm volatile (" ADDNE SP, SP, #32"); #else __asm volatile (" ADD SP, SP, #32"); #endif __asm volatile (" POP {R0, R1}"); __asm volatile (" MSR APSR_nzcvq, R0"); __asm volatile (" BX R1"); __asm volatile ("Unknown_SVC_Request:"); __asm volatile (" B Unknown_SVC_Request"); } В итоге SysTick_Isr будет самовложенной. Что скажете? Изменено 17 ноября, 2017 пользователем IgorKossak [codebox] для длинного кода, [code] - для короткого! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AlexandrY 3 17 ноября, 2017 Опубликовано 17 ноября, 2017 · Жалоба Знающие люди подсказали такой вариант. У них работает: В итоге SysTick_Isr будет самовложенной. Что скажете? Кто-то что-то наковырял в симулинке? А кто тогда покажет файл SysTickScheduler.c? Там невооруженным глазом видно, что обработчик вызывает функцию rt_OneStep в течении которой все! прерывания запрещены. Вот у них и работает. Лузеры! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
syoma 1 17 ноября, 2017 Опубликовано 17 ноября, 2017 · Жалоба Кто-то что-то наковырял в симулинке? А кто тогда покажет файл SysTickScheduler.c? Там невооруженным глазом видно, что обработчик вызывает функцию rt_OneStep в течении которой все! прерывания запрещены. Вот у них и работает. Лузеры! Если бы в rt_OneStep были бы запрещены прерывания, разве был бы смысл в данных извращениях? Поэтому прерывания в rt_OneStep разрешены и приветствуются. Могу прикрепить файл, если хотите. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AlexandrY 3 17 ноября, 2017 Опубликовано 17 ноября, 2017 · Жалоба Если бы в rt_OneStep были бы запрещены прерывания, разве был бы смысл в данных извращениях? Поэтому прерывания в rt_OneStep разрешены и приветствуются. Могу прикрепить файл, если хотите. Они запрещены перед вызовом rt_OneStep. Прикреплять надо весь проект. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться