реклама на сайте
подробности

 
 
> Выход из handler-mode в cortex-m3
Omnicake
сообщение May 11 2014, 08:01
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 56
Регистрация: 12-01-14
Из: Омск
Пользователь №: 80 002



Здравствуйте, столкнулся с проблемой. Сделал обработку прерывания на системный таймер Systick, во время обработки прерывания производится изменения битов и в конце грузятся значения регистров LR и SP для другой подзадачи (тем самым реализовано переключение задач), однако при выходе на задачу процессор почему-то остается в handler-mode - то есть по сути не выходит из прерывания. Соответственно на последующие срабатывания прерывания от таймера процессор никак не реагирует. Прочитал, что для корректного переключения режимов, надо в регистр LR заносить специальное значение EXC_RETURN, однако как это сделать если в LR мне одновременно нужно занести и значение для переключения на задачу? Как быть?
Go to the top of the page
 
+Quote Post
3 страниц V   1 2 3 >  
Start new topic
Ответов (1 - 14)
1113
сообщение May 11 2014, 08:08
Сообщение #2


Знающий
****

Группа: Свой
Сообщений: 604
Регистрация: 24-02-06
Из: Москва
Пользователь №: 14 658



разве режим - Handler или Thread - каким-либо образом влияют на факт срабатывания прерывания или факт исполнения соответствующего обработчика?
Go to the top of the page
 
+Quote Post
Omnicake
сообщение May 11 2014, 08:19
Сообщение #3


Участник
*

Группа: Участник
Сообщений: 56
Регистрация: 12-01-14
Из: Омск
Пользователь №: 80 002



Как мне казалось, handler-mode включается при обработке прерывания, а при его выходе возвращается в thread-mode с обнулением флага прерывания, что позволяет прерыванию снова сработать. Возможно я ошибаюсь, но в противном случае я не могу понять почему прерывание от таймера у меня срабатывает только один раз.
Go to the top of the page
 
+Quote Post
1113
сообщение May 11 2014, 08:30
Сообщение #4


Знающий
****

Группа: Свой
Сообщений: 604
Регистрация: 24-02-06
Из: Москва
Пользователь №: 14 658



приведите код настройки таймера и код обработчика
Go to the top of the page
 
+Quote Post
Omnicake
сообщение May 11 2014, 08:48
Сообщение #5


Участник
*

Группа: Участник
Сообщений: 56
Регистрация: 12-01-14
Из: Омск
Пользователь №: 80 002



Инициализация таймера
Код
    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
Go to the top of the page
 
+Quote Post
1113
сообщение May 11 2014, 08:58
Сообщение #6


Знающий
****

Группа: Свой
Сообщений: 604
Регистрация: 24-02-06
Из: Москва
Пользователь №: 14 658



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

orr lr, lr, #0x4
Go to the top of the page
 
+Quote Post
Omnicake
сообщение May 11 2014, 09:05
Сообщение #7


Участник
*

Группа: Участник
Сообщений: 56
Регистрация: 12-01-14
Из: Омск
Пользователь №: 80 002



Не помогло, на задаче он все также в handler-mode и на прерывание не возвращается.
Go to the top of the page
 
+Quote Post
1113
сообщение May 11 2014, 09:13
Сообщение #8


Знающий
****

Группа: Свой
Сообщений: 604
Регистрация: 24-02-06
Из: Москва
Пользователь №: 14 658



предлагаю вам отладиться без переключения контекста. имхо у вас со стеками проблема, а не с таймерами. уберите из обработчика изменения указателя стэка.
Go to the top of the page
 
+Quote Post
Omnicake
сообщение May 11 2014, 09:15
Сообщение #9


Участник
*

Группа: Участник
Сообщений: 56
Регистрация: 12-01-14
Из: Омск
Пользователь №: 80 002



Забыл кстати упомянуть, что компилируется все это с одним ворнингом ..\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 - May 11 2014, 09:19
Go to the top of the page
 
+Quote Post
1113
сообщение May 11 2014, 09:17
Сообщение #10


Знающий
****

Группа: Свой
Сообщений: 604
Регистрация: 24-02-06
Из: Москва
Пользователь №: 14 658



Цитата(Omnicake @ May 11 2014, 12:15) *
Забыл кстати упомянуть, что компилируется все это с одним ворнингом ..\scheduler.asm(40): warning: A1581W: Added 2 bytes of padding at address 0x3e, возможно в этом причина.
нет. компилятор для выравнивания границ добавил два "пустых" байта.
Go to the top of the page
 
+Quote Post
Omnicake
сообщение May 11 2014, 10:22
Сообщение #11


Участник
*

Группа: Участник
Сообщений: 56
Регистрация: 12-01-14
Из: Омск
Пользователь №: 80 002



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

А есть ли в cortex-m3 аналог команды reti? Я поспрашивал у людей, говорят на других процессорах она помогает из прерывания выходить.
Go to the top of the page
 
+Quote Post
1113
сообщение May 11 2014, 10:28
Сообщение #12


Знающий
****

Группа: Свой
Сообщений: 604
Регистрация: 24-02-06
Из: Москва
Пользователь №: 14 658



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

Цитата(Omnicake @ May 11 2014, 13:22) *
Попробовал убрать загрузку указателя стэка - ничего не изменилось.

А есть ли в 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?
Go to the top of the page
 
+Quote Post
Omnicake
сообщение May 11 2014, 10:31
Сообщение #13


Участник
*

Группа: Участник
Сообщений: 56
Регистрация: 12-01-14
Из: Омск
Пользователь №: 80 002



Таймер точно работает и генерирует прерывания, для примера убрал вызов шедулера и поставил простейшую команду i++, он корректно увеличивает ее через равные промежутки времени. В инструкции меня смущает строка "The processor saves an EXC_RETURN value to the LR on exception entry." Получается когда я заменяю LR внутри прерывания на LR задачи, я затираю тот самый EXC_RETURN value?
Go to the top of the page
 
+Quote Post
1113
сообщение May 11 2014, 11:00
Сообщение #14


Знающий
****

Группа: Свой
Сообщений: 604
Регистрация: 24-02-06
Из: Москва
Пользователь №: 14 658



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

... переключение контекста должно происходить только в exception, тогда в какой бы стек не попал LR и какой бы задаче он ни принадлежал, по входу в exception, и, соответственно, по выходу из него значение будет правильным и одинаковым для любой задачи. нужно только откорректировать биты режима процессора.
Go to the top of the page
 
+Quote Post
Omnicake
сообщение May 11 2014, 11:41
Сообщение #15


Участник
*

Группа: Участник
Сообщений: 56
Регистрация: 12-01-14
Из: Омск
Пользователь №: 80 002



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

3 страниц V   1 2 3 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 23rd July 2025 - 11:33
Рейтинг@Mail.ru


Страница сгенерированна за 0.01468 секунд с 7
ELECTRONIX ©2004-2016