저는 USB 통신이 필요한 프로젝트 작업 중입니다. 48mhz, 20kb RAM 및 64kb 플래시 메모리의 속도로 ARM 피질 M0 코어를 실행하는 Nuvoton NUC123을 사용하고 있습니다. 마이크로 컨트롤러는 USB 엔드 포인트가 Ack, Nak 또는 설정 패킷이든간에 호스트에서 데이터를 전송할 때마다 하드웨어 인터럽트를 구현합니다. 제조업체가 제공 한 샘플 코드는 다소 더럽습니다. 인터럽트가 속한 끝점을 switch-case-ing하고 클래스 별 요청을 포함하는 설치 패킷 인 경우 모든 인터페이스 또는 인터페이스에 대해 스위치 케이스를 만듭니다. 엔드 포인트는 요청의 대상이 될 수 있습니다.인터럽트를 처리하는 적절한 방법은 무엇입니까?
이 나는 구조의 배열 정의하여 예쁜 일을 할 수 있습니다 생각 :
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자를 초과하지 않도록 코드를 들여 쓰기 할 수도 있습니다. –