STM32 USB VCP hatası


8

Son iki haftadır bir proje üzerinde çalışıyorum ve bu sorunun ayıklanması tüm hafta sürdü. Birinin yardım edip edemeyeceğini merak ederek, olabildiğince açık ve net olmaya çalışacağım.

STM32F302K8 (Cortex M4) tabanlı bir MicroController üzerinde bir USB Sanal İletişim Portu uygulamaya çalışıyorum. Bir CDC sınıfı uygulayan bir USB Tam Hızlı Aygıt kurmak için gereken kodu oluşturmak için STM32CubMX kullandım. Cihazım hem Windows'da (Cihaz Yöneticisi) hem de Linux'ta görünüyor. Örnek koda dayalı basit bir yankı işlevi uygulayabiliyorum ama şimdi PC'ye veri göndermek için USBD_CDC_SetTxBuffer işlevini kullanmaya çalıştığımda , bu bir Sabit Hata İşleyici başlatır . UsbDeviceFS.pClass (USBD_CDC_SetTxBuffer tarafından ihtiyaç duyulan) alanının asla USB aygıtının başlatılmasında USBD_CDC_Init () hiçbir zaman çağrılmadığı için daraltıldım .

ST forumunda belgelendiği gibi örnek kodda birkaç hatayı (yığın boyutunu değiştirmek, iletim bayrağını USBD_CDC_TransmitPacket'te düzeltmek ve CDC_DATA_HS_MAX_PACKET_SIZE'yi 512'den 256'ya değiştirmek) düzeltmeler uyguladım , ancak yine de aynı hata alıyorum.

Cihaz kurulum kodum

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

}

En son bir STM üzerinde USB ile çalıştığımdan bu yana bir süre geçti, ancak USBD_CDC_Init () bir malloc yapmaya çalıştığını düşünüyorum. Sorun, varsayılan kurulumda yığın üzerinde yeterli alan olmaması ve artırmanız gerektiğiydi.
brhans

Merhaba, yığın boyutunu 0x600'e çıkardım ve hiçbir şey olmuyor. Hangi işlevi malloc olarak adlandırır çünkü üzerine bir kesme noktası koyduğumda, asla çağrılmaz.
Galaxy

Yanıtlar:


6

Kendi sorumu cevaplamak için sorun, kodumun USB'nin başlatmayı bitirmesini beklememesi ve hemen veri göndermeye başlamasıydı. Bir boole üzerinde etkin bir bekleme eklemek veya bir gecikme eklemek (@ramez tarafından belirtildiği gibi) sorunu çözer.

GÜNCELLEME Bu hata, ST'nin sonraki USB CDC sürücüsü sürümlerinde giderilmiştir. Şimdi kurulumda bir HAL_Delay var. Uyarı, Sys_Tick herhangi bir nedenle çalışmazsa / devre dışı bırakılırsa / henüz başlatılmazsa, kodunuzun askıda kalacağıdır.


1
Evet, bunu ayrı bir soru olarak göndermelisiniz. Bu cevapta yalnızca asıl soru ile ilgili bilgileri saklayın.
m.Alin

2

STM32F4 keşfi için kod oluşturmak amacıyla CubeMX kullandım. Senin gibi sanal COM portu olarak kullandım. Ben kullanmadım USBD_CDC_SetTxBuffer () işlevi doğrudan. Gelen usbd_cdc_if.c dosyasının adında bir işlevi var CDC_Transmit_FS () . Oluşturulan kodda bir hata vardı, fonksiyon parametre olarak bir tampon aldı ve onunla hiçbir şey yapmadı. Düzeltilmiş fonksiyon kodu aşağıdaki gibidir:

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;
}

Aslında koda memcpy eklemek zorunda kaldı. Bu düzeltmeden sonra bu iletim fonksiyonu ile mikrodenetleyiciden PC'ye veri gönderebilirim. Örneğin:

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

İçinde initalization MX_USB_DEVICE_Init () sizinkiyle bana aynıdır.


1
Teşekkürler ramez. Sorunu buldum, sanal iletişim portunun başlatma işlemini tamamlayıp tamamlamadığını test etmek zorunda kaldım, CDC_Transmit_FS'yi çağırmadan önce ana döngü doğru olmasını beklediğim CDC_Init_FS'de bir boole kullandım. Kodunuzdaki HAL_DELAY'in aynı etkiyi elde ettiğini düşünüyorum. Yardım için teşekkürler.
Galaxy

1

İlk olarak, hUsbDevice_0 öğesinin boş olup olmadığını kontrol edin (çözümünüzde eksik öğe):

    if (hUsbDevice_0 == NULL)
            return USBD_FAIL;

Bu, UC'nizi asmayı önler ve gecikmelerde meşgul beklemeye gerek yoktur.

CDC_Transmit_FS içinde bir yere yerleştirebilirsiniz:

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

Aynı sorunu yaşadım ama yapmam gereken tek şey USB bağlantısını bilgisayara yeniden takmak oldu. Çoğu zaman kodu yanıp söner ve mikro denetleyiciyi sıfırlarsınız, ancak PC tarafında numaralandırma güncellenmez. Ana bilgisayar cihazınızı incelemeye başladığında USBD_CDC_Init çağrılır ve bu yüzden pClassData NULL olur.


1
Yazılımda da numaralandırmayı zorlayabilirsiniz. Yeniden taktıktan sonra ikinci en saçma yol, bunu daha süslü bir şekilde işleyen özel bir sürücünüz yoksa, cihaz yöneticisinde bağlantı noktanızı devre dışı bırakmak / etkinleştirmektir
stiebrs
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.