Я работаю над проектом, который требует USB-связи. Я использую Nuvoton NUC123, который запускает ядро M0 с сердечником ARM со скоростью 48 МГц, 20 КБ оперативной памяти и флэш-памятью 64 КБ. Микроконтроллер реализует аппаратное прерывание всякий раз, когда конечная точка USB получает данные, переданные ему от хоста, будь то Ack, Nak или установочный пакет. Образец кода, предоставленный производителем, довольно грязный, он включает в себя коммутатор с конечной точкой, к которой относится прерывание, и если это пакет установки, содержащий запрос на конкретный класс, он создает случай переключения для каждого интерфейса или конечной точкой, которая может быть объектом запроса.Каков правильный способ обработки прерываний?
Я полагал, что я могу сделать вещи красивее, определив массив структуры:
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;) –