Die PDC zeigt bei meinem Projekt ein komisches verhalten und dazu steht nix in den Errata, villeicht kann mir ja wer helfen. Sitze da jetzt schon länger dranne und komm nicht weiter. Was solls also werden? Ich hab hier nen Protokollstapel und dieser soll über UART mit dem passenden Gerät kommunizieren. Da dabei ordentlich Daten geschaufelt werden sollen, muss der UART auf 2MBaud aufgedreht werden. Das Gerät kann bis 4 MBaud und die Baudrate ist auf 1% genau getroffen. Weiterhin wird der Hardware Handshake (CTS/RTS) unbedingt benötigt. Bei den hohen Baudraten macht DMA Sinn, bei den Atmel ARM CPUs gibt es dazu eine spezielle DMA, nämlich die PDC. Ein DMA Controller für die Peripherie, diese steuert auch den Hardwarehandshake. RX Puffer voll? -> RTS auf HIGH. Der Protokollstapel hat auch nur Funktionen für DMA, diese müssen natürlich vom Benutzer (mir) mit Code speziell für diese CPU gefüllt werden. Das Problem existiert nur beim Empfangen, also vom Gerät zur CPU. In dieser Richtung können unterschiedliche Paketarten eintreffen. Daher sind diese pakete so aufgebaut:TypByte - Header - Payload Die Payloadlänge steht im Header und der Header ist je nach Pakettyp unterschiedlich lang. Was macht der Protokollstapel also? Er fordert ersteinmal 1 Byte per DMA an! Das eine Byte kommt dann irgendwann über den UART, der RX Buffer der PDC ist nun voll und RTS der CPU geht auf HIGH. Dadurch, dass die CPU RTS auf HIGH setzt, darf das Gerät nichts mehr senden, also Header und Payload müssen warten. Nun ist dem Protokollstapel der Typ bekannt und er fordert 2 oder 4 Byte an für den Header, per PDC/DMA wieder natürlich. Die PDC hat wieder einen Buffer und somit geht RTS auf LOW, die Headerbytes werden übertragen. Headerbytes fertig übertragen und RX Buffer voll -> RTS auf HIGH. Header kann jetzt interpretiert werden und die Payload wird per PDC/DMA angefragt. Das können jetzt bis zu 1,6kbyte sein. Bytes fertig übertragen und RX Buffer voll -> RTS auf HIGH. Ist das fertig, beginnt das Spiel von vorn (TypByte anfordern). Mit anfänglichen 115200baud funktionierte alles einwandfrei. Dann auf 830kbaud erhöht. Das ist so krumm, weil das genau einen Teiler in der CPU getroffen hat. Jetzt kamen die ersten Fehler. So besagte ein TypByte, dass der Header jetzt 2 Byte lang ist, aber es werden 4 Byte angefordert. WAS ZUM?! Ab jetzt Oszibilder! Alle UART Signale sind so beschriftet wie am Gerät. Also TXD: Gerät zu CPU und CTS ist RTS von der CPU Hier funktionierts noch: Schön zu sehen wie das TypByte kommt (04) und dann 2 Byte als Header angefordert werden (0E, 04), danach die Payload. Es ist auch das Gewackel am CTS zu sehen. --Hierzu gehört Bild 001.png--- Jetzt kommt der Fehler! Zu beachten ist der kurze Abstand zwischen TypByte und Header als es noch funktionierte, dieser Abstand wird jetzt ziemlich groß und so lange sind Interrupts auch nie gesperrt. Also der Abstand zwichen 04 und dann 13, 05, 01, 01 Der Interrupt wird ausgeführt wenn die mit TYP beschriftete Linie von LOW auf HIGH geht. Nun ist das TypByte wieder 04, also müssten 2 Headerbytes angefordert werden, es werden aber 4 angefordert! Es sieht so aus, als hätte die PDC die 04 NICHT in den RAM geschrieben. Wie ich darauf komme? Das Paket davor (jetzt nicht abgebildet) hatte ein TypByte von 02, dieses braucht dann 4 Headerbytes. Also wurde das erste Byte im Buffer des Protkollstapels nicht überschrieben?! Dann habe ich einen Workaround eingebaut, wenn eh nur 1 Byte angefordert wurde, dann wird das ja noch im Receive Holding Register des UART liegen, also dieses dann imemr auslesen. BINGO! nun funktionierts auch bei 830kBaud ohne Probleme. Die PDC speichert also manchmal nicht in den RAM! --Hierzu gehört Bild 006.png--- Jetzt kommts zu einem weiteren Problem, bei 2MBaud setzt die CPU dann die RTS Leitung zu spät auf HIGH wodurch das Gerät ein Byte zu viel sendet. Wann setzt die CPU RTS auf HIGH? 1. Die PDC muss aktiv sein 2. Der Empfangspuffer der PDC muss voll sein (die PDC bekommt einen Pointer auf den RAM und einen Counter wieviel Bytes angefordert werden). Ist der Counter = 0, so ist der Empfangspuffer voll und das Interrupt Flag RXBUFF wird gesetzt (RX Buffer voll). 3. RXBUFF ist gesetzt -> RTS auf HIGH Wann bekommt die PDC mit, dass ein Zeichen empfangen wurde? Das passiert nach dem halben Stopbit des UART laut diesem Diagramm, dann wird RXRDY gesetzt und die PDC holt das Zeichen ab. nachdem die PDC das Zeichen abgeholt hat wird der Counter der PDC decrementiert. --Hierzu gehört Bild rxrdy.png--- Laut diesem Bild aus dem Datenblatt sollte aber RTS schon viel früher auf HIGH gehen. Nämlich während das letzte in den RX Buffer passende Byte empfangen wird. Während des Stopbits den RTS ändern ist ja auch recht spät. --Hierzu gehört Bild rts.png--- Was sagt die Realität? RTS (im Oszibild CTS) wird genau beim halben Stopbit auf HIGH gesetzt, was das Gerät am UART auch mitbekommt und dann kein weiteres Zeichen sendet. Violett ist CTS und gelb ist TXD. Die LOW -> HIGH Flanke von TXD ist der Anfang des Stopbits, danach ist dann TXT Idle. --Hierzu gehört Bild scr02.png--- Und hier den sporadisch auftretenden Fehler! Ab und zu wechselt RTS (im Oszibild CTS) zu spät auf HIGH, nämlich nicht zur halben Bitzeit des Stopbits, sondern eher im letzten Viertel. Das bekommt das Gerät am UART nicht mit und sendet somit ein weiteres Byte. Dieses Byte erwartet die CPU/PDC aber nicht wodurch es verloren geht. --Hierzu gehört Bild scr01.png--- Dazu fällt mir jetzt kein Workaround mehr ein. Hatte jemand schonmal son problem oder kennt die Lösung? In den Erratas steht dazu nichts und das problem tritt auch nur auf, wenn der PDC nur 1 byte abverlangt wird.
:
Bearbeitet durch User
Fällt dazu keinem was ein? Ist schon sehr störend nicht über 1Mbaud gehen zu können.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.