Omnicake 0 11 мая, 2014 Опубликовано 11 мая, 2014 · Жалоба Здравствуйте, столкнулся с проблемой. Сделал обработку прерывания на системный таймер Systick, во время обработки прерывания производится изменения битов и в конце грузятся значения регистров LR и SP для другой подзадачи (тем самым реализовано переключение задач), однако при выходе на задачу процессор почему-то остается в handler-mode - то есть по сути не выходит из прерывания. Соответственно на последующие срабатывания прерывания от таймера процессор никак не реагирует. Прочитал, что для корректного переключения режимов, надо в регистр LR заносить специальное значение EXC_RETURN, однако как это сделать если в LR мне одновременно нужно занести и значение для переключения на задачу? Как быть? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
1113 5 11 мая, 2014 Опубликовано 11 мая, 2014 · Жалоба разве режим - Handler или Thread - каким-либо образом влияют на факт срабатывания прерывания или факт исполнения соответствующего обработчика? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Omnicake 0 11 мая, 2014 Опубликовано 11 мая, 2014 · Жалоба Как мне казалось, handler-mode включается при обработке прерывания, а при его выходе возвращается в thread-mode с обнулением флага прерывания, что позволяет прерыванию снова сработать. Возможно я ошибаюсь, но в противном случае я не могу понять почему прерывание от таймера у меня срабатывает только один раз. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
1113 5 11 мая, 2014 Опубликовано 11 мая, 2014 · Жалоба приведите код настройки таймера и код обработчика Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Omnicake 0 11 мая, 2014 Опубликовано 11 мая, 2014 · Жалоба Инициализация таймера AREA HEAP, CODE, READONLY systick PROC EXPORT systick MOV R0,#0x03e8; 0x03e8 = 1000 - количество тактов до прерывания MOV R1,#0xe000e000 STR R0,[r1,#0x14] STR R0,[r1,#0x18] MOVS R0,#0x07 STR R0,[r1,#0x10] ENDP BX LR END Обработчик вызывается из main.c таким образом void SysTick_Handler() { scheduler(); } В scheduler() выполняются следующие действия: LDR r0, =TaskPointer LDR r0, [r0] LDR r0, [r0] MOV r1, r0 LDR sp, [r1,#24] LDR lr, [r1,#16] BX LR Где TaskPointer - это массив в котором содержится определенная информация о задачах, которые нужно переключать, соответственно [r1,#24] - адрес указателя стэка для задачи 1, [r1,#16] - значение pc регистра для задачи 1. После BX LR прграмма выходит на зацикленную задачу task1.c int task1(des1* ddd) { int i, j, x, y; ddd->temp = 0x12345678; while(1) for( i = 0; i < 30000; i++ ) for( j = 0; j < 30000; j++ ) { x = 1; y = x; x = y; } } И на ней и остается, то есть при попытке поставить breakpoint на моменте до входа в scheduler() программа не останавливается а продолжает выполнять task1.c Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
1113 5 11 мая, 2014 Опубликовано 11 мая, 2014 · Жалоба инициализация и обработчик - правильные. но для переключения режимов добавьте в шедулере перед bx lr orr lr, lr, #0x4 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Omnicake 0 11 мая, 2014 Опубликовано 11 мая, 2014 · Жалоба Не помогло, на задаче он все также в handler-mode и на прерывание не возвращается. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
1113 5 11 мая, 2014 Опубликовано 11 мая, 2014 · Жалоба предлагаю вам отладиться без переключения контекста. имхо у вас со стеками проблема, а не с таймерами. уберите из обработчика изменения указателя стэка. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Omnicake 0 11 мая, 2014 Опубликовано 11 мая, 2014 (изменено) · Жалоба Забыл кстати упомянуть, что компилируется все это с одним ворнингом ..\scheduler.asm(40): warning: A1581W: Added 2 bytes of padding at address 0x3e, возможно в этом причина. Также в дизасемблере при входе в scheduler() выполняется команда PUSH{r4,lp} а на выходе - POP {r4,pc}. Попробовал сейчас оставить в шедулере только BX LR (то есть возврат на main) режим процессора переключился на thread, как и должно быть. Изменено 11 мая, 2014 пользователем Omnicake Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
1113 5 11 мая, 2014 Опубликовано 11 мая, 2014 · Жалоба Забыл кстати упомянуть, что компилируется все это с одним ворнингом ..\scheduler.asm(40): warning: A1581W: Added 2 bytes of padding at address 0x3e, возможно в этом причина.нет. компилятор для выравнивания границ добавил два "пустых" байта. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Omnicake 0 11 мая, 2014 Опубликовано 11 мая, 2014 · Жалоба Попробовал убрать загрузку указателя стэка - ничего не изменилось. А есть ли в cortex-m3 аналог команды reti? Я поспрашивал у людей, говорят на других процессорах она помогает из прерывания выходить. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
1113 5 11 мая, 2014 Опубликовано 11 мая, 2014 · Жалоба а вы уверены, что таймер считает, а не находится в выключенном состоянии из-за отладки или режима сна какого-нибудь? Попробовал убрать загрузку указателя стэка - ничего не изменилось. А есть ли в cortex-m3 аналог команды reti? Я поспрашивал у людей, говорят на других процессорах она помогает из прерывания выходить. нет.Exception return Exception return occurs when the processor is in Handler mode and executes one of the following instructions attempts to set the PC to an EXC_RETURN value: an LDM or POP instruction that loads the PC an LDR instruction with PC as the destination a BX instruction using any register. The processor saves an EXC_RETURN value to the LR on exception entry. The exception mechanism relies on this value to detect when the processor has completed an exception handler. Bits[31:4] of an EXC_RETURN value are 0xFFFFFFF. When the processor loads a value matching this pattern to the PC it detects that the operation is a not a normal branch operation and, instead, that the exception is complete. Therefore, it starts the exception return sequence. Bits[3:0] of the EXC_RETURN value indicate the required return stack and processor mode, as Table 2.17 shows. http://infocenter.arm.com/help/index.jsp?t...a/Babefdjc.html в связи с этим, что у вас в LR перед выполнением bx lr? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Omnicake 0 11 мая, 2014 Опубликовано 11 мая, 2014 · Жалоба Таймер точно работает и генерирует прерывания, для примера убрал вызов шедулера и поставил простейшую команду i++, он корректно увеличивает ее через равные промежутки времени. В инструкции меня смущает строка "The processor saves an EXC_RETURN value to the LR on exception entry." Получается когда я заменяю LR внутри прерывания на LR задачи, я затираю тот самый EXC_RETURN value? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
1113 5 11 мая, 2014 Опубликовано 11 мая, 2014 · Жалоба Таймер точно работает и генерирует прерывания, для примера убрал вызов шедулера и поставил простейшую команду i++, он корректно увеличивает ее через равные промежутки времени. В инструкции меня смущает строка "The processor saves an EXC_RETURN value to the LR on exception entry." Получается когда я заменяю LR внутри прерывания на LR задачи, я затираю тот самый EXC_RETURN value?походу так. потому как по его значению "процессор определяет, что это не простой переход, а выход из эксепшена" ... переключение контекста должно происходить только в exception, тогда в какой бы стек не попал LR и какой бы задаче он ни принадлежал, по входу в exception, и, соответственно, по выходу из него значение будет правильным и одинаковым для любой задачи. нужно только откорректировать биты режима процессора. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Omnicake 0 11 мая, 2014 Опубликовано 11 мая, 2014 · Жалоба Оно и происходит внутри прерывания, ведь scheduler() выполняется внутри SysTick_Handler. Сейчас обратил внимание на другую особенность при обработке задачи. В Cortex-M# есть регистр xPSR, которые содержит в себе под-регистр ISR в момент до прерывания значение этого регистра равно 0, при входе в прерывание оно изменяется на 15 (что как я понимаю соответствует прерыванию от системного таймера), однако при выходе на task1 ISR не обнуляется, а так и остается равным 15. Есть ли возможность ручной корректировке этого бита, и можно ли с помощью этого решить проблему? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться