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 "stm32l1xx.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 typedef struct
36 {
37     UART_HandleTypeDef UartHandle;
38     uint8_t RxData;
39     uint8_t TxData;
40 }UartContext_t;
41 
42 UartContext_t UartContext[2];
43 
44 extern Uart_t Uart1;
45 extern Uart_t Uart2;
46 
UartMcuInit(Uart_t * obj,UartId_t uartId,PinNames tx,PinNames rx)47 void UartMcuInit( Uart_t *obj, UartId_t uartId, PinNames tx, PinNames rx )
48 {
49     if( uartId == UART_USB_CDC )
50     {
51 #if defined( USE_USB_CDC )
52         UartUsbInit( obj, uartId, NC, NC );
53 #endif
54     }
55     else
56     {
57         obj->UartId = uartId;
58 
59         if( obj->UartId == UART_1 )
60         {
61             __HAL_RCC_USART1_FORCE_RESET( );
62             __HAL_RCC_USART1_RELEASE_RESET( );
63             __HAL_RCC_USART1_CLK_ENABLE( );
64 
65             GpioInit( &obj->Tx, tx, PIN_ALTERNATE_FCT, PIN_PUSH_PULL, PIN_PULL_UP, GPIO_AF7_USART1 );
66             GpioInit( &obj->Rx, rx, PIN_ALTERNATE_FCT, PIN_PUSH_PULL, PIN_PULL_UP, GPIO_AF7_USART1 );
67         }
68         else if( obj->UartId == UART_2 )
69         {
70             __HAL_RCC_USART2_FORCE_RESET( );
71             __HAL_RCC_USART2_RELEASE_RESET( );
72             __HAL_RCC_USART2_CLK_ENABLE( );
73 
74             GpioInit( &obj->Tx, tx, PIN_ALTERNATE_FCT, PIN_PUSH_PULL, PIN_PULL_UP, GPIO_AF7_USART2 );
75             GpioInit( &obj->Rx, rx, PIN_ALTERNATE_FCT, PIN_PUSH_PULL, PIN_PULL_UP, GPIO_AF7_USART2 );
76         }
77     }
78 }
79 
UartMcuConfig(Uart_t * obj,UartMode_t mode,uint32_t baudrate,WordLength_t wordLength,StopBits_t stopBits,Parity_t parity,FlowCtrl_t flowCtrl)80 void UartMcuConfig( Uart_t *obj, UartMode_t mode, uint32_t baudrate, WordLength_t wordLength, StopBits_t stopBits, Parity_t parity, FlowCtrl_t flowCtrl )
81 {
82     if( obj->UartId == UART_USB_CDC )
83     {
84 #if defined( USE_USB_CDC )
85         UartUsbConfig( obj, mode, baudrate, wordLength, stopBits, parity, flowCtrl );
86 #endif
87     }
88     else
89     {
90         if( obj->UartId == UART_1 )
91         {
92             UartContext[obj->UartId].UartHandle.Instance = USART1;
93         }
94         else if( obj->UartId == UART_2 )
95         {
96             UartContext[obj->UartId].UartHandle.Instance = USART2;
97         }
98         UartContext[obj->UartId].UartHandle.Init.BaudRate = baudrate;
99 
100         if( mode == TX_ONLY )
101         {
102             if( obj->FifoTx.Data == NULL )
103             {
104                 assert_param( LMN_STATUS_ERROR );
105             }
106             UartContext[obj->UartId].UartHandle.Init.Mode = UART_MODE_TX;
107         }
108         else if( mode == RX_ONLY )
109         {
110             if( obj->FifoRx.Data == NULL )
111             {
112                 assert_param( LMN_STATUS_ERROR );
113             }
114             UartContext[obj->UartId].UartHandle.Init.Mode = UART_MODE_RX;
115         }
116         else if( mode == RX_TX )
117         {
118             if( ( obj->FifoTx.Data == NULL ) || ( obj->FifoRx.Data == NULL ) )
119             {
120                 assert_param( LMN_STATUS_ERROR );
121             }
122             UartContext[obj->UartId].UartHandle.Init.Mode = UART_MODE_TX_RX;
123         }
124         else
125         {
126             assert_param( LMN_STATUS_ERROR );
127         }
128 
129         if( wordLength == UART_8_BIT )
130         {
131             UartContext[obj->UartId].UartHandle.Init.WordLength = UART_WORDLENGTH_8B;
132         }
133         else if( wordLength == UART_9_BIT )
134         {
135             UartContext[obj->UartId].UartHandle.Init.WordLength = UART_WORDLENGTH_9B;
136         }
137 
138         switch( stopBits )
139         {
140         case UART_2_STOP_BIT:
141             UartContext[obj->UartId].UartHandle.Init.StopBits = UART_STOPBITS_2;
142             break;
143         case UART_1_STOP_BIT:
144         default:
145             UartContext[obj->UartId].UartHandle.Init.StopBits = UART_STOPBITS_1;
146             break;
147         }
148 
149         if( parity == NO_PARITY )
150         {
151             UartContext[obj->UartId].UartHandle.Init.Parity = UART_PARITY_NONE;
152         }
153         else if( parity == EVEN_PARITY )
154         {
155             UartContext[obj->UartId].UartHandle.Init.Parity = UART_PARITY_EVEN;
156         }
157         else
158         {
159             UartContext[obj->UartId].UartHandle.Init.Parity = UART_PARITY_ODD;
160         }
161 
162         if( flowCtrl == NO_FLOW_CTRL )
163         {
164             UartContext[obj->UartId].UartHandle.Init.HwFlowCtl = UART_HWCONTROL_NONE;
165         }
166         else if( flowCtrl == RTS_FLOW_CTRL )
167         {
168             UartContext[obj->UartId].UartHandle.Init.HwFlowCtl = UART_HWCONTROL_RTS;
169         }
170         else if( flowCtrl == CTS_FLOW_CTRL )
171         {
172             UartContext[obj->UartId].UartHandle.Init.HwFlowCtl = UART_HWCONTROL_CTS;
173         }
174         else if( flowCtrl == RTS_CTS_FLOW_CTRL )
175         {
176             UartContext[obj->UartId].UartHandle.Init.HwFlowCtl = UART_HWCONTROL_RTS_CTS;
177         }
178 
179         UartContext[obj->UartId].UartHandle.Init.OverSampling = UART_OVERSAMPLING_16;
180 
181         if( HAL_UART_Init( &UartContext[obj->UartId].UartHandle ) != HAL_OK )
182         {
183             assert_param( LMN_STATUS_ERROR );
184         }
185 
186         if( obj->UartId == UART_1 )
187         {
188             HAL_NVIC_SetPriority( USART1_IRQn, 1, 0 );
189             HAL_NVIC_EnableIRQ( USART1_IRQn );
190         }
191         else if( obj->UartId == UART_2 )
192         {
193             HAL_NVIC_SetPriority( USART2_IRQn, 1, 0 );
194             HAL_NVIC_EnableIRQ( USART2_IRQn );
195         }
196 
197         /* Enable the UART Data Register not empty Interrupt */
198         HAL_UART_Receive_IT( &UartContext[obj->UartId].UartHandle, &UartContext[obj->UartId].RxData, 1 );
199     }
200 }
201 
UartMcuDeInit(Uart_t * obj)202 void UartMcuDeInit( Uart_t *obj )
203 {
204     if( obj->UartId == UART_USB_CDC )
205     {
206 #if defined( USE_USB_CDC )
207         UartUsbDeInit( obj );
208 #endif
209     }
210     else
211     {
212         if( obj->UartId == UART_1 )
213         {
214             __HAL_RCC_USART1_FORCE_RESET( );
215             __HAL_RCC_USART1_RELEASE_RESET( );
216             __HAL_RCC_USART1_CLK_DISABLE( );
217         }
218         else if( obj->UartId == UART_2 )
219         {
220             __HAL_RCC_USART2_FORCE_RESET( );
221             __HAL_RCC_USART2_RELEASE_RESET( );
222             __HAL_RCC_USART2_CLK_DISABLE( );
223         }
224 
225         GpioInit( &obj->Tx, obj->Tx.pin, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
226         GpioInit( &obj->Rx, obj->Rx.pin, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
227     }
228 }
229 
UartMcuPutChar(Uart_t * obj,uint8_t data)230 uint8_t UartMcuPutChar( Uart_t *obj, uint8_t data )
231 {
232     if( obj->UartId == UART_USB_CDC )
233     {
234 #if defined( USE_USB_CDC )
235         return UartUsbPutChar( obj, data );
236 #else
237         return 255; // Not supported
238 #endif
239     }
240     else
241     {
242         CRITICAL_SECTION_BEGIN( );
243         UartContext[obj->UartId].TxData = data;
244 
245         if( IsFifoFull( &obj->FifoTx ) == false )
246         {
247             FifoPush( &obj->FifoTx, UartContext[obj->UartId].TxData );
248 
249             // Trig UART Tx interrupt to start sending the FIFO contents.
250             __HAL_UART_ENABLE_IT( &UartContext[obj->UartId].UartHandle, UART_IT_TC );
251 
252             CRITICAL_SECTION_END( );
253             return 0; // OK
254         }
255         CRITICAL_SECTION_END( );
256         return 1; // Busy
257     }
258 }
259 
UartMcuGetChar(Uart_t * obj,uint8_t * data)260 uint8_t UartMcuGetChar( Uart_t *obj, uint8_t *data )
261 {
262     if( obj->UartId == UART_USB_CDC )
263     {
264 #if defined( USE_USB_CDC )
265         return UartUsbGetChar( obj, data );
266 #else
267         return 255; // Not supported
268 #endif
269     }
270     else
271     {
272         CRITICAL_SECTION_BEGIN( );
273 
274         if( IsFifoEmpty( &obj->FifoRx ) == false )
275         {
276             *data = FifoPop( &obj->FifoRx );
277             CRITICAL_SECTION_END( );
278             return 0;
279         }
280         CRITICAL_SECTION_END( );
281         return 1;
282     }
283 }
284 
UartMcuPutBuffer(Uart_t * obj,uint8_t * buffer,uint16_t size)285 uint8_t UartMcuPutBuffer( Uart_t *obj, uint8_t *buffer, uint16_t size )
286 {
287     if( obj->UartId == UART_USB_CDC )
288     {
289 #if defined( USE_USB_CDC )
290         return UartUsbPutBuffer( obj, buffer, size );
291 #else
292         return 255; // Not supported
293 #endif
294     }
295     else
296     {
297         uint8_t retryCount;
298         uint16_t i;
299 
300         for( i = 0; i < size; i++ )
301         {
302             retryCount = 0;
303             while( UartPutChar( obj, buffer[i] ) != 0 )
304             {
305                 retryCount++;
306 
307                 // Exit if something goes terribly wrong
308                 if( retryCount > TX_BUFFER_RETRY_COUNT )
309                 {
310                     return 1; // Error
311                 }
312             }
313         }
314         return 0; // OK
315     }
316 }
317 
UartMcuGetBuffer(Uart_t * obj,uint8_t * buffer,uint16_t size,uint16_t * nbReadBytes)318 uint8_t UartMcuGetBuffer( Uart_t *obj, uint8_t *buffer, uint16_t size, uint16_t *nbReadBytes )
319 {
320     uint16_t localSize = 0;
321 
322     while( localSize < size )
323     {
324         if( UartGetChar( obj, buffer + localSize ) == 0 )
325         {
326             localSize++;
327         }
328         else
329         {
330             break;
331         }
332     }
333 
334     *nbReadBytes = localSize;
335 
336     if( localSize == 0 )
337     {
338         return 1; // Empty
339     }
340     return 0; // OK
341 }
342 
HAL_UART_TxCpltCallback(UART_HandleTypeDef * handle)343 void HAL_UART_TxCpltCallback( UART_HandleTypeDef *handle )
344 {
345     Uart_t *uart = &Uart1;
346     UartId_t uartId = UART_1;
347 
348     if( handle == &UartContext[UART_1].UartHandle )
349     {
350         uart = &Uart1;
351         uartId = UART_1;
352     }
353     else if( handle == &UartContext[UART_2].UartHandle )
354     {
355         uart = &Uart2;
356         uartId = UART_2;
357     }
358     else
359     {
360         // Unknown UART peripheral skip processing
361         return;
362     }
363     if( IsFifoEmpty( &uart->FifoTx ) == false )
364     {
365         UartContext[uartId].TxData = FifoPop( &uart->FifoTx );
366         //  Write one byte to the transmit data register
367         HAL_UART_Transmit_IT( &UartContext[uartId].UartHandle, &UartContext[uartId].TxData, 1 );
368     }
369 
370     if( uart->IrqNotify != NULL )
371     {
372         uart->IrqNotify( UART_NOTIFY_TX );
373     }
374 }
375 
HAL_UART_RxCpltCallback(UART_HandleTypeDef * handle)376 void HAL_UART_RxCpltCallback( UART_HandleTypeDef *handle )
377 {
378     Uart_t *uart = &Uart1;
379     UartId_t uartId = UART_1;
380 
381     if( handle == &UartContext[UART_1].UartHandle )
382     {
383         uart = &Uart1;
384         uartId = UART_1;
385     }
386     else if( handle == &UartContext[UART_2].UartHandle )
387     {
388         uart = &Uart2;
389         uartId = UART_2;
390     }
391     else
392     {
393         // Unknown UART peripheral skip processing
394         return;
395     }
396     if( IsFifoFull( &uart->FifoRx ) == false )
397     {
398         // Read one byte from the receive data register
399         FifoPush( &uart->FifoRx, UartContext[uartId].RxData );
400     }
401 
402     if( uart->IrqNotify != NULL )
403     {
404         uart->IrqNotify( UART_NOTIFY_RX );
405     }
406 
407     HAL_UART_Receive_IT( &UartContext[uartId].UartHandle, &UartContext[uartId].RxData, 1 );
408 }
409 
HAL_UART_ErrorCallback(UART_HandleTypeDef * handle)410 void HAL_UART_ErrorCallback( UART_HandleTypeDef *handle )
411 {
412     UartId_t uartId = UART_1;
413 
414     if( handle == &UartContext[UART_1].UartHandle )
415     {
416         uartId = UART_1;
417     }
418     else if( handle == &UartContext[UART_2].UartHandle )
419     {
420         uartId = UART_2;
421     }
422     else
423     {
424         // Unknown UART peripheral skip processing
425         return;
426     }
427     HAL_UART_Receive_IT( &UartContext[uartId].UartHandle, &UartContext[uartId].RxData, 1 );
428 }
429 
USART1_IRQHandler(void)430 void USART1_IRQHandler( void )
431 {
432     // [BEGIN] Workaround to solve an issue with the HAL drivers not managing the uart state correctly.
433     uint32_t tmpFlag = 0, tmpItSource = 0;
434 
435     tmpFlag = __HAL_UART_GET_FLAG( &UartContext[UART_1].UartHandle, UART_FLAG_TC );
436     tmpItSource = __HAL_UART_GET_IT_SOURCE( &UartContext[UART_1].UartHandle, UART_IT_TC );
437     // UART in mode Transmitter end
438     if( ( tmpFlag != RESET ) && ( tmpItSource != RESET ) )
439     {
440         if( ( UartContext[UART_1].UartHandle.State == HAL_UART_STATE_BUSY_RX ) || UartContext[UART_1].UartHandle.State == HAL_UART_STATE_BUSY_TX_RX )
441         {
442             UartContext[UART_1].UartHandle.State = HAL_UART_STATE_BUSY_TX_RX;
443         }
444     }
445     // [END] Workaround to solve an issue with the HAL drivers not managing the uart state correctly.
446 
447     HAL_UART_IRQHandler( &UartContext[UART_1].UartHandle );
448 }
449 
USART2_IRQHandler(void)450 void USART2_IRQHandler( void )
451 {
452     // [BEGIN] Workaround to solve an issue with the HAL drivers not managing the uart state correctly.
453     uint32_t tmpFlag = 0, tmpItSource = 0;
454 
455     tmpFlag = __HAL_UART_GET_FLAG( &UartContext[UART_2].UartHandle, UART_FLAG_TC );
456     tmpItSource = __HAL_UART_GET_IT_SOURCE( &UartContext[UART_2].UartHandle, UART_IT_TC );
457     // UART in mode Transmitter end
458     if( ( tmpFlag != RESET ) && ( tmpItSource != RESET ) )
459     {
460         if( ( UartContext[UART_2].UartHandle.State == HAL_UART_STATE_BUSY_RX ) || UartContext[UART_2].UartHandle.State == HAL_UART_STATE_BUSY_TX_RX )
461         {
462             UartContext[UART_2].UartHandle.State = HAL_UART_STATE_BUSY_TX_RX;
463         }
464     }
465     // [END] Workaround to solve an issue with the HAL drivers not managing the uart state correctly.
466 
467     HAL_UART_IRQHandler( &UartContext[UART_2].UartHandle );
468 }
469