12.10.2011 - Verwendung binärer Semaphoren
(EN google-translate)
(PL google-translate)
Theoretischer Teil: RTOS Grundlagen (Fortsetzung Kapitel 2 Salvo-Manual)
|
Übung
Schreiben Sie ein Programm mit drei Tasks:
|
Lexikon
Englischer Begriff | Direkte Übersetzung (im Sinne von RTOS) | Erläuterungen |
---|---|---|
Reentrancy | Eintrittsinvarianz (von Funktionen) | Wird eine Funktion während sie läuft an anderer Stelle aufgerufen, korrumpiert das nicht ihre Ausführung. |
to signal | melden | to signal a semaphore: Ereignis, das eine Semaphore in ihrem Zustand ändert. |
task control block pointer(tcb p) | Zeiger auf einen Scheduler internen Task-Steuerungs-Block | ...der eine Funktion über einen Zeiger als Task zugeordnet werden kann. |
Tabelle 0-1: Lexikon zentraler Begriffe im Zusammenhang mit RTOS
Verständnisfragen / Themen
|
Lösungsbeispiel
/************************************************************ Programmidee: Ein schneller Prozess prüft ständig, ob die Taster PB0 oder PB1 gedrückt werden und inkrementiert, bzw. dekrementiert einen Zähler "zaehler" Wenn dies geschieht, bekommt eine binäre Semaphore ein Signal. Auf die Semaphore wartet ein zweiter Prozeß, der den Zählerstand über die serielle Schnittstelle an das Hyperterminal schickt. Ein dritter Prozess erzeugt ständig einen Ton von 500Hz. ************************************************************/ #include <salvo.h> extern void board_init ( void ); extern void board_enable_interrupt ( void ); #define TASK_TASTER_P OSTCBP(1) // task #1 #define TASK_RS232_P OSTCBP(2) // "" #2 #define TASK_BLINK_P OSTCBP(3) // "" #3 #define PRIO_TASTER 6 // task priorities #define PRIO_RS232 10 // "" #define PRIO_BLINK 4 // "" #define BINSEM_UPDATE_PORT_P OSECBP(1) // binSem #1 //Definition von Taktfrequenz und Bausrate als Konstanten #define TAKTFREQUENZ 9216000 #define BAUDRATE 115200 volatile unsigned char zaehler; volatile unsigned char taster; volatile unsigned char zustand; void TaskRS232(void) { unsigned char l,m,r; //Variablen für Anzeige links, mitte, rechts unsigned char akku=0; DDRC = 255; //Merken des in UBRR zu speichernden Wertes. unsigned int baudregister = TAKTFREQUENZ/8/BAUDRATE-1; //setzen der Baudrate UBRRH = (unsigned char) (baudregister>>8); //Setzen des HIGH-Bytes des Baudraten-Registers UBRRL = (unsigned char) baudregister; //Setzen des LOW -Bytes des Baudraten-Registers //Einschalten des Senders und des Empfängers UCSRB = (1<<TXEN) | (1<<RXEN); //Setzen des Nachrichtenformats: 8 Datenbits, 1 Stopbits UCSRC = (1<<URSEL)|(1<<UCSZ0)|(1<<UCSZ1); UCSRA = (1<<U2X); while (1) { //Weiterer Durchlauf, nur wenn binäre Semaphore ein Signal erhalten hat: OS_WaitBinSem(BINSEM_UPDATE_PORT_P, OSNO_TIMEOUT); akku = zaehler; //Zahl außerdem wie gewohnt nach Port C schicken: PORTC = akku; OS_Yield(); l= akku / 100; //links = Inhalt von akku dividiert mit 100 OS_Yield(); m= (akku % 100) / 10; //mitte = Inhalt von akku modulo mit 100 , anschließend dividiert mit 10 OS_Yield(); r= akku % 10; //rechts = Inhalt von akku modulo mit 10 //Die drei Ziffern der aktuellen Zahl werden in ASCII-Zeichen umgewandelt //und mit UDR = ... seriell gesendet. //Dann muß gewartet werden, bis das Senden beendet ist. //Es folgen ein Zeilenumbruch und ein Zurücksetzen des Cursers auf den //Zeilenanfang: while( !(UCSRA & (1<<UDRE)) ) //Warten bis der Uebertragungspuffer leer ist OS_Yield(); UDR = l+48; //Daten in den Puffer schreiben und übertragen while( !(UCSRA & (1<<UDRE)) ) OS_Yield(); UDR = m+48; while( !(UCSRA & (1<<UDRE)) ) OS_Yield(); UDR = r+48; while( !(UCSRA & (1<<UDRE)) ) OS_Yield(); UDR = '\n'; while( !(UCSRA & (1<<UDRE)) ) OS_Yield(); UDR = '\r'; } // Context-switch, damit der andere Task laufen kann. OS_Yield(); } void TaskBlink(void) { //PD7 als Beeper benutzen: DDRD = 0b10000000; PORTD = 0b00000000; while (1) { // Toggle PORTD:0 PORTD ^= 0b10000000; //EXOR // Context-switch für 1 tick. OS_Delay(1); } } void TaskTaster(void) { //Zähler initialiseren. zaehler = 0; taster = 0; zustand = 0; DDRB &= 0b11111100; while (1) { taster = PINB; taster &=0b00000011; if(zustand!=1 && taster==1) { zustand = 1; zaehler++; OSSignalBinSem(BINSEM_UPDATE_PORT_P); OS_Delay(5); } if(zustand!=2 && taster==2) { zustand = 2; zaehler--; OSSignalBinSem(BINSEM_UPDATE_PORT_P); OS_Delay(5); } if(taster==0) { zustand = 0; OS_Delay(5); } OS_Yield(); } } int main (void) { //Hardware abhängige Initialisierung. board_init(); //Salvo initialisieren. OSInit(); //Erzeugen von Salvo Tasks. OSCreateTask(TaskTaster, TASK_TASTER_P, PRIO_TASTER); OSCreateTask(TaskRS232, TASK_RS232_P, PRIO_RS232 ); OSCreateTask(TaskBlink, TASK_BLINK_P, PRIO_BLINK); //Erzeugen von Salvo Events. OSCreateBinSem(BINSEM_UPDATE_PORT_P, 0); //Interrupts aktivieren wg. Scheduler bzw. Timer 1. board_enable_interrupt(); //Scheduler / Multitasking starten. while (1) { OSSched(); } return 0; }
Code 0-1: Lösungsbeispiel zu der Übung mit binärer Semaphore.