]> git.sur5r.net Git - freertos/blob
5b00acca8c5fab837018c6fed45cd0fa1fd78649
[freertos] /
1 /*******************************************************************************\r
2  * (c) Copyright 2011-2013 Microsemi SoC Products Group.  All rights reserved.\r
3  *\r
4  * SmartFusion2 Microcontroller Subsystem MMUART bare metal software driver\r
5  * implementation.\r
6  *\r
7  * SVN $Revision: 5610 $\r
8  * SVN $Date: 2013-04-05 14:19:30 +0100 (Fri, 05 Apr 2013) $\r
9  */\r
10 #include "mss_uart.h"\r
11 #include "mss_uart_regs.h"\r
12 #include "../../CMSIS/mss_assert.h"\r
13 #include "../../CMSIS/hw_reg_io.h"\r
14 #include "../../CMSIS/system_m2sxxx.h"\r
15 \r
16 #ifdef __cplusplus\r
17 extern "C" {\r
18 #endif\r
19 \r
20 /*******************************************************************************\r
21  * Defines\r
22  */\r
23 #define TX_COMPLETE            0u\r
24 #define TX_FIFO_SIZE           16u\r
25 \r
26 #define FCR_TRIG_LEVEL_MASK    0xC0u\r
27 \r
28 #define IIRF_MASK              0x0Fu\r
29 \r
30 #define INVALID_INTERRUPT      0u\r
31 #define INVALID_IRQ_HANDLER    ((mss_uart_irq_handler_t) 0)\r
32 #define NULL_HANDLER           ((mss_uart_irq_handler_t) 0)\r
33 \r
34 #define MSS_UART_DATA_READY    ((uint8_t) 0x01)\r
35 \r
36 #define SYNC_ASYNC_MODE_MASK   (0x7u)\r
37 \r
38 /*******************************************************************************\r
39  * Possible values for Interrupt Identification Register Field.\r
40  */\r
41 #define IIRF_MODEM_STATUS   0x00u\r
42 #define IIRF_THRE           0x02u\r
43 #define IIRF_MMI            0x03u\r
44 #define IIRF_RX_DATA        0x04u\r
45 #define IIRF_RX_LINE_STATUS 0x06u\r
46 #define IIRF_DATA_TIMEOUT   0x0Cu\r
47 \r
48 /*******************************************************************************\r
49  * Receiver error status mask.\r
50  */\r
51 #define STATUS_ERROR_MASK    ( MSS_UART_OVERUN_ERROR | MSS_UART_PARITY_ERROR | \\r
52                                MSS_UART_FRAMING_ERROR  | MSS_UART_BREAK_ERROR | \\r
53                                MSS_UART_FIFO_ERROR)\r
54 \r
55 /*******************************************************************************\r
56  * Cortex-M3 interrupt handler functions implemented as part of the MSS UART\r
57  * driver.\r
58  */\r
59 #if defined(__GNUC__)\r
60 __attribute__((__interrupt__)) void UART0_IRQHandler(void);\r
61 #else\r
62 void UART0_IRQHandler(void);\r
63 #endif\r
64 \r
65 #if defined(__GNUC__)\r
66 __attribute__((__interrupt__)) void UART1_IRQHandler(void);\r
67 #else\r
68 void UART1_IRQHandler(void);\r
69 #endif\r
70 \r
71 /*******************************************************************************\r
72  * Local functions.\r
73  */\r
74 static void global_init(mss_uart_instance_t * this_uart, uint32_t baud_rate,\r
75                         uint8_t line_config);\r
76 static void MSS_UART_isr(mss_uart_instance_t * this_uart);\r
77 static void default_tx_handler(mss_uart_instance_t * this_uart);\r
78 \r
79 static void config_baud_divisors\r
80 (\r
81     mss_uart_instance_t * this_uart,\r
82     uint32_t baudrate\r
83 );\r
84 \r
85 /*******************************************************************************\r
86  * Instance definitions\r
87  */\r
88 mss_uart_instance_t g_mss_uart0;\r
89 mss_uart_instance_t g_mss_uart1;\r
90 \r
91 \r
92 /*******************************************************************************\r
93  * Public Functions\r
94  *******************************************************************************/\r
95 /***************************************************************************//**\r
96  * See mss_uart.h for details of how to use this function.\r
97  */\r
98 void\r
99 MSS_UART_init\r
100 (\r
101     mss_uart_instance_t* this_uart,\r
102     uint32_t baud_rate,\r
103     uint8_t line_config\r
104 )\r
105 {\r
106     /* The driver expects g_mss_uart0 and g_mss_uart1 to be the only\r
107      * mss_uart_instance_t instances used to identify UART0 and UART1. */\r
108     ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));\r
109 \r
110     /* Perform generic initialization */\r
111     global_init(this_uart, baud_rate, line_config);\r
112 \r
113     /* Disable LIN mode */\r
114     clear_bit_reg8(&this_uart->hw_reg->MM0, ELIN);\r
115 \r
116     /* Disable IrDA mode */\r
117     clear_bit_reg8(&this_uart->hw_reg->MM1, EIRD);\r
118 \r
119     /* Disable SmartCard Mode */\r
120     clear_bit_reg8(&this_uart->hw_reg->MM2, EERR);\r
121 \r
122     /* set default tx handler for automated TX using interrupt in USART mode */\r
123     this_uart->tx_handler = default_tx_handler;\r
124 }\r
125 \r
126 /***************************************************************************//**\r
127  * See mss_uart.h for details of how to use this function.\r
128  */\r
129 void MSS_UART_lin_init\r
130 (\r
131     mss_uart_instance_t* this_uart,\r
132     uint32_t baud_rate,\r
133     uint8_t line_config\r
134 )\r
135 {\r
136     /* The driver expects g_mss_uart0 and g_mss_uart1 to be the only\r
137      * mss_uart_instance_t instances used to identify UART0 and UART1. */\r
138     ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));\r
139 \r
140     /* Perform generic initialization */\r
141     global_init(this_uart, baud_rate, line_config);\r
142 \r
143      /* Enable LIN mode */\r
144     set_bit_reg8(&this_uart->hw_reg->MM0, ELIN);\r
145 \r
146     /* Disable IrDA mode */\r
147     clear_bit_reg8(&this_uart->hw_reg->MM1, EIRD);\r
148 \r
149     /* Disable SmartCard Mode */\r
150     clear_bit_reg8(&this_uart->hw_reg->MM2, EERR);\r
151 }\r
152 \r
153 /***************************************************************************//**\r
154  * See mss_uart.h for details of how to use this function.\r
155  */\r
156 void\r
157 MSS_UART_irda_init\r
158 (\r
159     mss_uart_instance_t* this_uart,\r
160     uint32_t baud_rate,\r
161     uint8_t line_config,\r
162     mss_uart_rzi_polarity_t rxpol,\r
163     mss_uart_rzi_polarity_t txpol,\r
164     mss_uart_rzi_pulsewidth_t pw\r
165 )\r
166 {\r
167     /* The driver expects g_mss_uart0 and g_mss_uart1 to be the only\r
168      * mss_uart_instance_t instances used to identify UART0 and UART1. */\r
169     ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));\r
170 \r
171     /* Perform generic initialization */\r
172     global_init(this_uart, baud_rate, line_config);\r
173 \r
174      /* Enable LIN mode */\r
175     clear_bit_reg8(&this_uart->hw_reg->MM0, ELIN);\r
176 \r
177     /* Disable IrDA mode */\r
178     set_bit_reg8(&this_uart->hw_reg->MM1, EIRD);\r
179     ((rxpol == MSS_UART_ACTIVE_LOW) ? clear_bit_reg8(&this_uart->hw_reg->MM1,EIRX) :\r
180                                       set_bit_reg8(&this_uart->hw_reg->MM1,EIRX));\r
181 \r
182     ((txpol == MSS_UART_ACTIVE_LOW) ? clear_bit_reg8(&this_uart->hw_reg->MM1,EITX) :\r
183                                       set_bit_reg8(&this_uart->hw_reg->MM1,EITX));\r
184 \r
185     ((pw == MSS_UART_3_BY_16) ? clear_bit_reg8(&this_uart->hw_reg->MM1,EITP) :\r
186                                       set_bit_reg8(&this_uart->hw_reg->MM1,EITP));\r
187     /* Disable SmartCard Mode */\r
188     clear_bit_reg8(&this_uart->hw_reg->MM2, EERR);\r
189 }\r
190 \r
191 /***************************************************************************//**\r
192  * See mss_uart.h for details of how to use this function.\r
193  */\r
194 void\r
195 MSS_UART_smartcard_init\r
196 (\r
197     mss_uart_instance_t* this_uart,\r
198     uint32_t baud_rate,\r
199     uint8_t line_config\r
200 )\r
201 {\r
202     /* The driver expects g_mss_uart0 and g_mss_uart1 to be the only\r
203      * mss_uart_instance_t instances used to identify UART0 and UART1. */\r
204     ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));\r
205 \r
206     /* Perform generic initialization */\r
207     global_init(this_uart, baud_rate, line_config);\r
208 \r
209     /* Disable LIN mode */\r
210     clear_bit_reg8(&this_uart->hw_reg->MM0, ELIN);\r
211 \r
212     /* Disable IrDA mode */\r
213     clear_bit_reg8(&this_uart->hw_reg->MM1, EIRD);\r
214 \r
215     /* Enable SmartCard Mode : Only when data is 8-bit and 2 stop bits*/\r
216     if( ( MSS_UART_DATA_8_BITS | MSS_UART_TWO_STOP_BITS) ==\r
217         (line_config & (MSS_UART_DATA_8_BITS | MSS_UART_TWO_STOP_BITS)))\r
218     {\r
219         set_bit_reg8(&this_uart->hw_reg->MM2, EERR);\r
220         /* Enable single wire half-duplex mode */\r
221         set_bit_reg8(&this_uart->hw_reg->MM2,ESWM);\r
222     }\r
223 }\r
224 \r
225 /***************************************************************************//**\r
226  * See mss_uart.h for details of how to use this function.\r
227  */\r
228 void\r
229 MSS_UART_polled_tx\r
230 (\r
231     mss_uart_instance_t * this_uart,\r
232     const uint8_t * pbuff,\r
233     uint32_t tx_size\r
234 )\r
235 {\r
236     uint32_t char_idx = 0u;\r
237     uint32_t size_sent;\r
238     uint8_t status;\r
239 \r
240     ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));\r
241     ASSERT(pbuff != ( (uint8_t *)0));\r
242     ASSERT(tx_size > 0u);\r
243 \r
244     if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&\r
245         (pbuff != ((uint8_t *)0)) && (tx_size > 0u))\r
246     {\r
247          /* Remain in this loop until the entire input buffer\r
248           * has been transferred to the UART.\r
249           */\r
250         do {\r
251             /* Read the Line Status Register and update the sticky record */\r
252             status = this_uart->hw_reg->LSR;\r
253             this_uart->status |= status;\r
254 \r
255             /* Check if TX FIFO is empty. */\r
256             if(status & MSS_UART_THRE)\r
257             {\r
258                 uint32_t fill_size = TX_FIFO_SIZE;\r
259 \r
260                 /* Calculate the number of bytes to transmit. */\r
261                 if(tx_size < TX_FIFO_SIZE)\r
262                 {\r
263                     fill_size = tx_size;\r
264                 }\r
265 \r
266                 /* Fill the TX FIFO with the calculated the number of bytes. */\r
267                 for(size_sent = 0u; size_sent < fill_size; ++size_sent)\r
268                 {\r
269                     /* Send next character in the buffer. */\r
270                     this_uart->hw_reg->THR = pbuff[char_idx];\r
271                     char_idx++;\r
272                 }\r
273 \r
274                 /* Calculate the number of untransmitted bytes remaining. */\r
275                 tx_size -= size_sent;\r
276             }\r
277         } while(tx_size);\r
278     }\r
279 }\r
280 \r
281 /***************************************************************************//**\r
282  * See mss_uart.h for details of how to use this function.\r
283  */\r
284 void\r
285 MSS_UART_polled_tx_string\r
286 (\r
287     mss_uart_instance_t * this_uart,\r
288     const uint8_t * p_sz_string\r
289 )\r
290 {\r
291     uint32_t char_idx = 0u;\r
292     uint32_t fill_size;\r
293     uint8_t data_byte;\r
294     uint8_t status;\r
295 \r
296     ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));\r
297     ASSERT(p_sz_string != ((uint8_t *)0));\r
298 \r
299     if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&\r
300        (p_sz_string != ((uint8_t *)0)))\r
301     {\r
302         /* Get the first data byte from the input buffer */\r
303         data_byte = p_sz_string[char_idx];\r
304 \r
305         /* First check for the NULL terminator byte.\r
306          * Then remain in this loop until the entire string in the input buffer\r
307          * has been transferred to the UART.\r
308          */\r
309         while(0u != data_byte)\r
310         {\r
311             /* Wait until TX FIFO is empty. */\r
312             do {\r
313                 status = this_uart->hw_reg->LSR;\r
314                 this_uart->status |= status;\r
315             } while (0u == (status & MSS_UART_THRE));\r
316 \r
317             /* Send bytes from the input buffer until the TX FIFO is full\r
318              * or we reach the NULL terminator byte.\r
319              */\r
320             fill_size = 0u;\r
321             while((0u != data_byte) && (fill_size < TX_FIFO_SIZE))\r
322             {\r
323                 /* Send the data byte */\r
324                 this_uart->hw_reg->THR = data_byte;\r
325                 ++fill_size;\r
326                 char_idx++;\r
327                 /* Get the next data byte from the input buffer */\r
328                 data_byte = p_sz_string[char_idx];\r
329             }\r
330         }\r
331     }\r
332 }\r
333 \r
334 /***************************************************************************//**\r
335  * See mss_uart.h for details of how to use this function.\r
336  */\r
337 void\r
338 MSS_UART_irq_tx\r
339 (\r
340     mss_uart_instance_t * this_uart,\r
341     const uint8_t * pbuff,\r
342     uint32_t tx_size\r
343 )\r
344 {\r
345     ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));\r
346     ASSERT(pbuff != ((uint8_t *)0));\r
347     ASSERT(tx_size > 0u);\r
348 \r
349     if((tx_size > 0u) && ( pbuff != ((uint8_t *)0)) &&\r
350       ((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)))\r
351     {\r
352         /*Initialise the transmit info for the UART instance with the arguments.*/\r
353         this_uart->tx_buffer = pbuff;\r
354         this_uart->tx_buff_size = tx_size;\r
355         this_uart->tx_idx = (uint16_t)0;\r
356 \r
357         /* Clear any previously pended interrupts */\r
358         NVIC_ClearPendingIRQ(this_uart->irqn);\r
359 \r
360         /* assign default handler for data transfer */\r
361         this_uart->tx_handler = default_tx_handler;\r
362 \r
363         /* enables TX interrupt */\r
364         set_bit_reg8(&this_uart->hw_reg->IER,ETBEI);\r
365 \r
366         /* Enable UART instance interrupt in Cortex-M3 NVIC. */\r
367         NVIC_EnableIRQ(this_uart->irqn);\r
368     }\r
369 }\r
370 \r
371 /***************************************************************************//**\r
372  * See mss_uart.h for details of how to use this function.\r
373  */\r
374 int8_t\r
375 MSS_UART_tx_complete\r
376 (\r
377     mss_uart_instance_t * this_uart\r
378 )\r
379 {\r
380     int8_t ret_value = 0;\r
381     uint8_t status = 0u;\r
382 \r
383     ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));\r
384 \r
385     if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))\r
386     {\r
387         /* Read the Line Status Register and update the sticky record. */\r
388         status = this_uart->hw_reg->LSR;\r
389         this_uart->status |= status;\r
390 \r
391         if((TX_COMPLETE == this_uart->tx_buff_size) &&\r
392            ((status & MSS_UART_TEMT) != 0u))\r
393         {\r
394             ret_value = (int8_t)1;\r
395         }\r
396     }\r
397     return ret_value;\r
398 }\r
399 \r
400 \r
401 /***************************************************************************//**\r
402  * See mss_uart.h for details of how to use this function.\r
403  */\r
404 size_t\r
405 MSS_UART_get_rx\r
406 (\r
407     mss_uart_instance_t * this_uart,\r
408     uint8_t * rx_buff,\r
409     size_t buff_size\r
410 )\r
411 {\r
412     size_t rx_size = 0u;\r
413     uint8_t status = 0u;\r
414 \r
415     ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));\r
416     ASSERT(rx_buff != ((uint8_t *)0));\r
417     ASSERT(buff_size > 0u);\r
418 \r
419     if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&\r
420        (rx_buff != ((uint8_t *)0)) && (buff_size > 0u))\r
421     {\r
422         status = this_uart->hw_reg->LSR;\r
423         this_uart->status |= status;\r
424 \r
425         while(((status & MSS_UART_DATA_READY) != 0u) &&\r
426               (rx_size < buff_size))\r
427         {\r
428             rx_buff[rx_size] = this_uart->hw_reg->RBR;\r
429             ++rx_size;\r
430             status = this_uart->hw_reg->LSR;\r
431             this_uart->status |= status;\r
432         }\r
433     }\r
434     return rx_size;\r
435 }\r
436 /***************************************************************************//**\r
437  * See mss_uart.h for details of how to use this function.\r
438  */\r
439 void\r
440 MSS_UART_enable_irq\r
441 (\r
442     mss_uart_instance_t * this_uart,\r
443     mss_uart_irq_t irq_mask\r
444 )\r
445 {\r
446     ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));\r
447     ASSERT(MSS_UART_INVALID_IRQ > irq_mask);\r
448 \r
449     if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&\r
450        (MSS_UART_INVALID_IRQ > irq_mask))\r
451     {\r
452         /* Clear any previously pended interrupts */\r
453         NVIC_ClearPendingIRQ(this_uart->irqn);\r
454 \r
455         /* irq_mask encoding: 1- enable\r
456          * bit 0 - Receive Data Available Interrupt\r
457          * bit 1 - Transmitter Holding  Register Empty Interrupt\r
458          * bit 2 - Receiver Line Status Interrupt\r
459          * bit 3 - Modem Status Interrupt\r
460          */\r
461         this_uart->hw_reg->IER |= (uint8_t)irq_mask & IIRF_MASK;\r
462 \r
463         /*\r
464          * bit 4 - Receiver time-out interrupt\r
465          * bit 5 - NACK / ERR signal interrupt\r
466          * bit 6 - PID parity error interrupt\r
467          * bit 7 - LIN break detection interrupt\r
468          * bit 8 - LIN Sync detection interrupt\r
469          */\r
470         this_uart->hw_reg->IEM |= (uint8_t)(((uint32_t)irq_mask & ~((uint32_t)IIRF_MASK)) >> 4u);\r
471 \r
472         /* Enable UART instance interrupt in Cortex-M3 NVIC. */\r
473         NVIC_EnableIRQ(this_uart->irqn);\r
474     }\r
475 }\r
476 \r
477 /***************************************************************************//**\r
478  * See mss_uart.h for details of how to use this function.\r
479  */\r
480 void\r
481 MSS_UART_disable_irq\r
482 (\r
483     mss_uart_instance_t * this_uart,\r
484     mss_uart_irq_t irq_mask\r
485 )\r
486 {\r
487     ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));\r
488 \r
489     if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))\r
490     {\r
491         /* irq_mask encoding: 1 - disable\r
492          * bit 0 - Receive Data Available Interrupt\r
493          * bit 1 - Transmitter Holding  Register Empty Interrupt\r
494          * bit 2 - Receiver Line Status Interrupt\r
495          * bit 3 - Modem Status Interrupt\r
496          */\r
497         this_uart->hw_reg->IER &= ((uint8_t)(~((uint32_t)irq_mask & (uint32_t)IIRF_MASK)));\r
498 \r
499         /*\r
500          * bit 4 - Receiver time-out interrupt\r
501          * bit 5 - NACK / ERR signal interrupt\r
502          * bit 6 - PID parity error interrupt\r
503          * bit 7 - LIN break detection interrupt\r
504          * bit 8 - LIN Sync detection interrupt\r
505          */\r
506         this_uart->hw_reg->IEM |= (uint8_t)(~(((uint32_t)irq_mask & ~((uint32_t)IIRF_MASK)) >> 8u));\r
507 \r
508         /* Clear any previously pended interrupts */\r
509         NVIC_ClearPendingIRQ(this_uart->irqn);\r
510 \r
511         if(irq_mask == IIRF_MASK)\r
512         {\r
513             /* Disable UART instance interrupt in Cortex-M3 NVIC. */\r
514             NVIC_DisableIRQ(this_uart->irqn);\r
515 \r
516         }\r
517     }\r
518 }\r
519 \r
520 /***************************************************************************//**\r
521  * See mss_uart.h for details of how to use this function.\r
522  */\r
523 void\r
524 MSS_UART_set_rx_handler\r
525 (\r
526     mss_uart_instance_t *       this_uart,\r
527     mss_uart_irq_handler_t      handler,\r
528     mss_uart_rx_trig_level_t    trigger_level\r
529 )\r
530 {\r
531     ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));\r
532     ASSERT(handler != INVALID_IRQ_HANDLER );\r
533     ASSERT(trigger_level < MSS_UART_FIFO_INVALID_TRIG_LEVEL);\r
534 \r
535     if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&\r
536        (handler != INVALID_IRQ_HANDLER) &&\r
537        (trigger_level < MSS_UART_FIFO_INVALID_TRIG_LEVEL))\r
538     {\r
539         this_uart->rx_handler = handler;\r
540 \r
541         /* Set the receive interrupt trigger level. */\r
542         this_uart->hw_reg->FCR = (this_uart->hw_reg->FCR &\r
543                                  (uint8_t)(~((uint8_t)FCR_TRIG_LEVEL_MASK))) |\r
544                                  (uint8_t)trigger_level;\r
545         /* Clear any previously pended interrupts */\r
546         NVIC_ClearPendingIRQ(this_uart->irqn);\r
547 \r
548         /* Enable receive interrupt. */\r
549         set_bit_reg8(&this_uart->hw_reg->IER,ERBFI);\r
550 \r
551         /* Enable UART instance interrupt in Cortex-M3 NVIC. */\r
552         NVIC_EnableIRQ(this_uart->irqn);\r
553     }\r
554 }\r
555 \r
556 /***************************************************************************//**\r
557  * See mss_uart.h for details of how to use this function.\r
558  */\r
559 void\r
560 MSS_UART_set_loopback\r
561 (\r
562     mss_uart_instance_t *   this_uart,\r
563     mss_uart_loopback_t     loopback\r
564 )\r
565 {\r
566     ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));\r
567     ASSERT(MSS_UART_INVALID_LOOPBACK > loopback);\r
568 \r
569     if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) ||\r
570        (MSS_UART_INVALID_LOOPBACK > loopback))\r
571     {\r
572         switch(loopback)\r
573         {\r
574             case MSS_UART_LOCAL_LOOPBACK_OFF:\r
575                 /* Disable local loopback */\r
576                 clear_bit_reg8(&this_uart->hw_reg->MCR,LOOP);\r
577                 break;\r
578 \r
579             case MSS_UART_LOCAL_LOOPBACK_ON:\r
580                 /* Enable local loopback */\r
581                 set_bit_reg8(&this_uart->hw_reg->MCR,LOOP);\r
582                 break;\r
583 \r
584             case MSS_UART_REMOTE_LOOPBACK_OFF:\r
585             case MSS_UART_AUTO_ECHO_OFF:\r
586                 /* Disable remote loopback & automatic echo*/\r
587                 this_uart->hw_reg->MCR &= ~RLOOP_MASK;\r
588                 break;\r
589 \r
590             case MSS_UART_REMOTE_LOOPBACK_ON:\r
591                 /* Enable remote loopback */\r
592                 this_uart->hw_reg->MCR |= (1u << RLOOP);\r
593                 break;\r
594 \r
595             case MSS_UART_AUTO_ECHO_ON:\r
596                 /* Enable automatic echo */\r
597                 this_uart->hw_reg->MCR |= (1u << ECHO);\r
598                 break;\r
599 \r
600             case MSS_UART_INVALID_LOOPBACK:\r
601                 /* Fall through to default. */\r
602             default:\r
603                 ASSERT(0);\r
604                 break;\r
605         }\r
606     }\r
607 }\r
608 \r
609 /***************************************************************************//**\r
610  * UART0 interrupt service routine.\r
611  * UART0_IRQHandler is included within the Cortex-M3 vector table as part of the\r
612  * Fusion 2 CMSIS.\r
613  */\r
614 #if defined(__GNUC__)\r
615 __attribute__((__interrupt__)) void UART0_IRQHandler(void)\r
616 #else\r
617 void UART0_IRQHandler(void)\r
618 #endif\r
619 {\r
620     MSS_UART_isr(&g_mss_uart0);\r
621 }\r
622 \r
623 /***************************************************************************//**\r
624  * UART1 interrupt service routine.\r
625  * UART2_IRQHandler is included within the Cortex-M3 vector table as part of the\r
626  * Fusion 2 CMSIS.\r
627  */\r
628 #if defined(__GNUC__)\r
629 __attribute__((__interrupt__)) void UART1_IRQHandler(void)\r
630 #else\r
631 void UART1_IRQHandler(void)\r
632 #endif\r
633 {\r
634     MSS_UART_isr(&g_mss_uart1);\r
635 }\r
636 \r
637 /***************************************************************************//**\r
638  * See mss_uart.h for details of how to use this function.\r
639  */\r
640 void\r
641 MSS_UART_set_rxstatus_handler\r
642 (\r
643     mss_uart_instance_t * this_uart,\r
644     mss_uart_irq_handler_t handler\r
645 )\r
646 {\r
647     ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));\r
648     ASSERT(handler != INVALID_IRQ_HANDLER);\r
649 \r
650     if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&\r
651        (handler != INVALID_IRQ_HANDLER))\r
652     {\r
653         this_uart->linests_handler = handler;\r
654 \r
655         /* Clear any previously pended interrupts */\r
656         NVIC_ClearPendingIRQ(this_uart->irqn);\r
657 \r
658         /* Enable receiver line status interrupt. */\r
659         set_bit_reg8(&this_uart->hw_reg->IER,ELSI);\r
660 \r
661         /* Enable UART instance interrupt in Cortex-M3 NVIC. */\r
662         NVIC_EnableIRQ(this_uart->irqn);\r
663     }\r
664 }\r
665 \r
666 /***************************************************************************//**\r
667  * See mss_uart.h for details of how to use this function.\r
668  */\r
669 void\r
670 MSS_UART_set_tx_handler\r
671 (\r
672     mss_uart_instance_t * this_uart,\r
673     mss_uart_irq_handler_t handler\r
674 )\r
675 {\r
676     ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));\r
677     ASSERT(handler != INVALID_IRQ_HANDLER);\r
678 \r
679     if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&\r
680        (handler != INVALID_IRQ_HANDLER))\r
681     {\r
682         this_uart->tx_handler = handler;\r
683 \r
684         /* Make TX buffer info invalid */\r
685         this_uart->tx_buffer = (const uint8_t *)0;\r
686         this_uart->tx_buff_size = 0u;\r
687 \r
688         /* Clear any previously pended interrupts */\r
689         NVIC_ClearPendingIRQ(this_uart->irqn);\r
690 \r
691         /* Enable transmitter holding register Empty interrupt. */\r
692         set_bit_reg8(&this_uart->hw_reg->IER,ETBEI);\r
693 \r
694         /* Enable UART instance interrupt in Cortex-M3 NVIC. */\r
695         NVIC_EnableIRQ(this_uart->irqn);\r
696     }\r
697 }\r
698 \r
699 /***************************************************************************//**\r
700  * See mss_uart.h for details of how to use this function.\r
701  */\r
702 void\r
703 MSS_UART_set_modemstatus_handler\r
704 (\r
705     mss_uart_instance_t * this_uart,\r
706     mss_uart_irq_handler_t handler\r
707 )\r
708 {\r
709     ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));\r
710     ASSERT(handler != INVALID_IRQ_HANDLER);\r
711 \r
712     if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&\r
713        (handler != INVALID_IRQ_HANDLER))\r
714     {\r
715         this_uart->modemsts_handler = handler;\r
716 \r
717         /* Clear any previously pended interrupts */\r
718         NVIC_ClearPendingIRQ(this_uart->irqn);\r
719 \r
720         /* Enable modem status interrupt. */\r
721         set_bit_reg8(&this_uart->hw_reg->IER,EDSSI);\r
722 \r
723         /* Enable UART instance interrupt in Cortex-M3 NVIC. */\r
724         NVIC_EnableIRQ(this_uart->irqn);\r
725     }\r
726 }\r
727 \r
728 /***************************************************************************//**\r
729  * See mss_uart.h for details of how to use this function.\r
730  */\r
731 size_t\r
732 MSS_UART_fill_tx_fifo\r
733 (\r
734     mss_uart_instance_t * this_uart,\r
735     const uint8_t * tx_buffer,\r
736     size_t tx_size\r
737 )\r
738 {\r
739     uint8_t status = 0u;\r
740     size_t size_sent = 0u;\r
741 \r
742     ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));\r
743     ASSERT(tx_buffer != ( (uint8_t *)0));\r
744     ASSERT(tx_size > 0);\r
745 \r
746     /* Fill the UART's Tx FIFO until the FIFO is full or the complete input\r
747      * buffer has been written. */\r
748     if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&\r
749        (tx_buffer != ((uint8_t *)0))   &&\r
750        (tx_size > 0u))\r
751     {\r
752         status = this_uart->hw_reg->LSR;\r
753         this_uart->status |= status;\r
754 \r
755         if(status & MSS_UART_THRE)\r
756         {\r
757             uint32_t fill_size = TX_FIFO_SIZE;\r
758 \r
759             if(tx_size < TX_FIFO_SIZE)\r
760             {\r
761                 fill_size = tx_size;\r
762             }\r
763             /* Fill up FIFO */\r
764             for(size_sent = 0u; size_sent < fill_size; ++size_sent)\r
765             {\r
766 \r
767                 /* Send next character in the buffer. */\r
768                 this_uart->hw_reg->THR = tx_buffer[size_sent];\r
769             }\r
770         }\r
771     }\r
772     return size_sent;\r
773 }\r
774 \r
775 /***************************************************************************//**\r
776  * See mss_uart.h for details of how to use this function.\r
777  */\r
778 uint8_t\r
779 MSS_UART_get_rx_status\r
780 (\r
781     mss_uart_instance_t * this_uart\r
782 )\r
783 {\r
784     uint8_t status = MSS_UART_INVALID_PARAM;\r
785 \r
786     ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));\r
787 \r
788     if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))\r
789     {\r
790         /*\r
791          * Extract UART receive error status.\r
792          * Bit 1 - Overflow error status\r
793          * Bit 2 - Parity error status\r
794          * Bit 3 - Frame error status\r
795          * Bit 4 - Break interrupt indicator\r
796          * Bit 7 - FIFO data error status\r
797          */\r
798         this_uart->status |= (this_uart->hw_reg->LSR);\r
799         status = (this_uart->status & STATUS_ERROR_MASK);\r
800         /* Clear the sticky status after reading */\r
801         this_uart->status = 0u;\r
802     }\r
803     return status;\r
804 }\r
805 \r
806 /***************************************************************************//**\r
807  * See mss_uart.h for details of how to use this function.\r
808  */\r
809 uint8_t\r
810 MSS_UART_get_modem_status\r
811 (\r
812     mss_uart_instance_t * this_uart\r
813 )\r
814 {\r
815     uint8_t status = MSS_UART_INVALID_PARAM;\r
816 \r
817     ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));\r
818 \r
819     if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))\r
820     {\r
821         /*\r
822          * Extract UART modem status and place in lower bits of "status".\r
823          * Bit 0 - Delta Clear to Send Indicator\r
824          * Bit 1 - Delta Clear to Receive Indicator\r
825          * Bit 2 - Trailing edge of Ring Indicator detector\r
826          * Bit 3 - Delta Data Carrier Detect indicator\r
827          * Bit 4 - Clear To Send\r
828          * Bit 5 - Data Set Ready\r
829          * Bit 6 - Ring Indicator\r
830          * Bit 7 - Data Carrier Detect\r
831          */\r
832         status = this_uart->hw_reg->MSR;\r
833     }\r
834     return status;\r
835 }\r
836 \r
837 /***************************************************************************//**\r
838  * MSS_UART_get_tx_status.\r
839  * See mss_uart.h for details of how to use this function.\r
840  */\r
841 uint8_t\r
842 MSS_UART_get_tx_status\r
843 (\r
844     mss_uart_instance_t * this_uart\r
845 )\r
846 {\r
847     uint8_t status = MSS_UART_TX_BUSY;\r
848 \r
849     ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));\r
850 \r
851     if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))\r
852     {\r
853         /* Read the Line Status Register and update the sticky record. */\r
854         status = this_uart->hw_reg->LSR;\r
855         this_uart->status |= status;\r
856         /*\r
857          * Extract the transmit status bits from the UART's Line Status Register.\r
858          * Bit 5 - Transmitter Holding Register/FIFO Empty (THRE) status. (If = 1, TX FIFO is empty)\r
859          * Bit 6 - Transmitter Empty (TEMT) status. (If = 1, both TX FIFO and shift register are empty)\r
860          */\r
861         status &= (MSS_UART_THRE | MSS_UART_TEMT);\r
862     }\r
863     return status;\r
864 }\r
865 \r
866 /***************************************************************************//**\r
867  * See mss_uart.h for details of how to use this function.\r
868  */\r
869 void\r
870 MSS_UART_set_break\r
871 (\r
872     mss_uart_instance_t * this_uart\r
873 )\r
874 {\r
875     ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));\r
876     if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))\r
877     {\r
878         /* set break charecter on Tx line */\r
879         set_bit_reg8(&this_uart->hw_reg->LCR,SB);\r
880     }\r
881 }\r
882 \r
883 /***************************************************************************//**\r
884  * See mss_uart.h for details of how to use this function.\r
885  */\r
886 void\r
887 MSS_UART_clear_break\r
888 (\r
889     mss_uart_instance_t * this_uart\r
890 )\r
891 {\r
892     ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));\r
893     if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))\r
894     {\r
895         /* remove break charecter from Tx line */\r
896         clear_bit_reg8(&this_uart->hw_reg->LCR,SB);\r
897     }\r
898 }\r
899 \r
900 /***************************************************************************//**\r
901  * See mss_uart.h for details of how to use this function.\r
902  */\r
903 void\r
904 MSS_UART_set_pidpei_handler\r
905 (\r
906     mss_uart_instance_t * this_uart,\r
907     mss_uart_irq_handler_t handler\r
908 )\r
909 {\r
910     ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));\r
911     ASSERT(handler != INVALID_IRQ_HANDLER);\r
912 \r
913     if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&\r
914        (handler != INVALID_IRQ_HANDLER))\r
915     {\r
916         this_uart->pid_pei_handler = handler;\r
917 \r
918         /* Clear any previously pended interrupts */\r
919         NVIC_ClearPendingIRQ( this_uart->irqn );\r
920 \r
921         /* Enable PID parity error interrupt. */\r
922         set_bit_reg8(&this_uart->hw_reg->IEM,EPID_PEI);\r
923 \r
924         /* Enable UART instance interrupt in Cortex-M3 NVIC. */\r
925         NVIC_EnableIRQ(this_uart->irqn);\r
926     }\r
927 }\r
928 \r
929 /***************************************************************************//**\r
930  * See mss_uart.h for details of how to use this function.\r
931  */\r
932 void\r
933 MSS_UART_set_linbreak_handler\r
934 (\r
935     mss_uart_instance_t * this_uart,\r
936     mss_uart_irq_handler_t handler\r
937 )\r
938 {\r
939     ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));\r
940     ASSERT(handler != INVALID_IRQ_HANDLER);\r
941 \r
942     if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&\r
943        (handler != INVALID_IRQ_HANDLER))\r
944     {\r
945         this_uart->break_handler = handler;\r
946 \r
947         /* Clear any previously pended interrupts */\r
948         NVIC_ClearPendingIRQ( this_uart->irqn );\r
949 \r
950         /* Enable LIN break detection interrupt. */\r
951         set_bit_reg8(&this_uart->hw_reg->IEM,ELINBI);\r
952 \r
953         /* Enable UART instance interrupt in Cortex-M3 NVIC. */\r
954         NVIC_EnableIRQ(this_uart->irqn);\r
955     }\r
956 }\r
957 \r
958 /***************************************************************************//**\r
959  * See mss_uart.h for details of how to use this function.\r
960  */\r
961 void\r
962 MSS_UART_set_linsync_handler\r
963 (\r
964     mss_uart_instance_t * this_uart,\r
965     mss_uart_irq_handler_t handler\r
966 )\r
967 {\r
968     ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));\r
969     ASSERT(handler != INVALID_IRQ_HANDLER);\r
970 \r
971     if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&\r
972        (handler != INVALID_IRQ_HANDLER))\r
973     {\r
974         this_uart->sync_handler = handler;\r
975 \r
976         /* Clear any previously pended interrupts */\r
977         NVIC_ClearPendingIRQ( this_uart->irqn );\r
978 \r
979         /* Enable LIN sync detection interrupt. */\r
980         set_bit_reg8(&this_uart->hw_reg->IEM,ELINSI);\r
981 \r
982         /* Enable UART instance interrupt in Cortex-M3 NVIC. */\r
983         NVIC_EnableIRQ(this_uart->irqn);\r
984     }\r
985 }\r
986 \r
987 /***************************************************************************//**\r
988  * See mss_uart.h for details of how to use this function.\r
989  */\r
990 void\r
991 MSS_UART_set_nack_handler\r
992 (\r
993     mss_uart_instance_t * this_uart,\r
994     mss_uart_irq_handler_t handler\r
995 )\r
996 {\r
997     ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));\r
998     ASSERT(handler != INVALID_IRQ_HANDLER);\r
999 \r
1000     if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&\r
1001        (handler != INVALID_IRQ_HANDLER))\r
1002     {\r
1003         this_uart->nack_handler = handler;\r
1004 \r
1005         /* Clear any previously pended interrupts */\r
1006         NVIC_ClearPendingIRQ( this_uart->irqn );\r
1007 \r
1008         /* Enable LIN sync detection interrupt. */\r
1009         set_bit_reg8(&this_uart->hw_reg->IEM,ENACKI);\r
1010 \r
1011         /* Enable UART instance interrupt in Cortex-M3 NVIC. */\r
1012         NVIC_EnableIRQ(this_uart->irqn);\r
1013     }\r
1014 }\r
1015 \r
1016 /***************************************************************************//**\r
1017  * See mss_uart.h for details of how to use this function.\r
1018  */\r
1019 void\r
1020 MSS_UART_set_rx_timeout_handler\r
1021 (\r
1022     mss_uart_instance_t * this_uart,\r
1023     mss_uart_irq_handler_t handler\r
1024 )\r
1025 {\r
1026     ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));\r
1027     ASSERT(handler != INVALID_IRQ_HANDLER);\r
1028 \r
1029     if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&\r
1030        (handler != INVALID_IRQ_HANDLER))\r
1031     {\r
1032         this_uart->rto_handler = handler;\r
1033 \r
1034         /* Clear any previously pended interrupts */\r
1035         NVIC_ClearPendingIRQ( this_uart->irqn );\r
1036 \r
1037         /* Enable receiver timeout interrupt. */\r
1038         set_bit_reg8(&this_uart->hw_reg->IEM,ERTOI);\r
1039 \r
1040         /* Enable UART instance interrupt in Cortex-M3 NVIC. */\r
1041         NVIC_EnableIRQ(this_uart->irqn);\r
1042     }\r
1043 }\r
1044 \r
1045 /***************************************************************************//**\r
1046  * See mss_uart.h for details of how to use this function.\r
1047  */\r
1048 void\r
1049 MSS_UART_enable_half_duplex\r
1050 (\r
1051     mss_uart_instance_t * this_uart\r
1052 )\r
1053 {\r
1054     ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));\r
1055     if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))\r
1056     {\r
1057         /* enable single wire half-duplex mode */\r
1058         set_bit_reg8(&this_uart->hw_reg->MM2,ESWM);\r
1059     }\r
1060 }\r
1061 \r
1062 /***************************************************************************//**\r
1063  * See mss_uart.h for details of how to use this function.\r
1064  */\r
1065 void\r
1066 MSS_UART_disable_half_duplex\r
1067 (\r
1068     mss_uart_instance_t * this_uart\r
1069 )\r
1070 {\r
1071     ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));\r
1072     if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))\r
1073     {\r
1074         /* enable single wire half-duplex mode */\r
1075         clear_bit_reg8(&this_uart->hw_reg->MM2,ESWM);\r
1076     }\r
1077 }\r
1078 \r
1079 /***************************************************************************//**\r
1080  * See mss_uart.h for details of how to use this function.\r
1081  */\r
1082 void\r
1083 MSS_UART_set_rx_endian\r
1084 (\r
1085     mss_uart_instance_t * this_uart,\r
1086     mss_uart_endian_t endian\r
1087 )\r
1088 {\r
1089     ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));\r
1090     ASSERT(MSS_UART_INVALID_ENDIAN > endian);\r
1091 \r
1092     if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&\r
1093        (MSS_UART_INVALID_ENDIAN > endian))\r
1094     {\r
1095         /* Configure MSB first / LSB first for receiver */\r
1096         ((MSS_UART_LITTLEEND == endian) ? (clear_bit_reg8(&this_uart->hw_reg->MM1,E_MSB_RX)) :\r
1097                                           (set_bit_reg8(&this_uart->hw_reg->MM1,E_MSB_RX)));\r
1098     }\r
1099 }\r
1100 \r
1101 /***************************************************************************//**\r
1102  * See mss_uart.h for details of how to use this function.\r
1103  */\r
1104 void\r
1105 MSS_UART_set_tx_endian\r
1106 (\r
1107     mss_uart_instance_t * this_uart,\r
1108     mss_uart_endian_t endian\r
1109 )\r
1110 {\r
1111     ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));\r
1112     ASSERT(MSS_UART_INVALID_ENDIAN > endian);\r
1113 \r
1114     if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&\r
1115        (MSS_UART_INVALID_ENDIAN > endian))\r
1116     {\r
1117         /* Configure MSB first / LSB first for transmitter */\r
1118         ((MSS_UART_LITTLEEND == endian) ? (clear_bit_reg8(&this_uart->hw_reg->MM1,E_MSB_TX)) :\r
1119                                           (set_bit_reg8(&this_uart->hw_reg->MM1,E_MSB_TX)) ) ;\r
1120     }\r
1121 }\r
1122 \r
1123 /***************************************************************************//**\r
1124  * See mss_uart.h for details of how to use this function.\r
1125  */\r
1126 void\r
1127 MSS_UART_set_filter_length\r
1128 (\r
1129     mss_uart_instance_t * this_uart,\r
1130     mss_uart_filter_length_t length\r
1131 )\r
1132 {\r
1133     ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));\r
1134     ASSERT(MSS_UART_INVALID_FILTER_LENGTH > length);\r
1135 \r
1136     if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&\r
1137        (MSS_UART_INVALID_FILTER_LENGTH > length))\r
1138     {\r
1139         /* Configure glitch filter length */\r
1140         this_uart->hw_reg->GFR = (uint8_t)length;\r
1141     }\r
1142 }\r
1143 \r
1144 /***************************************************************************//**\r
1145  * See mss_uart.h for details of how to use this function.\r
1146  */\r
1147 void\r
1148 MSS_UART_enable_afm\r
1149 (\r
1150      mss_uart_instance_t * this_uart\r
1151 )\r
1152 {\r
1153     ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));\r
1154 \r
1155     if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))\r
1156     {\r
1157         /* Disable RX FIFO till address flag with correct address is received */\r
1158         set_bit_reg8(&this_uart->hw_reg->MM2,EAFM);\r
1159     }\r
1160 }\r
1161 \r
1162 /***************************************************************************//**\r
1163  * See mss_uart.h for details of how to use this function.\r
1164  */\r
1165 void\r
1166 MSS_UART_disable_afm\r
1167 (\r
1168      mss_uart_instance_t * this_uart\r
1169 )\r
1170 {\r
1171     ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));\r
1172 \r
1173     if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))\r
1174     {\r
1175         /* Enable RX FIFO irrespective of address flag and\r
1176            correct address is received */\r
1177         clear_bit_reg8(&this_uart->hw_reg->MM2,EAFM);\r
1178     }\r
1179 }\r
1180 \r
1181 /***************************************************************************//**\r
1182  * See mss_uart.h for details of how to use this function.\r
1183  */\r
1184 void\r
1185 MSS_UART_enable_afclear\r
1186 (\r
1187      mss_uart_instance_t * this_uart\r
1188 )\r
1189 {\r
1190     ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));\r
1191 \r
1192     if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))\r
1193     {\r
1194         /* Enable address flag clearing */\r
1195         /* Disable RX FIFO till another address flag with\r
1196            correct address is received */\r
1197         set_bit_reg8(&this_uart->hw_reg->MM2,EAFC);\r
1198     }\r
1199 }\r
1200 \r
1201 /***************************************************************************//**\r
1202  * See mss_uart.h for details of how to use this function.\r
1203  */\r
1204 void\r
1205 MSS_UART_disable_afclear\r
1206 (\r
1207      mss_uart_instance_t * this_uart\r
1208 )\r
1209 {\r
1210     ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));\r
1211 \r
1212     if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))\r
1213     {\r
1214         /* Disable address flag clearing */\r
1215         clear_bit_reg8(&this_uart->hw_reg->MM2,EAFC);\r
1216     }\r
1217 }\r
1218 \r
1219 /***************************************************************************//**\r
1220  * See mss_uart.h for details of how to use this function.\r
1221  */\r
1222 void\r
1223 MSS_UART_enable_rx_timeout\r
1224 (\r
1225     mss_uart_instance_t * this_uart,\r
1226     uint8_t timeout\r
1227 )\r
1228 {\r
1229     ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));\r
1230 \r
1231     if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))\r
1232     {\r
1233         /* Load the receive timeout value */\r
1234         this_uart->hw_reg->RTO = timeout;\r
1235         /*Enable receiver time-out */\r
1236         set_bit_reg8(&this_uart->hw_reg->MM0,ERTO);\r
1237     }\r
1238 }\r
1239 \r
1240 /***************************************************************************//**\r
1241  * See mss_uart.h for details of how to use this function.\r
1242  */\r
1243 void\r
1244 MSS_UART_disable_rx_timeout\r
1245 (\r
1246     mss_uart_instance_t * this_uart\r
1247 )\r
1248 {\r
1249     ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));\r
1250 \r
1251     if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))\r
1252     {\r
1253         /*Disable receiver time-out */\r
1254         clear_bit_reg8(&this_uart->hw_reg->MM0,ERTO);\r
1255     }\r
1256 }\r
1257 \r
1258 /***************************************************************************//**\r
1259  * See mss_uart.h for details of how to use this function.\r
1260  */\r
1261 void\r
1262 MSS_UART_enable_tx_time_guard\r
1263 (\r
1264     mss_uart_instance_t * this_uart,\r
1265     uint8_t timeguard\r
1266 )\r
1267 {\r
1268     ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));\r
1269 \r
1270     if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))\r
1271     {\r
1272         /* Load the transmitter time guard value */\r
1273         this_uart->hw_reg->TTG = timeguard;\r
1274         /*Enable transmitter time guard */\r
1275         set_bit_reg8(&this_uart->hw_reg->MM0,ETTG);\r
1276     }\r
1277 }\r
1278 \r
1279 /***************************************************************************//**\r
1280  * See mss_uart.h for details of how to use this function.\r
1281  */\r
1282 void\r
1283 MSS_UART_disable_tx_time_guard\r
1284 (\r
1285     mss_uart_instance_t * this_uart\r
1286 )\r
1287 {\r
1288     ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));\r
1289 \r
1290     if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))\r
1291     {\r
1292         /*Disable transmitter time guard */\r
1293         clear_bit_reg8(&this_uart->hw_reg->MM0,ETTG);\r
1294     }\r
1295 }\r
1296 \r
1297 /***************************************************************************//**\r
1298  * See mss_uart.h for details of how to use this function.\r
1299  */\r
1300 void\r
1301 MSS_UART_set_address\r
1302 (\r
1303     mss_uart_instance_t * this_uart,\r
1304     uint8_t address\r
1305 )\r
1306 {\r
1307     ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));\r
1308 \r
1309     if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))\r
1310     {\r
1311         this_uart->hw_reg->ADR = address;\r
1312     }\r
1313 }\r
1314 \r
1315 /***************************************************************************//**\r
1316  * See mss_uart.h for details of how to use this function.\r
1317  */\r
1318 void\r
1319 MSS_UART_set_ready_mode\r
1320 (\r
1321     mss_uart_instance_t * this_uart,\r
1322     mss_uart_ready_mode_t mode\r
1323 )\r
1324 {\r
1325     ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));\r
1326     ASSERT(MSS_UART_INVALID_READY_MODE > mode);\r
1327 \r
1328     if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&\r
1329        (MSS_UART_INVALID_READY_MODE > mode ) )\r
1330     {\r
1331         /* Configure mode 0 or mode 1 for TXRDY and RXRDY */\r
1332         ((MSS_UART_READY_MODE0 == mode) ? clear_bit_reg8(&this_uart->hw_reg->FCR,RDYMODE) :\r
1333                                  set_bit_reg8(&this_uart->hw_reg->FCR,RDYMODE) );\r
1334     }\r
1335 }\r
1336 \r
1337 /***************************************************************************//**\r
1338  * Configure baud divisors using fractional baud rate if possible.\r
1339  */\r
1340 static void\r
1341 config_baud_divisors\r
1342 (\r
1343     mss_uart_instance_t * this_uart,\r
1344     uint32_t baudrate\r
1345 )\r
1346 {\r
1347     ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));\r
1348 \r
1349     if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))\r
1350     {\r
1351         uint32_t baud_value;\r
1352         uint32_t baud_value_by_64;\r
1353         uint32_t baud_value_by_128;\r
1354         uint32_t fractional_baud_value;\r
1355         uint32_t pclk_freq;\r
1356 \r
1357         this_uart->baudrate = baudrate;\r
1358 \r
1359         /* Force the value of the CMSIS global variables holding the various system\r
1360           * clock frequencies to be updated. */\r
1361         SystemCoreClockUpdate();\r
1362         if(this_uart == &g_mss_uart0)\r
1363         {\r
1364             pclk_freq = g_FrequencyPCLK0;\r
1365         }\r
1366         else\r
1367         {\r
1368             pclk_freq = g_FrequencyPCLK1;\r
1369         }\r
1370 \r
1371         /*\r
1372          * Compute baud value based on requested baud rate and PCLK frequency.\r
1373          * The baud value is computed using the following equation:\r
1374          *      baud_value = PCLK_Frequency / (baud_rate * 16)\r
1375          */\r
1376         baud_value_by_128 = (8u * pclk_freq) / baudrate;\r
1377         baud_value_by_64 = baud_value_by_128 / 2u;\r
1378         baud_value = baud_value_by_64 / 64u;\r
1379         fractional_baud_value = baud_value_by_64 - (baud_value * 64u);\r
1380         fractional_baud_value += (baud_value_by_128 - (baud_value * 128u)) - (fractional_baud_value * 2u);\r
1381 \r
1382         /* Assert if integer baud value fits in 16-bit. */\r
1383         ASSERT(baud_value <= UINT16_MAX);\r
1384 \r
1385         if(baud_value <= (uint32_t)UINT16_MAX)\r
1386         {\r
1387             if(baud_value > 1u)\r
1388             {\r
1389                 /*\r
1390                  * Use Frational baud rate divisors\r
1391                  */\r
1392                 /* set divisor latch */\r
1393                 set_bit_reg8(&this_uart->hw_reg->LCR,DLAB);\r
1394 \r
1395                 /* msb of baud value */\r
1396                 this_uart->hw_reg->DMR = (uint8_t)(baud_value >> 8);\r
1397                 /* lsb of baud value */\r
1398                 this_uart->hw_reg->DLR = (uint8_t)baud_value;\r
1399 \r
1400                 /* reset divisor latch */\r
1401                 clear_bit_reg8(&this_uart->hw_reg->LCR,DLAB);\r
1402 \r
1403                 /* Enable Fractional baud rate */\r
1404                 set_bit_reg8(&this_uart->hw_reg->MM0,EFBR);\r
1405 \r
1406                 /* Load the fractional baud rate register */\r
1407                 ASSERT(fractional_baud_value <= (uint32_t)UINT8_MAX);\r
1408                 this_uart->hw_reg->DFR = (uint8_t)fractional_baud_value;\r
1409             }\r
1410             else\r
1411             {\r
1412                 /*\r
1413                  * Do NOT use Frational baud rate divisors.\r
1414                  */\r
1415                 /* set divisor latch */\r
1416                 set_bit_reg8(&this_uart->hw_reg->LCR,DLAB);\r
1417 \r
1418                 /* msb of baud value */\r
1419                 this_uart->hw_reg->DMR = (uint8_t)(baud_value >> 8u);\r
1420                 /* lsb of baud value */\r
1421                 this_uart->hw_reg->DLR = (uint8_t)baud_value;\r
1422 \r
1423                 /* reset divisor latch */\r
1424                 clear_bit_reg8(&this_uart->hw_reg->LCR,DLAB);\r
1425 \r
1426                 /* Disable Fractional baud rate */\r
1427                 clear_bit_reg8(&this_uart->hw_reg->MM0,EFBR);\r
1428             }\r
1429         }\r
1430     }\r
1431 }\r
1432 \r
1433 /***************************************************************************//**\r
1434  * See mss_uart.h for details of how to use this function.\r
1435  */\r
1436 void\r
1437 MSS_UART_set_usart_mode\r
1438 (\r
1439     mss_uart_instance_t * this_uart,\r
1440     mss_uart_usart_mode_t mode\r
1441 )\r
1442 {\r
1443     ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));\r
1444     ASSERT(MSS_UART_INVALID_SYNC_MODE > mode);\r
1445 \r
1446     if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&\r
1447        (MSS_UART_INVALID_SYNC_MODE > mode))\r
1448     {\r
1449         /* Nothing to do for the baudrate: operates at PCLK / 2 + glitch filter length */\r
1450         /* Clear the ESYN bits 2:0 */\r
1451         this_uart->hw_reg->MM0 &= ~SYNC_ASYNC_MODE_MASK;\r
1452         this_uart->hw_reg->MM0 |= (uint8_t)mode;\r
1453     }\r
1454 }\r
1455 \r
1456 /*******************************************************************************\r
1457  * Local Functions\r
1458  *******************************************************************************/\r
1459 /*******************************************************************************\r
1460  * Global initialization for all modes\r
1461  */\r
1462 static void global_init\r
1463 (\r
1464     mss_uart_instance_t * this_uart,\r
1465     uint32_t baud_rate,\r
1466     uint8_t line_config\r
1467 )\r
1468 {\r
1469     /* The driver expects g_mss_uart0 and g_mss_uart1 to be the only\r
1470      * mss_uart_instance_t instances used to identify UART0 and UART1. */\r
1471     ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));\r
1472 \r
1473     if(this_uart == &g_mss_uart0)\r
1474     {\r
1475         this_uart->hw_reg = UART0;\r
1476         this_uart->irqn = UART0_IRQn;\r
1477         /* reset UART0 */\r
1478         SYSREG->SOFT_RST_CR |= SYSREG_MMUART0_SOFTRESET_MASK;\r
1479         /* Clear any previously pended UART0 interrupt */\r
1480         NVIC_ClearPendingIRQ(UART0_IRQn);\r
1481         /* Take UART0 out of reset. */\r
1482         SYSREG->SOFT_RST_CR &= ~SYSREG_MMUART0_SOFTRESET_MASK;\r
1483     }\r
1484     else\r
1485     {\r
1486         this_uart->hw_reg = UART1;\r
1487         this_uart->irqn = UART1_IRQn;\r
1488         /* Reset UART1 */\r
1489         SYSREG->SOFT_RST_CR |= SYSREG_MMUART1_SOFTRESET_MASK;\r
1490         /* Clear any previously pended UART1 interrupt */\r
1491         NVIC_ClearPendingIRQ(UART1_IRQn);\r
1492         /* Take UART1 out of reset. */\r
1493         SYSREG->SOFT_RST_CR &= ~SYSREG_MMUART1_SOFTRESET_MASK;\r
1494     }\r
1495 \r
1496     /* disable interrupts */\r
1497     this_uart->hw_reg->IER = 0u;\r
1498 \r
1499     /* FIFO configuration */\r
1500     this_uart->hw_reg->FCR = (uint8_t)MSS_UART_FIFO_SINGLE_BYTE;\r
1501     /* clear receiver FIFO */\r
1502     set_bit_reg8(&this_uart->hw_reg->FCR,CLEAR_RX_FIFO);\r
1503     /* clear transmitter FIFO */\r
1504     set_bit_reg8(&this_uart->hw_reg->FCR,CLEAR_TX_FIFO);\r
1505 \r
1506     /* set default READY mode : Mode 0*/\r
1507     /* enable RXRDYN and TXRDYN pins. The earlier FCR write to set the TX FIFO\r
1508      * trigger level inadvertently disabled the FCR_RXRDY_TXRDYN_EN bit. */\r
1509     set_bit_reg8(&this_uart->hw_reg->FCR,RXRDY_TXRDYN_EN);\r
1510 \r
1511     /* disable loopback : local * remote */\r
1512     clear_bit_reg8(&this_uart->hw_reg->MCR,LOOP);\r
1513     clear_bit_reg8(&this_uart->hw_reg->MCR,RLOOP);\r
1514 \r
1515     /* set default TX endian */\r
1516     clear_bit_reg8(&this_uart->hw_reg->MM1,E_MSB_TX);\r
1517     /* set default RX endian */\r
1518     clear_bit_reg8(&this_uart->hw_reg->MM1,E_MSB_RX);\r
1519 \r
1520     /* default AFM : disabled */\r
1521     clear_bit_reg8(&this_uart->hw_reg->MM2,EAFM);\r
1522 \r
1523     /* disable TX time gaurd */\r
1524     clear_bit_reg8(&this_uart->hw_reg->MM0,ETTG);\r
1525 \r
1526     /* set default RX timeout */\r
1527     clear_bit_reg8(&this_uart->hw_reg->MM0,ERTO);\r
1528 \r
1529     /* disable fractional baud-rate */\r
1530     clear_bit_reg8(&this_uart->hw_reg->MM0,EFBR);\r
1531 \r
1532     /* disable single wire mode */\r
1533     clear_bit_reg8(&this_uart->hw_reg->MM2,ESWM);\r
1534 \r
1535     /* set filter to minimum value */\r
1536     this_uart->hw_reg->GFR = 0u;\r
1537     /* set default TX time gaurd */\r
1538     this_uart->hw_reg->TTG = 0u;\r
1539     /* set default RX timeout */\r
1540     this_uart->hw_reg->RTO = 0u;\r
1541 \r
1542     /*\r
1543      * Configure baud rate divisors. This uses the frational baud rate divisor\r
1544      * where possible to provide the most accurate baud rat possible.\r
1545      */\r
1546     config_baud_divisors(this_uart, baud_rate);\r
1547 \r
1548     /* set the line control register (bit length, stop bits, parity) */\r
1549     this_uart->hw_reg->LCR = line_config;\r
1550 \r
1551     /* Instance setup */\r
1552     this_uart->baudrate = baud_rate;\r
1553     this_uart->lineconfig = line_config;\r
1554     this_uart->tx_buff_size = TX_COMPLETE;\r
1555     this_uart->tx_buffer = (const uint8_t *)0;\r
1556     this_uart->tx_idx = 0u;\r
1557 \r
1558     /* Default handlers for MSS UART interrupts */\r
1559     this_uart->rx_handler       = NULL_HANDLER;\r
1560     this_uart->tx_handler       = NULL_HANDLER;\r
1561     this_uart->linests_handler  = NULL_HANDLER;\r
1562     this_uart->modemsts_handler = NULL_HANDLER;\r
1563     this_uart->rto_handler      = NULL_HANDLER;\r
1564     this_uart->nack_handler     = NULL_HANDLER;\r
1565     this_uart->pid_pei_handler  = NULL_HANDLER;\r
1566     this_uart->break_handler    = NULL_HANDLER;\r
1567     this_uart->sync_handler     = NULL_HANDLER;\r
1568 \r
1569     /* Initialize the sticky status */\r
1570     this_uart->status = 0u;\r
1571 }\r
1572 \r
1573 /***************************************************************************//**\r
1574  * Interrupt service routine triggered by any MSS UART interrupt. This routine\r
1575  * will call the handler function appropriate to the interrupt from the\r
1576  * handlers previously registered with the driver through calls to the\r
1577  * MSS_UART_set_*_handler() functions, or it will call the default_tx_handler()\r
1578  * function in response to transmit interrupts if MSS_UART_irq_tx() is used to\r
1579  * transmit data.\r
1580  */\r
1581 static void\r
1582 MSS_UART_isr\r
1583 (\r
1584     mss_uart_instance_t * this_uart\r
1585 )\r
1586 {\r
1587     uint8_t iirf;\r
1588 \r
1589     ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));\r
1590 \r
1591     if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))\r
1592     {\r
1593         iirf = this_uart->hw_reg->IIR & IIRF_MASK;\r
1594 \r
1595         switch (iirf)\r
1596         {\r
1597             case IIRF_MODEM_STATUS:  /* Modem status interrupt */\r
1598             {\r
1599                 ASSERT(NULL_HANDLER != this_uart->modemsts_handler);\r
1600                 if(NULL_HANDLER != this_uart->modemsts_handler)\r
1601                 {\r
1602                    (*(this_uart->modemsts_handler))(this_uart);\r
1603                 }\r
1604             }\r
1605             break;\r
1606 \r
1607             case IIRF_THRE: /* Transmitter Holding Register Empty */\r
1608             {\r
1609                 ASSERT(NULL_HANDLER != this_uart->tx_handler);\r
1610                 if(NULL_HANDLER != this_uart->tx_handler)\r
1611                 {\r
1612                     (*(this_uart->tx_handler))(this_uart);\r
1613                 }\r
1614             }\r
1615             break;\r
1616 \r
1617             case IIRF_RX_DATA:      /* Received Data Available */\r
1618             case IIRF_DATA_TIMEOUT: /* Received Data Timed-out */\r
1619             {\r
1620                 ASSERT(NULL_HANDLER != this_uart->rx_handler);\r
1621                 if(NULL_HANDLER != this_uart->rx_handler)\r
1622                 {\r
1623                     (*(this_uart->rx_handler))(this_uart);\r
1624                 }\r
1625             }\r
1626             break;\r
1627 \r
1628             case IIRF_RX_LINE_STATUS:  /* Line Status Interrupt */\r
1629             {\r
1630                 ASSERT(NULL_HANDLER != this_uart->linests_handler);\r
1631                 if(NULL_HANDLER != this_uart->linests_handler)\r
1632                 {\r
1633                    (*(this_uart->linests_handler))(this_uart);\r
1634                 }\r
1635             }\r
1636             break;\r
1637 \r
1638             case IIRF_MMI:\r
1639             {\r
1640                 /* Identify multimode interrupts and handle */\r
1641 \r
1642                 /* Receiver time-out interrupt */\r
1643                 if(read_bit_reg8(&this_uart->hw_reg->IIM,ERTOI))\r
1644                 {\r
1645                     ASSERT(NULL_HANDLER != this_uart->rto_handler);\r
1646                     if(NULL_HANDLER != this_uart->rto_handler)\r
1647                     {\r
1648                         (*(this_uart->rto_handler))(this_uart);\r
1649                     }\r
1650                 }\r
1651                 /* NACK interrupt */\r
1652                 if(read_bit_reg8(&this_uart->hw_reg->IIM,ENACKI))\r
1653                 {\r
1654                     ASSERT(NULL_HANDLER != this_uart->nack_handler);\r
1655                     if(NULL_HANDLER != this_uart->nack_handler)\r
1656                     {\r
1657                         (*(this_uart->nack_handler))(this_uart);\r
1658                     }\r
1659                 }\r
1660 \r
1661                 /* PID parity error interrupt */\r
1662                 if(read_bit_reg8(&this_uart->hw_reg->IIM,EPID_PEI))\r
1663                 {\r
1664                     ASSERT(NULL_HANDLER != this_uart->pid_pei_handler);\r
1665                     if(NULL_HANDLER != this_uart->pid_pei_handler)\r
1666                     {\r
1667                         (*(this_uart->pid_pei_handler))(this_uart);\r
1668                     }\r
1669                 }\r
1670 \r
1671                 /* LIN break detection interrupt */\r
1672                 if(read_bit_reg8(&this_uart->hw_reg->IIM,ELINBI))\r
1673                 {\r
1674                     ASSERT(NULL_HANDLER != this_uart->break_handler);\r
1675                     if(NULL_HANDLER != this_uart->break_handler)\r
1676                     {\r
1677                         (*(this_uart->break_handler))(this_uart);\r
1678                     }\r
1679                 }\r
1680 \r
1681                 /* LIN Sync detection interrupt */\r
1682                 if(read_bit_reg8(&this_uart->hw_reg->IIM,ELINSI))\r
1683                 {\r
1684                     ASSERT(NULL_HANDLER != this_uart->sync_handler);\r
1685                     if(NULL_HANDLER != this_uart->sync_handler)\r
1686                     {\r
1687                         (*(this_uart->sync_handler))(this_uart);\r
1688                     }\r
1689                 }\r
1690                 break;\r
1691             }\r
1692 \r
1693             default:\r
1694             {\r
1695                 ASSERT(INVALID_INTERRUPT);\r
1696             }\r
1697             break;\r
1698         }\r
1699     }\r
1700 }\r
1701 \r
1702 /***************************************************************************//**\r
1703  * See mss_uart.h for details of how to use this function.\r
1704  */\r
1705 static void\r
1706 default_tx_handler\r
1707 (\r
1708     mss_uart_instance_t * this_uart\r
1709 )\r
1710 {\r
1711     uint8_t status;\r
1712 \r
1713     ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));\r
1714     ASSERT(( (uint8_t *)0 ) != this_uart->tx_buffer);\r
1715     ASSERT(0u < this_uart->tx_buff_size);\r
1716 \r
1717     if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&\r
1718        (((uint8_t *)0 ) != this_uart->tx_buffer) &&\r
1719        (0u < this_uart->tx_buff_size))\r
1720     {\r
1721         /* Read the Line Status Register and update the sticky record. */\r
1722         status = this_uart->hw_reg->LSR;\r
1723         this_uart->status |= status;\r
1724 \r
1725         /*\r
1726          * This function should only be called as a result of a THRE interrupt.\r
1727          * Verify that this is true before proceeding to transmit data.\r
1728          */\r
1729         if(status & MSS_UART_THRE)\r
1730         {\r
1731             uint32_t i;\r
1732             uint32_t fill_size = TX_FIFO_SIZE;\r
1733             uint32_t tx_remain = this_uart->tx_buff_size - this_uart->tx_idx;\r
1734 \r
1735             /* Calculate the number of bytes to transmit. */\r
1736             if(tx_remain < TX_FIFO_SIZE)\r
1737             {\r
1738                 fill_size = tx_remain;\r
1739             }\r
1740 \r
1741             /* Fill the TX FIFO with the calculated the number of bytes. */\r
1742             for(i = 0u; i < fill_size; ++i)\r
1743             {\r
1744                 /* Send next character in the buffer. */\r
1745                 this_uart->hw_reg->THR = this_uart->tx_buffer[this_uart->tx_idx];\r
1746                 ++this_uart->tx_idx;\r
1747             }\r
1748         }\r
1749 \r
1750         /* Flag Tx as complete if all data has been pushed into the Tx FIFO. */\r
1751         if(this_uart->tx_idx == this_uart->tx_buff_size)\r
1752         {\r
1753             this_uart->tx_buff_size = TX_COMPLETE;\r
1754             /* disables TX interrupt */\r
1755             clear_bit_reg8(&this_uart->hw_reg->IER,ETBEI);\r
1756         }\r
1757     }\r
1758 }\r
1759 \r
1760 #ifdef __cplusplus\r
1761 }\r
1762 #endif\r