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