2016-06-01 2 views
1

Я пытаюсь написать переключатель контекста в обработчике прерываний таймера. В настоящее время коммутатор контекста может переключаться между контекстами команды (кооператив). В обработчик прерываний, я пытался:ARM v6 Переключатель контекста IRQ

  1. Сохранить текущий счетчик программы как место старого поток должен держать выполнение
  2. Переключитесь в режим SVC на самом деле выполнить переключение контекста
  3. переключатель обратно в режим IRQ и изменить регистр связи, чтобы быть сохранены PC от нового потока
  4. Возврат из обработчика IRQ в ссылке IRQ регистр

Я считаю, что могу сделать первые два правильно, но мне было интересно: как я могу переключиться в режим прерывания или, по крайней мере, изменить SVC R13 и R15 из обработчика прерываний?

Я использую процессор ARM v6; Большое спасибо за помощь!

Edit: здесь в основном то, что мой переключатель:

void interrupt_yield() { 
    unsigned int old_mode; 
    __asm__("mrs %0, cpsr" : "=r" (old_mode)); 
    __asm__("msr cpsr_c, %0" : : "r" (MODE_SVC)); 

    PUSH_ALL; // Macro for push {r0-r12, lr} 
    __asm__("mov %0, sp" : "=r"(sp)); 
    manager->threads[manager->current_thread].sp = sp; 

    unsigned nt = (manager->current_thread + 1) % manager->thread_counter; 
    if (CURRENT_THREAD.status == ACTIVE) { 
     CURRENT_THREAD.status = INACTIVE; 
    } 
    manager->current_thread = nt; 

    CURRENT_THREAD.status = ACTIVE; 
    SET_SP(CURRENT_THREAD.sp); 
    POP_ALL; 

    __asm__("msr cpsr, %0" : : "r" (old_mode)); 
} 


void timer_vector() { // This is called by assembly in interrupt mode 
    armtimer_clear_interrupt(); // clear timer interrupt 
    interrupt_yield(); // Calls above function 
} 

Цель состоит в том, чтобы изменить IRQ ссылку регистра для возврата к новой функции. Однако я не могу вернуться в режим прерывания, чтобы сделать это.

1 еще править: я никогда не переключаю регистр ссылок IRQ; Я понимаю это, но я даже не переключаюсь в режим IRQ, так что это более поздняя проблема для исправления.

+1

Можете ли вы поделиться тем, что вы сделали/пытались до сих пор? Это поможет ответить на ваш вопрос. – PhilDulac

+0

Зачем вам нужно переключиться на обработчик SVC для переключения контекста? У него нет больше привилегий. – Dric512

+0

@ Dric512 Я хочу сделать это в режиме SVC, чтобы изменить указатель стека режима SVC, а не IRQ. Я не могу просто переключиться в режим SVC и перейти в регистр ссылок, потому что, когда происходит прерывание, я хочу сохранить r15 из работающего потока и переключиться на хранимый программный счетчик. –

ответ

1

Для ARMv6 вам необходимо изменить режимы, чтобы получить регистры банка. В вашем примере кода уже есть много необходимых данных.

#define MODE_IRQ 0x12 
    #define MODE_SVC 0x13 
    unsigned int mode; /* original mode */ 

    /* target data... */ 
    unsigned int lr_irq; 
    unsigned int sp_irq; 
    unsigned int spsr; 

    asm (" mrs %0, cpsr\n" /* Save mode. */ 
     " msr cpsr_c,%4 \n" /* to irq mode */ 
     " mov %1, lr\n"  /* Get lr_irq */ 
     " mov %2, sp\n"  /* Get sp_irq */ 
     " mrs %3, spsr\n" /* Get spsr_irq */ 
     " msr cpsr, %0\n" /* back to old mode */ 
     : "=&r" (mode), "=r"(lr_irq), 
      "=r"(sp_irq), "=r"(spsr) 
     : "I" (MODE_IRQ)); 

НКУ выделим lr_irq и т.д. для регистров общего назначения (не накренился), и вы можете передавать данные через режимы. ARMv7 с расширениями виртуализации имеет инструкцию, чтобы избежать этого переключателя.

Вы должны знать, что прерывание таймера может происходить во многих контекстах. Вероятно, разумно, по крайней мере, проверить spsr из режима IRQ и получить отладку (утверждать как), которая проверяет, что это пользовательский режим. Если это никогда не срабатывает, и вы считаете, что IRQ может произойти только в пользовательском режиме, тогда отладка может быть удалена.

Другой метод заключается в том, чтобы сделать это в ассемблере обработчика IRQ и передать их, например, в процедуру interrupt_yield() в r0-r2. ARM EABI задает параметры в r0-r2, поэтому для параметров прерывания требуются параметры. Если у вас есть эти данные, нет необходимости возвращаться в режим IRQ. Я очень рекомендую этот метод для производственного кода. Вышеприведенное хорошо для прототипирования.


Похожие: Explicitly accessing banked registers on ARM

+0

Спасибо, это очень помогает. Как я могу изменить lr_irq и sp_irq? Я считаю, что мне нужно сделать это, чтобы действительно вернуться к новой теме. –

+0

Я вижу это: /var/folders/qb/njcg85_123s4jqr_n0kkt71w0000gn/T//ccStXA95.s:39: Ошибка: выбранный процессор не поддерживает режим ARM 'cpsid aif, # 18 ' –

+0

Есть ли все-таки обойти его? @ artless-noise –

Смежные вопросы