|
|
  |
Прерывание в прерывании, Для реализации Super Simple Tasker |
|
|
|
Nov 17 2017, 11:07
|

Профессионал
    
Группа: Свой
Сообщений: 1 215
Регистрация: 22-02-05
Пользователь №: 2 831

|
Цитата(syoma @ Nov 17 2017, 13:45)  что ARM не поддерживает reentrant прерывания Дык, это вполне логично, и касается не только для ARM )) Цитата и выполнение Step_1s() полностью блокирует прерывание и Step_10ms() при этом не исполняется. Нашел в инете, что народ играется ассемблером и пытается восстанавливать стек и прочие вещи, чтобы процессор опять мог заходить в это же прерывание, но хотелось бы узнать - есть ли простое решение, без RTOS, так В ARM (не во всех) реализована поддержка вложенных прерываний. Почитайте про PendSV и заодно про SVC вызовы. Про это уже давно исписаны все заборы интернеты. Это если желаете толстые фунции вызывать в фоне прерываний (кстати, за подобные "дела" в некоторых конторах очень сурово карают). Цитата как кроме этой функции RTOS будет не нужна. Это вы сейчас так говорите, в данный момент. А в перспективе?  Но, если же проект такой примитивный, то все можно сделать на паре/тройке аппаратных таймеров. В самом убогом ARM как минимум два-три штуки найдутся (помимо стандартного SysTimer). Такое решение простое, наглядное и железобетонное. Если правильно назначить приоритеты этим таймерам, то получится относительно работоспособный "шедулер" с поддержкой приоритетов. Еще еще вариант - простейший супер-луп, использующий лишь один таймер (systimer), где код из фона прерываний переносится в фон задач. Фактически пишете шедулер RTOS самостоятельно руками (со всеми вытекающими). зы. В любом проекте в фоне прерываний не должны вызываться никакие толстые функции! Иначе другие толстые функции поплывут и в итоге поплывет времянка всего проектика. Кто пытался писать сложные проекты в супер-лупе (продвинутые ардуинщики), то понимает, что я имею ввиду )))
--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
|
|
|
|
|
Nov 17 2017, 11:37
|

Профессионал
    
Группа: Свой
Сообщений: 1 215
Регистрация: 22-02-05
Пользователь №: 2 831

|
Цитата(scifi @ Nov 17 2017, 14:15)  Всё он поддерживает. Здесь под словом reentrant имеется ввиду возможность обработчика прервать самого себя. Наподобие вызова функции внутри самой себя. А вытесняющие прерывания называются иначе - nesting interrupts, т.е. вложенные прерывания (в некоторой литературе может встречаться другое название - preemptive). Они подразумевают вытеснение одного обработчика прерываний ДРУГИМ обработчиком. Если же прерывание от того же самого источника произойдет в то время, пока обрабатывается прерывание от этого же источника (скажем, байты по USART сыпятся быстрее, чем успеваем их обрабатывать), то новое прерывание станет отложенным (pending) и вызовется сразу же после обработки текущего (если конечно никто более приоритетный его не прервет). Другими словами, встанет в очередь. Это если объяснять грубо и на пальцах, на деле там полно своих нюансов.
--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
|
|
|
|
|
Nov 17 2017, 12:01
|
Знающий
   
Группа: Участник
Сообщений: 835
Регистрация: 9-08-08
Из: Санкт-Петербург
Пользователь №: 39 515

|
Цитата(syoma @ Nov 17 2017, 13:45)  Каково же было мое удивление, когда оказалось, что ARM не поддерживает reentrant прерывания и выполнение Step_1s() полностью блокирует прерывание и Step_10ms() при этом не исполняется. Нашел в инете, что народ играется ассемблером и пытается восстанавливать стек и прочие вещи, чтобы процессор опять мог заходить в это же прерывание, но хотелось бы узнать - есть ли простое решение, без RTOS, так как кроме этой функции RTOS будет не нужна. Эта задача легко решается при помощи программных прерываний с различным приоритетом. Для программных прерываний можно использовать любые вектора неиспользуемых в проекте периферийных устройств. Для инициализации вызываем, как обычно, NVIC_SetPriority() и NVIC_EnableIRQ(), а чтобы позвать программное прерывание вызываем NVIC_SetPendingIRQ().
|
|
|
|
|
Nov 17 2017, 12:02
|
Профессионал
    
Группа: Свой
Сообщений: 1 817
Регистрация: 14-02-07
Из: наших, которые работают за бугром
Пользователь №: 25 368

|
Цитата(scifi @ Nov 17 2017, 14:15)  Всё он поддерживает. Обработчик прерывания не будет вызван повторно, пока он выполняется. Вообще-то это разумно, не находите? Для того, чтобы он был прерван, должно произойти прерывание с более высоким приоритетом, а не с равным. Ну я нахожу разумным, если есть возможность выбора - так или этак. И мое представление об обработчике прерывания очень простое - произошло прерывание - процессор должен безусловно перейти на адрес обработчика. Если пользователь хочет - не снимает флаг, пока не обработает все прерывание и теряет возможность поимки следующего прерывания, пришедшего во время обработки. Если хочет - снимает, и не теряет. Насколько я помню 8051-ых так было реализовано.
|
|
|
|
|
Nov 17 2017, 18:04
|
Профессионал
    
Группа: Свой
Сообщений: 1 817
Регистрация: 14-02-07
Из: наших, которые работают за бугром
Пользователь №: 25 368

|
Знающие люди подсказали такой вариант. У них работает: CODE __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 будет самовложенной. Что скажете?
Сообщение отредактировал IgorKossak - Nov 17 2017, 20:08
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!
|
|
|
|
|
Nov 17 2017, 18:56
|

Ally
     
Группа: Модераторы
Сообщений: 6 232
Регистрация: 19-01-05
Пользователь №: 2 050

|
Цитата(syoma @ Nov 17 2017, 20:04)  Знающие люди подсказали такой вариант. У них работает:
В итоге SysTick_Isr будет самовложенной. Что скажете? Кто-то что-то наковырял в симулинке? А кто тогда покажет файл SysTickScheduler.c? Там невооруженным глазом видно, что обработчик вызывает функцию rt_OneStep в течении которой все! прерывания запрещены. Вот у них и работает. Лузеры!
|
|
|
|
|
  |
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0
|
|
|