Hallo, hab mir mal das uC-OSII angeschaut und einen fast fertigen Port verwendet. Funktioniert an sich, nur gibt es Probleme, wenn ich z.B. UART0 implementiere. Zu Beginn der ISR erhöhe ich den Nesting-Counter und sichere die Register. Beim Beenden rufe ich OSIntExit auf, worauf das OS schaut, ob ein Taskswitch erforderlich ist. Die Register werden am Ende wieder zurückgesichert. Das Problem ist jetzt, dass komische Zeichen eintreffen, wenn ich schnell Daten an den UART sende. Wenn ich jede Sekunde 1-2 Bytes schicke, kein Problem. Hat vielleicht jemand Erfahrungen mit uC-OSII und kann mir evtl. helfen? Danke mfg Andreas
Hallo Andreas, ich verwende ebenfalls das uC-OS 2 und benutze folgenden Port: http://www.ee.lut.fi/staff/Julius.Luukko/ucos-ii/index.shtml Habe bisher nur sehr gute Erfahrungen mit dem OS gemacht, läuft absolut stabil. Als Basis für meine UART Routinen verwende ich // AVR306: Using the AVR UART in C // Routines for interrupt controlled UART Hier ist die Senderoutine .. für ATMega128 #if defined(_AVR_ATmega128_) // // Send Data in Buffer // UCOSISR (USART0_UDRE_vect) { PushRS(); OSIntNesting++; if (OSIntNesting == 1) OSTCBCur->OSTCBStkPtr = (OS_STK *)SP; // Check if all data is transmitted if ( UART_TxHead != UART_TxTail ) { // Calculate buffer index tmptail = ( UART_TxTail + 1 ) & UART_TX_BUFFER_MASK; UART_TxTail = tmptail; // Store new index UDR0 = UART_TxBuf[tmptail]; // Start transmission } else { UCSR0B &= ~(1<<UDRIE0); // Disable UDRIE interrupt } OSIntExit(); PopRS(); } #endif Bei Bedarf kann ich dir die Routinen komplett zuschicken. Die passen halt nur für die entsprechende Portierung Gruß Roland
Hallo Roland, vielen Dank für deinen Tipp. Ich glaube, über den Port bin ich auch schon mal gestolpert... Werde mir das mal anschauen und dann melde ich mich wieder. Hast du auch mal versucht, ein Event in UART-RX-Interrupt zu posten? Ich wollte damit anzeigen, dass neue Daten im Buffer sind, hatte aber genau das gleiche Problem, wie oben beschrieben. Mein Test-Task sieht folgendermaßen aus (Echo zurücksenden): void TASK2_Run(void * data) { // init the uart UART0_Init(BR_9600); /* The data is not used. */ data = data; for (;;) { while (UART0_DataAvailable()) { // we got a new char INT8U res = UART0_Read(); UART0_PutChar(res); } OSTimeDlyHMSM(0, 0, 0, 20); } } Danke mfg Andreas
Hallo Roland, habe jetzt den Port von dir verwendet, aber noch immer das gleiche Problem. Wenn ich viele Daten sende, dass hängt sich das OS auf. Muss weiter schauen, woran das liegen könnte. Kannst du mir vielleicht deine Portfiles geben, damit ich den Fehler eingrenzen kann. Danke. mfg Andreas
Hallo Andreas, natürlich soll sich die Task suspendieren, wenn keine Zeichen im Empfangspuffer vorhanden sind. D.h. getchar() legt sich mit einem OSSemPend(Uart0_RxSem, timeout, &err) schlafen. Die Empfangsinterrupt Routine informiert bzw. weckt via OSSemPost(Uart0_RxSem) die Task bzw. die Funktion getchar() auf. Die Task arbeitet dann solange bis der Puffer leer ist und legt sich wieder schlafen. Mann kann das auch mit Events lösen, diese sind aber mächtiger und deren zusätzlichen Möglichkeiten werden dafür nicht gebraucht. Das Abfragen mittels While Schleife kostet nur cpu Zeit und sind in einem RTOS fehl am Platz, eigentlich überall.. Dein UART0_DataAvailable() könnte sich ja suspendieren, nur dann ist dein OSTimeDlyHMSM(0, 0, 0, 20) überflüssig.. Beispiel für ein einfaches getchar(), ich gebe in der Praxis noch ein timeout mit, falls man nicht ewig warten kann, um eine Fehlersituation zu behandeln.. unsigned char uart_getchar( void ) { uint8_t tmptail, err; if (UART_RxHead == UART_RxTail) { // no data available, suspend Task data_cnt = 0; OSSemPend(Uart0_RxSem, 0, &err); } // Calculate buffer index tmptail = (UART_RxTail+1) & UART_RX_BUFFER_MASK; UART_RxTail = tmptail; // Store new index return UART_RxBuf[tmptail]; // Return data } und hier die zugehörige Interrupt Routine #if defined(_AVR_ATmega128_) UCOSISR (USART0_RX_vect) { PushRS(); OSIntNesting++; if (OSIntNesting == 1) OSTCBCur->OSTCBStkPtr = (OS_STK *)SP; data = UDR0; // Read the received data // Calculate buffer index tmphead = ( UART_RxHead + 1 ) & UART_RX_BUFFER_MASK; UART_RxHead = tmphead; // Store new index // tmphead == UART_RxTail -> Receive buffer overflow ! // hier kann man sich was nettes ausdenken, je nach Erforderniss.. UART_RxBuf[tmphead] = data; // Store received data in buffer data_cnt++; if (data_cnt == 1) OSSemPost(Uart0_RxSem); // Notify getchar() / calling Task OSIntExit(); PopRS(); } #endif Hoffe das hilft weiter, viel Erfolg! Gruß Roland
Hallo Andreas, nur zur Sicherheit, ich verwende nicht die Beta Portversion ! Sorry, hatte ich vergessen zu erwähnen, ist schon so lange her.. Ich verwende die Version 1, d.h. die "141003" mit bugfix für avr_isr.h Ist aber alles auf der Port Homepage beschrieben. Ich schicke dir auch gerne die Dateien, dazu benötige ich deine Email Adresse.. Gruß Roland
Hallo Roland, danke für die Tipps. Habe auch die 141003 Version mit Bugfix verwendet. Hast du noch was zusätzlich am Port geändert? Welche OS_CRITICAL_METHOD verwendest du? Habe zuerst 1, dann 3 verwendet. Im Port ist aber wieder 1. Das mit der while-Schleife habe ich nur zum Testen gemacht. Sollte ja auch funktionieren, oder? Ich werde den UART nochmal umbauen und mit OSSemPost versehen. In meinen ersten Versuchen habe ich Events verwendet. Email ist: andreas.oyrer@gmx.at Danke für die Hilfe. mfg Andreas
Hallo Andreas, ich verwende #define OS_CRITICAL_METHOD 1 Am Port habe ich ansonsten nichts verändert. Der OS-TICK ist bei mir OS_TICKS_PER_SEC 50. Ich habe lediglich die Anregung von Julius Luuko umgesetzt und den OSUnMapTbl[] in das Programm Flash verlegt. Jetzt kann ich mit einem ATMega32 ohne RAM-Platznot 5 Tasks laufen lassen. Ich schicke dir mal die Portroutinen und die UART Routinen. Gruß Roland
wie viel speicher (flash, ram) braucht uC-OS 2 auf einem atmel atmega128?
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.