如何在 C 或内联汇编中设置 ARM 中断向量表分支? [英] How to setup ARM interrupt vector table branches in C or inline assembly?

查看:27
本文介绍了如何在 C 或内联汇编中设置 ARM 中断向量表分支?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

谁能告诉我如何在没有 RTOS 或 Linux 操作系统的裸机环境中使用 C 或内联汇编设置 ARM9 中断向量表的示例?

Can someone please show me an example of how to setup an ARM9 interrupt vector table using C or inline assembly in a bare-metal environment with no RTOS or Linux OS?

具体来说,我如何使用内联汇编或 C 将分支设置为以 C 编码的 IRQ 中断处理程序 ISR?

Specifically how can I use inline assembly or C to set branches to my IRQ interrupt handler ISR coded in C?

/// timer1 64-bit mode interrupt handler connected to TINT2 interrupt=#34
/// \todo I think I need to ACK it once I get working
interrupt void interruptHandlerTimer1(void) {
    printf("\n [* ISR *] \n");
    // ACK TINT2 interrupt #34
    AINTC ->IRQ1 = 1 << (34 - 32);
}
void main(void) {

    TIMER1 ->TCR = 0x00000000;
    // TGCR: TIMMODE=0 64-bit GP, TIM34RS=TIM12RS=1
    TIM0ER1 ->TGCR = 0x00000003;
    TIMER1 ->TIM34 = 0x00000000;
    TIMER1 ->TIM12 = 0x00000000;
    TIMER1 ->PRD34 = 0x00000000;
    TIMER1 ->PRD12 = 0x0000ffff;
    // TCR: inc until period match, then reset
    TIMER1 ->TCR = (2 << 6);

    // This is wrong.
    // I think I need to insert opcode or assembly to branch to interruptHandlerTimer1 ?
    // AINTC ->EABASE located @ 0x00000000
    uint32_t** ptrEabase = (uint32_t**) (AINTC ->EABASE);
    ptrEabase[34] = (uint32_t*) (interruptHandlerTimer1);

    // Set INT34 TINT2 to IRQ priority 2
    AINTC ->INTPRI4 = 0x00000200;
    // Enable INT34
    AINTC ->EINT1 = (1 << (34 - 32));

    // Enable IRQ in CPSR
    // "TMS32DM644x ARM Subsystem", 3.3 Processor Status registers
    asm("    ;Enable IRQ in CPSR");
    asm("    mrs     r0, cpsr");
    asm("    bic     r0, r0, #0x80");
    asm("    msr     cpsr_c, r0");

    // I expected to see " [* ISR *] " print
    // when TIMER1->TIM12 reaches 0x0000ffff
    while (1) {
        printf("%08x %08x\r\n", TIMER1 ->TIM34, TIMER1 ->TIM12);
    }
}

提前感谢您提供任何提示或指导.

Thanks in advance for any tips or direction.

很难找到 ARM9 的裸机开发示例.

Bare-metal development examples for ARM9 are very hard to find.

埃德

  • TI TMS320DM6466
  • Code Composer Studio v5.5

推荐答案

注意这个回答只适用于Cortex系列ARM处理器

我看到您不久前找到了解决方案,希望这对将来遇到类似问题的任何人都有用.

I see you reached a solution for this a while back, hopefully this will be useful to anyone with a similar problem in the future.

设置中断向量的方法有很多种,它们因硬件而异,某些平台可能需要额外的步骤.下面的解决方案在 ARM Cortex 微控制器上通常是可行的,并且与编译器无关.

There are many ways to set up interrupt vectors, they vary a lot between hardware and some platforms may require extra steps. The solution below is generally viable on ARM Cortex micro controllers and is compiler agnostic.

#include <string.h>

//Size of vector table, note yours is probably 16 entries
#define VECTOR_TABLE_ENTRIES 4
//Base address in MCU memory of vector table (by default 0x0 for ARM9)
#define HARDWARE_VECTOR_TABLE_ADDRESS 0x00000000

typedef void(*isr_vector)(void);

void myIsr1();
void myIsr2();
void myIsr3();
void myIsr4();

static isr_vector s_vector_table[VECTOR_TABLE_ENTRIES] =
{
    myIsr1,
    myIsr2,
    myIsr3,
    myIsr4
};

/**
 * Load interrupt vector to correct area in system memory, call on startup
 */
void load_vector_table()
{
    memcpy(HARDWARE_VECTOR_TABLE_ADDRESS, s_vector_table, sizeof(isr_vector));
}

void myIsr1()
{

}

...

如果您只需要向表中添加一个条目,您可以使用以下内容:

If you just need to add a single entry to the table you could use the following:

void set_vector_table_entry(int index, isr_vector vector)
{
    *(HARDWARE_VECTOR_TABLE_ADDRESS + (sizeof(isr_vector) * index)) = vector;
}

在一天结束时,设置表是简单的部分,您要做的就是将函数指针表加载到特定位置,困难的部分是在正确的寄存器中设置正确的位以启用中断并妥善清理他们.

At the end of the day setting up the table is the easy part, all you are doing is loading a table of function pointers to a specific location, the hard part is setting the right bits in the right registers to enable the interrupts and clear up after them properly.

进一步注意,中断函数通常需要使用编译器特定的关键字或编译指示来声明,以确保编译器生成正确的代码.这是因为调用中断向量时的函数调用和返回处理通常与调用普通函数时不同.

Further be aware that the interrupt functions typically need to be declared with a compiler specific keyword or pragma to make sure that the compiler generates correct code. This is because function call and return handling is often different when calling an interrupt vector to when calling a normal function.

请注意,ARMv7 架构支持重新映射向量表,这非常有用,这种方法为表的对齐添加了约束,尽管这反过来需要编译器/链接器特定的指令.

Note that ARMv7 architecture supports remapping the vector table which can be very useful, this approach adds constraints to the alignment of the table though which in turn requires compiler/linker specific directives.

这篇关于如何在 C 或内联汇编中设置 ARM 中断向量表分支?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆