1 /*
2   ******************************************************************************
3   * @file    HAL_LPUART.c
4   * @version V1.0.0
5   * @date    2020
6   * @brief   LPUART HAL module driver.
7   *          This file provides firmware functions to manage the following
8   *          functionalities of the Universal Asynchronous Receiver Transmitter Peripheral (LPUART).
9   *           @ Initialization and de-initialization functions
10   *           @ IO operation functions
11   *           @ Peripheral Control functions
12   ******************************************************************************
13 */
14 #include "ACM32Fxx_HAL.h"
15 
16 /*********************************************************************************
17 * Function    : HAL_LPUART_IRQHander
18 * Description : LPUART IRQHander
19 * Input       :
20 * Outpu       :
21 * Author      : CWT                         Data : 2020年
22 **********************************************************************************/
HAL_LPUART_IRQHander(LPUART_HandleTypeDef * hlpuart)23 void HAL_LPUART_IRQHander(LPUART_HandleTypeDef *hlpuart)
24 {
25     while ( (hlpuart->Instance->SR) & (1U << LPUART_SR_RX_INDEX))
26     {
27         if(hlpuart->rx_read_index != (((hlpuart->rx_write_index) + 1)% (hlpuart->rx_buffer_size) ) )
28         {
29             hlpuart->rx_buffer[hlpuart->rx_write_index] = hlpuart->Instance->RXDR;
30             hlpuart->rx_write_index = ((hlpuart->rx_write_index + 1)%(hlpuart->rx_buffer_size) );
31         }
32         else
33         {
34             hlpuart->Instance->SR = (1U << LPUART_SR_RX_INDEX);  // buffer overflow
35             return;
36         }
37     }
38 }
39 /************************************************************************
40  * function   : HAL_UART_Buffer_Init
41  * Description: uart buffer initiation.
42  * input :
43  *         UART_HandleTypeDef *huart: pointer to uart handle structure
44  * return: 0: FAIL; 1: SUCCESS
45  ************************************************************************/
HAL_LPUART_Buffer_Init(LPUART_HandleTypeDef * hlpuart)46 HAL_StatusTypeDef HAL_LPUART_Buffer_Init(LPUART_HandleTypeDef *hlpuart)
47 {
48     if(0x00 == IS_LPUART_INSTANCE(hlpuart->Instance))
49     {
50         return HAL_ERROR;
51     }
52     hlpuart->rx_read_index = 0;
53     hlpuart->rx_write_index = 0;
54     hlpuart->tx_busy = 0;
55     return HAL_OK;
56 }
57 
58 /**********************************************************************************
59  * function   : HAL_LPUART_MSPInit
60  * Description: UART MCU specific initiation, such as IO share, module clock, ...
61  * input :
62  *         UART_HandleTypeDef *huart: pointer to uart handle structure
63  * return: 0: FAIL; 1: SUCCESS
64  ***************************************************************************************/
65 
HAL_LPUART_MSPInit(LPUART_HandleTypeDef * hlpuart)66 __weak void HAL_LPUART_MSPInit(LPUART_HandleTypeDef *hlpuart)
67 {
68     GPIO_InitTypeDef gpio_init;
69 
70     System_Module_Reset(RST_LPUART);
71     gpio_init.Pin = GPIO_PIN_2|GPIO_PIN_3;  // TX PA2 RX PA3
72     gpio_init.Mode = GPIO_MODE_AF_PP;
73     gpio_init.Pull = GPIO_PULLUP;
74     gpio_init.Alternate = GPIO_FUNCTION_6;
75     HAL_GPIO_Init(GPIOA,&gpio_init);
76     System_Module_Enable(EN_LPUART);
77 }
78 
79 /*********************************************************************************
80 * Function    : HAL_LPUART_MspDeInit
81 * Description : LPUART MSP De-Initialization
82 *               This function frees the hardware resources used in this example:
83 *              - Disable the Peripheral's clock
84 *              - Revert GPIO configuration to their default state
85 * Input       : hcan : pointer to a CAN_HandleTypeDef structure that contains
86 *                      the configuration information for CAN module
87 * Output      :
88 * Author      : CWT                         Data : 2020年
89 **********************************************************************************/
HAL_LPUART_MspDeInit(LPUART_HandleTypeDef * hlpuart)90 void HAL_LPUART_MspDeInit(LPUART_HandleTypeDef *hlpuart)
91 {
92     /* Initialization GPIO */
93     /* // TX PA2    RX PA3 */
94     HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2);
95     HAL_GPIO_DeInit(GPIOA, GPIO_PIN_3);
96 }
97 /**********************************************************************************
98  * function   : HAL_LPUART_Set_Baud_Rate
99  * Description: set uart module's baud rate. It should be set when UART is disabled.
100  * input :
101  *         UART_HandleTypeDef *huart: pointer to uart handle structure
102  * return: 0: FAIL; 1: SUCCESS
103  ***************************************************************************************/
HAL_LPUART_Set_Baud_Rate(LPUART_HandleTypeDef * hlpuart,uint32_t lpuart_clk,uint32_t baud_rate)104 uint8_t HAL_LPUART_Set_Baud_Rate(LPUART_HandleTypeDef *hlpuart, uint32_t lpuart_clk, uint32_t baud_rate)
105 {
106     uint32_t ibaud, fbaud, rxsamp;
107 
108     if(0x00 == IS_LPUART_INSTANCE(hlpuart->Instance))
109     {
110         return 0;
111     }
112     ibaud = 2;
113     fbaud = 0x952;
114     rxsamp = 1;
115     switch(lpuart_clk)
116     {
117         case 32000:
118         case 32768:
119         switch(baud_rate)
120         {
121         case 9600:
122         ibaud = 2;
123         fbaud = 0x952;
124 //         ibaud = 2;
125 //        fbaud = 0xA44;
126         break;
127 
128         case 4800:
129         ibaud = 5;
130         fbaud = 0xefb;
131         break;
132 
133         case 2400:
134         ibaud = 12;
135         fbaud = 0x6db;
136         break;
137 
138         case 1200:
139         ibaud = 26;
140         fbaud = 0x492;
141         break;
142         default:
143         ibaud = 2;
144         fbaud = 0x952;
145         break;
146         }
147         rxsamp = ibaud >> 1;
148         break;
149 
150     default:
151         switch(baud_rate)
152         {
153             case 115200:
154             ibaud = 16;
155             fbaud = 0x924;
156             break;
157 
158             case 9600:
159             ibaud = 203;
160             fbaud = 0x888;
161             break;
162         }
163         rxsamp = ibaud >> 1;
164         break;
165     }
166     hlpuart->Instance->IBAUD = ibaud | (rxsamp << 8);
167     hlpuart->Instance->FBAUD = fbaud;
168     return 1;
169 }
170 
171 /************************************************************************
172  * function   : HAL_LPUART_Config
173  * Description: Configure UART module parameters, such as baudrate, parity,
174  *              stop bits, dataword.
175  * input :
176  *         UART_HandleTypeDef *huart: pointer to uart handle structure
177  * return: 0: FAIL; 1: SUCCESS
178  ************************************************************************/
HAL_LPUART_Config(LPUART_HandleTypeDef * hlpuart)179 uint8_t HAL_LPUART_Config(LPUART_HandleTypeDef *hlpuart)
180 {
181     volatile uint32_t temp_reg;
182     if(0x00 == IS_LPUART_INSTANCE(hlpuart->Instance))
183     {
184         return 0;
185     }
186     temp_reg = 1U << 7; // default value
187     temp_reg |= ((hlpuart->ConfigParam.WordLength << 4) | (hlpuart->ConfigParam.StopBits << 3));
188     switch(hlpuart->ConfigParam.Parity)
189     {
190         case LPUART_PARITY_NONE:
191         break;  // do nothing
192 
193         case LPUART_PARITY_SELECT_ODD:
194         case LPUART_PARITY_SELECT_EVEN:
195         temp_reg |= (((hlpuart->ConfigParam.Parity - LPUART_PARITY_SELECT_ODD) << LPUART_EPS_INDEX) | (1 << LPUART_PEN_INDEX));
196         break;
197 
198         case LPUART_PARITY_SELECT_ONE:
199         case LPUART_PARITY_SELECT_ZERO:
200         temp_reg |= (((hlpuart->ConfigParam.Parity - LPUART_PARITY_SELECT_ONE) << LPUART_EPS_INDEX) | (1 << LPUART_SPS_INDEX) | (1 << LPUART_PEN_INDEX) );
201         break;
202     }
203     hlpuart->Instance->LCR = temp_reg;
204     return 1;
205 }
206 
207 /*********************************************************************************
208 * Function    : LPUART_Clock_Select
209 * Description : Select the LPUART clock.
210 * Input       : lpuart_clk_src:Could be LPUART_CLOCK_SOURCE_RC32K        LPUART_CLOCK_SOURCE_XTAL       LPUART_CLOCK_SOURCE_PLL_DIV
211 * Outpu       :
212 * Author      : CWT                         Data : 2020年
213 **********************************************************************************/
LPUART_Clock_Select(uint8_t lpuart_clk_src)214 void LPUART_Clock_Select(uint8_t lpuart_clk_src)
215 {
216     if (0 == lpuart_clk_src)
217     {
218         SCU->CCR2 &= (~(BIT13 | BIT14) );     // RC32K
219     }
220     else if (1 == lpuart_clk_src)
221     {
222         SCU->CCR2 = (SCU->CCR2 & (~(BIT13 | BIT14) )) | (BIT13);     // XTAL
223     }
224     else
225     {
226         SCU->CCR2 = (SCU->CCR2 & (~(BIT11 | BIT12| BIT13 | BIT14) )) | (BIT11 | BIT12 | BIT14);  // pclk/32
227     }
228 }
229 /************************************************************************
230  * function   : HAL_LPUART_Init
231  * Description: uart initial with parameters.
232  * input :
233  *         UART_HandleTypeDef *huart: pointer to uart handle structure
234  * return: 0: FAIL; 1: SUCCESS
235  ************************************************************************/
HAL_LPUART_Init(LPUART_HandleTypeDef * hlpuart)236 HAL_StatusTypeDef HAL_LPUART_Init(LPUART_HandleTypeDef *hlpuart)
237 {
238     uint32_t lpuart_clock;
239     if(0x00 == IS_LPUART_INSTANCE(hlpuart->Instance))
240     {
241         return HAL_ERROR;;
242     }
243 
244     HAL_LPUART_Buffer_Init(hlpuart);
245     /*reset module, configure tx and rx, enable module clock*/
246     HAL_LPUART_MSPInit(hlpuart);
247 
248     if (LPUART_CLOCK_SOURCE_RC32K == hlpuart->ConfigParam.ClockSrc)
249     {
250         lpuart_clock = 32000;
251         System_Module_Enable(EN_RTC);
252         System_Enable_Disable_RTC_Domain_Access(FUNC_ENABLE);
253         System_Enable_RC32K();
254         LPUART_Clock_Select(0);
255     }
256     else if (LPUART_CLOCK_SOURCE_XTAL == hlpuart->ConfigParam.ClockSrc)
257     {
258         lpuart_clock = 32768;
259         System_Module_Enable(EN_RTC);
260        System_Enable_Disable_RTC_Domain_Access(FUNC_ENABLE);
261         System_Enable_XTAL();
262         LPUART_Clock_Select(1);
263     }
264     else
265     {
266         lpuart_clock = System_Get_APBClock()/32;
267         LPUART_Clock_Select(2);
268     }
269     HAL_LPUART_Set_Baud_Rate(hlpuart, lpuart_clock, hlpuart->ConfigParam.BaudRate);
270 
271     HAL_LPUART_Config(hlpuart);
272 
273     hlpuart->Instance->SR = LPUART_SR_BITS_ALL;
274     hlpuart->Instance->IE = (1U << LPUART_IE_RX_INDEX);
275     hlpuart->Instance->CR = (1U << LPUART_CR_RXE_INDEX) | (1 << LPUART_CR_TXE_INDEX);
276     hlpuart->Instance->LCR=((hlpuart->StopWakeup.Wakeup_Source<<5)|(hlpuart->StopWakeup.Wakeup_Check<<7));
277     hlpuart->Instance->ADDR=(hlpuart->StopWakeup.Wakeup_Addr);
278     NVIC_ClearPendingIRQ(LPUART_IRQn);
279     NVIC_EnableIRQ(LPUART_IRQn);
280     return HAL_OK;;
281 }
HAL_LPUART_DeInit(LPUART_HandleTypeDef * hlpuart)282 HAL_StatusTypeDef HAL_LPUART_DeInit(LPUART_HandleTypeDef *hlpuart)
283 {
284     /* Check  handle */
285     if(!IS_LPUART_INSTANCE(hlpuart->Instance)) return HAL_ERROR;
286     HAL_LPUART_MspDeInit(hlpuart);
287     /* Disable LPUART clock */
288     System_Module_Disable(EN_LPUART);
289     /* Return function status */
290     return HAL_OK;
291 }
292 /************************************************************************
293  * function   : HAL_LPUART_Wait_TX_Done
294  * Description: wait uart not busy
295  * input :
296  *         UART_HandleTypeDef *huart: pointer to uart handle structure
297  * return: 0: FAIL; 1: SUCCESS
298  ************************************************************************/
HAL_LPUART_Wait_TX_Done(LPUART_HandleTypeDef * hlpuart)299 HAL_StatusTypeDef HAL_LPUART_Wait_TX_Done(LPUART_HandleTypeDef *hlpuart)
300 {
301     while (0 == (hlpuart->Instance->SR & (1 << LPUART_SR_TX_FINISH_INDEX) ) ) {};
302     hlpuart->Instance->SR = (1 << LPUART_SR_TX_FINISH_INDEX);
303     return HAL_OK;
304 }
305 
HAL_LPUART_Output(LPUART_HandleTypeDef * hlpuart,unsigned char c)306 void HAL_LPUART_Output(LPUART_HandleTypeDef *hlpuart, unsigned char c)
307 {
308     if ((hlpuart->Instance->SR) & (1U << LPUART_SR_TX_EMPTY_INDEX) )
309     {
310         hlpuart->Instance->TXDR = c;
311     }
312 
313     HAL_LPUART_Wait_TX_Done(hlpuart);
314 }
315 
316 /************************************************************************
317  * function   : uart_send_bytes
318  * Description: uart send bytes
319  * input :
320  *         UINT32 uart_index: Serial port number
321  *         UINT8* buff: out buffer
322  *         UINT32 length: buffer length
323  * return: none
324  ************************************************************************/
HAL_LPUART_Send_Bytes(LPUART_HandleTypeDef * hlpuart,uint8_t * buff,uint32_t length)325 void HAL_LPUART_Send_Bytes(LPUART_HandleTypeDef *hlpuart, uint8_t *buff, uint32_t length)
326 {
327     uint32_t i;
328     for (i = 0; i < length; i++)
329     {
330         HAL_LPUART_Output(hlpuart, *buff++);
331     }
332 }
333 
334 /************************************************************************
335  * function   : HAL_LPUART_Receive_Bytes_Timeout
336  * Description: uart receive bytes
337  * input :
338  *         UART_HandleTypeDef *huart: pointer to uart handle structure
339  *         UINT8* buff: out buffer
340  *         UINT32 length: buffer length
341  *         UINT32 ms: number of ms to delay one byte
342  * return: received bytes
343  ************************************************************************/
HAL_LPUART_Receive_Bytes_Timeout(LPUART_HandleTypeDef * hlpuart,uint8_t * rxbuff,uint32_t length,uint32_t ms)344 uint32_t HAL_LPUART_Receive_Bytes_Timeout(LPUART_HandleTypeDef *hlpuart, uint8_t * rxbuff, uint32_t length, uint32_t ms)
345 {
346     volatile uint32_t i, timeout, count;;
347     if(0x00 == IS_LPUART_INSTANCE(hlpuart->Instance))
348     {
349         return 0;
350     }
351     timeout = (System_Get_APBClock() >> 13) * ms;
352     count = timeout;
353     i = 0;
354     while(i < length)
355     {
356         if((hlpuart->rx_read_index) != (hlpuart->rx_write_index))
357         {
358             rxbuff[i] = hlpuart->rx_buffer[hlpuart->rx_read_index];
359             hlpuart->rx_read_index = (((hlpuart->rx_read_index) + 1)%(hlpuart->rx_buffer_size) );
360             count = timeout;
361             i++;
362         }
363         else
364         {
365             if (0 == count)//timeout
366             {
367                 break;
368             }
369             else
370             {
371                 count--;
372             }
373         }
374     }
375     return i;
376 }
377 /************************************************************************
378  * function   : HAL_LPUART_Receive_Bytes
379  * Description: LPUART receive bytes.
380  * input :
381  *         UART_HandleTypeDef *huart: pointer to uart handle structure
382  *         buff:receive data buff
383  *         length:length of buff
384  * return:length
385  ************************************************************************/
HAL_LPUART_Receive_Bytes(LPUART_HandleTypeDef * hlpuart,uint8_t * rxbuff,uint32_t length)386 uint32_t HAL_LPUART_Receive_Bytes(LPUART_HandleTypeDef *hlpuart, uint8_t * rxbuff, uint32_t length)
387 {
388     volatile uint32_t i, ie_backup;
389     if(0x00 == IS_LPUART_INSTANCE(hlpuart->Instance))
390     {
391         return 0;
392     }
393     ie_backup = hlpuart->Instance->IE;
394     hlpuart->Instance->IE = 0;
395     i = 0;
396     while(i < length)
397     {
398         if( (hlpuart->Instance->SR) & (1U << LPUART_SR_RX_INDEX) )
399         {
400             rxbuff[i] = hlpuart->Instance->RXDR;
401             i++;
402         }
403     }
404     hlpuart->Instance->IE = ie_backup;
405     return length;
406 }
407 /************************************************************************
408  * function   : HAL_LPUART_DMA_Send_Bytes
409  * Description: LPUART send bytes by DMA.
410  * input :
411  *         UART_HandleTypeDef *huart: pointer to uart handle structure
412  *         buff:send data buff
413  *         length:length of buff
414  * return:none
415  ************************************************************************/
HAL_LPUART_DMA_Send_Bytes(LPUART_HandleTypeDef * hlpuart,uint8_t * buff,uint32_t length)416 void HAL_LPUART_DMA_Send_Bytes(LPUART_HandleTypeDef *hlpuart, uint8_t *buff, uint32_t length)
417 {
418     hlpuart->Instance->CR |= (1U << LPUART_CR_DMA_EN_INDEX);
419     hlpuart->tx_busy = 1;
420     HAL_DMA_Start_IT(hlpuart->dma_tx_handler, (uint32_t)buff, (uint32_t)&hlpuart->Instance->TXDR, length);
421  }
422 
423 /************************************************************************
424  * function   : HAL_LPUART_Clear_Wakeup_Flags
425  * Description: Clear the LPUART STOP wake up flag.
426  * input :
427  *         UART_HandleTypeDef *huart: pointer to uart handle structure
428  *         Wakeup_Bits:LPUART wakeup flag,could be: LPUART_WAKEUP_RX_BIT    LPUART_WAKEUP_MATCH_BIT    LPUART_WAKEUP_START_BIT
429  * return:none
430  ************************************************************************/
431 
HAL_LPUART_Clear_Wakeup_Flags(LPUART_HandleTypeDef * hlpuart,uint32_t Wakeup_Bits)432 void HAL_LPUART_Clear_Wakeup_Flags(LPUART_HandleTypeDef *hlpuart, uint32_t Wakeup_Bits)
433 {
434     hlpuart->Instance->SR = Wakeup_Bits;
435 }
436 
437 
438