Избыточный код при жесткой обработке ошибок процессора ARM Cortex-M - PullRequest
0 голосов
/ 28 июня 2018

С FreeRTOS.org , Относительно Отладка Hard Fault & Другие исключения на микроконтроллерах ARM Cortex-M3 и ARM Cortex-M4 , по словам ребят из FreeRTOS, мы можем использовать следующий код для отладки ARM Cortex-M Hard Fault-

/* The fault handler implementation calls a function called
prvGetRegistersFromStack(). */
static void HardFault_Handler(void)
{
    __asm volatile
    (
        " tst lr, #4                                                \n"
        " ite eq                                                    \n"
        " mrseq r0, msp                                             \n"
        " mrsne r0, psp                                             \n"
        " ldr r1, [r0, #24]    <======== NOTE THIS LINE             \n"
        " ldr r2, handler2_address_const                            \n"
        " bx r2                                                     \n"
        " handler2_address_const: .word prvGetRegistersFromStack    \n"
    );
}

Теперь, насколько я понимаю, отмеченная строка не имеет никакого эффекта и не используется в функции prvGetRegistersFromStack:

void prvGetRegistersFromStack( uint32_t *pulFaultStackAddress )
{
/* These are volatile to try and prevent the compiler/linker optimising them
away as the variables never actually get used.  If the debugger won't show the
values of the variables, make them global my moving their declaration outside
of this function. */
volatile uint32_t r0;
volatile uint32_t r1;
volatile uint32_t r2;
volatile uint32_t r3;
volatile uint32_t r12;
volatile uint32_t lr; /* Link register. */
volatile uint32_t pc; /* Program counter. */
volatile uint32_t psr;/* Program status register. */

    r0 = pulFaultStackAddress[ 0 ];
    r1 = pulFaultStackAddress[ 1 ];
    r2 = pulFaultStackAddress[ 2 ];
    r3 = pulFaultStackAddress[ 3 ];

    r12 = pulFaultStackAddress[ 4 ];
    lr = pulFaultStackAddress[ 5 ];
    pc = pulFaultStackAddress[ 6 ];
    psr = pulFaultStackAddress[ 7 ];

    /* When the following line is hit, the variables contain the register values. */
    for( ;; );
}

pulFaultStackAddress передается с использованием регистра r0, mrseq r0, msp или mrsne r0, psp, и это единственный аргумент, используемый в функции. Так есть ли цель для линии ldr r1, [r0, #24]?

Ответы [ 2 ]

0 голосов
/ 09 августа 2019

Возможно, мы слишком много читаем об этом. Я думаю, что это просто клочок, чтобы переместить адрес prvGetRegistersFromStack на 4-байтовую границу (требуется моим M7 и внешней SDRAM). Они могут использовать директиву выравнивания для достижения того же.

void HardFault_Handler(void)
{
    __asm volatile
        (
            " tst lr, #4                                                \n"
            " ite eq                                                    \n"
            " mrseq r0, msp                                             \n"
            " mrsne r0, psp                                             \n"
            " ldr r2, handler2_address_const                            \n"
            " bx r2                                                     \n"
            " .align 4                                                  \n"
            " handler2_address_const: .word prvGetRegistersFromStack    \n"
        );
}

Но, эй, если это сработает, кто скажет, какой путь лучше:)

Cheers, David

0 голосов
/ 30 июня 2018

Производители ЦП, ОС и компиляторов часто вступают в сговор, чтобы создать стандартный ABI (он же абстрактный двоичный интерфейс) для конкретной платформы. Это то, что позволяет вам связывать объектные файлы, созданные разными компиляторами / языками, с вашей программой. Соглашения о вызовах определяют, как возвращаемые значения и параметры передаются между вызывающим и вызываемым кодами, а также другие детали, необходимые для обеспечения взаимодействия компонентов, написанных на разных языках или скомпилированных разными инструментами.

То, что вы видите в ассемблерном коде, - это деталь ABI, которую следует задокументировать консорциумом ARM . Чтобы успешно вызывать код на C от ассемблера, вы должны понимать ABI. Обратите внимание, что разработчики компиляторов могут свободно реализовывать свои соглашения о вызовах так, как они хотят, поэтому ваш пробег может отличаться. Вот почему я предложил вам проверить документацию вашего компилятора Си. Большинство компиляторов C предоставляют настраиваемые схемы вызовов, иногда ABI по умолчанию используется по умолчанию, а иногда нет.

Учитывая, что вашей целью является ОСРВ, возможно, у них есть собственный ABI, и в этом случае они, вероятно, изменили цепочку инструментов компилятора OSS, но, скорее всего, они следуют ABI Cortex ABI. В тех случаях, когда на целевой плате нет доступных ОС, все ставки сняты, и вам следует обратиться к производителю платы за соответствующей документацией (если есть).

...