реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> М3/М4 - как сделать трюк с прерываниями?
Allregia
сообщение Oct 23 2012, 11:30
Сообщение #1


Профессионал
*****

Группа: Свой
Сообщений: 1 047
Регистрация: 28-06-07
Из: Israel
Пользователь №: 28 763



Подкажите решение:
1) есть проограмма, сейчас на М3 (lpc1768) но вообще будет на М4 (stm32f4), без ОС.
в ней выполняются фоновые задачи, в т.ч и пересылка DMA, и есть циклы типа while()
2) есть довольно высокочастотное прерывание (неважно от чего) INT1 с регулярной частотой (периодом - T1)
3) после каждых N должна выполниться подпрограмма SUB1, время выполнения SUB1 - T2
Естественно, T2< N*T1,
но - T2>T1.
Т.е. во время выплонения SUB1 обязательно произойдет прерывание INT1.
4) пропустить INT нельзя, как нельзя пропустить и SUB1.

Первой что пришло в голову - крутить в INT1 счетчик, когда он досчитал до N - выставлять флаг.
В SUB1 его проверять, но при в основной программе во всех циклах вставлять вызов SUB1
Код
#define N 10
u8 IntFlag=0;
//-----
void INT1(void){
static cnt=0;
    .........
   if(++cnt>N){
      cnt=0;
      IntFlag=1;
   }
}
//-----
void SUB1(void){
   if(IntFlag){
      IntFlag=0;
      ...........
   }
}
//
int main(void){
    .......
   while(xxxx){
      .....
      SUB1();
   }

    ........
}


Проблемы:
1) не пропустить бы какой-то while/for, это надо из все просматривать во всей программе, е везде вставлять вызов SUB1
2) на многочисленные вызовы SUB1 тратиться довольно много времени, так например скорость записи в SD-флешку (по DMA!) падает процентов на 20-30 (хотя и огстается в пределат требуемогодля моей задачи).

Может кто подскажет более элегантное решение ?
Может оформить SUB1 как прерывание более низкого уровня чем INT1 и вместо установки флага, как-то его иничиировать в конце N-ного INT1 ? но как это сделать ?
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Oct 23 2012, 11:38
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(Allregia @ Oct 23 2012, 14:30) *
Может оформить SUB1 как прерывание более низкого уровня чем INT1 и вместо установки флага, как-то его иничиировать в конце N-ного INT1 ? но как это сделать ?


Код
    NVIC_EnableIRQ(CMU_IRQn);// ненужное прерывание периферии
    NVIC_SetPendingIRQ(CMU_IRQn);

Если нет Оси, то можно использовать прерывание PendSVC или SVC (если обычные заняты).
Go to the top of the page
 
+Quote Post
Flexz
сообщение Oct 23 2012, 12:00
Сообщение #3


Местный
***

Группа: Свой
Сообщений: 252
Регистрация: 9-10-08
Из: Московская обл.
Пользователь №: 40 797



Если высокочастотное прерывание идет от внешнего источника, то завести его на таймер, который считает до N и дергает второе прерывание.
Если же оно внутреннее, то как уже сказали выше - использовать софтовые прерывания, в stm32 это можно сделать через EXTI, например.
Go to the top of the page
 
+Quote Post
Allregia
сообщение Oct 23 2012, 12:32
Сообщение #4


Профессионал
*****

Группа: Свой
Сообщений: 1 047
Регистрация: 28-06-07
Из: Israel
Пользователь №: 28 763



Цитата(_Артём_ @ Oct 23 2012, 13:38) *
Код
    NVIC_EnableIRQ(CMU_IRQn);// ненужное прерывание периферии
     NVIC_SetPendingIRQ(CMU_IRQn);

Если нет Оси, то можно использовать прерывание PendSVC или SVC (если обычные заняты).


Я вот помнил что что-то такое есть, где-то читал. а как понадобилось - не могу вспомнить и найти где это было описано. Не подскажете?
В любом случае - спасибо за ключевые слова" для поиска sm.gif

Цитата
Если высокочастотное прерывание идет от внешнего источника, то завести его на таймер, который считает до N и дергает второе прерывание.
Если же оно внутреннее, то как уже сказали выше - использовать софтовые прерывания, в stm32 это можно сделать через EXTI, например.


Прерывание внутрненее, от периферии. EXTI это же прерывание от ножки? Или его можно сьэмулировать программно?
Я тоже думал - может какое прерывание от неиспользованной периферии задействовать?
Go to the top of the page
 
+Quote Post
Flexz
сообщение Oct 23 2012, 12:50
Сообщение #5


Местный
***

Группа: Свой
Сообщений: 252
Регистрация: 9-10-08
Из: Московская обл.
Пользователь №: 40 797



Цитата(Allregia @ Oct 23 2012, 16:32) *
EXTI это же прерывание от ножки? Или его можно сьэмулировать программно?
Я тоже думал - может какое прерывание от неиспользованной периферии задействовать?

Да, можно программно сгенерить, есть специальный регистр для этого - EXTI_SWIER.
А вообще, контроллер прерываний вроде бы позволяет программно генерировать любое прерывание, хотя сам я этим не пользовался никогда. Так что выбор большой sm.gif
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Oct 23 2012, 13:00
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(Allregia @ Oct 23 2012, 15:32) *
Я вот помнил что что-то такое есть, где-то читал. а как понадобилось - не могу вспомнить и найти где это было описано. Не подскажете?
В любом случае - спасибо за ключевые слова" для поиска sm.gif


Чтобы вызвать SVC
Код
__ASM volatile ("svc 0");
.

PendSVC можно вызвать так:
Код
*( volatile uint32_t *) 0xE000ED04 )|= 0x10000000;

Где-то эти функции должны быть в хидерах от ARM, но чото не нахожу..

Цитата(Allregia @ Oct 23 2012, 15:32) *
Я тоже думал - может какое прерывание от неиспользованной периферии задействовать?


NVIC_SetPendingIRQ(UnesedIO_Irq);

Можно ещё вызвать через STIR.
Go to the top of the page
 
+Quote Post
Allregia
сообщение Oct 23 2012, 14:04
Сообщение #7


Профессионал
*****

Группа: Свой
Сообщений: 1 047
Регистрация: 28-06-07
Из: Israel
Пользователь №: 28 763



Т.е как я понял. проще всего через EXTI:

Код
//высокочастотное прерывание:
void INT1(void){
static cnt=0;
    .........
   if(++cnt>N){
      cnt=0;
      EXTI_GenerateSWInterrupt(EXTI_Line15);// "взвоим курок" - после выхода из INT1 произойдет вызов прерывания EXTI15_10  
   }
}

// программное прерывание:
void EXTI15_10_IRQHandler(void){
  if(EXTI_GetITStatus(EXTI_Line15) != RESET)  {
    SUB1();
    EXTI_ClearITPendingBit(EXTI_Line15); // Clear the EXTI line 15 pending bit
  }
}

// Настройки:
void Init_EXTI_SWI(void){
  EXTI_InitTypeDef   EXTI_InitStructure;
  NVIC_InitTypeDef   NVIC_InitStructure;

  /* Enable SYSCFG clock */
//  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
  
  /* Configure EXTI Line15 */
  EXTI_InitStructure.EXTI_Line = EXTI_Line15;
  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
  EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  EXTI_Init(&EXTI_InitStructure);

  /* Enable and set EXTI15_10 Interrupt to the lowest priority */
  NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0F;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0F;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

  NVIC_Init(&NVIC_InitStructure);

}
// в настройке ВЧ прерывания приоритет повыше:
//  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;
//  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;


А еще такой дурацкий вопрос - в SUB1 надо как-то специально разрешать прерывания более высокого уровня чтобы INT1 могло происходить во время выполнения SUB1 или это автоматически ?
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Oct 23 2012, 14:27
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(Allregia @ Oct 23 2012, 17:04) *
Т.е как я понял. проще всего через EXTI:

Ничего себе проще всего...еле в экран влезает... sm.gif

Цитата(Allregia @ Oct 23 2012, 17:04) *
А еще такой дурацкий вопрос - в SUB1 надо как-то специально разрешать прерывания более высокого уровня чтобы INT1 могло происходить во время выполнения SUB1 или это автоматически ?

Надо сконфигурировать количество уровней прерываний ( функция NVIC_SetPriorityGrouping) и задать уровень прерывания (функция NVIC_SetPriority).
Go to the top of the page
 
+Quote Post
Allregia
сообщение Oct 23 2012, 15:46
Сообщение #9


Профессионал
*****

Группа: Свой
Сообщений: 1 047
Регистрация: 28-06-07
Из: Israel
Пользователь №: 28 763



Я пока с NVIC до конца не разобрался.
Не очень вьехал чем отличается PreemptionPriority от SubPriority?

У меня в программе 4 прерывания, в порядке приоритета:
1) SPI
2) мое программное, инициируемое в прерывании SPI
3) UART
4) SysTick

и делать надо так:

Код
...
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
                        // Setup SysTick Timer for 1 msec interrupts, lowest priority
      if (SysTick_Config(SystemCoreClock / 1000)) { while (1);} // Capture error
        NVIC_SetPriority(SysTick_IRQn,  4);  //    SysTick priority=4
       ..

      // uart
      NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;
      NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
      ...
     // sw interrupt
     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
     ...
     // SPI, highest priority
     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    ...


Или можно просто после всех инициализаций, которые у меня есть сейчас, написать:
Код
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
        NVIC_SetPriority(SPI2_IRQn,                1);  //    SPI priority=1
        NVIC_SetPriority(EXTI15_10_IRQn,       2);  //    SW interrupt priority=2
        NVIC_SetPriority(USART3_IRQn_IRQn,  3);  //    UART=3
        NVIC_SetPriority(SysTick_IRQn,            4);  //    SysTick priority=4
Go to the top of the page
 
+Quote Post
esaulenka
сообщение Oct 23 2012, 16:54
Сообщение #10


Профессионал
*****

Группа: Свой
Сообщений: 1 032
Регистрация: 13-03-08
Из: Маськва
Пользователь №: 35 877



Цитата
Не очень вьехал чем отличается PreemptionPriority от SubPriority?

Первое - приоритет для вложенных прерываний. Если будет запрос на прерывание, у которого preemption будет выше, чем у текущего исполняющегося прерывания, будет вызвано высокоприоритетное.
Второе - порядок выполнения прерываний, если вдруг два запроса поступили одновременно.


--------------------
Тут обсуждается творческий порыв, а не соответствие каким-либо стандартам ©
Go to the top of the page
 
+Quote Post
Allregia
сообщение Oct 23 2012, 18:23
Сообщение #11


Профессионал
*****

Группа: Свой
Сообщений: 1 047
Регистрация: 28-06-07
Из: Israel
Пользователь №: 28 763



Цитата(esaulenka @ Oct 23 2012, 18:54) *
Первое - приоритет для вложенных прерываний. Если будет запрос на прерывание, у которого preemption будет выше, чем у текущего исполняющегося прерывания, будет вызвано высокоприоритетное.


Это понятно, непонятно зачем два уровня распределения приоритетов?
Цитата
Второе - порядок выполнения прерываний, если вдруг два запроса поступили одновременно.


Если эти два запроса имеют один приоритет? Т.е. это распределение приоритета среди прерываний с одинаковым приоритетом?

Т.е. один номер это группа (0-N), второй - номер внутри группы (0-M), интересно - чем это лучше чем один список приоритетов 0-N*M ?
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Oct 23 2012, 19:06
Сообщение #12


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(Allregia @ Oct 23 2012, 21:23) *
Это понятно, непонятно зачем два уровня распределения приоритетов?

Появляется возможность задать приоритет внутри группы.

Цитата(Allregia @ Oct 23 2012, 21:23) *
Если эти два запроса имеют один приоритет? Т.е. это распределение приоритета среди прерываний с одинаковым приоритетом?

Да
Цитата(Allregia @ Oct 23 2012, 21:23) *
Т.е. один номер это группа (0-N), второй - номер внутри группы (0-M), интересно - чем это лучше чем один список приоритетов 0-N*M ?

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

Go to the top of the page
 
+Quote Post
Allregia
сообщение Oct 23 2012, 20:00
Сообщение #13


Профессионал
*****

Группа: Свой
Сообщений: 1 047
Регистрация: 28-06-07
Из: Israel
Пользователь №: 28 763



Цитата(_Артём_ @ Oct 23 2012, 21:06) *
Появляется возможность задать приоритет внутри группы.


Да

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


Я вот о чем - предположим есть 3 группы, A,B,C, внутри каждой два прерывания, 0 и 1:
A 0,0
B 0,1
C 0,1

порядок приоритетов ведь все равно будет такой: A0,A1, B0, B1, C0, C1
так какая разница, если это будет порядок: 0,1,2,3,4,5
где:
0=A0
1=A1
2=B0
3=B1
4=C0
5=C1

ведь тоже самое?

но раз так сделали, значит о чем-то думали, вот и пытаюсь найти скрытый смысл sm.gif
---------------
ну ладно, это все теории, а что с тем что я спросил в #9 ?
Go to the top of the page
 
+Quote Post
ReAl
сообщение Oct 23 2012, 20:05
Сообщение #14


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(Allregia @ Oct 23 2012, 21:23) *
Т.е. один номер это группа (0-N), второй - номер внутри группы (0-M), интересно - чем это лучше чем один список приоритетов 0-N*M ?
Тем, что внутри группы кто первым встал, того и тапки. Приоритет внутри группы — он только на случай одновремённо анализирумеых запросов. Когда уже одно из них выполняется — другие возникшие не будут его прерывать. Группа (почти) равноправных прерываний, выполняемых последовательно, не будет дополнительно тратить время и стек на сохранение регистров R0-R3, R12, LR, PC, PSR («stacking»)

Совсем разные приоритеты, групп нет
isr1 enter -- stacking
...
isr2 enter -- stacking
...
...
isr2 exit -- unstacking
...
isr1 exit -- unstacking

Внутри группы
isr1 enter -- stacking
...
...
isr1 exit -- isr2 enter
...
...
isr2 exit -- unstacking

p.s. Похожее было и в Q-bus (электроника-60), хоть там и «stacking» включал в себя только PC и PSW.
Уровни приоритета это одно, а внутри каждого уровня распространение сигнала по платам/разъёмам обеспечивало «подприоритет» внутри группы, действующий только на момент входа в прерывание, дальше запросы этого уровня просто не воспринимались процессором (до понижения приоритета процессора в драйвере). И у всех остальных процессоров с несколькими уровнями приоритета -- внутри одного приоритета вытеснения уже работающего обработчика нет.
Только там железно было разбито на количество групп (число входов запросов прерывания у процессора) и количество в группе (сколько плат можно в корзину натолкать в случае Q-bus).
А тут дали возможность двигать границу.


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
Allregia
сообщение Oct 23 2012, 20:18
Сообщение #15


Профессионал
*****

Группа: Свой
Сообщений: 1 047
Регистрация: 28-06-07
Из: Israel
Пользователь №: 28 763



Цитата(ReAl @ Oct 23 2012, 22:05) *
Тем, что внутри группы кто первым встал, того и тапки. Приоритет внутри группы — он только на случай одновремённо анализирумеых запросов. Когда уже одно из них выполняется — другие возникшие не будут его прерывать.


Т.е. если я хочу чтобы прерывание с более высоким приоритетом прерывало прерывание с более низким, они обязательно долдны быть в разных группах?
А если они из одной группы, и выполняется прерывание с бОльшим номером подгруппы (т.е. менее приоритетное), то прерывание той-же группы с меньшим номером (по идее более приоритетное) его не прервет?


Цитата
Группа (почти) равноправных прерываний, выполняемых последовательно, не будет дополнительно тратить время и стек на сохранение регистров R0-R3, R12, LR, PC, PSR («stacking»)


А разве стекирование работает только для прерываний одной группы?
Т.е. если в момент выполнения высокоприоритетного прерывания возникает другое, менее приоритетное, то оно подождет и будет выполнено после, но пролог/эпилог не будут выполняться только если оба эти прерывания одной группы?
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 19th July 2025 - 19:09
Рейтинг@Mail.ru


Страница сгенерированна за 0.01515 секунд с 7
ELECTRONIX ©2004-2016