]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/drivers/Core16550/core_16550.c
Microsemi RISC-V project:
[freertos] / FreeRTOS / Demo / RISC-V_IGLOO2_Creative_SoftConsole / Microsemi_Code / drivers / Core16550 / core_16550.c
1 /*******************************************************************************\r
2  * (c) Copyright 2007-2015 Microsemi SoC Products Group. All rights reserved.\r
3  *\r
4  * Core16550 driver implementation. See file "core_16550.h" for a\r
5  * description of the functions implemented in this file.\r
6  *\r
7  * SVN $Revision: 7963 $\r
8  * SVN $Date: 2015-10-09 17:58:21 +0530 (Fri, 09 Oct 2015) $\r
9  */\r
10 #include "hal.h"\r
11 #include "core_16550.h"\r
12 #include "core16550_regs.h"\r
13 #include "hal_assert.h"\r
14 \r
15 #ifdef __cplusplus\r
16 extern "C" {\r
17 #endif\r
18 \r
19 /*******************************************************************************\r
20  * Definitions for transmitter states\r
21  */\r
22 #define TX_COMPLETE     0x00U\r
23 \r
24 /*******************************************************************************\r
25  * Definition for transmitter FIFO size\r
26  */\r
27 #define TX_FIFO_SIZE    16U\r
28 \r
29 /*******************************************************************************\r
30  * Default receive interrupt trigger level\r
31  */\r
32 #define DEFAULT_RX_TRIG_LEVEL  ((uint8_t)UART_16550_FIFO_SINGLE_BYTE)\r
33 \r
34 /*******************************************************************************\r
35  * Receiver error status mask and shift offset\r
36  */\r
37 #define STATUS_ERROR_MASK   ( LSR_OE_MASK | LSR_PE_MASK |  \\r
38                               LSR_FE_MASK | LSR_BI_MASK | LSR_FIER_MASK)\r
39 \r
40 /*******************************************************************************\r
41  * Definitions for invalid parameters with proper type\r
42  */\r
43 #define INVALID_INTERRUPT   0U\r
44 #define INVALID_IRQ_HANDLER ( (uart_16550_irq_handler_t) 0 )\r
45 \r
46 /*******************************************************************************\r
47  * Possible values for Interrupt Identification Register Field.\r
48  */\r
49 #define IIRF_MODEM_STATUS       0x00U\r
50 #define IIRF_THRE               0x02U\r
51 #define IIRF_RX_DATA            0x04U\r
52 #define IIRF_RX_LINE_STATUS     0x06U\r
53 #define IIRF_DATA_TIMEOUT       0x0CU\r
54 \r
55 /*******************************************************************************\r
56  * Null parameters with appropriate type definitions\r
57  */\r
58 #define NULL_ADDR       ( ( addr_t ) 0 )\r
59 #define NULL_INSTANCE   ( ( uart_16550_instance_t * ) 0 )\r
60 #define NULL_BUFF       ( ( uint8_t * ) 0 )\r
61 \r
62 /*******************************************************************************\r
63  * Possible states for different register bit fields\r
64  */\r
65 enum {\r
66     DISABLE = 0U,\r
67     ENABLE  = 1U\r
68 };\r
69 \r
70 /*******************************************************************************\r
71  * Static function declarations\r
72  */\r
73 static void default_tx_handler(uart_16550_instance_t * this_uart);\r
74 \r
75 /*******************************************************************************\r
76  * Public function definitions\r
77  */\r
78 \r
79 /***************************************************************************//**\r
80  * UART_16550_init.\r
81  * See core_16550.h for details of how to use this function.\r
82  */\r
83 void\r
84 UART_16550_init\r
85 (\r
86     uart_16550_instance_t* this_uart,\r
87     addr_t base_addr,\r
88     uint16_t baud_value,\r
89     uint8_t line_config\r
90 )\r
91 {\r
92 #ifndef NDEBUG\r
93     uint8_t dbg1;\r
94     uint8_t dbg2;\r
95 #endif\r
96     uint8_t fifo_config;\r
97     uint8_t temp;\r
98 \r
99     HAL_ASSERT( base_addr != NULL_ADDR );\r
100     HAL_ASSERT( this_uart != NULL_INSTANCE );\r
101 \r
102     if( ( base_addr != NULL_ADDR ) && ( this_uart != NULL_INSTANCE ) )\r
103     {\r
104         /* disable interrupts */\r
105         HAL_set_8bit_reg(base_addr, IER, DISABLE);\r
106 \r
107         /* reset divisor latch */\r
108         HAL_set_8bit_reg_field(base_addr, LCR_DLAB, ENABLE);\r
109 #ifndef NDEBUG\r
110         dbg1 =  HAL_get_8bit_reg_field(base_addr, LCR_DLAB );\r
111         HAL_ASSERT( dbg1 == ENABLE );\r
112 #endif\r
113         /* MSB of baud value */\r
114         temp = (uint8_t)(baud_value >> 8);\r
115         HAL_set_8bit_reg(base_addr, DMR, temp );\r
116         /* LSB of baud value */\r
117         HAL_set_8bit_reg(base_addr, DLR, ( (uint8_t)baud_value ) );\r
118 #ifndef NDEBUG\r
119         dbg1 =  HAL_get_8bit_reg(base_addr, DMR );\r
120         dbg2 =  HAL_get_8bit_reg(base_addr, DLR );\r
121         HAL_ASSERT( ( ( ( (uint16_t) dbg1 ) << 8 ) | dbg2 ) == baud_value );\r
122 #endif\r
123         /* reset divisor latch */\r
124         HAL_set_8bit_reg_field(base_addr, LCR_DLAB, DISABLE);\r
125 #ifndef NDEBUG\r
126         dbg1 =  HAL_get_8bit_reg_field(base_addr, LCR_DLAB );\r
127         HAL_ASSERT( dbg1 == DISABLE );\r
128 #endif\r
129         /* set the line control register (bit length, stop bits, parity) */\r
130         HAL_set_8bit_reg( base_addr, LCR, line_config );\r
131 #ifndef NDEBUG\r
132         dbg1 =  HAL_get_8bit_reg(base_addr, LCR );\r
133         HAL_ASSERT( dbg1 == line_config)\r
134 #endif\r
135         /* Enable and configure the RX and TX FIFOs. */\r
136         fifo_config = ((uint8_t)(DEFAULT_RX_TRIG_LEVEL << FCR_TRIG_LEVEL_SHIFT) |\r
137                                  FCR_RDYN_EN_MASK | FCR_CLEAR_RX_MASK |\r
138                                  FCR_CLEAR_TX_MASK | FCR_ENABLE_MASK );\r
139         HAL_set_8bit_reg( base_addr, FCR, fifo_config );\r
140 \r
141         /* disable loopback */\r
142         HAL_set_8bit_reg_field( base_addr, MCR_LOOP, DISABLE );\r
143 #ifndef NDEBUG\r
144         dbg1 =  HAL_get_8bit_reg_field(base_addr, MCR_LOOP);\r
145         HAL_ASSERT( dbg1 == DISABLE );\r
146 #endif\r
147 \r
148         /* Instance setup */\r
149         this_uart->base_address = base_addr;\r
150         this_uart->tx_buffer    = NULL_BUFF;\r
151         this_uart->tx_buff_size = TX_COMPLETE;\r
152         this_uart->tx_idx       = 0U;\r
153         this_uart->tx_handler   = default_tx_handler;\r
154 \r
155         this_uart->rx_handler  = ( (uart_16550_irq_handler_t) 0 );\r
156         this_uart->linests_handler  = ( (uart_16550_irq_handler_t) 0 );\r
157         this_uart->modemsts_handler = ( (uart_16550_irq_handler_t) 0 );\r
158         this_uart->status = 0U;\r
159     }\r
160 }\r
161 \r
162 /***************************************************************************//**\r
163  * UART_16550_polled_tx.\r
164  * See core_16550.h for details of how to use this function.\r
165  */\r
166 void\r
167 UART_16550_polled_tx\r
168 (\r
169     uart_16550_instance_t * this_uart,\r
170     const uint8_t * pbuff,\r
171     uint32_t tx_size\r
172 )\r
173 {\r
174     uint32_t char_idx = 0U;\r
175     uint32_t size_sent;\r
176     uint8_t status;\r
177 \r
178     HAL_ASSERT( this_uart != NULL_INSTANCE );\r
179     HAL_ASSERT( pbuff != NULL_BUFF );\r
180     HAL_ASSERT( tx_size > 0U );\r
181 \r
182     if( ( this_uart != NULL_INSTANCE ) &&\r
183         ( pbuff != NULL_BUFF ) &&\r
184         ( tx_size > 0U ) )\r
185     {\r
186         /* Remain in this loop until the entire input buffer\r
187          * has been transferred to the UART.\r
188          */\r
189         do {\r
190             /* Read the Line Status Register and update the sticky record */\r
191             status = HAL_get_8bit_reg( this_uart->base_address, LSR );\r
192             this_uart->status |= status;\r
193 \r
194             /* Check if TX FIFO is empty. */\r
195             if( status & LSR_THRE_MASK )\r
196             {\r
197                 uint32_t fill_size = TX_FIFO_SIZE;\r
198 \r
199                 /* Calculate the number of bytes to transmit. */\r
200                 if ( tx_size < TX_FIFO_SIZE )\r
201                 {\r
202                     fill_size = tx_size;\r
203                 }\r
204 \r
205                 /* Fill the TX FIFO with the calculated the number of bytes. */\r
206                 for ( size_sent = 0U; size_sent < fill_size; ++size_sent )\r
207                 {\r
208                     /* Send next character in the buffer. */\r
209                     HAL_set_8bit_reg( this_uart->base_address, THR,\r
210                                       (uint_fast8_t)pbuff[char_idx++]);\r
211                 }\r
212 \r
213                 /* Calculate the number of untransmitted bytes remaining. */\r
214                 tx_size -= size_sent;\r
215             }\r
216         } while ( tx_size );\r
217     }\r
218 }\r
219 \r
220 /***************************************************************************//**\r
221  * UART_16550_polled_tx_string.\r
222  * See core_16550.h for details of how to use this function.\r
223  */\r
224 void\r
225 UART_16550_polled_tx_string\r
226 (\r
227     uart_16550_instance_t * this_uart,\r
228     const uint8_t * p_sz_string\r
229 )\r
230 {\r
231     uint32_t char_idx = 0U;\r
232     uint32_t fill_size;\r
233     uint_fast8_t data_byte;\r
234     uint8_t status;\r
235 \r
236     HAL_ASSERT( this_uart != NULL_INSTANCE );\r
237     HAL_ASSERT( p_sz_string != NULL_BUFF );\r
238 \r
239     if( ( this_uart != NULL_INSTANCE ) && ( p_sz_string != NULL_BUFF ) )\r
240     {\r
241         char_idx = 0U;\r
242 \r
243         /* Get the first data byte from the input buffer */\r
244         data_byte = (uint_fast8_t)p_sz_string[char_idx];\r
245 \r
246         /* First check for the NULL terminator byte.\r
247          * Then remain in this loop until the entire string in the input buffer\r
248          * has been transferred to the UART.\r
249          */\r
250         while ( 0U != data_byte )\r
251         {\r
252             /* Wait until TX FIFO is empty. */\r
253             do {\r
254                 status = HAL_get_8bit_reg( this_uart->base_address,LSR);\r
255                 this_uart->status |= status;\r
256             } while ( !( status & LSR_THRE_MASK ) );\r
257 \r
258             /* Send bytes from the input buffer until the TX FIFO is full\r
259              * or we reach the NULL terminator byte.\r
260              */\r
261             fill_size = 0U;\r
262             while ( (0U != data_byte) && (fill_size < TX_FIFO_SIZE) )\r
263             {\r
264                 /* Send the data byte */\r
265                 HAL_set_8bit_reg( this_uart->base_address, THR, data_byte );\r
266                 ++fill_size;\r
267                 char_idx++;\r
268                 /* Get the next data byte from the input buffer */\r
269                 data_byte = (uint_fast8_t)p_sz_string[char_idx];\r
270             }\r
271         }\r
272     }\r
273 }\r
274 \r
275 \r
276 /***************************************************************************//**\r
277  * UART_16550_irq_tx.\r
278  * See core_16550.h for details of how to use this function.\r
279  */\r
280 void\r
281 UART_16550_irq_tx\r
282 (\r
283     uart_16550_instance_t * this_uart,\r
284     const uint8_t * pbuff,\r
285     uint32_t tx_size\r
286 )\r
287 {\r
288     HAL_ASSERT( this_uart != NULL_INSTANCE )\r
289     HAL_ASSERT( pbuff != NULL_BUFF )\r
290     HAL_ASSERT( tx_size > 0U )\r
291 \r
292     if( ( this_uart != NULL_INSTANCE ) &&\r
293         ( pbuff != NULL_BUFF ) &&\r
294         ( tx_size > 0U ) )\r
295     {\r
296         /*Initialize the UART instance with\r
297           parameters required for transmission.*/\r
298         this_uart->tx_buffer = pbuff;\r
299         this_uart->tx_buff_size = tx_size;\r
300         /* char_idx; */\r
301         this_uart->tx_idx = 0U;\r
302         /* assign handler for default data transmission */\r
303         this_uart->tx_handler = default_tx_handler;\r
304 \r
305         /* enables TX interrupt */\r
306         HAL_set_8bit_reg_field(this_uart->base_address, IER_ETBEI, ENABLE);\r
307     }\r
308 }\r
309 \r
310 /***************************************************************************//**\r
311  * UART_16550_tx_complete.\r
312  * See core_16550.h for details of how to use this function.\r
313  */\r
314 int8_t\r
315 UART_16550_tx_complete\r
316 (\r
317     uart_16550_instance_t * this_uart\r
318 )\r
319 {\r
320     int8_t returnvalue = 0;\r
321     uint8_t status = 0U;\r
322 \r
323     HAL_ASSERT( this_uart != NULL_INSTANCE )\r
324 \r
325     if( this_uart != NULL_INSTANCE )\r
326     {\r
327         status = HAL_get_8bit_reg(this_uart->base_address,LSR);\r
328         this_uart->status |= status;\r
329 \r
330         if( ( this_uart->tx_buff_size == TX_COMPLETE ) &&\r
331                              ( status & LSR_TEMT_MASK ) )\r
332         {\r
333             returnvalue = (int8_t)1;\r
334         }\r
335     }\r
336     return returnvalue;\r
337 }\r
338 \r
339 \r
340 /***************************************************************************//**\r
341  * UART_16550_get_rx.\r
342  * See core_16550.h for details of how to use this function.\r
343  */\r
344 size_t\r
345 UART_16550_get_rx\r
346 (\r
347     uart_16550_instance_t * this_uart,\r
348     uint8_t * rx_buff,\r
349     size_t buff_size\r
350 )\r
351 {\r
352     uint8_t status;\r
353     size_t rx_size = 0U;\r
354 \r
355     HAL_ASSERT( this_uart != NULL_INSTANCE )\r
356     HAL_ASSERT( rx_buff != (uint8_t *)0 )\r
357     HAL_ASSERT( buff_size > 0U )\r
358 \r
359     if( ( this_uart != NULL_INSTANCE ) &&\r
360         ( rx_buff != (uint8_t *)0 ) &&\r
361         ( buff_size > 0U ) )\r
362     {\r
363         status = HAL_get_8bit_reg( this_uart->base_address, LSR );\r
364         this_uart->status |= status;\r
365         while ( ((status & LSR_DR_MASK) != 0U) && ( rx_size < buff_size ) )\r
366         {\r
367             rx_buff[rx_size] = HAL_get_8bit_reg( this_uart->base_address, RBR );\r
368             rx_size++;\r
369             status = HAL_get_8bit_reg( this_uart->base_address, LSR );\r
370             this_uart->status |= status;\r
371         }\r
372     }\r
373     return rx_size;\r
374 }\r
375 \r
376 /***************************************************************************//**\r
377  * UART_16550_isr.\r
378  * See core_16550.h for details of how to use this function.\r
379  */\r
380 void\r
381 UART_16550_isr\r
382 (\r
383     uart_16550_instance_t * this_uart\r
384 )\r
385 {\r
386     uint8_t iirf;\r
387 \r
388     HAL_ASSERT( this_uart != NULL_INSTANCE )\r
389 \r
390     if(this_uart != NULL_INSTANCE )\r
391     {\r
392         iirf = HAL_get_8bit_reg_field( this_uart->base_address, IIR_IIR );\r
393 \r
394         switch ( iirf )\r
395         {\r
396             /* Modem status interrupt */\r
397             case IIRF_MODEM_STATUS:\r
398             {\r
399                 if( INVALID_IRQ_HANDLER != this_uart->modemsts_handler  )\r
400                 {\r
401                     HAL_ASSERT( INVALID_IRQ_HANDLER != this_uart->modemsts_handler );\r
402                     if( INVALID_IRQ_HANDLER != this_uart->modemsts_handler )\r
403                     {\r
404                         (*(this_uart->modemsts_handler))(this_uart);\r
405                     }\r
406                 }\r
407             }\r
408             break;\r
409             /* Transmitter Holding Register Empty interrupt */\r
410             case IIRF_THRE:\r
411             {\r
412                 HAL_ASSERT( INVALID_IRQ_HANDLER != this_uart->tx_handler );\r
413                 if ( INVALID_IRQ_HANDLER != this_uart->tx_handler )\r
414                 {\r
415                     (*(this_uart->tx_handler))(this_uart);\r
416                 }\r
417             }\r
418             break;\r
419             /* Received Data Available interrupt */\r
420             case IIRF_RX_DATA:\r
421             case IIRF_DATA_TIMEOUT:\r
422             {\r
423                 HAL_ASSERT( INVALID_IRQ_HANDLER != this_uart->rx_handler );\r
424                 if ( INVALID_IRQ_HANDLER != this_uart->rx_handler )\r
425                 {\r
426                     (*(this_uart->rx_handler))(this_uart);\r
427                 }\r
428             }\r
429             break;\r
430             /* Line status interrupt */\r
431             case IIRF_RX_LINE_STATUS:\r
432             {\r
433                 HAL_ASSERT( INVALID_IRQ_HANDLER != this_uart->linests_handler );\r
434                 if ( INVALID_IRQ_HANDLER != this_uart->linests_handler )\r
435                 {\r
436                     (*(this_uart->linests_handler))(this_uart);\r
437                 }\r
438             }\r
439             break;\r
440             /* Unidentified interrupt */\r
441             default:\r
442             {\r
443                 HAL_ASSERT( INVALID_INTERRUPT )\r
444             }\r
445         }\r
446     }\r
447 }\r
448 \r
449 /***************************************************************************//**\r
450  * UART_16550_set_rx_handler.\r
451  * See core_16550.h for details of how to use this function.\r
452  */\r
453 void\r
454 UART_16550_set_rx_handler\r
455 (\r
456     uart_16550_instance_t * this_uart,\r
457     uart_16550_irq_handler_t handler,\r
458     uart_16550_rx_trig_level_t trigger_level\r
459 )\r
460 {\r
461     HAL_ASSERT( this_uart != NULL_INSTANCE )\r
462     HAL_ASSERT( handler != INVALID_IRQ_HANDLER)\r
463     HAL_ASSERT( trigger_level < UART_16550_FIFO_INVALID_TRIG_LEVEL)\r
464 \r
465     if( ( this_uart != NULL_INSTANCE ) &&\r
466         ( handler != INVALID_IRQ_HANDLER) &&\r
467         ( trigger_level < UART_16550_FIFO_INVALID_TRIG_LEVEL) )\r
468     {\r
469         this_uart->rx_handler = handler;\r
470 \r
471         /* Set the receive interrupt trigger level. */\r
472         HAL_set_8bit_reg_field( this_uart->base_address,\r
473                             FCR_TRIG_LEVEL, trigger_level );\r
474 \r
475         /* Enable receive interrupt. */\r
476         HAL_set_8bit_reg_field( this_uart->base_address, IER_ERBFI, ENABLE );\r
477     }\r
478 }\r
479 \r
480 /***************************************************************************//**\r
481  * UART_16550_set_loopback.\r
482  * See core_16550.h for details of how to use this function.\r
483  */\r
484 void\r
485 UART_16550_set_loopback\r
486 (\r
487     uart_16550_instance_t * this_uart,\r
488     uart_16550_loopback_t loopback\r
489 )\r
490 {\r
491     HAL_ASSERT( this_uart != NULL_INSTANCE );\r
492     HAL_ASSERT( loopback < UART_16550_INVALID_LOOPBACK );\r
493 \r
494     if( ( this_uart != NULL_INSTANCE ) &&\r
495         ( loopback < UART_16550_INVALID_LOOPBACK ) )\r
496     {\r
497         if ( loopback == UART_16550_LOOPBACK_OFF )\r
498         {\r
499             HAL_set_8bit_reg_field( this_uart->base_address,\r
500                                     MCR_LOOP,\r
501                                     DISABLE );\r
502         }\r
503         else\r
504         {\r
505             HAL_set_8bit_reg_field( this_uart->base_address,\r
506                                     MCR_LOOP,\r
507                                     ENABLE );\r
508         }\r
509     }\r
510 }\r
511 \r
512 /***************************************************************************//**\r
513  * UART_16550_get_rx_status.\r
514  * See core_16550.h for details of how to use this function.\r
515  */\r
516 uint8_t\r
517 UART_16550_get_rx_status\r
518 (\r
519     uart_16550_instance_t * this_uart\r
520 )\r
521 {\r
522     uint8_t status = UART_16550_INVALID_PARAM;\r
523     HAL_ASSERT( this_uart != NULL_INSTANCE );\r
524 \r
525     if( ( this_uart != NULL_INSTANCE ) )\r
526     {\r
527         /*\r
528          * Bit 1 - Overflow error status\r
529          * Bit 2 - Parity error status\r
530          * Bit 3 - Frame error status\r
531          * Bit 4 - Break interrupt indicator\r
532          * Bit 7 - FIFO data error status\r
533          */\r
534         this_uart->status |= HAL_get_8bit_reg( this_uart->base_address, LSR );\r
535         status = ( this_uart->status & STATUS_ERROR_MASK );\r
536         /*\r
537          * Clear the sticky status for this instance.\r
538          */\r
539         this_uart->status = (uint8_t)0;\r
540     }\r
541     return status;\r
542 }\r
543 \r
544 /***************************************************************************//**\r
545  * UART_16550_get_modem_status.\r
546  * See core_16550.h for details of how to use this function.\r
547  */\r
548 uint8_t\r
549 UART_16550_get_modem_status\r
550 (\r
551     uart_16550_instance_t * this_uart\r
552 )\r
553 {\r
554     uint8_t status = UART_16550_NO_ERROR;\r
555     HAL_ASSERT( this_uart != NULL_INSTANCE )\r
556 \r
557     if( ( this_uart != NULL_INSTANCE ) )\r
558     {\r
559         /*\r
560          * Extract UART error status and place in lower bits of "status".\r
561          * Bit 0 - Delta Clear to Send Indicator\r
562          * Bit 1 - Delta Clear to Receive Indicator\r
563          * Bit 2 - Trailing edge of Ring Indicator detector\r
564          * Bit 3 - Delta Data Carrier Detect indicator\r
565          * Bit 4 - Clear To Send\r
566          * Bit 5 - Data Set Ready\r
567          * Bit 6 - Ring Indicator\r
568          * Bit 7 - Data Carrier Detect\r
569          */\r
570         status = HAL_get_8bit_reg( this_uart->base_address, MSR );\r
571     }\r
572     return status;\r
573 }\r
574 \r
575 /***************************************************************************//**\r
576  * Default TX interrupt handler to automatically transmit data from\r
577  * user assgined TX buffer.\r
578  */\r
579 static void\r
580 default_tx_handler\r
581 (\r
582     uart_16550_instance_t * this_uart\r
583 )\r
584 {\r
585     uint8_t status;\r
586 \r
587     HAL_ASSERT( NULL_INSTANCE != this_uart )\r
588 \r
589     if ( this_uart != NULL_INSTANCE )\r
590     {\r
591         HAL_ASSERT( NULL_BUFF != this_uart->tx_buffer )\r
592         HAL_ASSERT( 0U != this_uart->tx_buff_size )\r
593 \r
594         if ( ( this_uart->tx_buffer != NULL_BUFF ) &&\r
595              ( 0U != this_uart->tx_buff_size ) )\r
596         {\r
597             /* Read the Line Status Register and update the sticky record. */\r
598             status = HAL_get_8bit_reg( this_uart->base_address,LSR);\r
599             this_uart->status |= status;\r
600     \r
601             /*\r
602              * This function should only be called as a result of a THRE interrupt.\r
603              * Verify that this is true before proceeding to transmit data.\r
604              */\r
605             if ( status & LSR_THRE_MASK )\r
606             {\r
607                 uint32_t size_sent = 0U;\r
608                 uint32_t fill_size = TX_FIFO_SIZE;\r
609                 uint32_t tx_remain = this_uart->tx_buff_size - this_uart->tx_idx;\r
610     \r
611                 /* Calculate the number of bytes to transmit. */\r
612                 if ( tx_remain < TX_FIFO_SIZE )\r
613                 {\r
614                     fill_size = tx_remain;\r
615                 }\r
616     \r
617                 /* Fill the TX FIFO with the calculated the number of bytes. */\r
618                 for ( size_sent = 0U; size_sent < fill_size; ++size_sent )\r
619                 {\r
620                     /* Send next character in the buffer. */\r
621                     HAL_set_8bit_reg( this_uart->base_address, THR,\r
622                             (uint_fast8_t)this_uart->tx_buffer[this_uart->tx_idx]);\r
623                     ++this_uart->tx_idx;\r
624                 }\r
625             }\r
626     \r
627             /* Flag Tx as complete if all data has been pushed into the Tx FIFO. */\r
628             if ( this_uart->tx_idx == this_uart->tx_buff_size )\r
629             {\r
630                 this_uart->tx_buff_size = TX_COMPLETE;\r
631                 /* disables TX interrupt */\r
632                 HAL_set_8bit_reg_field( this_uart->base_address,\r
633                                         IER_ETBEI, DISABLE);\r
634             }\r
635         }\r
636     }\r
637 }\r
638 \r
639 /***************************************************************************//**\r
640  * UART_16550_enable_irq.\r
641  * See core_16550.h for details of how to use this function.\r
642  */\r
643 void\r
644 UART_16550_enable_irq\r
645 (\r
646     uart_16550_instance_t * this_uart,\r
647     uint8_t irq_mask\r
648 )\r
649 {\r
650     HAL_ASSERT( this_uart != NULL_INSTANCE )\r
651 \r
652     if( this_uart != NULL_INSTANCE )\r
653     {\r
654         /* irq_mask encoding: 1- enable\r
655          * bit 0 - Receive Data Available Interrupt\r
656          * bit 1 - Transmitter Holding  Register Empty Interrupt\r
657          * bit 2 - Receiver Line Status Interrupt\r
658          * bit 3 - Modem Status Interrupt\r
659          */\r
660         /* read present interrupts for enabled ones*/\r
661         irq_mask |= HAL_get_8bit_reg( this_uart->base_address, IER );\r
662         /* Enable interrupts */\r
663         HAL_set_8bit_reg( this_uart->base_address, IER, irq_mask );\r
664     }\r
665 }\r
666 \r
667 /***************************************************************************//**\r
668  * UART_16550_disable_irq.\r
669  * See core_16550.h for details of how to use this function.\r
670  */\r
671 void\r
672 UART_16550_disable_irq\r
673 (\r
674     uart_16550_instance_t * this_uart,\r
675     uint8_t irq_mask\r
676 )\r
677 {\r
678     HAL_ASSERT( this_uart != NULL_INSTANCE )\r
679 \r
680     if( this_uart != NULL_INSTANCE )\r
681     {\r
682         /* irq_mask encoding:  1 - disable\r
683          * bit 0 - Receive Data Available Interrupt\r
684          * bit 1 - Transmitter Holding  Register Empty Interrupt\r
685          * bit 2 - Receiver Line Status Interrupt\r
686          * bit 3 - Modem Status Interrupt\r
687          */\r
688         /* read present interrupts for enabled ones */\r
689         irq_mask = (( (uint8_t)~irq_mask ) & \r
690                     HAL_get_8bit_reg( this_uart->base_address, IER ));\r
691         /* Disable interrupts */\r
692         HAL_set_8bit_reg( this_uart->base_address, IER, irq_mask );\r
693     }\r
694 }\r
695 \r
696 /***************************************************************************//**\r
697  * UART_16550_set_rxstatus_handler.\r
698  * See core_16550.h for details of how to use this function.\r
699  */\r
700 void\r
701 UART_16550_set_rxstatus_handler\r
702 (\r
703     uart_16550_instance_t * this_uart,\r
704     uart_16550_irq_handler_t handler\r
705 )\r
706 {\r
707     HAL_ASSERT( this_uart != NULL_INSTANCE )\r
708     HAL_ASSERT( handler != INVALID_IRQ_HANDLER)\r
709 \r
710     if( ( this_uart != NULL_INSTANCE ) &&\r
711         ( handler != INVALID_IRQ_HANDLER) )\r
712     {\r
713         this_uart->linests_handler = handler;\r
714         /* Enable receiver line status interrupt. */\r
715         HAL_set_8bit_reg_field( this_uart->base_address, IER_ELSI, ENABLE );\r
716     }\r
717 }\r
718 \r
719 /***************************************************************************//**\r
720  * UART_16550_set_tx_handler.\r
721  * See core_16550.h for details of how to use this function.\r
722  */\r
723 void\r
724 UART_16550_set_tx_handler\r
725 (\r
726     uart_16550_instance_t * this_uart,\r
727     uart_16550_irq_handler_t handler\r
728 )\r
729 {\r
730     HAL_ASSERT( this_uart != NULL_INSTANCE )\r
731     HAL_ASSERT( handler != INVALID_IRQ_HANDLER)\r
732 \r
733     if( ( this_uart != NULL_INSTANCE ) &&\r
734         ( handler != INVALID_IRQ_HANDLER) )\r
735     {\r
736         this_uart->tx_handler = handler;\r
737 \r
738         /* Make TX buffer info invalid */\r
739         this_uart->tx_buffer = NULL_BUFF;\r
740         this_uart->tx_buff_size = 0U;\r
741 \r
742         /* Enable transmitter holding register Empty interrupt. */\r
743         HAL_set_8bit_reg_field( this_uart->base_address, IER_ETBEI, ENABLE );\r
744     }\r
745 }\r
746 \r
747 /***************************************************************************//**\r
748  * UART_16550_set_modemstatus_handler.\r
749  * See core_16550.h for details of how to use this function.\r
750  */\r
751 void\r
752 UART_16550_set_modemstatus_handler\r
753 (\r
754     uart_16550_instance_t * this_uart,\r
755     uart_16550_irq_handler_t handler\r
756 )\r
757 {\r
758     HAL_ASSERT( this_uart != NULL_INSTANCE )\r
759     HAL_ASSERT( handler != INVALID_IRQ_HANDLER)\r
760 \r
761     if( ( this_uart != NULL_INSTANCE ) &&\r
762         ( handler != INVALID_IRQ_HANDLER) )\r
763     {\r
764         this_uart->modemsts_handler = handler;\r
765         /* Enable modem status interrupt. */\r
766         HAL_set_8bit_reg_field( this_uart->base_address, IER_EDSSI, ENABLE );\r
767     }\r
768 }\r
769 \r
770 /***************************************************************************//**\r
771  * UART_16550_fill_tx_fifo.\r
772  * See core_16550.h for details of how to use this function.\r
773  */\r
774 size_t\r
775 UART_16550_fill_tx_fifo\r
776 (\r
777     uart_16550_instance_t * this_uart,\r
778     const uint8_t * tx_buffer,\r
779     size_t tx_size\r
780 )\r
781 {\r
782     uint8_t status;\r
783     size_t size_sent = 0U;\r
784 \r
785     HAL_ASSERT( this_uart != NULL_INSTANCE )\r
786     HAL_ASSERT( tx_buffer != NULL_BUFF )\r
787     HAL_ASSERT( tx_size > 0U )\r
788 \r
789     /* Fill the UART's Tx FIFO until the FIFO is full or the complete input\r
790      * buffer has been written. */\r
791     if( (this_uart != NULL_INSTANCE) &&\r
792         (tx_buffer != NULL_BUFF)   &&\r
793         (tx_size > 0U) )\r
794     {\r
795         /* Read the Line Status Register and update the sticky record. */\r
796         status = HAL_get_8bit_reg( this_uart->base_address, LSR );\r
797         this_uart->status |= status;\r
798 \r
799         /* Check if TX FIFO is empty. */\r
800         if( status & LSR_THRE_MASK )\r
801         {\r
802             uint32_t fill_size = TX_FIFO_SIZE;\r
803 \r
804             /* Calculate the number of bytes to transmit. */\r
805             if ( tx_size < TX_FIFO_SIZE )\r
806             {\r
807                 fill_size = tx_size;\r
808             }\r
809 \r
810             /* Fill the TX FIFO with the calculated the number of bytes. */\r
811             for ( size_sent = 0U; size_sent < fill_size; ++size_sent )\r
812             {\r
813                 /* Send next character in the buffer. */\r
814                 HAL_set_8bit_reg( this_uart->base_address, THR,\r
815                                   (uint_fast8_t)tx_buffer[size_sent]);\r
816             }\r
817         }\r
818     }\r
819     return size_sent;\r
820 }\r
821 \r
822 /***************************************************************************//**\r
823  * UART_16550_get_tx_status.\r
824  * See core_16550.h for details of how to use this function.\r
825  */\r
826 uint8_t\r
827 UART_16550_get_tx_status\r
828 (\r
829     uart_16550_instance_t * this_uart\r
830 )\r
831 {\r
832     uint8_t status = UART_16550_TX_BUSY;\r
833     HAL_ASSERT( this_uart != NULL_INSTANCE );\r
834 \r
835     if( ( this_uart != NULL_INSTANCE ) )\r
836     {\r
837         /* Read the Line Status Register and update the sticky record. */\r
838         status = HAL_get_8bit_reg( this_uart->base_address, LSR );\r
839         this_uart->status |= status;\r
840         /*\r
841          * Extract the transmit status bits from the UART's Line Status Register.\r
842          * Bit 5 - Transmitter Holding Register/FIFO Empty (THRE) status. (If = 1, TX FIFO is empty)\r
843          * Bit 6 - Transmitter Empty (TEMT) status. (If = 1, both TX FIFO and shift register are empty)\r
844          */\r
845         status &= ( LSR_THRE_MASK | LSR_TEMT_MASK );\r
846     }\r
847     return status;\r
848 }\r
849 \r
850 \r
851 #ifdef __cplusplus\r
852 }\r
853 #endif\r
854 \r
855 \r
856 \r
857 \r
858 \r
859 \r
860 \r
861 \r
862 \r
863 \r
864 \r
865 \r