USB CDC Seriell-Emulator
Mittwoch, 23. Mai 2012
 
 

PIC Mikrocontroller Forum  |  PIC Mikrocontroller  |  Programmiersprache C  |  USB CDC Seriell-Emulator « vorheriges nächstes »
Seiten: [1] Nach unten Drucken
Autor Thema: USB CDC Seriell-Emulator  (Gelesen 1068 mal)
 
BL1
Jr. Member
**
Offline Offline

Beiträge: 82


Profil anzeigen
« am: Januar 08, 2011, 16:17:48 »

Hallo Gemeinde,



ich versuche mich gerade am MC-Framework; CD-RS232-Emulator.
Ich bin soweit gekommen, dass das Device erkannt wird und via eines Terminals oder auch mit Sprut's USB4all-PC-Demo Daten empfängt und finde diese in der Funktion
Code:
BYTE getsUSBUSART(char *buffer, BYTE len)
{
    cdc_rx_len = 0;
    
    if(!USBHandleBusy(CDCDataOutHandle))
    {
        /*
         * Adjust the expected number of BYTEs to equal
         * the actual number of BYTEs received.
         */
        if(len > USBHandleGetLength(CDCDataOutHandle))
            len = USBHandleGetLength(CDCDataOutHandle);
        
        /*
         * Copy data from dual-ram buffer to user's buffer
         */
        for(cdc_rx_len = 0; cdc_rx_len < len; cdc_rx_len++)
 [u][i][b]           buffer[cdc_rx_len] = cdc_data_rx[cdc_rx_len];
[/b][/i][/u]
        /*
         * Prepare dual-ram buffer for next OUT transaction
         */

        CDCDataOutHandle = USBRxOnePacket(CDC_DATA_EP,(BYTE*)&cdc_data_rx,sizeof(cdc_data_rx));

    }//end if
    
    return cdc_rx_len;
    
}//end getsUSBUSART
fett gekennzeichneten Stelle wieder.

Soweit, so gut. Jetzt wollte ich was zurück zum PC schicken. dazu gibt die ansonsten äußerst dürftig dokumentierte Software die Empfehlung
Code:
       if(USBUSARTIsTxTrfReady())
        {
            char data[] = "Hello World";
            putsUSBUSART(data);
        }
. UNd da hört es im Moment auf. Wo finde ich diese Bedingung USBUSARTIsTxTrfReady().Wie wird die gehandelt? Und an welcher Stelle setzt man dieses(oder einen anderen "Sende-"Code am dümmsten hin?
Noch eine Frage zum Empfangen von Daten im Device: Nehmen wir an, es ist ein Daten-Transfer vom PC zum Device geglückt. Da wird doch bestimmt irgendwo ein Flag dazu gesetzt, welches eine USer-Application dann zur Weiterverarbeitung anregen könnte. Ich würde auch eines selber machen, aber da versteckt sich doch bestimmt irgendwas irgendwo in diesem Wust.


Besten Dank!


BL

Wo finde ich diese Bedingung USBUSARTIsTxTrfReady().
Hab ich gefunden. Es bezetchnet, dass die "cdc_trf_state"-Maschine im Zustand "CDC_TX_READY". Schön. Nur wie kommt die dahin?
« Letzte Änderung: Januar 08, 2011, 16:31:49 von BL1 » Gespeichert
BL1
Jr. Member
**
Offline Offline

Beiträge: 82


Profil anzeigen
« Antworten #1 am: Januar 14, 2011, 18:29:52 »

Hat da wirklich keiner Ahnung von oder noch nie einer gemacht, die Geschichte?


Folgendes hab ich bis jetzt noch rausgefunden:
Der Zustand der State-Maschine wird in der Funktion void CDCTxService(void) gesetzt. Dort ist aber am Anfang ein Rausschmeißer
Code:
  ************************************************************************/
 
void CDCTxService(void)
{
    BYTE byte_to_send;
    BYTE i;
   
    USBMaskInterrupts();
    if(USBHandleBusy(CDCDataInHandle))
    {
        USBUnmaskInterrupts();
        return;
    }

    /*
     * Completing stage is necessary while [ mCDCUSartTxIsBusy()==1 ].
     * By having this stage, user can always check cdc_trf_state,
     * and not having to call mCDCUsartTxIsBusy() directly.
     */
    if(cdc_trf_state == CDC_TX_COMPLETING)
        cdc_trf_state = CDC_TX_READY;
   
    /*
     * If CDC_TX_READY state, nothing to do, just return.
     */
    if(cdc_trf_state == CDC_TX_READY)
    {
        USBUnmaskInterrupts();
        return;
    }
   
    /*
     * If CDC_TX_BUSY_ZLP state, send zero length packet
     */
    if(cdc_trf_state == CDC_TX_BUSY_ZLP)
    {
        CDCDataInHandle = USBTxOnePacket(CDC_DATA_EP,NULL,0);
        //CDC_DATA_BD_IN.CNT = 0;
        cdc_trf_state = CDC_TX_COMPLETING;
    }
    else if(cdc_trf_state == CDC_TX_BUSY)
    {
        /*
         * First, have to figure out how many byte of data to send.
         */
    if(cdc_tx_len > sizeof(cdc_data_tx))
        byte_to_send = sizeof(cdc_data_tx);
    else
        byte_to_send = cdc_tx_len;

        /*
         * Subtract the number of bytes just about to be sent from the total.
         */
    cdc_tx_len = cdc_tx_len - byte_to_send;
     
        pCDCDst.bRam = (BYTE*)&cdc_data_tx; // Set destination pointer
       
        i = byte_to_send;
        if(cdc_mem_type == USB_EP0_ROM)            // Determine type of memory source
        {
            while(i)
            {
                *pCDCDst.bRam = *pCDCSrc.bRom;
                pCDCDst.bRam++;
                pCDCSrc.bRom++;
                i--;
            }//end while(byte_to_send)
        }
        else // _RAM
        {
            while(i)
            {
                *pCDCDst.bRam = *pCDCSrc.bRam;
                pCDCDst.bRam++;
                pCDCSrc.bRam++;
                i--;
            }//end while(byte_to_send._word)
        }//end if(cdc_mem_type...)
       
        /*
         * Lastly, determine if a zero length packet state is necessary.
         * See explanation in USB Specification 2.0: Section 5.8.3
         */
        if(cdc_tx_len == 0)
        {
            if(byte_to_send == CDC_DATA_IN_EP_SIZE)
                cdc_trf_state = CDC_TX_BUSY_ZLP;
            else
                cdc_trf_state = CDC_TX_COMPLETING;
        }//end if(cdc_tx_len...)
        CDCDataInHandle = USBTxOnePacket(CDC_DATA_EP,(BYTE*)&cdc_data_tx,byte_to_send);

    }//end if(cdc_tx_sate == CDC_TX_BUSY)
    USBUnmaskInterrupts();
}//end CDCTxService

#endif //USB_USE_CDC

und der leistet ganz Arbeit. Die Funktion wird also abgebrochen, wenn der Zustand des USBHandleBusy() nicht CDCDataInHandle ist. Das wiederum müßte oder könnte bedeuten, dass die vorherige "Out"-Transaktion(meinem Fall hatte ich vom PC via Terminal zwei Byte gesendet) nicht richtig beendet wurde- irgendeine Zustandmaschine also nicht in den richtigen Zustand kommt.
Sende ich Zeichen vom Device zum Host, bevor ich etwas empfangen habe, geht's auch. Empfange ich aber was, stimmt dieser Zustand offensichtlich nicht und dasn Device schickt nichts raus. Empfangen geht aber weiterhin.


Wer hat denn mal eine Idee?



BL
Gespeichert
BL1
Jr. Member
**
Offline Offline

Beiträge: 82


Profil anzeigen
« Antworten #2 am: Februar 03, 2012, 18:34:35 »

Alle Jahre wieder.

Hat sich denn schon mal jemand mit diesem Thema Framework/USB/CDC-Seriel beschäftigt?

Es gibt das eine Statemashine mit der Zustandsvariablen cdc_trf_state. Will man etwas senden, muß vorher deren Zustand auf "CDC_TX_READY" abfragen. Ist soweit verstanden, funktioniert auch. Manchmal.

Manchmal steht das blöde Ding nämlich nicht auf diesem Zustand und bringt es irgendwelchen Gründen auch nicht dahin. Dann gehen die Sende-Versuche logischerweise in die Hose.

Nun habe ich mich noch nicht getraut, in diese Zustandsmaschine einzugreifen, weil ich nirgends eine Systematik dazu beschrieben finde und das anhand der Software zu Fuß rauszufinden - naja.

Kennt sich da jemand aus oder hat einen Tipp, wo man was zu lesen findet?



BL
Gespeichert
Edson
Globaler Moderator
Sr. Member
*****
Offline Offline

Beiträge: 373



Profil anzeigen
« Antworten #3 am: Februar 04, 2012, 11:52:29 »

Hallo BL,

Zitat
an welcher Stelle setzt man dieses(oder einen anderen "Sende-"Code am dümmsten hin?

das gesamte MCHPUSB-Device-Framework ist so aufgebaut, dass dies innerhalb der ProcessIO() vorgenommen werden kann. Du bist bereits in Tiefen des Treibers eingestiegen, an denen (eigentlich) keine Manipulation erforderlich ist. Gerade beim CDC-SerialEmulator ist der Code in ProcessIO() nicht sehr elegant, aber durchaus nachzuvollziehen. Schreib dir eine eigene Implementierung der ProcessIO() mit den Mitteln, die im Beispiel verwendet werden - dann sollte das auch klappen.

Was genau hast du denn vor, benötigst du Ein-/Ausgabe über USART oder möchtest du nur über USB kommunizieren?

Gruß,
Edson
Gespeichert
BL1
Jr. Member
**
Offline Offline

Beiträge: 82


Profil anzeigen
« Antworten #4 am: Februar 06, 2012, 17:59:46 »

Hallo Edson,


der Tröt ist zweigeteilt. Ein Teil ist ein Jahr alt, am zweiten fummle ich gerade. Das Problem betraf nur eben die gleiche Zustandsmaschine, weshalb ich keinen neuen aufmachen wollte.


Eigentlich bezieht es sich auf eben diese Maschine, die original nur aufgerufen wird, wenn eine USB-Aktion gerade stattfindet. Da nun im Vorteil ist, wer lesen kann, las ich nun auch mal. Und da steht, dass man den Aufruf dieses Unterprogramms, nämlich oben stehende "CDCTxService(void)" in die Endlos-Main-Schleife setzen soll. Nun tat ich wie geheißen und muß mal sehen ob's hilft.

Die Fehlererscheinung war ansich folgende. Die Schaltung nimmt via I²C Daten auf und schuckt sie zum PC via USB weiter. Eine Log-Funktion. Das klappte auch. Stundenlang. Aber nach Stunden klappte es eben auch mal nicht mehr. Nun war aus dem Abstand nicht nachvollziehbar, weshalb im PC keine Daten mehr ankamen weshalb ich im Nebel stochern mußte.
Dabei fiel auf, dass ich zum Senden den Zustand auf "CDC_TX_READY" abfrage und wenn dem so ist, meine Daten zum PC schicke. Das problem nun ist: Was passiert, wenn der Zustand nicht CDC_TX_READY ist. Dann passierte eben nichts ud deshalb mußte man sich wenig wundern, wenn das Ding nichte mehr sendet. Nun hoffe ich, dass mit dem regelmäßigen Abarbeiten der Zustandsmaschine dauerhaft kein "Nicht-Ready-Zustand" mehr auftreten kann.



BL
Gespeichert
Seiten: [1] Nach oben Drucken 
« vorheriges nächstes »
Gehe zu:  

Powered by MySQL Powered by PHP Made for Mozilla (Firefox) Made for Internet Explorer
Seite erstellt in 0.036 Sekunden mit 18 Zugriffen.
 
Top! Top!