STM32 USB VCP 버그


8

나는 지난 2 주 동안 프로젝트를 진행해 왔으며 이번 주 디버깅이 이번 주 전체를 차지했습니다. 누구든지 도울 수 있는지 궁금하면 가능한 한 명확하고 명료하게 노력할 것입니다.

STM32F302K8 (Cortex M4) 기반의 MicroController에서 USB 가상 통신 포트를 구현하려고합니다. CDC 클래스를 구현하는 USB Full Speed ​​Device를 설정하는 데 필요한 코드를 생성하기 위해 STM32CubMX를 사용했습니다. 내 장치는 Windows (장치 관리자)와 Linux 모두에 나타납니다. 예제 코드를 기반으로 간단한 에코 함수를 구현할 수 있지만 이제 USBD_CDC_SetTxBuffer 함수를 사용하여 데이터를 PC로 보내려고하면 하드 오류 처리기가 시작됩니다. USB 장치를 초기화 할 때 USBD_CDC_Init ()가 호출되지 않기 때문에 UsbDeviceFS.pClass ( USBD_CDC_SetTxBuffer에 필요) 필드가 초기화되지 않는다는 사실로이 범위를 좁혔습니다 .

ST 포럼에 문서화되었지만 여전히 동일한 오류가 발생하는 예제 코드에서 힙 크기 변경, USBD_CDC_TransmitPacket 에서 전송 플래그 수정 및 CDC_DATA_HS_MAX_PACKET_SIZE 의 크기를 512에서 256으로 변경하는 것을 포함하여 몇 가지 버그에 대한 수정 사항을 구현 했습니다.

내 장치 설정 코드는

* USB Device Core handle declaration */
USBD_HandleTypeDef hUsbDeviceFS;

/* init function */                    
void MX_USB_DEVICE_Init(void)
{
  /* Init Device Library,Add Supported Class and Start the library*/
  USBD_Init(&hUsbDeviceFS, &FS_Desc, DEVICE_FS);

  USBD_RegisterClass(&hUsbDeviceFS, &USBD_CDC);

  USBD_CDC_RegisterInterface(&hUsbDeviceFS, &USBD_Interface_fops_FS);

  USBD_Start(&hUsbDeviceFS);

}

STM에서 USB로 마지막으로 작업 한 지 오래되었지만 USBD_CDC_Init ()가 malloc을 시도한다고 생각합니다. 문제는 기본 설정에서 힙에 충분한 공간이 없기 때문에 증가시켜야한다는 것입니다.
brhans

안녕하세요, 힙 크기를 0x600으로 늘 렸는데 아무 일도 일어나지 않았습니다. 중단 점을 넣을 때 호출되지 않는 것처럼 보이기 때문에 malloc을 호출하는 함수는 무엇입니까?
Galaxy

답변:


6

내 자신의 질문에 대답하기 위해 문제는 내 코드가 USB가 초기화를 완료하기를 기다리지 않고 즉시 데이터를 보내기 시작했다는 것입니다. 부울에 활성 대기를 삽입하거나 지연을 추가하면 (@ramez에서 지적한대로) 문제가 해결됩니다.

업데이트이 버그는 ST의 후속 USB CDC 드라이버 버전에서 수정되었습니다. 설정에 HAL_Delay가 있습니다. 어떤 이유로 Sys_Tick이 작동하지 않거나 비활성화 / 아직 초기화되지 않은 경우 코드가 중단됩니다.


1
예,이 질문을 별도의 질문으로 게시해야합니다. 이 답변에는 원래 질문과 관련된 정보 만 보관하십시오.
m.Alin

2

STM32F4 감지를위한 코드 생성에 CubeMX를 사용했습니다. 나는 당신처럼 가상 COM 포트로 사용했습니다. USBD_CDC_SetTxBuffer () 함수를 직접 사용하지 않았습니다 . 에서 usbd_cdc_if.c 파일이라는 함수가 CDC_Transmit_FS은 () . 생성 된 코드에 버그가있었습니다. 함수는 버퍼를 매개 변수로 사용하여 아무 것도 수행하지 않았습니다. 수정 된 기능 코드는 다음과 같습니다.

uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
{
  uint8_t result = USBD_OK;
  memcpy(UserTxBufferFS, Buf, sizeof(char) * Len);
  USBD_CDC_SetTxBuffer(hUsbDevice_0, UserTxBufferFS, Len);   
  result = USBD_CDC_TransmitPacket(hUsbDevice_0);
  return result;
}

실제로 코드에 memcpy를 추가해야했습니다. 이 수정 후이 전송 기능을 사용하여 마이크로 트롤러에서 PC로 데이터를 전송할 수 있습니다. 예를 들면 다음과 같습니다.

int main(void)
{
  HAL_Init();

  SystemClock_Config();

  MX_GPIO_Init();
  MX_USB_DEVICE_Init();
  configureGPIOs();

  uint8_t Buf[] = "Test";

  HAL_Delay(1000);

  while (1)
  {
      CDC_Transmit_FS(Buf, 4);
      HAL_Delay(1000);
  }
}

MX_USB_DEVICE_Init () 의 초기화는 귀하 와 동일합니다.


1
라 메즈 감사합니다. 문제를 발견하고 가상 통신 포트가 초기화를 완료했는지 테스트해야했으며 CDC_Inmit_FS의 부울을 사용하여 CDC_Transmit_FS를 호출하기 전에 주 루프가 참이기를 기다렸습니다. 코드의 HAL_DELAY가 동일한 효과를 얻는다고 생각합니다. 도움을 주셔서 감사합니다.
Galaxy

1

먼저 hUsbDevice_0이 null인지 확인하십시오 (솔루션에서 누락 된 요소).

    if (hUsbDevice_0 == NULL)
            return USBD_FAIL;

이렇게하면 uC가 중단되는 것을 방지 할 수 있으며 지연 대기 시간이 필요하지 않습니다.

CDC_Transmit_FS의 어딘가에 배치 할 수 있습니다.

USBD_StatusTypeDef CDC_Transmit_FS(uint8_t* Buf, uint16_t Len) {

    if (hUsbDevice_0 == NULL)
        return USBD_FAIL;

    USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*) hUsbDevice_0->pClassData;

    if (hcdc->TxState != 0)
        return USBD_BUSY;

    uint8_t result = USBD_OK;

    USBD_CDC_SetTxBuffer(hUsbDevice_0, Buf, Len);
    result = USBD_CDC_TransmitPacket(hUsbDevice_0);

    return result;
}

0

나는 같은 문제가 있었지만 내가해야 할 유일한 일은 USB 연결을 컴퓨터에 다시 연결하는 것입니다. 대부분 코드를 플래시하고 마이크로 컨트롤러를 재설정하지만 PC 측에서는 열거가 업데이트되지 않습니다. USBD_CDC_Init 는 호스트가 장치를 검사하기 시작할 때 호출되므로 pClassData가 NULL입니다.


1
소프트웨어에서 강제로 다시 열거 할 수도 있습니다. 다시 연결 한 후 두 번째로 가장 좋은 방법은 장치 관리자에서 포트를 비활성화 / 활성화하는 것입니다. 사용자 지정 드라이버가 더 멋진 방법으로 처리되지 않는 경우
stiebrs
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.