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 "stm32l0xx.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 Uart1;
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_USART1_FORCE_RESET( );
54         __HAL_RCC_USART1_RELEASE_RESET( );
55         __HAL_RCC_USART1_CLK_ENABLE( );
56 
57         GpioInit( &obj->Tx, tx, PIN_ALTERNATE_FCT, PIN_PUSH_PULL, PIN_PULL_UP, GPIO_AF4_USART1 );
58         GpioInit( &obj->Rx, rx, PIN_ALTERNATE_FCT, PIN_PUSH_PULL, PIN_PULL_UP, GPIO_AF4_USART1 );
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 = USART1;
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_5_STOP_BIT:
119             UartHandle.Init.StopBits = UART_STOPBITS_1_5;
120             break;
121         case UART_1_STOP_BIT:
122         default:
123             UartHandle.Init.StopBits = UART_STOPBITS_1;
124             break;
125         }
126 
127         if( parity == NO_PARITY )
128         {
129             UartHandle.Init.Parity = UART_PARITY_NONE;
130         }
131         else if( parity == EVEN_PARITY )
132         {
133             UartHandle.Init.Parity = UART_PARITY_EVEN;
134         }
135         else
136         {
137             UartHandle.Init.Parity = UART_PARITY_ODD;
138         }
139 
140         if( flowCtrl == NO_FLOW_CTRL )
141         {
142             UartHandle.Init.HwFlowCtl = UART_HWCONTROL_NONE;
143         }
144         else if( flowCtrl == RTS_FLOW_CTRL )
145         {
146             UartHandle.Init.HwFlowCtl = UART_HWCONTROL_RTS;
147         }
148         else if( flowCtrl == CTS_FLOW_CTRL )
149         {
150             UartHandle.Init.HwFlowCtl = UART_HWCONTROL_CTS;
151         }
152         else if( flowCtrl == RTS_CTS_FLOW_CTRL )
153         {
154             UartHandle.Init.HwFlowCtl = UART_HWCONTROL_RTS_CTS;
155         }
156 
157         UartHandle.Init.OverSampling = UART_OVERSAMPLING_16;
158 
159         if( HAL_UART_Init( &UartHandle ) != HAL_OK )
160         {
161             assert_param( LMN_STATUS_ERROR );
162         }
163 
164         HAL_NVIC_SetPriority( USART1_IRQn, 1, 0 );
165         HAL_NVIC_EnableIRQ( USART1_IRQn );
166 
167         /* Enable the UART Data Register not empty Interrupt */
168         HAL_UART_Receive_IT( &UartHandle, &RxData, 1 );
169     }
170 }
171 
UartMcuDeInit(Uart_t * obj)172 void UartMcuDeInit( Uart_t *obj )
173 {
174     if( obj->UartId == UART_USB_CDC )
175     {
176 #if defined( USE_USB_CDC )
177         UartUsbDeInit( obj );
178 #endif
179     }
180     else
181     {
182         __HAL_RCC_USART1_FORCE_RESET( );
183         __HAL_RCC_USART1_RELEASE_RESET( );
184         __HAL_RCC_USART1_CLK_DISABLE( );
185 
186         GpioInit( &obj->Tx, obj->Tx.pin, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
187         GpioInit( &obj->Rx, obj->Rx.pin, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
188     }
189 }
190 
UartMcuPutChar(Uart_t * obj,uint8_t data)191 uint8_t UartMcuPutChar( Uart_t *obj, uint8_t data )
192 {
193     if( obj->UartId == UART_USB_CDC )
194     {
195 #if defined( USE_USB_CDC )
196         return UartUsbPutChar( obj, data );
197 #else
198         return 255; // Not supported
199 #endif
200     }
201     else
202     {
203         CRITICAL_SECTION_BEGIN( );
204         TxData = data;
205 
206         if( IsFifoFull( &obj->FifoTx ) == false )
207         {
208             FifoPush( &obj->FifoTx, TxData );
209 
210             // Trig UART Tx interrupt to start sending the FIFO contents.
211             __HAL_UART_ENABLE_IT( &UartHandle, UART_IT_TC );
212 
213             CRITICAL_SECTION_END( );
214             return 0; // OK
215         }
216         CRITICAL_SECTION_END( );
217         return 1; // Busy
218     }
219 }
220 
UartMcuGetChar(Uart_t * obj,uint8_t * data)221 uint8_t UartMcuGetChar( Uart_t *obj, uint8_t *data )
222 {
223     if( obj->UartId == UART_USB_CDC )
224     {
225 #if defined( USE_USB_CDC )
226         return UartUsbGetChar( obj, data );
227 #else
228         return 255; // Not supported
229 #endif
230     }
231     else
232     {
233         CRITICAL_SECTION_BEGIN( );
234 
235         if( IsFifoEmpty( &obj->FifoRx ) == false )
236         {
237             *data = FifoPop( &obj->FifoRx );
238             CRITICAL_SECTION_END( );
239             return 0;
240         }
241         CRITICAL_SECTION_END( );
242         return 1;
243     }
244 }
245 
UartMcuPutBuffer(Uart_t * obj,uint8_t * buffer,uint16_t size)246 uint8_t UartMcuPutBuffer( Uart_t *obj, uint8_t *buffer, uint16_t size )
247 {
248     if( obj->UartId == UART_USB_CDC )
249     {
250 #if defined( USE_USB_CDC )
251         return UartUsbPutBuffer( obj, buffer, size );
252 #else
253         return 255; // Not supported
254 #endif
255     }
256     else
257     {
258         uint8_t retryCount;
259         uint16_t i;
260 
261         for( i = 0; i < size; i++ )
262         {
263             retryCount = 0;
264             while( UartPutChar( obj, buffer[i] ) != 0 )
265             {
266                 retryCount++;
267 
268                 // Exit if something goes terribly wrong
269                 if( retryCount > TX_BUFFER_RETRY_COUNT )
270                 {
271                     return 1; // Error
272                 }
273             }
274         }
275         return 0; // OK
276     }
277 }
278 
UartMcuGetBuffer(Uart_t * obj,uint8_t * buffer,uint16_t size,uint16_t * nbReadBytes)279 uint8_t UartMcuGetBuffer( Uart_t *obj, uint8_t *buffer, uint16_t size, uint16_t *nbReadBytes )
280 {
281     uint16_t localSize = 0;
282 
283     while( localSize < size )
284     {
285         if( UartGetChar( obj, buffer + localSize ) == 0 )
286         {
287             localSize++;
288         }
289         else
290         {
291             break;
292         }
293     }
294 
295     *nbReadBytes = localSize;
296 
297     if( localSize == 0 )
298     {
299         return 1; // Empty
300     }
301     return 0; // OK
302 }
303 
HAL_UART_TxCpltCallback(UART_HandleTypeDef * handle)304 void HAL_UART_TxCpltCallback( UART_HandleTypeDef *handle )
305 {
306     if( IsFifoEmpty( &Uart1.FifoTx ) == false )
307     {
308         TxData = FifoPop( &Uart1.FifoTx );
309         //  Write one byte to the transmit data register
310         HAL_UART_Transmit_IT( &UartHandle, &TxData, 1 );
311     }
312 
313     if( Uart1.IrqNotify != NULL )
314     {
315         Uart1.IrqNotify( UART_NOTIFY_TX );
316     }
317 }
318 
HAL_UART_RxCpltCallback(UART_HandleTypeDef * handle)319 void HAL_UART_RxCpltCallback( UART_HandleTypeDef *handle )
320 {
321     if( IsFifoFull( &Uart1.FifoRx ) == false )
322     {
323         // Read one byte from the receive data register
324         FifoPush( &Uart1.FifoRx, RxData );
325     }
326 
327     if( Uart1.IrqNotify != NULL )
328     {
329         Uart1.IrqNotify( UART_NOTIFY_RX );
330     }
331 
332     HAL_UART_Receive_IT( &UartHandle, &RxData, 1 );
333 }
334 
HAL_UART_ErrorCallback(UART_HandleTypeDef * handle)335 void HAL_UART_ErrorCallback( UART_HandleTypeDef *handle )
336 {
337     HAL_UART_Receive_IT( &UartHandle, &RxData, 1 );
338 }
339 
USART1_IRQHandler(void)340 void USART1_IRQHandler( void )
341 {
342     HAL_UART_IRQHandler( &UartHandle );
343 }
344