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

Выход из handler-mode в cortex-m3

Здравствуйте, столкнулся с проблемой. Сделал обработку прерывания на системный таймер Systick, во время обработки прерывания производится изменения битов и в конце грузятся значения регистров LR и SP для другой подзадачи (тем самым реализовано переключение задач), однако при выходе на задачу процессор почему-то остается в handler-mode - то есть по сути не выходит из прерывания. Соответственно на последующие срабатывания прерывания от таймера процессор никак не реагирует. Прочитал, что для корректного переключения режимов, надо в регистр LR заносить специальное значение EXC_RETURN, однако как это сделать если в LR мне одновременно нужно занести и значение для переключения на задачу? Как быть?

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


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

разве режим - Handler или Thread - каким-либо образом влияют на факт срабатывания прерывания или факт исполнения соответствующего обработчика?

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


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

Как мне казалось, handler-mode включается при обработке прерывания, а при его выходе возвращается в thread-mode с обнулением флага прерывания, что позволяет прерыванию снова сработать. Возможно я ошибаюсь, но в противном случае я не могу понять почему прерывание от таймера у меня срабатывает только один раз.

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


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

Инициализация таймера

    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

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


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

инициализация и обработчик - правильные. но для переключения режимов добавьте в шедулере перед bx lr

 

orr lr, lr, #0x4

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


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

Не помогло, на задаче он все также в handler-mode и на прерывание не возвращается.

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


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

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

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


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

Забыл кстати упомянуть, что компилируется все это с одним ворнингом ..\scheduler.asm(40): warning: A1581W: Added 2 bytes of padding at address 0x3e, возможно в этом причина.

Также в дизасемблере при входе в scheduler() выполняется команда PUSH{r4,lp} а на выходе - POP {r4,pc}. Попробовал сейчас оставить в шедулере только BX LR (то есть возврат на main) режим процессора переключился на thread, как и должно быть.

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

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


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

Забыл кстати упомянуть, что компилируется все это с одним ворнингом ..\scheduler.asm(40): warning: A1581W: Added 2 bytes of padding at address 0x3e, возможно в этом причина.
нет. компилятор для выравнивания границ добавил два "пустых" байта.

 

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


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

Попробовал убрать загрузку указателя стэка - ничего не изменилось.

 

А есть ли в cortex-m3 аналог команды reti? Я поспрашивал у людей, говорят на других процессорах она помогает из прерывания выходить.

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


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

а вы уверены, что таймер считает, а не находится в выключенном состоянии из-за отладки или режима сна какого-нибудь?

 

Попробовал убрать загрузку указателя стэка - ничего не изменилось.

 

А есть ли в 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?

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


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

Таймер точно работает и генерирует прерывания, для примера убрал вызов шедулера и поставил простейшую команду i++, он корректно увеличивает ее через равные промежутки времени. В инструкции меня смущает строка "The processor saves an EXC_RETURN value to the LR on exception entry." Получается когда я заменяю LR внутри прерывания на LR задачи, я затираю тот самый EXC_RETURN value?

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


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

Таймер точно работает и генерирует прерывания, для примера убрал вызов шедулера и поставил простейшую команду i++, он корректно увеличивает ее через равные промежутки времени. В инструкции меня смущает строка "The processor saves an EXC_RETURN value to the LR on exception entry." Получается когда я заменяю LR внутри прерывания на LR задачи, я затираю тот самый EXC_RETURN value?
походу так. потому как по его значению "процессор определяет, что это не простой переход, а выход из эксепшена"

 

... переключение контекста должно происходить только в exception, тогда в какой бы стек не попал LR и какой бы задаче он ни принадлежал, по входу в exception, и, соответственно, по выходу из него значение будет правильным и одинаковым для любой задачи. нужно только откорректировать биты режима процессора.

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


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

Оно и происходит внутри прерывания, ведь scheduler() выполняется внутри SysTick_Handler. Сейчас обратил внимание на другую особенность при обработке задачи. В Cortex-M# есть регистр xPSR, которые содержит в себе под-регистр ISR в момент до прерывания значение этого регистра равно 0, при входе в прерывание оно изменяется на 15 (что как я понимаю соответствует прерыванию от системного таймера), однако при выходе на task1 ISR не обнуляется, а так и остается равным 15. Есть ли возможность ручной корректировке этого бита, и можно ли с помощью этого решить проблему?

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


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

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

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

Гость
Ответить в этой теме...

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

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

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

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

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

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