【问题标题】:What is the proper way to process interrupts?处理中断的正确方法是什么?
【发布时间】:2014-11-27 21:14:43
【问题描述】:

我正在做一个需要 USB 通信的项目。 我使用的是运行 ARM cortex M0 内核的 Nuvoton NUC123,速度为 48MHz、20kb RAM 和 64kb 闪存。 每当 USB 端点从主机接收到数据传输给它时,微控制器就会实现硬件中断,无论是 Ack、Nak 还是设置数据包。 制造商提供的示例代码相当脏,它涉及对中断所属的端点进行 switch-case,如果它是包含特定于类的请求的设置数据包,它会为每个接口或端点创建一个 switch-case这可能是请求的目标。

我想我可以通过定义一个结构数组来让事情变得更漂亮:

typedef void UsbEventCallback(uint32_t u32IntFlag, uint32_t u32EPSTS);
typedef uint32_t UsbClassReqCallback(void);

typedef struct
{
    uint8_t ep_address;
    uint32_t config;
    uint32_t buff_offset;
    UsbClassReqCallback *usb_classreq_cb;
    UsbEventCallback *usb_event_cb;
} ATTR_PACKED EP_Config_Struct;

typedef struct
{
    uint8_t interface_id;
    UsbClassReqCallback *usb_classreq_cb;
} ATTR_PACKED Interface_Config_Struct;

extern const EP_Config_Struct EP_config_settings[TOTAL_NUM_ENDPOINTS];
extern const Interface_Config_Struct interfaces_config_settings[TOTAL_NUM_INTERFACES];

然后,在我做的中断回调中:

switch(  req_destination )
{
case 1: //interface
    for ( uint8_t interface_index = 0 ; interface_index < TOTAL_NUM_INTERFACES ; interface_index++ )
    {
        if ( interfaces_config_settings[interface_index].interface_id == UsbDev.Setup.wIndex )
        {
            if ( interfaces_config_settings[interface_index].usb_classreq_cb == NULL )
                return FALSE;
            else
                return (*interfaces_config_settings[interface_index].usb_classreq_cb)();
        }
    }
    break;
case 2: //endpoint
    for ( uint8_t ep_index = 0 ; ep_index < TOTAL_NUM_ENDPOINTS ; ep_index++ )
    {
        if ( EP_config_settings[ep_index].ep_address == UsbDev.Setup.wIndex )
        {
            if ( EP_config_settings[ep_index].usb_classreq_cb == NULL )
                return FALSE;
            else
                return (*EP_config_settings[ep_index].usb_classreq_cb)();
        }
    }
    break;
}
return FALSE;

我的问题是: 不实际做出所有这些决定并在中断时间调用所有这些其他函数会更好吗?我最好只保存中断数据并打开一些标志,要求主线程处理中断吗? 尽快从回调中返回有多重要?

您认为这样一个程序的正确架构是什么?

谢谢

【问题讨论】:

  • 您可以考虑缩进您的代码,使一行不超过 100 个字符,甚至更好的是 80 个字符;)

标签: c embedded usb interrupt


【解决方案1】:

如果不准确了解您的应用程序,很难说,但您的中断处理程序看起来很合理。

通常对于多任务系统,建议尽可能少地使用中断处理程序,因为在处理中断时,系统上的不同任务不再被调度。这可能比这复杂得多,尤其是在使用中断优先级和中断嵌套时,但总体思路仍然是避免在中断处理程序中停留太久。

对于您的 USB 驱动程序,我会在中断处理程序中选择适当的端点/接口,然后将接收到的数据写入适当的队列/数组中,最后触发一个标志/信号量来表示已接收到一些数据。然后,我将解析在正常任务中接收到的数据,而不是直接在中断处理程序中,以保持中断处理程序最小化。

【讨论】:

    【解决方案2】:

    不确定在项目中保持繁忙的 ISR 是否重要,但原则上中断处理程序应尽快返回。如果我是你,无论情况如何,我都会跟随。

    在 ISR 中解析协议,然后将数据作为解析后的数据包提供给环形缓冲区。环形缓冲区可能需要根据协议进行可变长度数据 peek/push/pop 的能力。然后在 main 中进行耗时的工作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-02-11
      • 2014-09-23
      • 2010-10-08
      • 2013-07-24
      • 2011-12-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多