c - LPC12xx I2C vector 到服务例程

标签 c embedded

我在用 C 实现“服务例程的 vector ”时遇到了一些问题。

现在我像这样实现 I2C 接口(interface)的 IRQ 处理程序:

    void I2C0_IRQHandler(void)
    {
        statusCode = LPC_I2C->STAT;
        switch ( statusCode ) { (...) }
    }

对于许多状态代码,这很慢,因为必须访问所有情况。

LPC12xx微 Controller 的用户手册给出了提示:

If the status code is used as a vector to service routines, then the routines are displaced by eight address locations. Eight bytes of code is sufficient for most of the service routines

所以我应该编写一些代码大小恰好为 8 字节的处理函数,并将它们放在正确的内存位置:

0xABCDEF00: handler_for_code_0x00
0xABCDEF08: handler_for_code_0x08
(...)
0xABCDEF90: handler_for_code_0x90

在中断处理程序中

  1. 将状态代码添加到内存偏移量(此处为 0xABCDEF00)
  2. 将这个地址转换为一个函数指针
  3. 并调用函数。

我有这个权利吗?我如何在 C 中实现它?

最佳答案

您如何确定 switch 会因其他情况而变慢?

大多数编译器会生成一个确定性的跳转表,当然不会“访问”每个案例。您可以通过确保案例在数字上是连续的而不是稀疏地分开(即值之间没有间隙)来帮助编译器生成高效的代码。

只有 32 种可能的状态代码,因此一个包含所有代码的 case 的详尽 switch(即使 case 是空的)可能并不令人望而却步。 STAT 的前三位未使用,因此如果您首先将状态右移三位以便状态值从零开始,这也可以使编译器生成更高效的代码。事实上,我希望它生成一个与@Dill 的建议(这将是我的建议)等同的跳转表。

下面是一个被大多数编译器简单优化的惯用示例,只需将代码添加到您明确想要处理的那些情况。如果您的编译器不会由此生成确定性代码,请尝试使用编译器优化级别进行试验。但是,如果它不能做到这一点,我会考虑使用不同的编译器!

void I2C0_IRQHandler(void)
{
    switch( LPC_I2C->STAT >> 3 ) 
    { 
        case 0x01 :
            break ;
        case 0x02 :
            break ;
        case 0x03 :
            break ;
        case 0x04 :
            break ;
        case 0x05 :
            break ;
        case 0x06 :
            break ;
        case 0x07 :
            break ;
        case 0x08 :
            break ;
        case 0x09 :
            break ;
        case 0x0a :
            break ;
        case 0x0b :
            break ;
        case 0x0c :
            break ;
        case 0x0d :
            break ;
        case 0x0e :
            break ;
        case 0x0f :
            break ;
        case 0x10:
            break ;
        case 0x11 :
            break ;
        case 0x12 :
            break ;
        case 0x13 :
            break ;
        case 0x14 :
            break ;
        case 0x15 :
            break ;
        case 0x16 :
            break ;
        case 0x17 :
            break ;
        case 0x18 :
            break ;
        case 0x19 :
            break ;
        case 0x1a :
            break ;
        case 0x1b :
            break ;
        case 0x1c :
            break ;
        case 0x1d :
            break ;
        case 0x1e :
            break ;
        case 0x1f :
            break ;
    }
}

关于c - LPC12xx I2C vector 到服务例程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12218748/

相关文章:

c - 什么时候初始化指针?

c - 嵌入式 C 语言中的宏如何影响内存?

embedded - 我可以将哪些 Cortex-M3 中断用于通用工作?

assembly - 为什么使用 staa 的 M68HC12 上的内存区域 $1020 不可写入?

c - 结构体中的指针问题

c - 如何使用 SSE 汇编指令查找毕达哥拉斯三元组?

c - 如何在 C 中创建(和使用)指向字符串数组的指针数组?

c - 如何在 GCC 11.1 中禁用警告 -mgeral-regs-only' -ARM 架构中断上下文中的属性?

c - 理想的跨平台库

c - 奇异值分解的时间复杂度