eRTK
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros
uart.c
Go to the documentation of this file.
1 /*
2  * uart.c
3  *
4  * Created: 04.05.2015 15:52:33
5  * Author: er
6  */
7 #include <avr/interrupt.h>
8 #include "eRTK.h"
9 #include "uart.h"
10 
11 #ifdef UART0_BAUD
12 static volatile uint8_t rx_buf0[RX0_SIZE];
13 static volatile uint8_t rx_in0, rx_out0;
14 static uint8_t tx_buff0[TX0_SIZE];
15 static volatile uint8_t tx_in0, tx_out0;
16 static uint8_t rxtid0; //task id die hier lesend wartet
17 static uint8_t nrx0; //anzahl an zeichen auf die gewartet wird
18 static uint8_t txtid0; //task id die hier schreibend wartet
19 #endif
20 
21 #ifdef UART1_BAUD
22 static volatile uint8_t rx_buf1[RX1_SIZE];
23 static volatile uint8_t rx_in1, rx_out1;
24 static uint8_t tx_buff1[TX1_SIZE];
25 static volatile uint8_t tx_in1, tx_out1;
26 static uint8_t rxtid1; //task id die hier lesend wartet
27 static uint8_t nrx1; //anzahl an zeichen auf die gewartet wird
28 static uint8_t txtid1; //task id die hier schreibend wartet
29 #endif
30 
31 #ifdef UART2_BAUD
32 static volatile uint8_t rx_buf2[RX2_SIZE];
33 static volatile uint8_t rx_in2, rx_out2;
34 static uint8_t tx_buff2[TX2_SIZE];
35 static volatile uint8_t tx_in2, tx_out2;
36 static uint8_t rxtid2; //task id die hier lesend wartet
37 static uint8_t nrx2; //anzahl an zeichen auf die gewartet wird
38 static uint8_t txtid2; //task id die hier schreibend wartet
39 #endif
40 
41 #ifdef UART3_BAUD
42 static volatile uint8_t rx_buf3[RX0_SIZE];
43 static volatile uint8_t rx_in3, rx_out3;
44 static uint8_t tx_buff3[TX3_SIZE];
45 static volatile uint8_t tx_in3, tx_out3;
46 static uint8_t rxtid3; //task id die hier lesend wartet
47 static uint8_t nrx3; //anzahl an zeichen auf die gewartet wird
48 static uint8_t txtid3; //task id die hier schreibend wartet
49 #endif
50 
51 tUART open( tUART port ) {
52  eRTK_get_sema( port );
53  switch( port ) {
54 #ifdef UART0_BAUD
55  case UART0: {
56  UBRR0H = ( UBRR0_VAL>>8 );
57  UBRR0L = UBRR0_VAL; //set baud rate
58  UCSR0A = 0; //no U2X, MPCM
59  UCSR0C = ( 1<<UCSZ01 )^( 1<<UCSZ00 )^( 1<<USBS0 )^( 0<<UPM01 )^( 0<<UPM00 ); // 8 Bit, no parity
60  UCSR0B = ( 1<<RXEN0 )^( 1<<TXEN0 )^( 1<<RXCIE0 ); // enable RX, TX, RX interrupt
61  rx_in0=rx_out0=0; // set rx buffer empty
62  break;
63  }
64 #endif
65 #ifdef UART1_BAUD
66  case UART1: {
67  UBRR1H = ( UBRR1_VAL>>8 );
68  UBRR1L = UBRR1_VAL; //set baud rate
69  UCSR1A = 0; //no U2X, MPCM
70  UCSR1C = ( 1<<UCSZ11 )^( 1<<UCSZ10 )^( 1<<USBS1 )^( 0<<UPM11 )^( 0<<UPM10 ); // 8 Bit, no parity
71  UCSR1B = ( 1<<RXEN1 )^( 1<<TXEN1 )^( 1<<RXCIE1 ); // enable RX, TX, RX interrupt
72  rx_in1=rx_out1=0; // set rx buffer empty
73  break;
74  }
75 #endif
76 #ifdef UART2_BAUD
77  case UART2: {
78  UBRR2H = ( UBRR2_VAL>>8 );
79  UBRR2L = UBRR2_VAL; //set baud rate
80  UCSR2A = 0; //no U2X, MPCM
81  UCSR2C = ( 1<<UCSZ21 )^( 1<<UCSZ20 )^( 1<<USBS2 )^( 0<<UPM21 )^( 0<<UPM20 ); // 8 Bit, no parity
82  UCSR2B = ( 1<<RXEN2 )^( 1<<TXEN2 )^( 1<<RXCIE2 ); // enable RX, TX, RX interrupt
83  rx_in2=rx_out2=0; // set rx buffer empty
84  break;
85  }
86 #endif
87 #ifdef UART3_BAUD
88  case UART3: {
89  UBRR3H = ( UBRR3_VAL>>8 );
90  UBRR3L = UBRR3_VAL; //set baud rate
91  UCSR3A = 0; //no U2X, MPCM
92  UCSR3C = ( 1<<UCSZ31 )^( 1<<UCSZ30 )^( 1<<USBS3 )^( 0<<UPM31 )^( 0<<UPM30 ); // 8 Bit, no parity
93  UCSR3B = ( 1<<RXEN3 )^( 1<<TXEN3 )^( 1<<RXCIE3 ); // enable RX, TX, RX interrupt
94  rx_in3=rx_out3=0; // set rx buffer empty
95  break;
96  }
97 #endif
98  default: deadbeef( SYS_UNKNOWN );
99  }
100  return port;
101  }
102 
103 #ifdef UART0_BAUD
104 ISR( USART0_RX_vect ) { //uart hat ein neues zeichen
105  oIDLE( 0 );
106  if( nrx0 ) { //es soll ein event erzeugt werden nach nrx0 zeichen
107  if( !--nrx0 ) {
108  if( rxtid0 ) {
109  eRTK_SetReady( rxtid0 ); //task hat genug input
110  rxtid0=0;
111  }
112  }
113  }
114  uint8_t i = rx_in0;
115  ROLLOVER( i, RX0_SIZE );
116  if( i == rx_out0 ) { //buffer overflow
117  UCSR0B&=~( 1<<RXCIE0 ); //disable RX interrupt
118  return; //discard char
119  }
120  rx_buf0[rx_in0] = UDR0; //speichere im ringbuffer
121  rx_in0 = i;
122  }
123 
124 ISR( USART0_UDRE_vect ) { //uart will naechstes zeichen senden
125  oIDLE( 0 );
126  if( tx_in0==tx_out0 ) { //nothing to send
127  if( txtid0 ) {
128  eRTK_SetReady( txtid0 ); //set task ready
129  txtid0=0;
130  }
131  UCSR0B&=~( 1<<UDRIE0 ); //disable TX interrupt
132  return;
133  }
134  UDR0 = tx_buff0[tx_out0]; //zeichen aus ringbuffer auslesen
135  ROLLOVER( tx_out0, TX0_SIZE );
136  }
137 #endif
138 
139 #ifdef UART1_BAUD
140 ISR( USART1_RX_vect ) { //uart hat ein neues zeichen
141  oIDLE( 0 );
142  if( nrx1 ) { //es soll ein event erzeugt werden nach nrx1 zeichen
143  if( !--nrx1 ) {
144  if( rxtid1 ) {
145  eRTK_SetReady( rxtid1 ); //task hat genug input
146  rxtid1=0;
147  }
148  }
149  }
150  uint8_t i = rx_in1;
151  ROLLOVER( i, RX1_SIZE );
152  if( i == rx_out1 ) { //buffer overflow
153  UCSR1B&=~( 1<<RXCIE1 ); //disable RX interrupt
154  return; //discard char
155  }
156  rx_buf1[rx_in1] = UDR1; //speichere im ringbuffer
157  rx_in1 = i;
158  }
159 
160 ISR( USART1_UDRE_vect ) { //uart will naechstes zeichen senden
161  oIDLE( 0 );
162  if( tx_in1==tx_out1 ) { //nothing to send
163  if( txtid1 ) {
164  eRTK_SetReady( txtid1 ); //set task ready
165  txtid1=0;
166  }
167  UCSR1B&=~( 1<<UDRIE1 ); //disable TX interrupt
168  return;
169  }
170  UDR1 = tx_buff1[tx_out1]; //zeichen aus ringbuffer auslesen
171  ROLLOVER( tx_out1, TX1_SIZE );
172  }
173 #endif
174 
175 #ifdef UART2_BAUD
176 ISR( USART2_RX_vect ) { //uart hat ein neues zeichen
177  oIDLE( 0 );
178  if( nrx2 ) { //es soll ein event erzeugt werden nach nrx2 zeichen
179  if( !--nrx2 ) {
180  if( rxtid2 ) {
181  eRTK_SetReady( rxtid2 ); //task hat genug input
182  rxtid2=0;
183  }
184  }
185  }
186  uint8_t i = rx_in2;
187  ROLLOVER( i, RX2_SIZE );
188  if( i == rx_out2 ) { //buffer overflow
189  UCSR2B&=~( 1<<RXCIE2 ); //disable RX interrupt
190  return; //discard char
191  }
192  rx_buf2[rx_in2] = UDR2; //speichere im ringbuffer
193  rx_in2 = i;
194  }
195 
196 ISR( USART2_UDRE_vect ) { //uart will naechstes zeichen senden
197  oIDLE( 0 );
198  if( tx_in2==tx_out2 ) { //nothing to send
199  if( txtid2 ) {
200  eRTK_SetReady( txtid2 ); //set task ready
201  txtid2=0;
202  }
203  UCSR2B&=~( 1<<UDRIE2 ); //disable TX interrupt
204  return;
205  }
206  UDR2 = tx_buff2[tx_out2]; //zeichen aus ringbuffer auslesen
207  ROLLOVER( tx_out2, TX2_SIZE );
208  }
209 #endif
210 
211 #ifdef UART3_BAUD
212 ISR( USART3_RX_vect ) { //uart hat ein neues zeichen
213  oIDLE( 0 );
214  if( nrx3 ) { //es soll ein event erzeugt werden nach nrx3 zeichen
215  if( !--nrx3 ) {
216  if( rxtid3 ) {
217  eRTK_SetReady( rxtid3 ); //task hat genug input
218  rxtid3=0;
219  }
220  }
221  }
222  uint8_t i = rx_in3;
223  ROLLOVER( i, RX3_SIZE );
224  if( i == rx_out3 ) { //buffer overflow
225  UCSR3B&=~( 1<<RXCIE3 ); //disable RX interrupt
226  return; //discard char
227  }
228  rx_buf3[rx_in3] = UDR3; //speichere im ringbuffer
229  rx_in3 = i;
230  }
231 
232 ISR( USART3_UDRE_vect ) { //uart will naechstes zeichen senden
233  oIDLE( 0 );
234  if( tx_in3==tx_out3 ) { //nothing to send
235  if( txtid3 ) {
236  eRTK_SetReady( txtid3 ); //set task ready
237  txtid3=0;
238  }
239  UCSR3B&=~( 1<<UDRIE3 ); //disable TX interrupt
240  return;
241  }
242  UDR3 = tx_buff3[tx_out3]; //zeichen aus ringbuffer auslesen
243  ROLLOVER( tx_out3, TX3_SIZE );
244  }
245 #endif
246 
247 //read liest am port maximal nbytes zeichen in den puffer ein und wartet maximal timeout ms
248 //read gibt die anzahl eingelesener zeicehn im puffer zurueck
249 uint8_t read( tUART port, void * puffer, uint8_t nbytes, uint8_t timeout ) {
250  register uint8_t anz=0;
251  switch( port ) {
252 #ifdef UART0_BAUD
253  case UART0: {
254  if( puffer==NULL ) { //clear buffer
255  rx_in0=rx_out0;
256  return 0;
257  }
258  UCSR0B|=( 1<<RXCIE0 ); //enable RX interrupt
259  while( anz<nbytes ) { //bis genug im puffer steht
260  if( rx_in0!=rx_out0 ) { //puffer auslesen wenn zeichen vorhanden sind
261  *( uint8_t * )puffer++=rx_buf0[rx_out0];
262  ROLLOVER( rx_out0, RX0_SIZE );
263  ++anz;
264  }
265  else { //auf neue zeichen warten
266  if( timeout ) { //wenn ein timeout angegeben wurde
267  ATOMIC_BLOCK( ATOMIC_RESTORESTATE ) {
268  rxtid0=eRTK_GetTid();
269  nrx0=nbytes-anz;
270  eRTK_wefet( timeout );
271  rxtid0=0;
272  }
273  timeout=0;
274  }
275  else break;
276  }
277  }
278  break;
279  }
280 #endif
281 #ifdef UART1_BAUD
282  case UART1: {
283  if( puffer==NULL ) { //clear buffer
284  rx_in1=rx_out1;
285  return 0;
286  }
287  UCSR1B|=( 1<<RXCIE1 ); //enable RX interrupt
288  while( anz<nbytes ) { //bis genug im puffer steht
289  if( rx_in1!=rx_out1 ) { //puffer auslesen wenn zeichen vorhanden sind
290  *( uint8_t * )puffer++=rx_buf1[rx_out1];
291  ROLLOVER( rx_out1, RX1_SIZE );
292  ++anz;
293  }
294  else { //auf neue zeichen warten
295  if( timeout ) { //wenn ein timeout angegeben wurde
296  ATOMIC_BLOCK( ATOMIC_RESTORESTATE ) {
297  rxtid1=eRTK_GetTid();
298  nrx1=nbytes-anz;
299  eRTK_wefet( timeout );
300  rxtid1=0;
301  }
302  timeout=0;
303  }
304  else break;
305  }
306  }
307  break;
308  }
309 #endif
310 #ifdef UART2_BAUD
311  case UART2: {
312  if( puffer==NULL ) { //clear buffer
313  rx_in2=rx_out2;
314  return 0;
315  }
316  UCSR2B|=( 1<<RXCIE2 ); //enable RX interrupt
317  while( anz<nbytes ) { //bis genug im puffer steht
318  if( rx_in2!=rx_out2 ) { //puffer auslesen wenn zeichen vorhanden sind
319  *( uint8_t * )puffer++=rx_buf2[rx_out2];
320  ROLLOVER( rx_out2, RX2_SIZE );
321  ++anz;
322  }
323  else { //auf neue zeichen warten
324  if( timeout ) { //wenn ein timeout angegeben wurde
325  ATOMIC_BLOCK( ATOMIC_RESTORESTATE ) {
326  rxtid2=eRTK_GetTid();
327  nrx2=nbytes-anz;
328  eRTK_wefet( timeout );
329  rxtid2=0;
330  }
331  timeout=0;
332  }
333  else break;
334  }
335  }
336  break;
337  }
338 #endif
339 #ifdef UART3_BAUD
340  case UART3: {
341  if( puffer==NULL ) { //clear buffer
342  rx_in3=rx_out3;
343  return 0;
344  }
345  UCSR3B|=( 1<<RXCIE3 ); //enable RX interrupt
346  while( anz<nbytes ) { //bis genug im puffer steht
347  if( rx_in3!=rx_out3 ) { //puffer auslesen wenn zeichen vorhanden sind
348  *( uint8_t * )puffer++=rx_buf3[rx_out3];
349  ROLLOVER( rx_out3, RX3_SIZE );
350  ++anz;
351  }
352  else { //auf neue zeichen warten
353  if( timeout ) { //wenn ein timeout angegeben wurde
354  ATOMIC_BLOCK( ATOMIC_RESTORESTATE ) {
355  rxtid3=eRTK_GetTid();
356  nrx3=nbytes-anz;
357  eRTK_wefet( timeout );
358  rxtid3=0;
359  }
360  timeout=0;
361  }
362  else break;
363  }
364  }
365  break;
366  }
367 #endif
368  default: deadbeef( SYS_UNKNOWN );
369  }
370  return anz;
371  }
372 
373 void write( tUART port, void * puffer, uint8_t nbytes ) {
374  switch( port ) {
375 #ifdef UART0_BAUD
376  case( UART0 ): {
377  while( nbytes-- ) {
378  while( 1 ) { //notfalls warte bis der sendepuffer ein zeichen fassen kann
379  register uint8_t i=tx_in0;
380  ROLLOVER( i, TX0_SIZE );
381  if( i!=tx_out0 ) break; //noch platz im sendepuffer
382  ATOMIC_BLOCK( ATOMIC_RESTORESTATE ) {
383  UCSR0B|=( 1<<UDRIE0 ); //sonst sende interrupt wieder einschalten
384  txtid0=eRTK_GetTid(); //damit wir nicht aktiv warten
385  eRTK_SetSuspended( txtid0 );
386  eRTK_scheduler();
387  }
388  }
389  tx_buff0[tx_in0] = *( uint8_t * )puffer++;
390  ROLLOVER( tx_in0, TX0_SIZE );
391  UCSR0B|=( 1<<UDRIE0 ); //sende interrupt einschalten
392  }
393  break;
394  }
395 #endif
396 #ifdef UART1_BAUD
397  case( UART1 ): {
398  while( nbytes-- ) {
399  while( 1 ) { //notfalls warte bis der sendepuffer ein zeichen fassen kann
400  register uint8_t i=tx_in1;
401  ROLLOVER( i, TX1_SIZE );
402  if( i!=tx_out1 ) break; //noch platz im sendepuffer
403  ATOMIC_BLOCK( ATOMIC_RESTORESTATE ) {
404  UCSR1B|=( 1<<UDRIE1 ); //sonst sende interrupt wieder einschalten
405  txtid1=eRTK_GetTid(); //damit wir nicht aktiv warten
406  eRTK_SetSuspended( txtid1 );
407  eRTK_scheduler();
408  }
409  }
410  tx_buff1[tx_in1] = *( uint8_t * )puffer++;
411  ROLLOVER( tx_in1, TX1_SIZE );
412  UCSR1B|=( 1<<UDRIE1 ); //sende interrupt einschalten
413  }
414  break;
415  }
416 #endif
417 #ifdef UART2_BAUD
418  case( UART2 ): {
419  while( nbytes-- ) {
420  while( 1 ) { //notfalls warte bis der sendepuffer ein zeichen fassen kann
421  register uint8_t i=tx_in2;
422  ROLLOVER( i, TX2_SIZE );
423  if( i!=tx_out2 ) break; //noch platz im sendepuffer
424  ATOMIC_BLOCK( ATOMIC_RESTORESTATE ) {
425  UCSR2B|=( 1<<UDRIE2 ); //sonst sende interrupt wieder einschalten
426  txtid2=eRTK_GetTid(); //damit wir nicht aktiv warten
427  eRTK_SetSuspended( txtid2 );
428  eRTK_scheduler();
429  }
430  }
431  tx_buff2[tx_in2] = *( uint8_t * )puffer++;
432  ROLLOVER( tx_in2, TX2_SIZE );
433  UCSR2B|=( 1<<UDRIE2 ); //sende interrupt einschalten
434  }
435  break;
436  }
437 #endif
438 #ifdef UART3_BAUD
439  case( UART3 ): {
440  while( nbytes-- ) {
441  while( 1 ) { //notfalls warte bis der sendepuffer ein zeichen fassen kann
442  register uint8_t i=tx_in3;
443  ROLLOVER( i, TX3_SIZE );
444  if( i!=tx_out3 ) break; //noch platz im sendepuffer
445  ATOMIC_BLOCK( ATOMIC_RESTORESTATE ) {
446  UCSR3B|=( 1<<UDRIE3 ); //sonst sende interrupt wieder einschalten
447  txtid3=eRTK_GetTid(); //damit wir nicht aktiv warten
448  eRTK_SetSuspended( txtid3 );
449  eRTK_scheduler();
450  }
451  }
452  tx_buff3[tx_in3] = *( uint8_t * )puffer++;
453  ROLLOVER( tx_in3, TX3_SIZE );
454  UCSR3B|=( 1<<UDRIE3 ); //sende interrupt einschalten
455  }
456  break;
457  }
458 #endif
459  default: deadbeef( SYS_UNKNOWN );
460  }
461  }
462 
#define RX0_SIZE
Definition: uart.h:24
#define RX1_SIZE
Definition: uart.h:36
tUART
Definition: uart.h:68
Definition: uart.h:76
uint8_t eRTK_GetTid(void)
Definition: eRTK.c:233
#define UBRR2_VAL
Definition: uart.h:49
void eRTK_wefet(uint8_t timeout)
Definition: eRTK.c:269
#define TX3_SIZE
Definition: uart.h:59
void eRTK_get_sema(uint8_t semaid)
Definition: eRTK.c:309
#define UBRR1_VAL
Definition: uart.h:38
ISR(USART0_RX_vect)
Definition: uart.c:104
Definition: uart.h:73
void write(tUART port, void *puffer, uint8_t nbytes)
Definition: uart.c:373
#define TX1_SIZE
Definition: uart.h:37
Definition: uart.h:79
#define oIDLE(a)
Definition: eRTK.h:41
#define TX2_SIZE
Definition: uart.h:48
#define ROLLOVER(x, max)
Definition: uart.h:21
#define UBRR3_VAL
Definition: uart.h:60
void eRTK_SetReady(uint8_t tid)
Definition: eRTK.c:238
void deadbeef(tsys reason)
void eRTK_SetSuspended(uint8_t tid)
Definition: eRTK.c:255
uint8_t read(tUART port, void *puffer, uint8_t nbytes, uint8_t timeout)
Definition: uart.c:249
#define RX3_SIZE
Definition: uart.h:58
tUART open(tUART port)
Definition: uart.c:51
#define RX2_SIZE
Definition: uart.h:47
Definition: uart.h:70
#define UBRR0_VAL
Definition: uart.h:26
#define TX0_SIZE
Definition: uart.h:25