2014-11-27 3 views
1

저는 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; 

내 질문은 : 이 더 나은가요 실제로 이러한 모든 결정을 내리지 않고 인터럽트 시간에이 모든 다른 기능들을 부르지 않겠습니까? 인터럽트 데이터를 저장하고 인터럽트를 처리하기 위해 주 스레드를 필요로하는 경우 일부 플래그를 전환하는 것이 좋습니다. 가능한 한 빨리 콜백에서 돌아 오는 것이 얼마나 중요합니까?

그런 프로그램에 올바른 아키텍처가 무엇이라고 생각하십니까?

정확하게 응용 프로그램을 모른 채 말을하기 어렵다하지만 인터럽트 핸들러는 매우 합리적인 보이는 당신

+0

한 줄의 글자 수가 100자를 초과하지 않도록 코드를 들여 쓰기 할 수도 있습니다. –

답변

3

감사드립니다.

일반적으로 다중 작업 시스템의 경우 인터럽트가 처리되는 동안 시스템의 다른 작업이 더 이상 예약되지 않으므로 인터럽트 처리기에서 가능한 한 최소한으로 수행하는 것이 좋습니다. 이것은 특히 인터럽트 우선 순위와 인터럽트 중첩을 사용하는 경우보다 훨씬 복잡 할 수 있지만 일반적으로 인터럽트 핸들러에 너무 오래 머 무르지 않는 것이 좋습니다.

USB 드라이버의 경우 적절한 종점/인터페이스를 인터럽트 처리기에서 선택한 다음 해당 큐/배열에 수신 된 데이터를 쓰고 마지막으로 플래그/세마포를 트리거하여 일부 데이터가 수신되었음을 알립니다. 그런 다음 인터럽트 처리기에서 직접 처리하는 대신 정상적인 작업에서받은 데이터를 구문 분석하여 인터럽트 처리기를 최소한으로 유지합니다.

1

프로젝트에서 ISR을 사용하는 것이 중요하지만 원칙적으로 인터럽트 처리기가 가능한 한 빨리 반환되어야하는지 여부는 확실하지 않습니다. 내가 너라면 상황을 무조건 따르 겠어.

ISR에서 구문 분석 프로토콜을 사용하고 데이터를 구문 분석 패킷으로 링 버퍼에 공급합니다. 링 버퍼는 프로토콜에 따라 가변 길이 데이터 peek/push/pop 기능이 필요할 수 있습니다. 그런 다음 메인에서 시간 소모적 인 작업을 진행하십시오.

관련 문제