Het opsporen van onderbrekingen PC COM-poort USB virtuele COM-poort apparaat

stemmen
5

Ik gebruik een STM32F105 microcontroller met de STM32_USB-FS-Device_Lib_V3.2.1 USB-bibliotheek en de VCP voorbeeld voor onze doeleinden (integratie met RTOS en seriële API) hebben aangepast.

Het probleem is dat als de USB-kabel is aangesloten, maar de poort niet open op de Windows-host, na een paar minuten eindigt het apparaat permanent op het opnieuw invoeren van de USB ISR totdat de poort wordt geopend en vervolgens het begint allemaal normaal.

Ik heb interruptafhandeling geïnstrumenteerd en kan zien dat wanneer de fout zich voordoet, de ISR geleider verlaat en vervolgens onmiddellijk opnieuw binnenkomt. Dit gebeurt omdat bij het verlaten van het onderbreken van de vlag IEPINT in OTG_FS_GINTSTS is niet duidelijk. De OTG_FS_DAINT op dit moment bevat 0x00000002 (IEPINT1 set), terwijl DIEPINT1 heeft 0x00000080 (TXFE). De lijn in OTGD_FS_Handle_InEP_ISR () die TXFE gewist wordt genoemd, maar de bit ofwel niet gewist of wordt direct weer gelden. Wanneer de COM-poort op de host opnieuw wordt geopend, de toestand van OTG_FS_GINTSTS en OTG_FS_DAINT aan het einde van de onderbreking is altijd nul en verdere onderbrekingen optreden bij het normale tarief. Merk op dat het probleem zich alleen voordoet wanneer gegevens wordt uitgevoerd maar de gastheer heeft geen poort open is. Als ofwel de poort open is of er geen gegevens worden uitgevoerd, draait het systeem voor onbepaalde tijd. Ik geloof dat hoe meer gegevens dat wordt uitgevoerd hoe eerder het probleem zich voordoet, maar dat is anekdotisch op dit moment.

De VCP code een toestandvariabele die de volgende opgesomde waarden neemt:

  UNCONNECTED,
  ATTACHED,
  POWERED,
  SUSPENDED,
  ADDRESSED,
  CONFIGURED

en we gebruiken de geconfigureerde staat om te bepalen of de gegevens in de driver buffer gezet voor het verzenden. Echter de ingestelde toestand wordt ingesteld wanneer de kabel is aangesloten niet wanneer de gastheer de open poort en een applicatie verbonden. Ik zie dat wanneer Windows doet open de poort, is er een uitbarsting van interrupts dus het lijkt erop dat sommige communicatie vindt plaats op dit evenement; Ik vraag me af of het dus mogelijk is om te detecteren of de gastheer heeft de poort geopend ,.

Ik moet een van de twee dingen misschien:

  1. Om de USB-code te voorkomen dat vast komen te zitten in de ISR in eerste instantie
  2. Te bepalen of de gastheer de open poort van het eindapparaat en druk alleen gegevens te verzenden wanneer open.
De vraag is gesteld op 17/03/2011 om 11:15
bron van user
In andere talen...                            


7 antwoorden

stemmen
7

(1) - het voorkomen van de interrupt lock-up - werd vergemakkelijkt door een USB-bibliotheek bug fix uit ST ondersteuning; het was niet correct opruimen van de TxEmpty interrupt.

detecteren of de host poort open is - na wat onderzoek en hulp van ST Ondersteuning, heb ik een oplossing voor een deel (2) bepaald. Conventioneel, wanneer een poort wordt geopend de DTR modem controle lijn wordt beweerd. Deze informatie wordt doorgegeven aan een CDC apparaat klasse, dus ik kan dit gebruiken om mijn doel te bereiken. Het is mogelijk voor een toepassing om het gedrag van DTR veranderen, maar dit mag niet gebeuren in een van de clienttoepassingen die waarschijnlijk dit apparaat verbinden in dit geval. Er is echter een back-up plan dat impliciet neemt de poort geopend indien de lijncodering (baud, framing) ingesteld. In dit geval is er geen wijze voor het detecteren gesloten, maar in ieder geval zal het niet voorkomen dat een onconventionele toepassing van het werken met dit apparaat, ook al om deze vervolgens vast als deze verbreekt.

Ten aanzien van ST's VCP voorbeeldcode specifiek heb ik de volgende wijzigingen in usb_prop.c gemaakt:

1) Toegevoegd de volgende functie:

#include <stdbool.h>
static bool host_port_open = false ;
bool Virtual_Com_Port_IsHostPortOpen()
{
    return bDeviceState == CONFIGURED && host_port_open ;
}

2) Gemodificeerde Virtual_Com_Port_NoData_Setup () behandeling van SET_CONTROL_LINE_STATE volgt:

else if (RequestNo == SET_CONTROL_LINE_STATE)
{
  // Test DTR state to determine if host port is open
  host_port_open = (pInformation->USBwValues.bw.bb0 & 0x01) != 0 ;
  return USB_SUCCESS;
}

3) Voor gebruik bij toepassingen die niet werken DTR conventioneel heb ik ook gemodificeerd Virtual_Com_Port_Data_Setup () behandeling van SET_LINE_CODING laten dan:

  else if (RequestNo == SET_LINE_CODING)
  {
    if (Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT))
    {
      CopyRoutine = Virtual_Com_Port_SetLineCoding;

      // If line coding is set the port is implicitly open 
      // regardless of host's DTR control.  Note: if this is 
      // the only indicator of port open, there will be no indication 
      // of closure, but this will at least allow applications that 
      // do not assert DTR to connect.
      host_port_open = true ;

    }
    Request = SET_LINE_CODING;
  }
antwoordde op 25/03/2011 om 11:19
bron van user

stemmen
0

Ik heb dezelfde eis om pc-poort open / dicht te detecteren. Ik heb het gezien geïmplementeerd het als volgt:

Open gedetecteerd door:

  • DTR beweerde
  • CDC bulkoverdracht

Sluit gedetecteerd door:

  • DTR deasserted
  • USB "unplugged", slapen etc

Dit lijkt redelijk goed te werken, hoewel meer grondig testen nodig zijn om te bevestigen het werkt robuust.

antwoordde op 12/04/2011 om 23:43
bron van user

stemmen
1

Na zo veel zoeken en een soort van reverse engineering vond ik eindelijk de methode voor het opsporen van de open terminal en ook is het einde. Ik vond dat in de CDC klasse is er drie data nodes, een is een controle knooppunt en de andere twee zijn data in en data-Out nodes.Now wanneer u een terminal openen van een code wordt aan de controle knooppunt verzonden en ook bij het sluiten . alles wat we moeten doen is om die codes te krijgen en door hen te beginnen en onze datatransmissie taken te stoppen. de code die wordt gezonden respectievelijk 0x21 en 0x22 voor het openen en sluiten van de terminal.In de usb_cdc_if.c is een functie die ontvangen en interpreteren die codes (er is een schakelaarhuis en de variabele cmd de code we het over) .dat functie CDC_Control_FS. Hier zijn we, nu alles wat we moeten doen is om die functie uit te breiden zodat het de 0x22 en 0x21 interpreteren. daar sta je dan, nu weet u in uw toepassing of de poort open is of niet.

antwoordde op 24/08/2015 om 20:58
bron van user

stemmen
1

Ik moet een van de twee dingen misschien:

  1. Om de USB-code te voorkomen dat vast komen te zitten in de ISR in eerste instantie
  2. Te bepalen of de gastheer de open poort van het eindapparaat en druk alleen gegevens te verzenden wanneer open.

Je moet proberen om de optie 1 in plaats van 2. doen In Windows en Linux, is het mogelijk om een ​​COM-poort te openen en gebruiken zonder dat de stuursignalen, wat betekent dat er is geen fool-proof, cross-platform manier om te detecteren dat de COM-poort is open.

Een goed geprogrammeerde apparaat laat zich niet stoppen met functioneren, alleen maar omdat de USB-host gestopt polling voor data; dit is een normale zaak die goed moeten worden behandeld. Bijvoorbeeld, zou u uw code te wijzigen, zodat u alleen de rij staan ​​gegevens naar de USB-host moet worden verzonden als er buffer ruimte beschikbaar is voor het eindpunt. Als er geen vrije buffer ruimte, kun je een aantal speciale foutafhandeling code te hebben.

antwoordde op 25/08/2015 om 23:14
bron van user

stemmen
1

Ik vond een andere oplossing door het aannemen van CDC_Transmit_FS. Het kan nu worden gebruikt als uitgang voor printf door het overschrijven _write functie.

Eerst controleert hij de verbinding staat, probeert vervolgens te sturen over USB endport in een drukke lus, die herhaalt het verzenden als USB is bezet.

Ik kwam er als dev_state niet USBD_STATE_CONFIGURED de USB-connector wordt losgekoppeld. Wanneer de stekker aangesloten maar geen VCP poort open via PuTTY of termieten, de tweede mislukt.

Deze implementatie werkt prima voor mij voor RTOS en CubeMX HAL applicatie. De drukke lus wordt niet meer het blokkeren van lage prioriteit threads.

uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
{
    uint8_t result = USBD_OK;


    // Check if USB interface is online and VCP connection is open.
    // prior to send:
    if ((hUsbDevice_0->dev_state != USBD_STATE_CONFIGURED)
            || (hUsbDevice_0->ep0_state == USBD_EP0_STATUS_IN))
    {
        // The physical connection fails.
        // Or: The phycical connection is open, but no VCP link up.
        result = USBD_FAIL;
    }
    else
    {

        USBD_CDC_SetTxBuffer(hUsbDevice_0, Buf, Len);

        // Busy wait if USB is busy or exit on success or disconnection happens
        while(1)
        {

            //Check if USB went offline while retrying
            if ((hUsbDevice_0->dev_state != USBD_STATE_CONFIGURED)
                        || (hUsbDevice_0->ep0_state == USBD_EP0_STATUS_IN))
            {
                result = USBD_FAIL;
                break;
            }

            // Try send
            result = USBD_CDC_TransmitPacket(hUsbDevice_0);
            if(result == USBD_OK)
            {
                break;
            }
            else if(result == USBD_BUSY)
            {
                // Retry until USB device free.
            }
            else
            {
                // Any other failure
                result = USBD_FAIL;
                break;
            }

        }
    }

    return result;
}

CDC_Transmit_FS wordt gebruikt door _write:

// This function is used by printf and puts.
int _write(int file, char *ptr, int len)
{
    (void) file; // Ignore file descriptor
    uint8_t result;

    result = CDC_Transmit_FS((uint8_t*)ptr, len);
    if(result == USBD_OK)
    {
        return (int)len;
    }
    else
    {
        return EOF;
    }
}

Regards Bernhard

antwoordde op 13/01/2016 om 10:52
bron van user

stemmen
0

Disclaimer: Ik gebruik code wordt gegenereerd door Cube, met als gevolg dat het werkt met HAL chauffeurs. Solutions, voorgesteld hier eerder, niet werken voor mij, dus ik heb een gevonden. Het is niet goed, maar werkt voor sommige doeleinden.

Eén van de indirecte teken van niet geopend poort doet zich voor wanneer u probeert om pakket te verzenden door CDC_Transmit_FS, en vervolgens wachten tot TxState is ingesteld op 0. Als de poort niet geopend wordt het nooit gebeurt. Dus mijn oplossing is om een ​​aantal time-out op te lossen:

uint16_t count = 0;
USBD_CDC_HandleTypeDef *hcdc =
        (USBD_CDC_HandleTypeDef*) USBD_Device.pClassData;

while (hcdc->TxState != 0) {
    if (++count > BUSY_TIMEOUT) { //number of cycles to wait till it makes decision
        //here it's clear that port is not opened
    }
}

Het probleem is ook dat als men probeert om poort te openen, nadat het apparaat heeft geprobeerd om een ​​pakket te sturen, kan niet worden gedaan. Daarom hele routine die ik gebruik:

uint8_t waitForTransferCompletion(void) {

    uint16_t count = 0;
    USBD_CDC_HandleTypeDef *hcdc =
             (USBD_CDC_HandleTypeDef*) USBD_Device.pClassData;

    while (hcdc->TxState != 0) {
        if (++count > BUSY_TIMEOUT) { //number of cycles to wait till it makes decision
            USBD_Stop(&USBD_Device); // stop and
            MX_USB_DEVICE_Init(); //            init device again
            HAL_Delay(RESET_DELAY); // give a chance to open port
            return USBD_FAIL; // return fail, to send last packet again
        }
    }

    return USBD_OK;
}

De vraag is, hoe groot time-out moet zijn, niet om de overdracht onderbreken terwijl poort wordt geopend. Ik zette BUSY_TIMEOUT tot 3000, en nu het werkt.

antwoordde op 16/01/2017 om 15:41
bron van user

stemmen
0

Ik bevestigde door het controleren van een variabele hUsbDeviceFS.ep0_state. Het gelijk 5 indien aangesloten en 4 als niet aangesloten of werd verbroken. Maar. Er zijn een aantal kwestie in de HAL. Het gelijk 5 als programma is gestart. Vervolgstappen losten het aan het begin van een programma

        /* USER CODE BEGIN 2 */
            HAL_Delay(500);
            hUsbDeviceFS.ep0_state = 4;

...

Ik heb geen wensen voor de HAL te leren - ik hoop dat dit bericht zal zien door de ontwikkelaars en zij zullen de HAL op te lossen. Het hielp me om mijn probleem op te lossen.

antwoordde op 01/01/2018 om 18:10
bron van user

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more