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

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

问题描述

有人可以给我一个例子,说明如何在没有RTOS或Linux操作系统的裸机环境中使用C或内联装配来设置ARM9中断向量表?



具体如何使用内联汇编或C设置分支到我的IRQ中断处理程序ISR编码在C?

  // / timer1 64位模式中断处理程序连接到TINT2中断=#34 
/// \todo我想我需要确认一旦我工作
中断void interruptHandlerTimer1(void){
printf(\\\
[* ISR *] \\\
);
// ACK TINT2 interrupt#34
AINTC - > IRQ1 = 1< (34-32);
}
void main(void){

TIMER1 - > TCR = 0x00000000;
// TGCR:TIMMODE = 0 64位GP,TIM34RS = TIM12RS = 1
TIM0ER1 - > TGCR = 0x00000003;
TIMER1 - > TIM34 = 0x00000000;
TIMER1 - > TIM12 = 0x00000000;
TIMER1 - > PRD34 = 0x00000000;
TIMER1 - > PRD12 = 0x0000ffff;
// TCR:inc直到期间匹配,然后重置
TIMER1 - > TCR =(2 <6);

//这是错误的。
//我想我需要插入操作码或汇编到分支到interruptHandlerTimer1?
// AINTC - > EABASE位于@ 0x00000000
uint32_t ** ptrEabase =(uint32_t **)(AINTC - > EABASE);
ptrEabase [34] =(uint32_t *)(interruptHandlerTimer1);

//将INT34 TINT2设置为IRQ优先级2
AINTC - > INTPRI4 = 0x00000200;
//启用INT34
AINTC - > EINT1 =(1<(34 - 32));

//在CPSR中启用IRQ
//TMS32DM644x ARM Subsystem,3.3处理器状态寄存器
asm(;在CPSR中启用IRQ);
asm(mrs r0,cpsr);
asm(bic r0,r0,#0x80);
asm(msr cpsr_c,r0);

//我希望看到[* ISR *]打印
//当TIMER1-> TIM12达到0x0000ffff
时(1){
printf (%08x%08x\r\\\
,TIMER1→TIM34,TIMER1→TIM12);
}
}



提前感谢任何提示或方向。



ARM9的裸金属开发示例很难找到。



Ed




  • TI TMS320DM6466

  • Code Composer Studio v5.5


解决方案

请注意,此答案仅适用于到Cortex系列ARM处理器



我看到你已经解决了这个问题,希望这对将来有类似问题的任何人都有用



有很多方法来设置中断向量,它们在硬件和某些平台之间变化很大,可能需要额外的步骤。以下解决方案通常在ARM Cortex微控制器上可行,并且与编译器无关。

  #include< string.h> 

//向量表的大小,注意你的大概16个条目
#define VECTOR_TABLE_ENTRIES 4
//向量表的MCU存储器中的基址(ARM9的默认值为0x0)
#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
};

/ **
*加载中断向量以纠正系统内存中的区域,调用启动
* /
void load_vector_table()
{
memcpy(HARDWARE_VECTOR_TABLE_ADDRESS,s_vector_table,sizeof(isr_vector));
}

void myIsr1()
{

}

...

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

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

在一天结束的时候,设置表是容易的部分,所有您正在做的是将功能指针表加载到特定位置,硬件正确设置正确的寄存器中的正确位以启用中断并将其清除。还要注意,中断函数通常需要使用编译器特定的关键字或pragma来声明,以确保编译器生成正确的代码。这是因为在调用正常函数时调用中断向量时函数调用和返回处理通常是不同的。



请注意,ARMv7架构支持重新映射可以非常有用,这种方法增加了表的对齐的约束,而这反过来需要编译器/链接器特定的指令。


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?

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.

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

Ed

  • TI TMS320DM6466
  • Code Composer Studio v5.5

解决方案

Note that this answer is only applicable to Cortex series ARM processors

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.

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.

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天全站免登陆