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

NVIC прерывание от EXTI в момент NVIC_Init

Здравствуйте господа.

 

Давно терзает меня вопрос, почему в момент инициализации NVIC_Init(&NVIC_InitStructure); может возникнуть прерывание?

Выглядит это так, как будто в момент запуска МК, в регистре EXTI->PR уже заранее что то есть, и когда включаем NVIC произсходит прерывание.

Микроконтроллер STM32F100C4

Вот код:

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 такое явление замечал.

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


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

Так оно и есть. При включении питания лапки меняют свой уровень. Соответственно пендинги взводятся. Так что NVIC приходится чистить.

 

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


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

А вы бы посмотрели

1. что конкретно делает функция NVIC_Init()

2. содержимое EXTI_PR до вызова NVIC_Init и сразу же после него (отладчиком, либо вывести в UART, либо на LCD)

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


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

Так оно и есть. При включении питания лапки меняют свой уровень. Соответственно пендинги взводятся. Так что NVIC приходится чистить.

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

Может вы имели в виду не NVIC чистить а EXTI?

 

 

А вы бы посмотрели

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.

Изменено пользователем Basilij

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


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

В мануале про EXTI_PR написано Reset value: undefined, так что очищать обязательно.

А вообще есть хорошее правило - всегда сбрасывать любые статусы, перед тем как разрешать соответствующее им прерывание, помогает избежать трудно-уловимых глюков.

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


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

Удалось добиться стабильной повторяемости. Судя по отладчику, флаг 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.

 

В мануале про 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." ?

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


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

А вот что значит ""...or by changing the sensitivity of the edge detector." ?

 

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

Изменено пользователем IgorKossak
бездумное цитирование

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


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

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

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

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

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

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

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

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

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

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