Я не уверен, что мне не хватает чего-то очевидного здесь, но у кого-то еще возникли проблемы с Cortex M0 + (или любым из диапазона Cortex M), возвращающимся с ISR в несколько случайную позицию в режиме потока после пробуждения из спящего режима (например, не возвращаясь к строке ниже инструкции WFI). Кажется, он проснулся в середине кода, например, в середине цикла for или в середине функции. Я использую ATSAMD218A микроконтроллер и использует отладчик в Atmel Studio, 7. Я пытался изолировать проблему и заметил следующее:Cortex M0 + возвращается в неправильное положение в режиме потока после прерывания сна
- Это происходит только тогда, когда устройство усыпить, когда устройство прерывается, когда он бодрствует, ISR всегда возвращается в нужное место.
- ISR всегда возвращается к тому же (некорректному) положению в коде, если я прокомментирую эту функцию или фрагмент кода, тогда он начнет возвращаться в другую неправильную позицию.
- Я неудачно вставил задержки и NOP, чтобы попытаться определить если он связан с синхронизацией или связан с синхронизацией, но он все равно всегда возвращается в ту же (неправильную) позицию
- Я попытался реализовать прерывания, используя как прямой доступ к регистру, так и используя библиотеку Arduino Interrupts.
- Это происходит как в режиме ожидания, так и в режиме ожидания.
- При просмотре инструкций по сборке во время отладки, перед выходом ISR выдается инструкция «bx lr», регистр ссылок. Регистр ссылок содержит значение, называемое EXC_RETURN, которое указывает на поведение возврата, которое в моем случае равно 0xFFFFFFF9 (возврат в режим потока). Однако я не могу найти фактический адрес памяти, который он возвращает в любом месте. Адрес памяти не входит ни в один из основных регистров R0-R15.
Я читал Справочное руководство по архитектуре ARMv6, а также Руководство пользователя Cortex M0 + Generic. Не совсем уверен, что происходит, и любые предложения по отладке будут высоко оценены. Кто-нибудь лучше понимает обработку исключений из серии Cortex M и может указать мне в правильном направлении, чтобы найти адрес памяти, в который возвращается поток, после ISR. Я мог бы предоставить код, если вы хотите, но даже простой фрагмент кода, который ничего не делает, кроме как считать в цикле, спать, а затем просыпаться, вызывает проблемы.
EDIT Я добавил соответствующий код ниже. Это самая удаленная версия (* striped), которая все еще вызывает проблемы. Я не включил функции кода RTC (использует библиотеку DS3231RTC), поскольку я уверен, что они не имеют никакого эффекта. Если вы думаете, что я должен загрузить больше, дайте мне знать.
void configInterrupt(void){
NVIC_DisableIRQ(EIC_IRQn);
NVIC_ClearPendingIRQ(EIC_IRQn);
NVIC_SetPriority(EIC_IRQn, 0);
NVIC_EnableIRQ(EIC_IRQn);
// Enable GCLK for IEC (External Interrupt Controller)
GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID(GCM_EIC));
EIC->WAKEUP.reg |= (1 << 0);
EIC->CONFIG[0].reg |= 0x2; // falling edge
pinConfig(16,INPUT,UP); // custom 'pinMode' function
PORT->Group[0].PINCFG[16].bit.PMUXEN = 1; // enable peripheral muxing
PORT->Group[0].PMUX[8].bit.PMUXE = 0x0; // function A (EIC) = 0x0
EIC->INTENSET.reg = EIC_INTENSET_EXTINT(1 << 0);
EIC->CTRL.bit.ENABLE = 1;
}
void EIC_Handler(void){
RTC_FLAG = 1; // my debug breakpoint is here, at this point the stack has already been pushed and I can see the PC value that will be popped off
int_count++;
EIC->INTFLAG.reg = 1 << 0;
}
void setup() {
configInterrupt();
configureRTC();
RTC_FLAG = 1;
}
void loop() {
if (RTC_FLAG == 1) {
RTC_FLAG = 0;
setNextAlarm();
}
for (int i = 0 ; i <= WINDOW-1 ; i++) {
String data = "";
rawVal = 0; // data gets read from sensor here (stripped)
data += String(rawVal);
data += ",";
distance = 0; // distance calculated from rawVal here (stripped)
data += String(distance);
data += ",";
mean = 0; // mean calculated in a function here (stripped)
data += String(mean);
data += ",";
data += String(int_count); // ISR returns here
// Data gets written to file here (stripped)
}
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
__DSB();
__WFI();
}
Можете ли вы опубликовать код, который вы использовали, и те моменты, которые, по вашему мнению, терпят неудачу? –
_ «Однако я не могу найти фактический адрес памяти, который он возвращает в любом месте» _ - См. B1.5.6 «Поведение элемента исключений» в ARM ARMv6-M; он находится в стеке. Как выглядит код ISR? – Notlikethat
Я сомневаюсь, что это ручная вещь, вероятно, вещь чипа, нужно прочитать руководство для устройства с особым упором на все, что он говорит о том, когда он ложится спать.Что сохранилось, а что нет, если есть рекомендация о том, как и где спать, и т. Д. –