Отключить прерывания таймера в источнике ядра для переключения режимов в ARM

У меня есть небольшая функция, которую я добавил в исходный код ядра (linux 3.0), которая выполняет некоторые задачи и прекрасно работает в режиме SVC. Но в режиме прерывания (то есть, когда прерывания по таймеру включены в ядре через local_irq_enable) это не работает. Поэтому я думаю о переходе в режим SVC перед выполнением своей функции. Я взял код для переключения режимов из одного из постов.

void myfunction(..some args)
{ 
    unsigned int oldmode = get_cpsr() & 0x1f;

    if (oldmode == 18) // Check for IRQ mode
        change_mode(MODE_SVC);
    // ...My code ....
    restore_mode(oldmode);
}

Определения следующие:

#define MODE_IRQ        0x12
#define MODE_SVC        0x13

#define change_mode(mode) asm("cps %0" : : "I"(mode))

#define restore_mode(mode) \
    mode &= 0x1f; \
    asm(" msr cpsr, %0\n" : : "r"(mode) : "cc")

static inline unsigned int get_cpsr(void)
{
    unsigned int val;

    __asm__ __volatile__ (" mrs %0, cpsr\n"
                          : "=r" (val));
    return val;
}

Даже после этого я не получаю правильный вывод. Выполнение функции где-то застревает. Я отладил адрес, где он застрял, и он указывает на эти символы System.map

__exception_text_start _stext asm_do_IRQ

Правильно ли мое использование функции. Можете ли вы предложить мне другое решение этой проблемы. Я запускаю этот образ на плате ARMv7. И, наконец, есть вызовы некоторых API-интерфейсов ядра, таких как printch() в моей функции после смены режима.

0 ответов

Другие вопросы по тегам