1 /*!
2 * \file uart-board.c
3 *
4 * \brief Target board UART driver implementation
5 *
6 * \copyright Revised BSD License, see section \ref LICENSE.
7 *
8 * \code
9 * ______ _
10 * / _____) _ | |
11 * ( (____ _____ ____ _| |_ _____ ____| |__
12 * \____ \| ___ | (_ _) ___ |/ ___) _ \
13 * _____) ) ____| | | || |_| ____( (___| | | |
14 * (______/|_____)_|_|_| \__)_____)\____)_| |_|
15 * (C)2013-2017 Semtech
16 *
17 * \endcode
18 *
19 * \author Miguel Luis ( Semtech )
20 *
21 * \author Gregory Cristian ( Semtech )
22 */
23 #include "stm32l4xx.h"
24 #include "utilities.h"
25 #include "board.h"
26 #include "sysIrqHandlers.h"
27 #include "uart-board.h"
28
29 /*!
30 * Number of times the UartPutBuffer will try to send the buffer before
31 * returning ERROR
32 */
33 #define TX_BUFFER_RETRY_COUNT 10
34
35 static UART_HandleTypeDef UartHandle;
36 uint8_t RxData = 0;
37 uint8_t TxData = 0;
38
39 extern Uart_t Uart2;
40
UartMcuInit(Uart_t * obj,UartId_t uartId,PinNames tx,PinNames rx)41 void UartMcuInit( Uart_t *obj, UartId_t uartId, PinNames tx, PinNames rx )
42 {
43 obj->UartId = uartId;
44
45 if( uartId == UART_USB_CDC )
46 {
47 #if defined( USE_USB_CDC )
48 UartUsbInit( obj, uartId, NC, NC );
49 #endif
50 }
51 else
52 {
53 __HAL_RCC_USART2_FORCE_RESET( );
54 __HAL_RCC_USART2_RELEASE_RESET( );
55 __HAL_RCC_USART2_CLK_ENABLE( );
56
57 GpioInit( &obj->Tx, tx, PIN_ALTERNATE_FCT, PIN_PUSH_PULL, PIN_PULL_UP, GPIO_AF7_USART2 );
58 GpioInit( &obj->Rx, rx, PIN_ALTERNATE_FCT, PIN_PUSH_PULL, PIN_PULL_UP, GPIO_AF7_USART2 );
59 }
60 }
61
UartMcuConfig(Uart_t * obj,UartMode_t mode,uint32_t baudrate,WordLength_t wordLength,StopBits_t stopBits,Parity_t parity,FlowCtrl_t flowCtrl)62 void UartMcuConfig( Uart_t *obj, UartMode_t mode, uint32_t baudrate, WordLength_t wordLength, StopBits_t stopBits, Parity_t parity, FlowCtrl_t flowCtrl )
63 {
64 if( obj->UartId == UART_USB_CDC )
65 {
66 #if defined( USE_USB_CDC )
67 UartUsbConfig( obj, mode, baudrate, wordLength, stopBits, parity, flowCtrl );
68 #endif
69 }
70 else
71 {
72 UartHandle.Instance = USART2;
73 UartHandle.Init.BaudRate = baudrate;
74
75 if( mode == TX_ONLY )
76 {
77 if( obj->FifoTx.Data == NULL )
78 {
79 assert_param( LMN_STATUS_ERROR );
80 }
81 UartHandle.Init.Mode = UART_MODE_TX;
82 }
83 else if( mode == RX_ONLY )
84 {
85 if( obj->FifoRx.Data == NULL )
86 {
87 assert_param( LMN_STATUS_ERROR );
88 }
89 UartHandle.Init.Mode = UART_MODE_RX;
90 }
91 else if( mode == RX_TX )
92 {
93 if( ( obj->FifoTx.Data == NULL ) || ( obj->FifoRx.Data == NULL ) )
94 {
95 assert_param( LMN_STATUS_ERROR );
96 }
97 UartHandle.Init.Mode = UART_MODE_TX_RX;
98 }
99 else
100 {
101 assert_param( LMN_STATUS_ERROR );
102 }
103
104 if( wordLength == UART_8_BIT )
105 {
106 UartHandle.Init.WordLength = UART_WORDLENGTH_8B;
107 }
108 else if( wordLength == UART_9_BIT )
109 {
110 UartHandle.Init.WordLength = UART_WORDLENGTH_9B;
111 }
112
113 switch( stopBits )
114 {
115 case UART_2_STOP_BIT:
116 UartHandle.Init.StopBits = UART_STOPBITS_2;
117 break;
118 case UART_1_STOP_BIT:
119 default:
120 UartHandle.Init.StopBits = UART_STOPBITS_1;
121 break;
122 }
123
124 if( parity == NO_PARITY )
125 {
126 UartHandle.Init.Parity = UART_PARITY_NONE;
127 }
128 else if( parity == EVEN_PARITY )
129 {
130 UartHandle.Init.Parity = UART_PARITY_EVEN;
131 }
132 else
133 {
134 UartHandle.Init.Parity = UART_PARITY_ODD;
135 }
136
137 if( flowCtrl == NO_FLOW_CTRL )
138 {
139 UartHandle.Init.HwFlowCtl = UART_HWCONTROL_NONE;
140 }
141 else if( flowCtrl == RTS_FLOW_CTRL )
142 {
143 UartHandle.Init.HwFlowCtl = UART_HWCONTROL_RTS;
144 }
145 else if( flowCtrl == CTS_FLOW_CTRL )
146 {
147 UartHandle.Init.HwFlowCtl = UART_HWCONTROL_CTS;
148 }
149 else if( flowCtrl == RTS_CTS_FLOW_CTRL )
150 {
151 UartHandle.Init.HwFlowCtl = UART_HWCONTROL_RTS_CTS;
152 }
153
154 UartHandle.Init.OverSampling = UART_OVERSAMPLING_16;
155
156 if( HAL_UART_Init( &UartHandle ) != HAL_OK )
157 {
158 assert_param( LMN_STATUS_ERROR );
159 }
160
161 HAL_NVIC_SetPriority( USART2_IRQn, 1, 0 );
162 HAL_NVIC_EnableIRQ( USART2_IRQn );
163
164 /* Enable the UART Data Register not empty Interrupt */
165 HAL_UART_Receive_IT( &UartHandle, &RxData, 1 );
166 }
167 }
168
UartMcuDeInit(Uart_t * obj)169 void UartMcuDeInit( Uart_t *obj )
170 {
171 if( obj->UartId == UART_USB_CDC )
172 {
173 #if defined( USE_USB_CDC )
174 UartUsbDeInit( obj );
175 #endif
176 }
177 else
178 {
179 __HAL_RCC_USART2_FORCE_RESET( );
180 __HAL_RCC_USART2_RELEASE_RESET( );
181 __HAL_RCC_USART2_CLK_DISABLE( );
182
183 GpioInit( &obj->Tx, obj->Tx.pin, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
184 GpioInit( &obj->Rx, obj->Rx.pin, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
185 }
186 }
187
UartMcuPutChar(Uart_t * obj,uint8_t data)188 uint8_t UartMcuPutChar( Uart_t *obj, uint8_t data )
189 {
190 if( obj->UartId == UART_USB_CDC )
191 {
192 #if defined( USE_USB_CDC )
193 return UartUsbPutChar( obj, data );
194 #else
195 return 255; // Not supported
196 #endif
197 }
198 else
199 {
200 CRITICAL_SECTION_BEGIN( );
201 TxData = data;
202
203 if( IsFifoFull( &obj->FifoTx ) == false )
204 {
205 FifoPush( &obj->FifoTx, TxData );
206
207 // Trig UART Tx interrupt to start sending the FIFO contents.
208 __HAL_UART_ENABLE_IT( &UartHandle, UART_IT_TC );
209
210 CRITICAL_SECTION_END( );
211 return 0; // OK
212 }
213 CRITICAL_SECTION_END( );
214 return 1; // Busy
215 }
216 }
217
UartMcuGetChar(Uart_t * obj,uint8_t * data)218 uint8_t UartMcuGetChar( Uart_t *obj, uint8_t *data )
219 {
220 if( obj->UartId == UART_USB_CDC )
221 {
222 #if defined( USE_USB_CDC )
223 return UartUsbGetChar( obj, data );
224 #else
225 return 255; // Not supported
226 #endif
227 }
228 else
229 {
230 CRITICAL_SECTION_BEGIN( );
231
232 if( IsFifoEmpty( &obj->FifoRx ) == false )
233 {
234 *data = FifoPop( &obj->FifoRx );
235 CRITICAL_SECTION_END( );
236 return 0;
237 }
238 CRITICAL_SECTION_END( );
239 return 1;
240 }
241 }
242
UartMcuPutBuffer(Uart_t * obj,uint8_t * buffer,uint16_t size)243 uint8_t UartMcuPutBuffer( Uart_t *obj, uint8_t *buffer, uint16_t size )
244 {
245 if( obj->UartId == UART_USB_CDC )
246 {
247 #if defined( USE_USB_CDC )
248 return UartUsbPutBuffer( obj, buffer, size );
249 #else
250 return 255; // Not supported
251 #endif
252 }
253 else
254 {
255 uint8_t retryCount;
256 uint16_t i;
257
258 for( i = 0; i < size; i++ )
259 {
260 retryCount = 0;
261 while( UartPutChar( obj, buffer[i] ) != 0 )
262 {
263 retryCount++;
264
265 // Exit if something goes terribly wrong
266 if( retryCount > TX_BUFFER_RETRY_COUNT )
267 {
268 return 1; // Error
269 }
270 }
271 }
272 return 0; // OK
273 }
274 }
275
UartMcuGetBuffer(Uart_t * obj,uint8_t * buffer,uint16_t size,uint16_t * nbReadBytes)276 uint8_t UartMcuGetBuffer( Uart_t *obj, uint8_t *buffer, uint16_t size, uint16_t *nbReadBytes )
277 {
278 uint16_t localSize = 0;
279
280 while( localSize < size )
281 {
282 if( UartGetChar( obj, buffer + localSize ) == 0 )
283 {
284 localSize++;
285 }
286 else
287 {
288 break;
289 }
290 }
291
292 *nbReadBytes = localSize;
293
294 if( localSize == 0 )
295 {
296 return 1; // Empty
297 }
298 return 0; // OK
299 }
300
HAL_UART_TxCpltCallback(UART_HandleTypeDef * handle)301 void HAL_UART_TxCpltCallback( UART_HandleTypeDef *handle )
302 {
303 if( IsFifoEmpty( &Uart2.FifoTx ) == false )
304 {
305 TxData = FifoPop( &Uart2.FifoTx );
306 // Write one byte to the transmit data register
307 HAL_UART_Transmit_IT( &UartHandle, &TxData, 1 );
308 }
309
310 if( Uart2.IrqNotify != NULL )
311 {
312 Uart2.IrqNotify( UART_NOTIFY_TX );
313 }
314 }
315
HAL_UART_RxCpltCallback(UART_HandleTypeDef * handle)316 void HAL_UART_RxCpltCallback( UART_HandleTypeDef *handle )
317 {
318 if( IsFifoFull( &Uart2.FifoRx ) == false )
319 {
320 // Read one byte from the receive data register
321 FifoPush( &Uart2.FifoRx, RxData );
322 }
323
324 if( Uart2.IrqNotify != NULL )
325 {
326 Uart2.IrqNotify( UART_NOTIFY_RX );
327 }
328
329 HAL_UART_Receive_IT( &UartHandle, &RxData, 1 );
330 }
331
HAL_UART_ErrorCallback(UART_HandleTypeDef * handle)332 void HAL_UART_ErrorCallback( UART_HandleTypeDef *handle )
333 {
334 HAL_UART_Receive_IT( &UartHandle, &RxData, 1 );
335 }
336
USART2_IRQHandler(void)337 void USART2_IRQHandler( void )
338 {
339 HAL_UART_IRQHandler( &UartHandle );
340 }
341