Перейти к содержанию
    

Прерывание в прерывании

что ARM не поддерживает reentrant прерывания

Дык, это вполне логично, и касается не только для ARM ))

 

и выполнение Step_1s() полностью блокирует прерывание и Step_10ms() при этом не исполняется. Нашел в инете, что народ играется ассемблером и пытается восстанавливать стек и прочие вещи, чтобы процессор опять мог заходить в это же прерывание, но хотелось бы узнать - есть ли простое решение, без RTOS, так

В ARM (не во всех) реализована поддержка вложенных прерываний.

Почитайте про PendSV и заодно про SVC вызовы. Про это уже давно исписаны все заборы интернеты.

Это если желаете толстые фунции вызывать в фоне прерываний (кстати, за подобные "дела" в некоторых конторах очень сурово карают).

 

как кроме этой функции RTOS будет не нужна.

Это вы сейчас так говорите, в данный момент. А в перспективе? ;)

 

Но, если же проект такой примитивный, то все можно сделать на паре/тройке аппаратных таймеров.

В самом убогом ARM как минимум два-три штуки найдутся (помимо стандартного SysTimer). Такое решение простое, наглядное и железобетонное.

Если правильно назначить приоритеты этим таймерам, то получится относительно работоспособный "шедулер" с поддержкой приоритетов.

 

Еще еще вариант - простейший супер-луп, использующий лишь один таймер (systimer), где код из фона прерываний переносится в фон задач.

Фактически пишете шедулер RTOS самостоятельно руками (со всеми вытекающими).

 

зы. В любом проекте в фоне прерываний не должны вызываться никакие толстые функции!

Иначе другие толстые функции поплывут и в итоге поплывет времянка всего проектика.

Кто пытался писать сложные проекты в супер-лупе (продвинутые ардуинщики), то понимает, что я имею ввиду )))

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Каково же было мое удивление, когда оказалось, что ARM не поддерживает reentrant прерывания и выполнение Step_1s() полностью блокирует прерывание и Step_10ms() при этом не исполняется.

Всё он поддерживает.

Обработчик прерывания не будет вызван повторно, пока он выполняется. Вообще-то это разумно, не находите? Для того, чтобы он был прерван, должно произойти прерывание с более высоким приоритетом, а не с равным.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Всё он поддерживает.

Здесь под словом reentrant имеется ввиду возможность обработчика прервать самого себя.

Наподобие вызова функции внутри самой себя.

 

А вытесняющие прерывания называются иначе - nesting interrupts, т.е. вложенные прерывания (в некоторой литературе может встречаться другое название - preemptive).

Они подразумевают вытеснение одного обработчика прерываний ДРУГИМ обработчиком.

Если же прерывание от того же самого источника произойдет в то время, пока обрабатывается прерывание от этого же источника (скажем, байты по USART сыпятся быстрее, чем успеваем их обрабатывать),

то новое прерывание станет отложенным (pending) и вызовется сразу же после обработки текущего (если конечно никто более приоритетный его не прервет). Другими словами, встанет в очередь.

Это если объяснять грубо и на пальцах, на деле там полно своих нюансов.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Каково же было мое удивление, когда оказалось, что ARM не поддерживает reentrant прерывания и выполнение Step_1s() полностью блокирует прерывание и Step_10ms() при этом не исполняется. Нашел в инете, что народ играется ассемблером и пытается восстанавливать стек и прочие вещи, чтобы процессор опять мог заходить в это же прерывание, но хотелось бы узнать - есть ли простое решение, без RTOS, так как кроме этой функции RTOS будет не нужна.

Эта задача легко решается при помощи программных прерываний с различным приоритетом. Для программных прерываний можно использовать любые вектора неиспользуемых в проекте периферийных устройств.

Для инициализации вызываем, как обычно, NVIC_SetPriority() и NVIC_EnableIRQ(),

а чтобы позвать программное прерывание вызываем NVIC_SetPendingIRQ().

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Всё он поддерживает.

Обработчик прерывания не будет вызван повторно, пока он выполняется. Вообще-то это разумно, не находите? Для того, чтобы он был прерван, должно произойти прерывание с более высоким приоритетом, а не с равным.

Ну я нахожу разумным, если есть возможность выбора - так или этак. И мое представление об обработчике прерывания очень простое - произошло прерывание - процессор должен безусловно перейти на адрес обработчика. Если пользователь хочет - не снимает флаг, пока не обработает все прерывание и теряет возможность поимки следующего прерывания, пришедшего во время обработки. Если хочет - снимает, и не теряет. Насколько я помню 8051-ых так было реализовано.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

И мое представление об обработчике прерывания очень простое - произошло прерывание - процессор должен безусловно перейти на адрес обработчика.

Напишите свое видение этой "проблемы" в компанию ARM ;)

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

…Если пользователь хочет - не снимает флаг, пока не обработает все прерывание и теряет возможность поимки следующего прерывания, пришедшего во время обработки. Если хочет - снимает, и не теряет. Насколько я помню 8051-ых так было реализовано.

"Пешим по-конному" (;

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну я нахожу разумным, если есть возможность выбора - так или этак. И мое представление об обработчике прерывания очень простое - произошло прерывание - процессор должен безусловно перейти на адрес обработчика. Если пользователь хочет - не снимает флаг, пока не обработает все прерывание и теряет возможность поимки следующего прерывания, пришедшего во время обработки. Если хочет - снимает, и не теряет. Насколько я помню 8051-ых так было реализовано.

Т.е. любой хакер берет подает внешние сигналы для прерываний чуть быстрее и переполняет стек настолько насколько ему нужно.

Это уже не программа будет, а настоящая диверсия.

К счастью ARM это дело пресёк.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Насколько я помню 8051-ых так было реализовано.

Видно что Вы со времён этого самого 8051 больше ничего другого не изучали.

Почитайте мануал на ARM-ядро и узнаете, что на нём всё что нужно легко реализуется.

А пока - рано вам ещё ISR-ы писать, не понимая как ядро работает.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Знающие люди подсказали такой вариант. У них работает:

 

__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
[codebox] для длинного кода, [code] - для короткого!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Знающие люди подсказали такой вариант. У них работает:

 

В итоге SysTick_Isr будет самовложенной. Что скажете?

Кто-то что-то наковырял в симулинке?

А кто тогда покажет файл SysTickScheduler.c?

Там невооруженным глазом видно, что обработчик вызывает функцию rt_OneStep в течении которой все! прерывания запрещены.

Вот у них и работает.

Лузеры!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Кто-то что-то наковырял в симулинке?

А кто тогда покажет файл SysTickScheduler.c?

Там невооруженным глазом видно, что обработчик вызывает функцию rt_OneStep в течении которой все! прерывания запрещены.

Вот у них и работает.

Лузеры!

Если бы в rt_OneStep были бы запрещены прерывания, разве был бы смысл в данных извращениях? Поэтому прерывания в rt_OneStep разрешены и приветствуются. Могу прикрепить файл, если хотите.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если бы в rt_OneStep были бы запрещены прерывания, разве был бы смысл в данных извращениях? Поэтому прерывания в rt_OneStep разрешены и приветствуются. Могу прикрепить файл, если хотите.

Они запрещены перед вызовом rt_OneStep.

Прикреплять надо весь проект.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...