// ============================================================================= // Testprogramm für serielle Schnittstellen (eigene Treiber) // ============================================================================= // #include "TestSerial.h" char *StartMsg = { "%@TestSerial " TmpVerMsg }; LoopCheck lc; // Eine statische Instanz der Klasse LoopCheck // Darüber wird das Zeitverhalten gesteuert (Software-Timer) und geprüft #ifdef DebugTerminal Monitor mon(modeEcho | modeNl,0,&lc); // Eine statische Instanz (mit Konstruktordaten) der Klasse Monitor // Darüber wird mit (direkten) Terminals (z.B. VT100) kommuniziert // Unter Linux werden hier GtkTerm (siehe Internet) und // ArduinoMonTerm (eigene Entwicklung mit grafischen Wertanzeigen) eingesetzt. // Das in den IDEs integrierte Terminal ist dafür meistens nicht geeignet, // weil damit keine direkte Kommunikation (getipptes Zeichen sofort gesendet) // möglich ist. // ----- Parameter ------------------------------------------------------------ // <mode Echo> Alle eintreffenden Zeichen werden sofort zurückgesendet // <mode NL> Vor der Ausgabe des Prompt (M>) erfolgt CR/LF // <0> Für Speicherzugriffe wird von 32 Bit ARM ausgegangen // <&lc> Für Zeitüberwachungen und entsprechende statistische Daten // greift die Monitor-Instanz auf die LoopCheck-Instanz zu char *infoThis = { "DHE TestSerial Version 1.0.0\r\n" "c0 Abschalten der periodischen Meldung\r\n" "c1 Prüfen der Speicheradressen\r\n" "c2 Testen der Ringpuffer und seriellen Schnittstellen\r\n" //"c3 Steuern/Analysieren der Messwerterfassung\r\n" //"c4 Testen von Peripheriezugriffen\r\n" //"c5 Temporäre lokale Tests\r\n" }; #endif #ifdef DebugTerminal #define smCycleTime 5 void smInit(); // Vorwärtsreferenz auf die weiter unten definierte Funktion StateMachine sm(smInit, NULL, smCycleTime); // Eine statische Instanz für die Zustandsmaschine, die hier für allgemeine // Steuerungen, Überwachungen und zum Debugging verwendet wird // ----- Parameter ------------------------------------------------------------ // <smInit> Der zuerst aufgerufene Zustand (Funktion). Weitere Zustände // werden in den weiteren Zustandsfunktionen eingesetzt. // <NULL> Hier kann eine weitere Zustandsfunktion angegeben werden, // die dann grundsätzlich vor dem Verzweigen in einen Zustand // aufgerufen wird. // <smCycleTime> Die Zukluszeit (Takt) der Zustandsmaschine in Millisekunden #endif SerParams tty1Params, tty2Params; // ---------------------------------------------------------------------------- nRF52840SerE tty1,tty2; // ---------------------------------------------------------------------------- // Eine statische Instanz der Klasse nRF52840SerE (UARTE) // Darüber werden die seriellen Schnittstellen (UARTE0 und UARTE1) des // nRF52840 bedient. // Die Parameter werden in einer Struktur <SerParams> über die Funktion // <begin(...)> gesetzt. #define sndBufSize 256 byte sndBuffer1[sndBufSize]; byte sndBuffer2[sndBufSize]; #define recBufSize 256 byte recBuffer1[recBufSize]; byte recBuffer2[recBufSize]; // ---------------------------------------------------------------------------- ComRingBuf crb1,crb2; // ---------------------------------------------------------------------------- // Eine statische Instanz der Klasse <ComRingBuf> // Damit wird ein Ringpuffer aufgebaut, der eine serielle Schnittstelle bedient. // Der Speicher muss extra eingerichtet und mit der Funktion // <setWriteBuffer(sndBufSize, sndBuffer)> übergeben werden. // Die Klasse für die serielle Schnittstelle muss von <IntrfSerial> abgeleitet // sein, die Instanz wird mit der Funktion <begin(...)> übergeben. void setup() { #if defined(DebugTerminal) #if defined(ArduinoMonTerm) mon.config(6); // 6 Anzeigekanäle, die von ArduinoMonTerm aufgebaut werden for(int i = 0; i < 6; i++) { if(i < 3) mon.config(i+1,'C',16000,-16000,NULL); // Kanalnummer, Typ, Maxwert, Minwert else mon.config(i+1,'C',4000,-4000,NULL); } #endif mon.setInfo(infoThis); #endif // Initialisierung von serieller Schnittstelle 1 und Ringpuffer 1 // -------------------------------------------------------------------------- tty1Params.inst = SerCom1; // Instanzindex der Schnittstelle (0,1) tty1Params.rxdPort = 1; // Nummer des IO-Port mit RxD-Pin tty1Params.rxdPin = 10; // Nummer des RxD-Pin am Port tty1Params.txdPort = 1; // Nummer des IO-Port mit TxD-Pin tty1Params.txdPin = 3; // Nummer des TxD-Pin am Port tty1Params.speed = Baud115200; // Enumerator für Bitrate tty1Params.type = stStd; // Standard-RS232 tty1.begin(&tty1Params, (IntrfBuf *) &crb1); // Übergeben von Parametern und Referenz auf Ringpufferverwaltung // für die Übergabe empfangener Zeichen crb1.setWriteBuffer(sndBufSize, sndBuffer1); crb1.setReadBuffer(recBufSize, recBuffer1); // Speicher an Ringpufferverwaltung übergeben crb1.begin((IntrfSerial *) &tty1); // Referenz auf Schnittstelle an Ringpufferverwaltung // für die Übergabe zu sendender Zeichen tty1.startSend(); // Sendebetrieb aktivieren tty1.startRec(); // Empfangsbetrieb aktivieren // Initialisierung von serieller Schnittstelle 2 und Ringpuffer 2 // -------------------------------------------------------------------------- tty2Params.inst = SerCom2; // Instanzindex der Schnittstelle (0,1) tty2Params.rxdPort = 1; // Nummer des IO-Port mit RxD-Pin tty2Params.rxdPin = 11; // Nummer des RxD-Pin am Port tty2Params.txdPort = 1; // Nummer des IO-Port mit TxD-Pin tty2Params.txdPin = 12; // Nummer des TxD-Pin am Port tty2Params.speed = Baud115200; // Enumerator für Bitrate tty2Params.type = stStd; // Standard-RS232 tty2.begin(&tty2Params, (IntrfBuf *) &crb2); // Übergeben von Parametern und Referenz auf Ringpufferverwaltung // für die Übergabe empfangener Zeichen crb2.setWriteBuffer(sndBufSize, sndBuffer2); crb2.setReadBuffer(recBufSize, recBuffer2); // Speicher an Ringpufferverwaltung übergeben crb2.begin((IntrfSerial *) &tty2); // Referenz auf Schnittstelle an Ringpufferverwaltung // für die Übergabe zu sendender Zeichen tty2.startSend(); // Sendebetrieb aktivieren tty2.startRec(); // Empfangsbetrieb aktivieren } #ifdef DebugTerminal char runView[4] = {'|','/','-','\\'}; int runViewIdx = 0; #endif void loop() { lc.begin(); // -------------------------------------------------------------------------- #ifdef DebugTerminal // Der Monitor wird ständig aufgerufen und stellt damit eine grundsätzliche // Belastung dar. Das ist für die Entwicklung auch vorgesehen. // Es entsteht dadurch eine Reserve für den produktiven Einsatz. // mon.run(); #endif #ifdef DebugTerminal // Alle 5 Millisekunden wird die Zustandsmaschine für // betriebliche Abläufe aufgerufen // if(lc.timerMilli(lcTimer4, smCycleTime, 0)) { sm.run(); } // Jede halbe Sekunde erfolgt die Ausgabe der Version // if(lc.timerMilli(lcTimer5, 500, 0)) { if(!mon.cFlag[0]) { mon.print(StartMsg); mon.cprintcr(runView[runViewIdx]); runViewIdx++; if(runViewIdx > 3) runViewIdx = 0; } } #endif // -------------------------------------------------------------------------- lc.end(); } #ifdef DebugTerminal // **************************************************************************** // Z u s t a n d s m a s c h i n e (für Monitor-Ergänzung) // **************************************************************************** // dword debDword; byte tmpByteArray[256]; int tmpInt; void smInit() { sm.enter(smCheckJobs); } // ---------------------------------------------------------------------------- // Abfrage der Monitorschalter // ---------------------------------------------------------------------------- // char tmpOut[256]; char charOut[2]; void smCheckJobs() { if(mon.cFlag[1] && !mon.busy) sm.enter(smCheckMemory); else if(mon.cFlag[2] && !mon.busy) sm.enter(smCheckRB); /* else if(mon.cFlag[3] && !mon.busy) sm.enter(sm); else if(mon.cFlag[4] && !mon.busy) sm.enter(sm); else if(mon.cFlag[5] && !mon.busy) sm.enter(sm); */ } // ---------------------------------------------------------------------------- // Testen der Speicherzugriffe (Datenstruktur) // ---------------------------------------------------------------------------- // void smCheckMemory() { if(sm.firstEnter()) { mon.print((char *) "Speichertest "); mon.lastKeyIn = ':'; } if(mon.lastKeyIn == ':') return; charOut[0] = mon.lastKeyIn; charOut[1] = '\0'; mon.println(charOut); if(mon.lastKeyIn == '0' || mon.lastKeyIn == ' ') { mon.cFlag[1] = false; mon.print((char *) "-- Schleifenabbruch - drücke Enter"); sm.enter(smCheckJobs); } else if(mon.lastKeyIn == 'S' || mon.lastKeyIn == 's') { mon.println(); sm.enter(smTestSerMem); } mon.lastKeyIn = ':'; sm.resetEnter(); } void smTestSerMem() { nrfSerPtr perMem = NULL; dword res1 = (dword) &perMem->EVENTS_ENDRX; dword res2 = (dword) &perMem->INTEN; dword res3 = (dword) &perMem->EVENTS_ERROR; dword res4 = (dword) &perMem->ENABLE; dword res5 = (dword) &perMem->BAUDRATE; dword res6 = (dword) &perMem->RXD_AMOUNT; dword res7 = (dword) &perMem->CONFIG; sprintf(tmpOut,"%X %X %X %X %X %X %X",res1,res2,res3,res4,res5,res6,res7); mon.println(tmpOut); sm.enter(smCheckMemory); } // ---------------------------------------------------------------------------- // Testen der Ringpuffer // ---------------------------------------------------------------------------- // char *smCheckRBHelp = { "A Zeichen in P1 eingeben\r\n" "B Zeichen in P2 eingeben\r\n" "I Anzahl der Interrupts anzeigen\r\n" "R Inhalte der Empfangspuffer auslesen\r\n" "Sx String in Px eingeben\r\n" "Z Zeiger/Index der Ringpuffer anzeigen\r\n" }; void smCheckRB() { if(sm.firstEnter()) { mon.print((char *) "Testen der Ringpuffer und seriellen Schnittstellen "); mon.lastKeyIn = ':'; } if(mon.lastKeyIn == ':') return; charOut[0] = mon.lastKeyIn; charOut[1] = '\0'; mon.println(charOut); if(mon.lastKeyIn == 'A' || mon.lastKeyIn == 'a') { sm.userVar = 1; sm.enter(smPutCharRB); } else if(mon.lastKeyIn == 'B' || mon.lastKeyIn == 'b') { sm.userVar = 2; sm.enter(smPutCharRB); } else if(mon.lastKeyIn == 'I' || mon.lastKeyIn == 'i') { sm.userVar = 1; sm.enter(smGetCntIntSer); } else if(mon.lastKeyIn == 'R' || mon.lastKeyIn == 'r') { sm.userVar = 1; sm.enter(smReadAllRB); } else if(mon.lastKeyIn == 'S' || mon.lastKeyIn == 's') { sm.userVar = 0; sm.enter(smWriteStrRB); } else if(mon.lastKeyIn == 'Z' || mon.lastKeyIn == 'z') { sm.userVar = 1; sm.enter(smReadPtrRB); } else if(mon.lastKeyIn == '0' || mon.lastKeyIn == ' ') { mon.cFlag[2] = false; mon.print((char *) "-- Schleifenabbruch - drücke Enter"); sm.enter(smCheckJobs); } else if(mon.lastKeyIn == 'H' || mon.lastKeyIn == 'h' || mon.lastKeyIn == '?') { mon.print(smCheckRBHelp); } mon.lastKeyIn = ':'; sm.resetEnter(); } void smPutCharRB() { int retv; if(sm.firstEnter()) { mon.print((char *) "Zeichen eingeben für Puffer "); mon.print(sm.userVar); mon.print((char *) " "); mon.lastKeyIn = ':'; } if(mon.lastKeyIn == ':') return; mon.cprint(mon.lastKeyIn); if(sm.userVar == 1) retv = crb1.putChr(mon.lastKeyIn); else retv = crb2.putChr(mon.lastKeyIn); mon.println(retv); mon.lastKeyIn = ':'; sm.enter(smCheckRB); } void smReadPtrRB() { ComRingBuf::DbBufValues bv; mon.print((char *) "Instanz ["); mon.print(sm.userVar); mon.print((char *) "]: Indizes RbIn="); if(sm.userVar == 1) crb1.dbGetBufValues(&bv); else crb2.dbGetBufValues(&bv); mon.print(bv.rbRdIdx); mon.print((char *) " RbOut="); mon.print(bv.rbWrIdx); mon.print((char *) " TbIn="); mon.print(bv.tbRdIdx); mon.print((char *) " TbOut="); mon.println(bv.tbWrIdx); if(sm.userVar == 2) { mon.lastKeyIn = ':'; sm.enter(smCheckRB); } else sm.userVar++; } void smGetCntIntSer() { int cnt1, cnt2; cnt1 = tty1.getIrqCount(); cnt2 = tty2.getIrqCount(); mon.print((char *) "Interrupts Ser1="); mon.print(cnt1); mon.print((char *) " Ser2="); mon.println(cnt2); mon.lastKeyIn = ':'; sm.enter(smCheckRB); } unsigned char tmpCharBuf[32]; void smReadAllRB() { int nrIn; if(sm.userVar == 1) { nrIn = crb1.getAll(tmpCharBuf); mon.print((char *) "In(1)={"); } else { nrIn = crb2.getAll(tmpCharBuf); mon.print((char *) "In(2)={"); } if(nrIn > 32) nrIn = 32; mon.print(tmpCharBuf,nrIn,','); mon.cprintln('}'); if(sm.userVar == 2) { mon.lastKeyIn = ':'; sm.enter(smCheckRB); } else sm.userVar++; } char smWrStNr; void smWriteStrRB() { if(sm.firstEnter()) { mon.print((char *) "String (Endezeichen TAB) eingeben für Puffer "); } if(mon.lastKeyIn == ':') return; if(sm.userVar < 1) { if(mon.lastKeyIn < '1' || mon.lastKeyIn > '2') return; smWrStNr = mon.lastKeyIn; mon.cprint(smWrStNr); mon.cprint(':'); mon.cprint(' '); sm.userVar++; mon.lastKeyIn = ':'; return; } if(mon.lastKeyIn != '\t') { tmpCharBuf[sm.userVar - 1] = mon.lastKeyIn; mon.cprint(mon.lastKeyIn); sm.userVar++; mon.lastKeyIn = ':'; return; } tmpCharBuf[sm.userVar - 1] = '\0'; if(smWrStNr == '1') crb1.putStr((char *) tmpCharBuf); else if(smWrStNr == '2') crb2.putStr((char *) tmpCharBuf); mon.println(); mon.lastKeyIn = ':'; sm.enter(smCheckRB); } #endif // DebugTerminal