Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: NVIC прерывание от EXTI в момент NVIC_Init
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Basilij
Здравствуйте господа.

Давно терзает меня вопрос, почему в момент инициализации NVIC_Init(&NVIC_InitStructure); может возникнуть прерывание?
Выглядит это так, как будто в момент запуска МК, в регистре EXTI->PR уже заранее что то есть, и когда включаем NVIC произсходит прерывание.
Микроконтроллер STM32F100C4
Вот код:
CODE
void InitButton()
{
GPIO_InitTypeDef GPIO_InitStructure;
EXTI_InitTypeDef EXTI_InitTypeDefStructure;
NVIC_InitTypeDef NVIC_InitStructure;

/* GPIOB clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
/*Включили тактирование AFIO на шине APB2. Этот блок отвечает за внешние прерывания как AF*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);

// Configure PB.13/13/14 as Input
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
GPIO_Init(GPIOB, &GPIO_InitStructure);

//Подключаем порт к прерыванию
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource12);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource13);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource14);

EXTI_InitTypeDefStructure.EXTI_Line = EXTI_Line12 | EXTI_Line13 | EXTI_Line14;
EXTI_InitTypeDefStructure.EXTI_LineCmd = ENABLE;
EXTI_InitTypeDefStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitTypeDefStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_Init(&EXTI_InitTypeDefStructure);
//EXTI_ClearITPendingBit(EXTI_Line12 | EXTI_Line13 | EXTI_Line14);

NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_Init(&NVIC_InitStructure);
};


void EXTI15_10_IRQHandler()
{
if (EXTI_GetITStatus(EXTI_Line12) != RESET)
{
EXTI_ClearITPendingBit(EXTI_Line12);
}
else if (EXTI_GetITStatus(EXTI_Line13) != RESET)
{
EXTI_ClearITPendingBit(EXTI_Line13);
}
else if (EXTI_GetITStatus(EXTI_Line14) != RESET)
{
EXTI_ClearITPendingBit(EXTI_Line14);
};
};


Перед Инициализацией NVIC пробовал очищать регистр прерываний EXTI командой
EXTI_ClearITPendingBit(EXTI_Line12 | EXTI_Line13 | EXTI_Line14);
После этого вроде как всё нормально.
Но почему так!?

Пины настраивал и внутренней и с внешней подтяжкой, но это не влияет. Внешняя подтяжка достаточная. Еще на STM32L152 такое явление замечал.
vlad_new
Так оно и есть. При включении питания лапки меняют свой уровень. Соответственно пендинги взводятся. Так что NVIC приходится чистить.
Sergey_Aleksandrovi4
А вы бы посмотрели
1. что конкретно делает функция NVIC_Init()
2. содержимое EXTI_PR до вызова NVIC_Init и сразу же после него (отладчиком, либо вывести в UART, либо на LCD)
Basilij
Цитата(vlad_new @ Oct 22 2012, 17:29) *
Так оно и есть. При включении питания лапки меняют свой уровень. Соответственно пендинги взводятся. Так что NVIC приходится чистить.

Предполагаю что если лапки подтянуты к GND, и ждут нажатия кнопки которая подтянет их к +3v то в момент включения там всётаки низкий уровень нежели высокий.
Может вы имели в виду не NVIC чистить а EXTI?


Цитата(Sergey_Aleksandrovi4 @ Oct 22 2012, 17:29) *
А вы бы посмотрели
1. что конкретно делает функция NVIC_Init()
2. содержимое EXTI_PR до вызова NVIC_Init и сразу же после него (отладчиком, либо вывести в UART, либо на LCD)

Конечно смотрел, в основном там "EXTI->PR" 0b010 0000 0000 0000 т.е. преимущественно на EXTI_Line13 флаг прерывания стоит после подачи питания и реже на EXTI_Line14. На EXTI_Line12 Вообще почти никогда из 1000 один раз может возникнет.

EXTI->PR Заполняется спонтанно, т.е. может быть заполнен на момент NVIC_Init может быть не заполнен.

Вопрос в том что я не нашёл примера от ST где бы вызывалась EXTI_ClearITPendingBit перед инициализацией NVIC. И в документации не нашёл где сказано что биты в EXTI->PR нужно чистить перед вызовом NVIC_Init.
Flexz
В мануале про EXTI_PR написано Reset value: undefined, так что очищать обязательно.
А вообще есть хорошее правило - всегда сбрасывать любые статусы, перед тем как разрешать соответствующее им прерывание, помогает избежать трудно-уловимых глюков.
Basilij
Удалось добиться стабильной повторяемости. Судя по отладчику, флаг EXTI->PR выставляеться не сразу после подачи питания, а в основном после GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource13);


Код
void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource)
{
  uint32_t tmp = 0x00;
  /* Check the parameters */
  assert_param(IS_GPIO_EXTI_PORT_SOURCE(GPIO_PortSource));
  assert_param(IS_GPIO_PIN_SOURCE(GPIO_PinSource));
  
  tmp = ((uint32_t)0x0F) << (0x04 * (GPIO_PinSource & (uint8_t)0x03));
  AFIO->EXTICR[GPIO_PinSource >> 0x02] &= ~tmp;
  AFIO->EXTICR[GPIO_PinSource >> 0x02] |= (((uint32_t)GPIO_PortSource) << (0x04 * (GPIO_PinSource & (uint8_t)0x03)));
}


Если возникло прерывание, и мы останавливаем отладку, но питание с МК не убираем, а просто перезапускаем отладку т.е. начинаем с Reset Handler то "EXTI->PR" уже равен 0b010 0000 0000 0000 при запуске. Т.е. значение регистра "EXTI->PR" в ОЗУ не очищается после Reset Handler.

Цитата(Flexz @ Oct 22 2012, 18:31) *
В мануале про EXTI_PR написано Reset value: undefined, так что очищать обязательно.
А вообще есть хорошее правило - всегда сбрасывать любые статусы, перед тем как разрешать соответствующее им прерывание, помогает избежать трудно-уловимых глюков.


Действительно написано.. Спасибо вам. Десять раз просмотрел весь это раздел и всё как то этот момент упускал из виду.

У меня ещё вопрос, ниже написано:
"This bit is cleared by writing a 1 into the bit or ..."
т.е. если в прерывание нас привело "EXTI->PR" 0b010 0000 0000 0000, то чтобы снять флаг прерывания мы должны выполнить команду
EXTI->PR = 0b010 0000 0000 0000 верно? В библиотеке так и есть.
А вот что значит ""...or by changing the sensitivity of the edge detector." ?
nis
Цитата(Basilij @ Oct 22 2012, 19:49) *
А вот что значит ""...or by changing the sensitivity of the edge detector." ?


Так сказано же что состояние не определено, а точнее определяется случайными факторами, т.к. внешние прерывания чувствительны к уровню а не к значению. Соответственно при подаче тактового сигнала на этот модуль мы получаем на выходе срабатывание.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.