IAR ассемблер BKPT немедленно в качестве входного операнда - PullRequest
0 голосов
/ 28 мая 2019

Я пишу флэш-загрузчик для устройства Cortex M4, и я хотел бы «вернуть» значение для приложения для ПК, используя непосредственное значение инструкции точки останова.

Хотя непосредственное жесткое кодирование работает нормально:

__asm("bkpt 0x70");
__asm("bkpt %0" : : "i" (0x70));

, как только я хочу "вернуть" что-то зависящее от времени выполнения, например

uint8_t status = Flash_EraseAll();
__asm("bkpt %0" : : "i" (status));

Компиляция завершается с

Ошибка [Ta090]:Непосредственный операнд не является постоянным

Я пытался использовать макросы препроцессора с различными настройками конкатенации, но безрезультатно.

Кто-нибудь получил представление о том, как я мог бы немедленно ввести флаги, зависящие от времени выполнения, в блок __asm() в IAR?Исходя из того, что я прочитал здесь , это не совсем возможно, но может быть хитрый способ сделать это.

PS: Да, в качестве обходного пути я мог бы использовать оператор switchгде я перечисляю и жестко кодирую каждое возможное состояние, но это просто уродливо и долго.

Ответы [ 2 ]

1 голос
/ 28 мая 2019

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

Примерно так (псевдокод):

__asm("push %0" : : "i" (status));
__asm("bkpt %0" : : "i" (0x70));

Конечно, вы не должны забывать впоследствии очищать стек.

Поскольку bkpt кодируется только с немедленным обращением, вы, очевидно, не можете изменить это во время выполнения, так как выпридется изменить код.

0 голосов
/ 12 июня 2019

Основываясь на идее @ Devolus , я получил следующее:

    uint32_t status = Flash_EraseAll();
    __asm volatile ("str %0, [sp, #-4]!\n\t"   // Push to stack
                    "bkpt 0x0\n\t"             // Halt CPU
                    "add sp, sp, #4\n\t"       // Restore SP
                    : : "r"(status));          // status as input to __asm()

Инструкция по сборке говорит компилятору поместить переменную состояния в удобный регистр «r» и сохранить содержимое этого регистра под предварительно уменьшенным адресом указателя стека, а затем остановить выполнение ЦП с немедленным 0.

Приложение вождения будет опрашивать цель, если она будет остановлена ​​(bkpt hit). В случае остановки, считывая 16-битные данные на текущем ПК (__asm ​​("bkpt 0x00") -> 0xbe00 -> #imm = 0xbe00 & 0x00ff = 0), приложение может убедиться, что выполнение остановлено справа место. Затем он считывает 32-разрядные данные по последнему адресу SP, чтобы получить информацию о состоянии выполнения встроенного кода.

Таким образом, вместо статического 8-битного кода из непосредственного bkpt, можно динамически «сообщать» больше материала во внешний мир (32-битный в данном случае).

Как подчеркивает @ PeterCordes , операторы push и bkpt должны находиться в одной и той же встроенной инструкции по сборке, в противном случае компилятор может решить вставить код между операторами. Кроме того, SP должен быть восстановлен до значения перед __asm ​​(), так как компилятор принимает единоличное управление над SP.

...