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

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> stm32 вопрос по приоритетам прерываний
Nikitoc
сообщение May 17 2011, 19:42
Сообщение #1


Местный
***

Группа: Validating
Сообщений: 207
Регистрация: 14-01-09
Из: Днепропетровск
Пользователь №: 43 367



Всем доброго времени суток. Я тут зацепился с прерываниями на stm32l152. Пишу на Си в Keil'е, использую либы производителя.
В общем ситуёвина такая: имеем прерывание по USART1 (по приходу символа в приемник) с приоритетом "1" и прерывание от SysTick таймера с приоритетом "3". Приоритеты выставляю вручную. По всем докам на CORTEX-M3 ясно, что прерывание с более высоким приоритетом должно моментально приостанавливать выполнение прерывания с более низким приоритетом (в данном случае USART1 должно прерывать SysTick). На практике же почему-то выходит наоборот - теряется часть посылки по USART1 если SysTick прерывания разрешены (в обработчике SysTick выполняется довольно много работы). Кто-нибудь сталкивался с подобным?
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение May 17 2011, 20:17
Сообщение #2


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Дык! Так и есть, чем меньше циферка, тем больше приоритетsm.gif


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
Nikitoc
сообщение May 17 2011, 21:19
Сообщение #3


Местный
***

Группа: Validating
Сообщений: 207
Регистрация: 14-01-09
Из: Днепропетровск
Пользователь №: 43 367



Цитата(AHTOXA @ May 17 2011, 23:17) *
Дык! Так и есть, чем меньше циферка, тем больше приоритетsm.gif

Вы наверное меня неправильно поняли. Поступающий в приемник USART1 (приоритет "1") байт НЕ прерывает выполнение обработчика SysTick (приоритет "3"), либо очень долго прерывает, т.к. за это время затираются другие принятые по USART1 байты...
После того как назначил приоритеты я их проверяю посредством такой ф-ции:
Код
NVIC_GetPriority(SysTick_IRQn);

Ну а выставляю соответственно:
Код
NVIC_SetPriority(SysTick_IRQn, 3);

Может это неправильный способ назначения приоритета системного таймера? Или нужно еще где-то что-то выставить? Просто такое впечатление, что у него остается его приоритет по дефолту "-1".

Сообщение отредактировал Nikitoc - May 17 2011, 21:28
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение May 18 2011, 03:29
Сообщение #4


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



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


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
ek74
сообщение May 18 2011, 05:34
Сообщение #5


Частый гость
**

Группа: Свой
Сообщений: 81
Регистрация: 4-08-05
Из: г. Саратов
Пользователь №: 7 351



Цитата(Nikitoc @ May 18 2011, 01:19) *
Ну а выставляю соответственно:
Код
NVIC_SetPriority(SysTick_IRQn, 3);

Используйте NVIC_EncodePriority(...). Например:
Код
/* 2 bits for pre-emption priority and 2 bits for subpriority */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

/* Set USART1 interrupt preemption priority to 1 */
NVIC_SetPriority(USART1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 1, 0));

/* Set SysTick interrupt preemption priority to 3 */
NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 3, 0));
Go to the top of the page
 
+Quote Post
Nikitoc
сообщение May 18 2011, 10:40
Сообщение #6


Местный
***

Группа: Validating
Сообщений: 207
Регистрация: 14-01-09
Из: Днепропетровск
Пользователь №: 43 367



Цитата(AHTOXA @ May 18 2011, 06:29) *
Дело в том, что есть ещё такое понятие, как группы приоритетов. По умолчанию все прерывания в одной группе, то есть, друг друга не прерывают. Для того, чтобы прерывали, надо включить несколько групп (NVIC_SetPriorityGrouping()), и развести прерывания по группам.

Т.е. preemption priority для всех одинаковый, а subpriority разные? А зачем тогда нужны эти subpriority если на выполнение прерываний они не влияют?

Цитата(ek74 @ May 18 2011, 08:34) *
Код
/* 2 bits for pre-emption priority and 2 bits for subpriority */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

Я делаю в самом начале инициализации так:
Код
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);

а потом уже при настройке отдельных периферийных модулей делаю вот так:
Код
/* Enable the USARTx Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = USART1_Receiver_Priority;      
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);


Это корректно?

Сообщение отредактировал Nikitoc - May 18 2011, 10:41
Go to the top of the page
 
+Quote Post
ek74
сообщение May 18 2011, 12:14
Сообщение #7


Частый гость
**

Группа: Свой
Сообщений: 81
Регистрация: 4-08-05
Из: г. Саратов
Пользователь №: 7 351



Цитата(Nikitoc @ May 18 2011, 14:40) *
Т.е. preemption priority для всех одинаковый, а subpriority разные? А зачем тогда нужны эти subpriority если на выполнение прерываний они не влияют?
[The Definitive Guide to the ARM Cortex-M3, Second Edition, Page 114]
The preempt priority level defines whether an interrupt can take place when the processor is already running another interrupt handler. The subpriority level value is used only when two exceptions with the same preempt priority level occurred at the same time. In this case, the exception with higher subpriority (lower value) will be handled first.

Цитата(Nikitoc @ May 18 2011, 14:40) *
Это корректно?
В принципе, да. И не забыть установить приоритет для SysTick.
Go to the top of the page
 
+Quote Post
Nikitoc
сообщение May 18 2011, 15:06
Сообщение #8


Местный
***

Группа: Validating
Сообщений: 207
Регистрация: 14-01-09
Из: Днепропетровск
Пользователь №: 43 367



Спасибо. Предельно ясно.
Go to the top of the page
 
+Quote Post
Nikitoc
сообщение May 25 2011, 22:34
Сообщение #9


Местный
***

Группа: Validating
Сообщений: 207
Регистрация: 14-01-09
Из: Днепропетровск
Пользователь №: 43 367



В продолжение темы о прерываниях. USART2 почему-то упорно не хочет генерировать повторное прерывание. Один раз все случилось, благополучно обработалось, а второй и последующие разы - полный игнор. Ниже привожу процедуры инициализации USART2:
Код
/*******************************************************************************
* Function Name  : UsartInit
* Description    : Configures the USART2.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void USART_Init() {
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    USART_DeInit(USART2);
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);        /* Enable GPIO clock */
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);        /* Enable UART clock */
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource2,  GPIO_AF_USART2);        /* Connect alternate function pins to USART */
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource3,  GPIO_AF_USART2);         /* Connect alternate function pins to USART */
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource1, GPIO_AF_USART2);        /* Connect alternate function pins to USART */
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource0, GPIO_AF_USART2);         /* Connect alternate function pins to USART */
                                                                    
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_1;        /* Configure USART Tx as alternate function push-pull */
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_0;         /* Configure USART Rx as input floating */
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_RTS_CTS;
    USART_InitStructure.USART_BaudRate = 921600;
    USART_Init(USART2, &USART_InitStructure);                             /* USART configuration */
    
    NVIC_SetPriority(USART2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 4, 0));
    NVIC_EnableIRQ(USART2_IRQn);
    USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);          
          
    USART_Cmd(USART2, ENABLE);                      /* Enable USART */
}
/*******************************************************************************/


и процедуру обработки прерывания:
Код
/*------------------------------------------------------------------------------
            This function handles USART2 global interrupt request.
    
*-----------------------------------------------------------------------------*/
void USART2_IRQHandler(void) {

    if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)  {

        HostProt_Parser();                                            // обработка принятого символа
                                          
    } else {

         ClearUSART_IT_Bits(USART2);

    }
    
    USART_ClearITPendingBit(USART2, USART_IT_RXNE);

}
/*------------------------------------------------------------------------------


В том что символ приходит на вход RX - уверен на 100%.
P.S. Я где-то натыкался на подобную тему, но не смог найти. Буду благодарен за любые подсказки.

Сообщение отредактировал Nikitoc - May 25 2011, 23:04
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение May 26 2011, 02:22
Сообщение #10


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



USART_IT_RXNE чистится автоматом при вычитывании USARTx->DR, поэтому вручную его чистить не надо.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
Nikitoc
сообщение May 26 2011, 06:56
Сообщение #11


Местный
***

Группа: Validating
Сообщений: 207
Регистрация: 14-01-09
Из: Днепропетровск
Пользователь №: 43 367



Цитата(AHTOXA @ May 26 2011, 05:22) *
USART_IT_RXNE чистится автоматом при вычитывании USARTx->DR, поэтому вручную его чистить не надо.

Да. Спасибо. Но повторного прерывания все равно не происходит :-(
Go to the top of the page
 
+Quote Post
SergSit
сообщение May 26 2011, 08:33
Сообщение #12


Частый гость
**

Группа: Свой
Сообщений: 173
Регистрация: 9-12-05
Пользователь №: 12 031



Цитата(AHTOXA @ May 18 2011, 06:29) *
А, понятно. Дело в том, что есть ещё такое понятие, как группы приоритетов. По умолчанию все прерывания в одной группе, то есть, друг друга не прерывают. Для того, чтобы прерывали, надо включить несколько групп (NVIC_SetPriorityGrouping()), и развести прерывания по группам.


Что то не понимаю. В Cortex™-M3 r2p0 Technical Reference Manual в разделе 5.3.2 сказано , что если поле PRIGROUP равно 0, то мы имеем 0-ой бит для подгруппы, и 1-7 биты для групп( выгружаемых). А в соответствии с PM0056 Programming manual STM32F10xxx Cortex-M3 programming manual раздел 4.3.4 Application interrupt and reset control register (SCB_AIRCR) поле PRIGROUP после сброса равно нулю. Т.е. после сброса мы имеем 16 выгружаемых групп приоритетов. Где ошибка у Вас или у меня?
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение May 26 2011, 09:30
Сообщение #13


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(Nikitoc @ May 26 2011, 12:56) *
Но повторного прерывания все равно не происходит :-(

Да вроде нормально всё...
Убедитесь, что в HostProt_Parser(); USARTx->DR вычитывается один и только один раз.
Попробуйте убрать это:
Код
ClearUSART_IT_Bits(USART2);

(Я не знаю что это такое, но по названию догадываюсь, что чистит какие-то флаги)
Попробуйте также сконфигурировать USART пока без контроля потока.

Цитата(SergSit @ May 26 2011, 14:33) *
Т.е. после сброса мы имеем 16 выгружаемых групп приоритетов. Где ошибка у Вас или у меня?

Похоже, что вы правы. При включении PRIGROUP=0, и все биты приоритета (кроме самого младшего, отсутствующего), являются pre-emption priority.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
Nikitoc
сообщение May 26 2011, 09:35
Сообщение #14


Местный
***

Группа: Validating
Сообщений: 207
Регистрация: 14-01-09
Из: Днепропетровск
Пользователь №: 43 367



Цитата(AHTOXA @ May 26 2011, 12:30) *
Убедитесь, что в HostProt_Parser(); USARTx->DR вычитывается один и только один раз.

Ээээ... Вообще-то вычитывается точно не один раз, в этой процедуре я принимаю несколько байт. А в чем собственно засада?
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение May 26 2011, 10:24
Сообщение #15


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(Nikitoc @ May 26 2011, 15:35) *
Вообще-то вычитывается точно не один раз, в этой процедуре я принимаю несколько байт. А в чем собственно засада?

Это как это? В прерывании по приёму одного байта вычитываете несколько? Ждёте что ли их? Опрашиваете RXNE? Отключаете прерывание при этом?


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
Nikitoc
сообщение May 26 2011, 10:39
Сообщение #16


Местный
***

Группа: Validating
Сообщений: 207
Регистрация: 14-01-09
Из: Днепропетровск
Пользователь №: 43 367



Цитата(AHTOXA @ May 26 2011, 13:24) *
Это как это? В прерывании по приёму одного байта вычитываете несколько? Ждёте что ли их? Опрашиваете RXNE? Отключаете прерывание при этом?

Да, ожидаю RXNE. Прерывания не отключаю. Получаю строчку и выхожу.
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение May 26 2011, 12:29
Сообщение #17


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(Nikitoc @ May 26 2011, 16:39) *
Да, ожидаю RXNE. Прерывания не отключаю. Получаю строчку и выхожу.

Хм. Как-то это криво, не? А если первый символ - помеха? Да и глухо висеть в прерывании столько времени - не комильфо. Хотя дело ваше конечно.
Ну хорошо. А строчка-то приходит? Целиком?
Если так, то проблема скорее всего в лишней зачистке RXNE. Либо напрямую, либо при вычитывании DR. По идее, каждому новому RXNE должно соответствовать ровно одно чтение DR. Причём первый раз RXNE уже взведён при входе в прерывание.
Больше в голову ничего не приходит.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
Nikitoc
сообщение May 26 2011, 14:01
Сообщение #18


Местный
***

Группа: Validating
Сообщений: 207
Регистрация: 14-01-09
Из: Днепропетровск
Пользователь №: 43 367



Цитата(AHTOXA @ May 26 2011, 15:29) *
Хм. Как-то это криво, не?

Похоже, что Вы правы. Если просто сохранять символ в буфер, все работает. Но стоит во время работы обработчика поступить еще хотя бы одному символу - как прерывания прекращаются несмотря на все танцы с бубном. Но ведь должно же быть хоть какое-то логическое объяснение происходящему!

Сообщение отредактировал Nikitoc - May 26 2011, 14:02
Go to the top of the page
 
+Quote Post
mdmitry
сообщение May 26 2011, 14:20
Сообщение #19


Начинающий профессионал
*****

Группа: Свой
Сообщений: 1 215
Регистрация: 25-10-06
Из: СПб
Пользователь №: 21 648



Не применительно к данному контроллеру, а по идеологии: прерывание вычитывает только один быйт и помещает его в буфер (скорее кольцевой). В основном потоке идет обработка принятых данных.


--------------------
Наука изощряет ум; ученье вострит память. Козьма Прутков
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение May 26 2011, 14:35
Сообщение #20


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(Nikitoc @ May 26 2011, 20:01) *
Но ведь должно же быть хоть какое-то логическое объяснение происходящему!

Мне тоже интересноsm.gif Давайте посмотрим на код HostProt_Parser()? (желательно упрощённый вариант, при котором ошибка ещё воспроизводится)
Ну или попробуйте сделать ещё один финт - перед каждым чтением DR вычитывайте SR. Это вычистит ошибки, может в них дело.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
Nikitoc
сообщение May 28 2011, 14:11
Сообщение #21


Местный
***

Группа: Validating
Сообщений: 207
Регистрация: 14-01-09
Из: Днепропетровск
Пользователь №: 43 367



Цитата(AHTOXA @ May 26 2011, 17:35) *
Давайте посмотрим на код HostProt_Parser()

В действительности там нет ничего особенного - я ожидаю RXNE, считываю байт-два оправляю строку в ответ и т.д.
После HostProt_Parser() - вычитываю SR - его значение 0x0280 - т.е. никаких ошибок, установлены только флаги CTS и TXE. И при этом дальнейших прерываний не происходит laughing.gif

Сообщение отредактировал Nikitoc - May 28 2011, 14:12
Go to the top of the page
 
+Quote Post
RusikOk
сообщение Dec 24 2016, 19:35
Сообщение #22


Участник
*

Группа: Участник
Сообщений: 46
Регистрация: 14-01-12
Пользователь №: 69 438




помогите понять в чем дело. выставляю приоритеты так. и в обработчик прерывания от UART системным таймером хоть убей не перебивается
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Dec 24 2016, 19:58
Сообщение #23


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



А вы не забыли вызвать NVIC_SetPriorityGrouping() ?


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
RusikOk
сообщение Dec 24 2016, 20:00
Сообщение #24


Участник
*

Группа: Участник
Сообщений: 46
Регистрация: 14-01-12
Пользователь №: 69 438



Код
HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_3);
не забыл
Go to the top of the page
 
+Quote Post
esaulenka
сообщение Dec 26 2016, 12:58
Сообщение #25


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

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



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


--------------------
Тут обсуждается творческий порыв, а не соответствие каким-либо стандартам ©
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 22nd July 2025 - 06:53
Рейтинг@Mail.ru


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