处理中断的正确方法是什么?

时间:2014-11-27 21:14:43

标签: c embedded usb interrupt

我正在开发一个需要USB通信的项目。 我使用的是运行ARM cortex M0内核的Nuvoton NUC123,速度为48MHz,内存为20kb,闪存为64kb。 只要USB端点从主机传输数据,微控制器就会实现硬件中断,无论它是Ack,Nak还是设置数据包。 制造商提供的示例代码相当脏,它涉及切换案例中断所属的端点,如果它是包含特定于类的请求的设置数据包,则为每个接口或端点创建一个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;

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

您认为此类计划的正确架构是什么?

谢谢

2 个答案:

答案 0 :(得分:3)

很难说不知道你的应用程序,但你的中断处理程序看起来很合理。

通常对于多任务系统,建议在中断处理程序中尽可能少,因为在处理中断时,系统上的不同任务不再被调度。这可能比这复杂得多,特别是在使用中断优先级和中断嵌套时,但一般的想法是避免在中断处理程序中保持太长时间。

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

答案 1 :(得分:1)

不确定在项目中保持繁忙的ISR是否至关重要,但原则上中断处理程序应尽快返回。如果我是你,我会按照这种情况进行跟踪。

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