Пока моя говяжья грудинка (см. « Моя первая домашняя копченая говяжья грудинка : день 1 ») курит ;-), у меня есть время для изучения проблемы, с которой я столкнулся в своей лекции в пятницу: щит Джойстика (см. « JoyStick»). Щит с платой FRDM “) на плате FRDM-KL25Z, я хотел использовать прерывание, если я нажимаю зеленую кнопку:
Однако это не сработало :-(.
Во-первых, я думал, что у платы могут быть проблемы, так как у меня были случаи, когда у таких плат были плохие точки пайки. Проверка с помощью логического анализатора показала, что аппаратная разводка работает:
Но нет прерывания для кнопки C :-(. И это работало для всех остальных контактов, которые имеют возможность прерывания. Так что может быть не так?
Во-первых, я должен отметить, что этот вывод находится на PTA4 на плате Freescale FRDM-KL25Z. PTA4 используется по умолчанию как NMI (вывод без прерывания). Я настроил его в Processor Expert с компонентом ExtInt (Внешнее прерывание):
Поскольку PTA4 по умолчанию настроен на прерывание NMI, я правильно отключил NMI в компоненте CPU:
У меня есть компоненты ExtInt для нескольких выводов порта A (PTA12, PTA4, PTA5 и PTA13), и все они правильно подключены к подпрограмме обслуживания прерываний Cpu_ivINT_PORTA и вектору прерываний:
PE_ISR(Cpu_ivINT_PORTA)
{
ExtIntLdd2_Interrupt(); /* Call the service routine */
ExtIntLdd3_Interrupt(); /* Call the service routine */
ExtIntLdd4_Interrupt(); /* Call the service routine */
ExtIntLdd5_Interrupt(); /* Call the service routine */
}
Таким образом, я полагаю, что, возможно, обнаружил ошибку Processor Expert? Каким-то образом мой компонент PTA4 ExtInt вступает в конфликт с настройками вектора внутреннего прерывания NMI. В результате мое пользовательское прерывание PTA4 не срабатывает :-(.
Я нашел хотя бы способ, как заставить его работать. Для этого я добавляю компонент Init_GPIO в свой проект и настраиваю его для создания прерывания для PTA4:
Теперь, когда мой вектор PORTA_OnInterrupt () используется для вектора прерывания, мне нужно направить его в обработчик в Cpu.c:
void PORTA_OnInterrupt(void) {
void Cpu_ivINT_PORTA(void); /* prototype of ISR in Cpu.c */
Cpu_ivINT_PORTA(); /* call interrupt handler created by the ExtInt components */
}
Cpu_ivINT_PORTA (), сгенерированный процессором Expert в Cpu.c:
PE_ISR(Cpu_ivINT_PORTA)
{
ExtIntLdd2_Interrupt(); /* Call the service routine */
ExtIntLdd3_Interrupt(); /* Call the service routine */
ExtIntLdd4_Interrupt(); /* Call the service routine */
ExtIntLdd5_Interrupt(); /* Call the service routine */
}
Это вызывает прерывание NMI, как это
void ExtIntLdd3_Interrupt(void)
{
/* {Default RTOS Adapter} ISR parameter is passed through the global variable */
ExtIntLdd3_TDeviceDataPtr DeviceDataPrv = INT_PORTA__DEFAULT_RTOS_ISRPARAM;
/* Check if the component is disabled */
if (!DeviceDataPrv->UserEnabled) {
return;
}
/* Call OnInterrupt event */
ExtIntLdd3_OnInterrupt(DeviceDataPrv->UserData);
}
Обратите внимание, что этот код * не * подтверждает флаг ISR. Затем он вызывает следующий обработчик:
void ExtIntLdd3_OnInterrupt(LDD_TUserData *UserDataPtr)
{
(void)UserDataPtr; /* Parameter is not used, suppress unused argument warning */
SW3_OnInterrupt(); /* Invoke OnInterrupt event */
}
При этом мне нужно обработать подтверждение флага прерывания в моем SW3_OnInterrupt ():
void SW3_OnInterrupt(void)
{
#if PL_HAS_KBI
#if 1 /* Problem with Processor Expert and sharing PTA4/NMI interrupt: code below is missing in ExtIntLdd3_OnInterrupt() */
/* Check the pin interrupt flag of the shared interrupt */
if (PORT_PDD_GetPinInterruptFlag(PORTA_BASE_PTR, ExtIntLdd3_PIN_INDEX)) {
/* Clear the interrupt flag */
PORT_PDD_ClearPinInterruptFlag(PORTA_BASE_PTR, ExtIntLdd3_PIN_INDEX);
/* call user event */
KEY_OnInterrupt(KEY_BTN3);
}
#else
if (KEY3_Get()) {
KEY_OnInterrupt(KEY_BTN3);
}
#endif
#endif
}
С этим все работает ?
Резюме
Можно отключить и предопределенные прерывания, такие как NMI для Kinetis. Однако это может конфликтовать с настройками ЦП по умолчанию (или является ошибкой в Processor Expert). В любом случае, я нашел решение, чтобы оно заработало:
- Используйте компонент Init_GPIO, чтобы разрешить прерывания в PORTA с пользовательским обработчиком.
- Направьте прерывания из пользовательского обработчика в обработчик компонента ЦП.
Счастливое прерывание ?




