]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/drivers/CoreUARTapb/core_uart_apb.c
Microsemi RISC-V project:
[freertos] / FreeRTOS / Demo / RISC-V_IGLOO2_Creative_SoftConsole / Microsemi_Code / drivers / CoreUARTapb / core_uart_apb.c
1 /*******************************************************************************\r
2  * (c) Copyright 2007-2017 Microsemi SoC Products Group. All rights reserved.\r
3  * \r
4  * CoreUARTapb driver implementation. See file "core_uart_apb.h" for a\r
5  * description of the functions implemented in this file.\r
6  * \r
7  * SVN $Revision: 9082 $\r
8  * SVN $Date: 2017-04-28 11:51:36 +0530 (Fri, 28 Apr 2017) $\r
9  */\r
10 #include "hal.h"\r
11 #include "coreuartapb_regs.h"\r
12 #include "core_uart_apb.h"\r
13 #include "hal_assert.h"\r
14 \r
15 #ifdef __cplusplus\r
16 extern "C" {\r
17 #endif\r
18 \r
19 #define NULL_INSTANCE ( ( UART_instance_t* ) 0 )\r
20 #define NULL_BUFFER   ( ( uint8_t* ) 0 )\r
21 \r
22 #define MAX_LINE_CONFIG     ( ( uint8_t )( DATA_8_BITS | ODD_PARITY ) )\r
23 #define MAX_BAUD_VALUE      ( ( uint16_t )( 0x1FFF ) )\r
24 #define STATUS_ERROR_MASK   ( ( uint8_t )( STATUS_PARITYERR_MASK | \\r
25                                            STATUS_OVERFLOW_MASK  | \\r
26                                            STATUS_FRAMERR_MASK ) )\r
27 #define BAUDVALUE_LSB ( (uint16_t) (0x00FF) )\r
28 #define BAUDVALUE_MSB ( (uint16_t) (0xFF00) )\r
29 #define BAUDVALUE_SHIFT ( (uint8_t) (5) )\r
30 \r
31 #define STATUS_ERROR_OFFSET STATUS_PARITYERR_SHIFT \r
32 \r
33 /***************************************************************************//**\r
34  * UART_init()\r
35  * See "core_uart_apb.h" for details of how to use this function.\r
36  */\r
37 void\r
38 UART_init\r
39 (\r
40     UART_instance_t * this_uart,\r
41     addr_t base_addr,\r
42     uint16_t baud_value,\r
43     uint8_t line_config\r
44 )\r
45 {\r
46     uint8_t rx_full;\r
47     \r
48     HAL_ASSERT( this_uart != NULL_INSTANCE )\r
49     HAL_ASSERT( line_config <= MAX_LINE_CONFIG )\r
50     HAL_ASSERT( baud_value <= MAX_BAUD_VALUE )\r
51 \r
52     if( ( this_uart != NULL_INSTANCE ) &&\r
53         ( line_config <= MAX_LINE_CONFIG ) &&\r
54         ( baud_value <= MAX_BAUD_VALUE ) )\r
55     {\r
56         /*\r
57          * Store lower 8-bits of baud value in CTRL1.\r
58          */\r
59         HAL_set_8bit_reg( base_addr, CTRL1, (uint_fast8_t)(baud_value &\r
60                                                        BAUDVALUE_LSB ) );\r
61     \r
62         /*\r
63          * Extract higher 5-bits of baud value and store in higher 5-bits \r
64          * of CTRL2, along with line configuration in lower 3 three bits.\r
65          */\r
66         HAL_set_8bit_reg( base_addr, CTRL2, (uint_fast8_t)line_config | \r
67                                            (uint_fast8_t)((baud_value &\r
68                                    BAUDVALUE_MSB) >> BAUDVALUE_SHIFT ) );\r
69     \r
70         this_uart->base_address = base_addr;\r
71 #ifndef NDEBUG\r
72         {\r
73             uint8_t  config;\r
74             uint8_t  temp;\r
75             uint16_t baud_val;\r
76             baud_val = HAL_get_8bit_reg( this_uart->base_address, CTRL1 );\r
77             config =  HAL_get_8bit_reg( this_uart->base_address, CTRL2 );\r
78             /*\r
79              * To resolve operator precedence between & and <<\r
80              */\r
81             temp =  ( config  &  (uint8_t)(CTRL2_BAUDVALUE_MASK ) );\r
82             baud_val |= (uint16_t)( (uint16_t)(temp) << BAUDVALUE_SHIFT );\r
83             config &= (uint8_t)(~CTRL2_BAUDVALUE_MASK);\r
84             HAL_ASSERT( baud_val == baud_value );\r
85             HAL_ASSERT( config == line_config );\r
86         }        \r
87 #endif\r
88         \r
89         /*\r
90          * Flush the receive FIFO of data that may have been received before the\r
91          * driver was initialized.\r
92          */\r
93         rx_full = HAL_get_8bit_reg( this_uart->base_address, STATUS ) &\r
94                                                     STATUS_RXFULL_MASK;\r
95         while ( rx_full )\r
96         {\r
97             HAL_get_8bit_reg( this_uart->base_address, RXDATA );\r
98             rx_full = HAL_get_8bit_reg( this_uart->base_address, STATUS ) &\r
99                                                         STATUS_RXFULL_MASK;\r
100         }\r
101 \r
102         /*\r
103          * Clear status of the UART instance.\r
104          */\r
105         this_uart->status = (uint8_t)0;\r
106     }\r
107 }\r
108 \r
109 /***************************************************************************//**\r
110  * UART_send()\r
111  * See "core_uart_apb.h" for details of how to use this function.\r
112  */\r
113 void\r
114 UART_send\r
115 (\r
116     UART_instance_t * this_uart,\r
117     const uint8_t * tx_buffer,\r
118     size_t tx_size\r
119 )\r
120 {\r
121     size_t char_idx;\r
122     uint8_t tx_ready;\r
123 \r
124     HAL_ASSERT( this_uart != NULL_INSTANCE )\r
125     HAL_ASSERT( tx_buffer != NULL_BUFFER )\r
126     HAL_ASSERT( tx_size > 0 )\r
127       \r
128     if( (this_uart != NULL_INSTANCE) &&\r
129         (tx_buffer != NULL_BUFFER)   &&\r
130         (tx_size > (size_t)0) )\r
131     {\r
132         for ( char_idx = (size_t)0; char_idx < tx_size; char_idx++ )\r
133         {\r
134             /* Wait for UART to become ready to transmit. */\r
135             do {\r
136                 tx_ready = HAL_get_8bit_reg( this_uart->base_address, STATUS ) &\r
137                                                               STATUS_TXRDY_MASK;\r
138             } while ( !tx_ready );\r
139             /* Send next character in the buffer. */\r
140             HAL_set_8bit_reg( this_uart->base_address, TXDATA,\r
141                               (uint_fast8_t)tx_buffer[char_idx] );\r
142         }\r
143     }\r
144 }\r
145 \r
146 /***************************************************************************//**\r
147  * UART_fill_tx_fifo()\r
148  * See "core_uart_apb.h" for details of how to use this function.\r
149  */\r
150 size_t\r
151 UART_fill_tx_fifo\r
152 (\r
153     UART_instance_t * this_uart,\r
154     const uint8_t * tx_buffer,\r
155     size_t tx_size\r
156 )\r
157 {\r
158     uint8_t tx_ready;\r
159     size_t size_sent = 0u;\r
160     \r
161     HAL_ASSERT( this_uart != NULL_INSTANCE )\r
162     HAL_ASSERT( tx_buffer != NULL_BUFFER )\r
163     HAL_ASSERT( tx_size > 0 )\r
164       \r
165     /* Fill the UART's Tx FIFO until the FIFO is full or the complete input \r
166      * buffer has been written. */\r
167     if( (this_uart != NULL_INSTANCE) &&\r
168         (tx_buffer != NULL_BUFFER)   &&\r
169         (tx_size > 0u) )\r
170     {\r
171         tx_ready = HAL_get_8bit_reg( this_uart->base_address, STATUS ) &\r
172                                                       STATUS_TXRDY_MASK;\r
173         if ( tx_ready )\r
174         {\r
175             do {\r
176                 HAL_set_8bit_reg( this_uart->base_address, TXDATA,\r
177                                   (uint_fast8_t)tx_buffer[size_sent] );\r
178                 size_sent++;\r
179                 tx_ready = HAL_get_8bit_reg( this_uart->base_address, STATUS ) &\r
180                                                               STATUS_TXRDY_MASK;\r
181             } while ( (tx_ready) && ( size_sent < tx_size ) );\r
182         }\r
183     }    \r
184     return size_sent;\r
185 }\r
186 \r
187 /***************************************************************************//**\r
188  * UART_get_rx()\r
189  * See "core_uart_apb.h" for details of how to use this function.\r
190  */\r
191 size_t\r
192 UART_get_rx\r
193 (\r
194     UART_instance_t * this_uart,\r
195     uint8_t * rx_buffer,\r
196     size_t buff_size\r
197 )\r
198 {\r
199     uint8_t new_status;\r
200     uint8_t rx_full;\r
201     size_t rx_idx = 0u;\r
202     \r
203     HAL_ASSERT( this_uart != NULL_INSTANCE )\r
204     HAL_ASSERT( rx_buffer != NULL_BUFFER )\r
205     HAL_ASSERT( buff_size > 0 )\r
206       \r
207     if( (this_uart != NULL_INSTANCE) &&\r
208         (rx_buffer != NULL_BUFFER)   &&\r
209         (buff_size > 0u) )\r
210     {\r
211         rx_idx = 0u;\r
212         new_status = HAL_get_8bit_reg( this_uart->base_address, STATUS );\r
213         this_uart->status |= new_status;\r
214         rx_full = new_status & STATUS_RXFULL_MASK;\r
215         while ( ( rx_full ) && ( rx_idx < buff_size ) )\r
216         {\r
217             rx_buffer[rx_idx] = HAL_get_8bit_reg( this_uart->base_address,\r
218                                                   RXDATA );\r
219             rx_idx++;\r
220             new_status = HAL_get_8bit_reg( this_uart->base_address, STATUS );\r
221             this_uart->status |= new_status;\r
222             rx_full = new_status & STATUS_RXFULL_MASK;\r
223         }\r
224     }\r
225     return rx_idx;\r
226 }\r
227 \r
228 /***************************************************************************//**\r
229  * UART_polled_tx_string()\r
230  * See "core_uart_apb.h" for details of how to use this function.\r
231  */\r
232 void \r
233 UART_polled_tx_string\r
234\r
235     UART_instance_t * this_uart, \r
236     const uint8_t * p_sz_string\r
237 )\r
238 {\r
239     uint32_t char_idx;\r
240     uint8_t tx_ready;\r
241 \r
242     HAL_ASSERT( this_uart != NULL_INSTANCE )\r
243     HAL_ASSERT( p_sz_string != NULL_BUFFER )\r
244     \r
245     if( ( this_uart != NULL_INSTANCE ) && ( p_sz_string != NULL_BUFFER ) )\r
246     {\r
247         char_idx = 0U;\r
248         while( 0U != p_sz_string[char_idx] )\r
249         {\r
250             /* Wait for UART to become ready to transmit. */\r
251             do {\r
252                 tx_ready = HAL_get_8bit_reg( this_uart->base_address, STATUS ) &\r
253                                                               STATUS_TXRDY_MASK;\r
254             } while ( !tx_ready );\r
255             /* Send next character in the buffer. */\r
256             HAL_set_8bit_reg( this_uart->base_address, TXDATA,\r
257                               (uint_fast8_t)p_sz_string[char_idx] );\r
258             char_idx++;\r
259         }\r
260     }\r
261 }\r
262 \r
263 /***************************************************************************//**\r
264  * UART_get_rx_status()\r
265  * See "core_uart_apb.h" for details of how to use this function.\r
266  */\r
267 uint8_t\r
268 UART_get_rx_status\r
269 (\r
270     UART_instance_t * this_uart\r
271 )\r
272 {\r
273     uint8_t status = UART_APB_INVALID_PARAM;\r
274 \r
275     HAL_ASSERT( this_uart != NULL_INSTANCE )\r
276     /*\r
277      * Extract UART error status and place in lower bits of "status".\r
278      * Bit 0 - Parity error status\r
279      * Bit 1 - Overflow error status\r
280      * Bit 2 - Frame error status\r
281      */\r
282     if( this_uart != NULL_INSTANCE )\r
283     {\r
284         status = ( ( this_uart->status & STATUS_ERROR_MASK ) >> \r
285                                           STATUS_ERROR_OFFSET );\r
286         /*\r
287          * Clear the sticky status for this instance.\r
288          */\r
289         this_uart->status = (uint8_t)0;\r
290     }\r
291     return status;\r
292 }\r
293 \r
294 #ifdef __cplusplus\r
295 }\r
296 #endif\r