Пока моя говяжья грудинка (см. « Моя первая домашняя копченая говяжья грудинка : день 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 с пользовательским обработчиком.
- Направьте прерывания из пользовательского обработчика в обработчик компонента ЦП.
Счастливое прерывание ?