บั๊ก STM32 USB VCP


8

ฉันทำงานเกี่ยวกับโปรเจคในช่วงสองสัปดาห์ที่ผ่านมาและการดีบั๊กปัญหานี้ได้เกิดขึ้นตลอดทั้งสัปดาห์ สงสัยว่าถ้าใครสามารถช่วยฉันจะพยายามที่จะชัดเจนและชัดเจนที่สุด

ฉันกำลังพยายามใช้ USB Virtual Comm Port บน MicroController ตาม STM32F302K8 (Cortex M4) ฉันใช้ STM32CubMX เพื่อสร้างรหัสที่จำเป็นในการตั้งค่าอุปกรณ์ USB Full Speed ​​ที่ใช้คลาส CDC อุปกรณ์ของฉันปรากฏขึ้นทั้งใน Windows (Device Manager) และ Linux ฉันสามารถใช้ฟังก์ชั่น echo อย่างง่ายโดยใช้โค้ดตัวอย่าง แต่เมื่อฉันลองใช้ฟังก์ชั่นUSBD_CDC_SetTxBufferเพื่อส่งข้อมูลไปยังพีซีนี่เป็นการตั้งค่าตัวจัดการฮาร์ดฟอลต์ ฉันได้ จำกัด สิ่งนี้ลงไปตามความจริงที่ว่าฟิลด์ UsbDeviceFS.pClass (ซึ่งเป็นที่ต้องการโดย USBD_CDC_SetTxBuffer) จะไม่ถูกกำหนดค่าเริ่มต้นเนื่องจากUSBD_CDC_Init () ไม่เคยถูกเรียกใช้ในการเริ่มต้นอุปกรณ์ USB

ฉันใช้การแก้ไขข้อบกพร่องหลายประการ (รวมถึงการเปลี่ยนขนาดฮีปการแก้ไขการตั้งค่าสถานะการส่งในUSBD_CDC_TransmitPacketและการเปลี่ยนขนาดของ CDC_DATA_HS_MAX_PACKET_SIZE เป็น 256 จาก 512) ในตัวอย่างโค้ดที่บันทึกไว้ในฟอรัม ST แต่ยังคงได้รับความผิดพลาดเหมือนเดิม

รหัสการตั้งค่าอุปกรณ์ของฉันคือ

* 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);

}

เป็นเวลานานแล้วที่ฉันได้ทำงานกับ USB ใน STM ครั้งล่าสุด แต่ฉันคิดว่า USBD_CDC_Init () พยายามทำ malloc ปัญหาคือมีฮีปในพื้นที่การตั้งค่าเริ่มต้นไม่เพียงพอและคุณต้องเพิ่มมัน
brhans

สวัสดีฉันได้เพิ่มขนาดฮีพเป็น 0x600 และไม่มีอะไรเกิดขึ้น ฟังก์ชั่นไหนเรียก malloc เพราะเมื่อฉันวางเบรกพอยต์ลงไปมันจะปรากฏขึ้นว่ามันไม่เคยถูกเรียก
Galaxy

คำตอบ:


6

เพื่อตอบคำถามของฉันเองปัญหาคือรหัสของฉันไม่ได้รอให้ USB ทำการเริ่มต้นและเริ่มส่งข้อมูลทันที การแทรกการรอที่ใช้งานบนบูลีนหรือเพิ่มการหน่วงเวลา (ตามที่ระบุโดย @ramez) จะช่วยแก้ปัญหาได้

อัพเดทข้อผิดพลาดนี้ได้รับการแก้ไขในไดรเวอร์ CDC USB รุ่นต่อมาจาก ST ขณะนี้มี HAL_Delay ในการตั้งค่า ข้อแม้คือว่าถ้าด้วยเหตุผลใดก็ตาม Sys_Tick ไม่ทำงาน / ถูกปิดใช้งาน / ยังไม่เริ่มต้นรหัสของคุณจะหยุดทำงาน


1
ใช่คุณควรโพสต์คำถามนี้เป็นคำถามแยกต่างหาก เก็บไว้ในคำตอบนี้เฉพาะข้อมูลที่เกี่ยวข้องกับคำถามเดิม
m.Alin

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 ลงในรหัส หลังจากการแก้ไขนี้ฉันสามารถส่งข้อมูลจากไมโครคอนโทรลเลอร์ไปยังพีซีด้วยฟังก์ชั่นการส่งสัญญาณนี้ ตัวอย่างเช่น:

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
ขอบคุณ ramez ฉันพบปัญหาฉันต้องทดสอบว่าพอร์ต comm เสมือนได้เริ่มต้นเสร็จฉันใช้บูลีนใน CDC_Init_FS ซึ่งลูปหลักรอให้เป็นจริงก่อนที่จะเรียก CDC_Transmit_FS ฉันคิดว่า HAL_DELAY ในรหัสของคุณจะมีผลเหมือนกัน ขอขอบคุณสำหรับความช่วยเหลือ.
Galaxy

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 เข้ากับคอมพิวเตอร์อีกครั้ง เวลาส่วนใหญ่ที่คุณแฟลชรหัสและรีเซ็ตไมโครคอนโทรลเลอร์ แต่ด้านพีซีการแจงนับไม่ได้รับการปรับปรุง USBD_CDC_Initถูกเรียกเมื่อโฮสต์เริ่มสอบสวนอุปกรณ์ของคุณและนั่นคือเหตุผลที่ pClassData เป็น NULL


1
คุณสามารถบังคับให้มีการแจงนับซ้ำในซอฟต์แวร์ได้เช่นกัน วิธีที่โง่ที่สุดที่สองหลังจากการเสียบซ้ำกำลังปิดใช้งาน / เปิดใช้งานพอร์ตของคุณในตัวจัดการอุปกรณ์หากคุณไม่มีไดรเวอร์ที่กำหนดเองที่จัดการสิ่งนี้ในลักษณะที่เป็นแฟนซีมากขึ้น
stiebrs
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.