eRTK
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros
main.c
Go to the documentation of this file.
1 /*
2  * main.c
3  *
4  * Created: 04.05.2015 07:54:15
5  * Author: er
6  */
7 
8 /*
9  Dies ist ein Beispiel der Anwendung und ein Test des Betriebssystems.
10  Es werden 5 Tasks definiert, eine mit hoher Prioritaet und 4 mit niedrigerer Prioritaet.
11  Die Task mit hoher Prio macht nichts anderes als zyklisch alle 10ms wieder zu starten,
12  in der Zwischenzeit suspendiert sie sich.
13  Wenn man damit z.B. einen Portpin toggelt kann man den Jitter des erreichbaren Echtzeitverhaltens prüfen.
14  Es sollten weniger als etwa 100 CPU Zyklen also bei 16MHz Takt 100/16 us Jitter erreichbar sein.
15  Die anderen 4 Tasks nutzen den selben Code (code sharing) lediglich eine Variable indiziert die Instanz der Task
16  welche aktuell laeuft, dies wird gleichzeitig in den Datenfeldern als Index genutzt.
17  Initial wird ueber den Startparameter param0 dieser Index uebergeben.
18  Zusammengefasst:
19  tskHighPrio wird alle 10ms kurz aktiv und beendet sich gleich wieder.
20  tskUART startet viermal, jede Instanz nimmt sich einen seriellen Port (UART)
21  und sendet 1..n Zeichen, wenn eine Verbindung Rx<->Tx existiert wird auch etwas empfangen.
22  Ansonsten entstehen time outs beim Warten auf die Zeichen.
23  Diese Prozesse bestehen aus kurzen Phasen von CPU Aktivitaet und relativ langen Wartezeiten auf die Peripherie.
24  Wenn das alles abgearbeitet ist wird die restliche CPU Zeit in der Idle Task verbracht.
25  Hier kommen die perfcounter ins Spiel.
26  Die Idle Task enthaelt eine Anzeige fuer die CPU Restzeit,
27  also wieviel Anteil die Summe aller Tasks von der verfügbaren Rechenzeit nimmt.
28  Im Leerlauf -> 1000
29  Bei 50% Last -> 500
30  Überlast -> 0
31 
32  Mit diesem Beispiel erreiche ich um 930 Zaehler, also etwa 7% der Zeit ist die CPU in den Tasks unterwegs,
33  der Rest ist Leerlauf.
34  Das bei einer Interruptbelastung von 1000Hz vom Systemtimer und 8 seriellen Sende- und Empfangsinterrupts
35  mit jeweils 2000Hz bei 19200Bd und 3x1000Hz bei 9600Bd ein gutes Ergebnis !
36 
37  14.05.2005 T. Erdmann t-erdmann@web.de
38 */
39 
40 #include <avr/io.h>
41 #include <stdio.h>
42 #include "eRTK.h"
43 #include "uart.h"
44 #include "adc.h"
45 
46 void tskHighPrio( uint16_t param0, void *param1 ) { //prio ist 20
47  while( 1 ) { //kurze aktivitaet auf prio 20 muss alles auf prio 10 sofort unterbrechen
48  eRTK_Sleep_ms( 10 );
49  }
50  }
51 
52 //tskUART wird viermal gestartet, param0 ist 0..3
53 //es wird derselbe programm code genutzt, anhand des param0 wird UART0..UART3 in jeder task genutzt
54 //und 1 byte, 16 byte == sendepuffergroesse oder 20 byte gesendet und wieder zurueckgelesen
55 //also eine sog. loop back gemacht.
56 //wird nichts empfangen so gibt es time outs.
57 //wird alles empfangen so geht es unverzueglich weiter in der schleife.
58 //ist gedacht als belastungstest der taskwechselmechanismen und datenstrukturen.
59 void tskUART( uint16_t param0, void *param1 ) { //prio ist 10
60  while( 1 ) { //com test
61  char buffer[50];
62  uint8_t rec;
63  tUART h=open( UART0+param0 ); //das klappt weil UART0+1=UART1, usw.
64  while( h ) { //bei einer loop back verbindung wird RX mit TX verbunden und es laeuft ohne time out
65  read( h, NULL, 0, 0 ); //clear rx buffer
66  write( h, "1", 1 ); //schreibe ein zeichen auf die leitung
67  rec=read( h, buffer, 1, 100 ); //lies ein zeichen mit 100ms time out
68  write( h, "abcdef", 6 );
69  rec=read( h, buffer, 6, 100 );
70  write( h, "0123456789ABCDEFGHIJ", 20 ); //hier ist der auszugebende string laenger als der interne puffer, es kommt ein spezieller mechanismus zum tragen, der abwartet bis der sendepuffer leer ist
71  rec=read( h, buffer, 16, 100 ); //hier muss timeout entstehen da der empfangspuffer nur auf 16 zeichen eingestellt ist und wir nicht rechtzeitig auslesen koennen bevor ein overflow entsteht
72  }
73  }
74  }
75 
76 //sequenzer liste mit adc mux selektor und scaler fuer die messrate
78  { .mux=0, .ref=( 1<<REFS0 ), .scaler=10 }, //bei jedem 10ten lauf messen
79  { .mux=8, .ref=( 1<<REFS0 ), .scaler=1 } //bei jedem lauf messen
80  };
81 
82 void tskADC( uint16_t param0, void *param1 ) { //prio ist 15
83  while( 1 ) { //task wartet bis neue adc messung vorliegt, kanal 0 hat teiler 10 -> 1000/10=100ms datenrate
84  static char txt[10];
85  snprintf( txt, sizeof txt, "%u", adc_wait( 0 ) );
86  eRTK_Sleep_ms( 10 );
87  }
88  }
89 
91  //tid adresse prio p0 p1
92  /*1*/ { tskUART, 10, 0, "UART1" },
93  /*2*/ { tskUART, 10, 1, "UART2" },
94  /*3*/ { tskUART, 10, 2, "UART3" },
95  /*4*/ { tskUART, 10, 3, "UART4" },
96  /*5*/ { tskHighPrio, 20, 1, "highp" },
97  /*6*/ { tskADC, 15, 0, "adc" }
98  };
99 
100 int main( void ) {
101  eRTK_init();
102  eRTK_timer_init();
103  adc_init();
104  eRTK_go();
105  }
tUART
Definition: uart.h:68
void eRTK_go(void)
Definition: eRTK.c:151
void eRTK_Sleep_ms(uint16_t ms)
Definition: eRTK.c:280
void tskHighPrio(uint16_t param0, void *param1)
Definition: main.c:46
void tskADC(uint16_t param0, void *param1)
Definition: main.c:82
void tskUART(uint16_t param0, void *param1)
Definition: main.c:59
#define VANZTASK
Definition: eRTK.h:15
void eRTK_init(void)
Definition: eRTK.c:371
uint16_t adc_wait(uint8_t mux)
Definition: adc.c:139
void write(tUART port, void *puffer, uint8_t nbytes)
Definition: uart.c:373
#define ANZ_ADC
Definition: adc.h:18
tadc adc_cntrl[ANZ_ADC]
Definition: main.c:77
Definition: adc.h:19
void adc_init(void)
uint8_t read(tUART port, void *puffer, uint8_t nbytes, uint8_t timeout)
Definition: uart.c:249
void eRTK_timer_init(void)
Definition: eRTK.c:515
const t_eRTK_tcb rom_tcb[VANZTASK]
Definition: main.c:90
tUART open(tUART port)
Definition: uart.c:51
Definition: uart.h:70
uint8_t mux
Definition: adc.h:20
int main(void)
Definition: main.c:100