STM32 USB VCP错误


8

我过去两个星期一直在研究一个项目,整整一个星期都在调试这个问题。我想知道是否有人可以提供帮助,所以我会尽量保持清晰明确。

我正在尝试在基于STM32F302K8(Cortex M4)的微控制器上实现USB虚拟通信端口。我已经使用STM32CubMX生成了设置实现CDC类的USB全速设备所需的代码。我的设备同时显示在Windows(设备管理器)和Linux中。我能够基于示例代码实现一个简单的回显功能,但是当我现在尝试使用功能USBD_CDC_SetTxBuffer将数据发送到PC时,这将启动一个硬故障处理程序。我将范围缩小到以下事实:从未初始化UsbDeviceFS.pClass(USBD_CDC_SetTxBuffer所需)字段,因为从未在USB设备的初始化中调用USBD_CDC_Init()。

我已经在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 2015年

嗨,我已经将堆大小增加到0x600,什么也没发生。哪个函数调用malloc,因为当我在其上放置一个断点时,似乎从未调用过它。
星系

Answers:


6

为了回答我自己的问题,问题在于我的代码没有等待USB完成初始化并立即开始发送数据。在布尔值上插入活动等待或添加延迟(如@ramez所指出的)可以解决此问题。

更新此错误已从ST的后续USB CDC驱动程序版本中修复。现在在设置中有一个HAL_Delay。请注意,如果由于任何原因Sys_Tick无法正常工作/已被停用/尚未初始化,则您的代码将挂起。


1
是的,您应该将此作为单独的问题发布。仅在此答案中保留与原始问题相关的信息。
m.Alin 2015年

2

我使用CubeMX为STM32F4发现生成代码。我和您一样将其用作虚拟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
谢谢拉梅兹。我发现了问题,我必须测试虚拟comm端口是否已完成初始化,我在CDC_Init_FS中使用了布尔值,在调用CDC_Transmit_FS之前,主循环等待其为真。我认为代码中的HAL_DELAY可以达到相同的效果。感谢您的帮助。
星系

1

首先,检查hUsbDevice_0是否为空(解决方案中缺少元素):

    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
您也可以在软件中强制进行重新枚举。重新插入后第二种最愚蠢的方法是在设备管理器中禁用/启用端口,如果您没有定制的驱动程序以更
出色的
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.