1 /******************************************************************************
2  * Copyright (c) 2022 Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
3  * All rights reserved.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *   http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  *****************************************************************************/
18 
19 /********************************************************************************************************
20  * @file	uart.c
21  *
22  * @brief	This is the source file for B91
23  *
24  * @author	Driver Group
25  *
26  *******************************************************************************************************/
27 #include "uart.h"
28 
29 /**********************************************************************************************************************
30  *                                			  local constants                                                       *
31  *********************************************************************************************************************/
32 
33 
34 /**********************************************************************************************************************
35  *                                           	local macro                                                        *
36  *********************************************************************************************************************/
37 
38 
39 /**********************************************************************************************************************
40  *                                             local data type                                                     *
41  *********************************************************************************************************************/
42 
43 
44 /**********************************************************************************************************************
45  *                                              global variable                                                       *
46  *********************************************************************************************************************/
47 dma_config_t uart_tx_dma_config[2]={
48 	{	.dst_req_sel 		= DMA_REQ_UART0_TX,//tx req
49 		.src_req_sel 		= 0,
50 		.dst_addr_ctrl		= DMA_ADDR_FIX,
51 		.src_addr_ctrl	 	= DMA_ADDR_INCREMENT,//increment
52 		.dstmode		 	= DMA_HANDSHAKE_MODE,//handshake
53 		.srcmode			= DMA_NORMAL_MODE,
54 		.dstwidth 			= DMA_CTR_WORD_WIDTH,//must be word
55 		.srcwidth 			= DMA_CTR_WORD_WIDTH,//must be word
56 		.src_burst_size 	= 0,//must be 0
57 		.read_num_en		= 0,
58 		.priority 			= 0,
59 		.write_num_en		= 0,
60 		.auto_en 			= 0,//must be 0
61 	},
62 	{	.dst_req_sel 		= DMA_REQ_UART1_TX,//tx req
63 		.src_req_sel 		= 0,
64 		.dst_addr_ctrl		= DMA_ADDR_FIX,
65 		.src_addr_ctrl	 	= DMA_ADDR_INCREMENT,//increment
66 		.dstmode		 	= DMA_HANDSHAKE_MODE,//handshake
67 		.srcmode			= DMA_NORMAL_MODE,
68 		.dstwidth 			= DMA_CTR_WORD_WIDTH,//must be word
69 		.srcwidth 			= DMA_CTR_WORD_WIDTH,//must be word
70 		.src_burst_size 	= 0,//must be 0
71 		.read_num_en		= 0,
72 		.priority 			= 0,
73 		.write_num_en		= 0,
74 		.auto_en 			= 0,//must be 0
75 	}
76 };
77 dma_config_t uart_rx_dma_config[2]={
78 	{ 	.dst_req_sel 		= 0,//tx req
79 		.src_req_sel 		= DMA_REQ_UART0_RX,
80 		.dst_addr_ctrl 		= DMA_ADDR_INCREMENT,
81 		.src_addr_ctrl 		= DMA_ADDR_FIX,
82 		.dstmode 			= DMA_NORMAL_MODE,
83 		.srcmode 			= DMA_HANDSHAKE_MODE,
84 		.dstwidth 			= DMA_CTR_WORD_WIDTH,//must be word
85 		.srcwidth 			= DMA_CTR_WORD_WIDTH,////must be word
86 		.src_burst_size 	= 0,
87 		.read_num_en 		= 0,
88 		.priority 			= 0,
89 		.write_num_en 		= 0,
90 		.auto_en 			= 0,//must be 0
91 	},
92 	{ 	.dst_req_sel 		= 0,//tx req
93 		.src_req_sel 		= DMA_REQ_UART1_RX,
94 		.dst_addr_ctrl 		= DMA_ADDR_INCREMENT,
95 		.src_addr_ctrl 		= DMA_ADDR_FIX,
96 		.dstmode 			= DMA_NORMAL_MODE,
97 		.srcmode 			= DMA_HANDSHAKE_MODE,
98 		.dstwidth 			= DMA_CTR_WORD_WIDTH,//must be word
99 		.srcwidth 			= DMA_CTR_WORD_WIDTH,////must be word
100 		.src_burst_size 	= 0,
101 		.read_num_en 		= 0,
102 		.priority 			= 0,
103 		.write_num_en 		= 0,
104 		.auto_en 			= 0,//must be 0
105 	}
106 };
107 /**********************************************************************************************************************
108  *                                              local variable                                                     *
109  *********************************************************************************************************************/
110  static unsigned char uart_dma_tx_chn[2];
111  static unsigned char uart_dma_rx_chn[2];
112  static unsigned int uart_dma_rev_size=0;
113 /**********************************************************************************************************************
114  *                                          local function prototype                                               *
115  *********************************************************************************************************************/
116  /**
117   * @brief     This function is used to look for the prime.if the prime is finded,it will return 1, or return 0.
118   * @param[in] n - the calue to judge.
119   * @return    0 or 1
120   */
121  static unsigned char uart_is_prime(unsigned int n);
122 
123  /**
124   *	@brief	This function serves to set pin for UART fuction.
125   *	@param  tx_pin - To set TX pin.
126   *	@param  rx_pin - To set RX pin.
127   *	@return	none
128   */
129 static void uart_set_fuc_pin(uart_tx_pin_e tx_pin,uart_rx_pin_e rx_pin);
130 
131 /**********************************************************************************************************************
132  *                                         global function implementation                                             *
133  *********************************************************************************************************************/
134 
135 /**
136  * @brief      This function initializes the UART module.
137  * @param[in]  uart_num    - UART0 or UART1.
138  * @param[in]  div         - uart clock divider.
139  * @param[in]  bwpc        - bitwidth, should be set to larger than 2.
140  * @param[in]  parity      - selected parity type for UART interface.
141  * @param[in]  stop_bit    - selected length of stop bit for UART interface.
142  * @return     none
143  * @note 	   sys_clk      baudrate   g_uart_div         g_bwpc
144  *
145  *  	       16Mhz        9600          118   			 13
146  *                          19200         118     			  6
147  *          	            115200          9       		 13
148  *
149  * 	           24Mhz        9600          249       		  9
150  *           	 	    	19200		  124                 9
151  *          	 	    	115200         12    			 15
152  *
153  *   	       32Mhz        9600          235       		 13
154  *          	 	        19200		  235                 6
155  *           	 	 	    115200         17    			 13
156  *
157  *   	       48Mhz        9600          499       		  9
158  *          	 	 	    19200		  249                 9
159  *           	 	 	    115200         25    			 15
160 */
uart_init(uart_num_e uart_num,unsigned short div,unsigned char bwpc,uart_parity_e parity,uart_stop_bit_e stop_bit)161 void uart_init(uart_num_e uart_num,unsigned short div, unsigned char bwpc, uart_parity_e parity, uart_stop_bit_e stop_bit)
162 {
163 	reg_uart_ctrl0(uart_num) &= ~ (FLD_UART_BPWC_O);
164 	reg_uart_ctrl0(uart_num) |= bwpc; //set bwpc
165     reg_uart_clk_div(uart_num) = (div | FLD_UART_CLK_DIV_EN); //set div_clock
166 
167     //parity config
168     if (parity) {
169     	reg_uart_ctrl1(uart_num)  |= FLD_UART_PARITY_ENABLE; //enable parity function
170         if (UART_PARITY_EVEN == parity) {
171         	reg_uart_ctrl1(uart_num)  &= (~FLD_UART_PARITY_POLARITY); //enable even parity
172         }
173         else if (UART_PARITY_ODD == parity) {
174         	reg_uart_ctrl1(uart_num)  |= FLD_UART_PARITY_POLARITY; //enable odd parity
175         }
176     }
177     else {
178     	reg_uart_ctrl1(uart_num)  &= (~FLD_UART_PARITY_ENABLE); //disable parity function
179     }
180 
181     //stop bit config
182     reg_uart_ctrl1(uart_num)  &= (~FLD_UART_STOP_SEL);
183     reg_uart_ctrl1(uart_num)  |= stop_bit;
184 }
185 
186 /***********************************************************
187  * @brief  		This function serves to calculate the best bwpc(bit width) .i.e reg0x96.
188  * @param[in]	baudrate - baut rate of UART.
189  * @param[in]	pclk   - system clock.
190  * @param[out]	div      - uart clock divider.
191  * @param[out]	bwpc     - bitwidth, should be set to larger than 2.
192  * @return 		none
193  * @note        BaudRate*(div+1)*(bwpc+1) = system clock
194  *  		    simplify the expression: div*bwpc =  constant(z)
195  * 		        bwpc range from 3 to 15.so loop and get the minimum one decimal point
196  */
uart_cal_div_and_bwpc(unsigned int baudrate,unsigned int pclk,unsigned short * div,unsigned char * bwpc)197 void uart_cal_div_and_bwpc(unsigned int baudrate, unsigned int pclk, unsigned short* div, unsigned char *bwpc)
198 {
199 	unsigned char i = 0, j= 0;
200 	unsigned int primeInt = 0;
201 	unsigned char primeDec = 0;
202 	unsigned int D_intdec[13],D_int[13];
203 	unsigned char D_dec[13];
204 
205 	primeInt = pclk/baudrate;
206 	primeDec = 10*pclk/baudrate - 10*primeInt;
207 
208 	if(uart_is_prime(primeInt)){ // primeInt is prime
209 		primeInt += 1;  //+1 must be not prime. and primeInt must be larger than 2.
210 	}
211 	else{
212 		if(primeDec > 5){ // >5
213 			primeInt += 1;
214 			if(uart_is_prime(primeInt)){
215 				primeInt -= 1;
216 			}
217 		}
218 	}
219 
220 	for(i=3;i<=15;i++){
221 		D_intdec[i-3] = (10*primeInt)/(i+1);////get the LSB
222 		D_dec[i-3] = D_intdec[i-3] - 10*(D_intdec[i-3]/10);///get the decimal section
223 		D_int[i-3] = D_intdec[i-3]/10;///get the integer section
224 	}
225 
226 	//find the max and min one decimation point
227 	unsigned char position_min = 0,position_max = 0;
228 	unsigned int min = 0xffffffff,max = 0x00;
229 	for(j=0;j<13;j++){
230 		if((D_dec[j] <= min)&&(D_int[j] != 0x01)){
231 			min = D_dec[j];
232 			position_min = j;
233 		}
234 		if(D_dec[j]>=max){
235 			max = D_dec[j];
236 			position_max = j;
237 		}
238 	}
239 
240 	if((D_dec[position_min]<5) && (D_dec[position_max]>=5)){
241 		if(D_dec[position_min]<(10-D_dec[position_max])){
242 			*bwpc = position_min + 3;
243 			*div = D_int[position_min]-1;
244 		}
245 		else{
246 			*bwpc = position_max + 3;
247 			*div = D_int[position_max];
248 		}
249 	}
250 	else if((D_dec[position_min]<5) && (D_dec[position_max]<5)){
251 		*bwpc = position_min + 3;
252 		*div = D_int[position_min] - 1;
253 	}
254 	else{
255 		*bwpc = position_max + 3;
256 		*div = D_int[position_max];
257 	}
258 }
259 
260 /**
261  * @brief  		This function serves to set r_rxtimeout. this setting is transfer one bytes need cycles base on uart_clk.
262  * 				For example, if  transfer one bytes (1start bit+8bits data+1 priority bit+2stop bits) total 12 bits,
263  * 				this register setting should be (bpwc+1)*12.
264  * @param[in]	uart_num - UART0 or UART1.
265  * @param[in]	bwpc     - bitwidth, should be set to larger than 2.
266  * @param[in]	bit_cnt  - bit number.
267  * @param[in]	mul	     - mul.
268  * @return 		none
269  */
uart_set_dma_rx_timeout(uart_num_e uart_num,unsigned char bwpc,unsigned char bit_cnt,uart_timeout_mul_e mul)270 void uart_set_dma_rx_timeout(uart_num_e uart_num,unsigned char bwpc, unsigned char bit_cnt, uart_timeout_mul_e mul)
271 {
272     reg_uart_rx_timeout0(uart_num) = (bwpc+1) * bit_cnt; //one byte includes 12 bits at most
273     reg_uart_rx_timeout1(uart_num) &= (~FLD_UART_TIMEOUT_MUL);
274 	reg_uart_rx_timeout1(uart_num) |= mul; //if over 2*(tmp_bwpc+1),one transaction end.
275 }
276 
277  unsigned char uart_tx_byte_index[2] = {0};
278 /**
279  * @brief     This function serves to send data by byte with not DMA method.
280  * @param[in] uart_num - UART0 or UART1.
281  * @param[in] tx_data  - the data to be send.
282  * @return    none
283  */
uart_send_byte(uart_num_e uart_num,unsigned char tx_data)284 void uart_send_byte(uart_num_e uart_num, unsigned char tx_data)
285 {
286 	while(uart_get_txfifo_num(uart_num)>7);
287 
288 	reg_uart_data_buf(uart_num, uart_tx_byte_index[uart_num]) = tx_data;
289 	uart_tx_byte_index[uart_num] ++;
290 	(uart_tx_byte_index[uart_num]) &= 0x03;
291 }
292 
293 unsigned char uart_rx_byte_index[2]={0};
294 /**
295  * @brief     This function serves to receive uart data by byte with not DMA method.
296  * @param[in] uart_num - UART0 or UART1.
297  * @return    none
298  */
uart_read_byte(uart_num_e uart_num)299 unsigned char uart_read_byte(uart_num_e uart_num)
300 {
301 	unsigned char rx_data = reg_uart_data_buf(uart_num, uart_rx_byte_index[uart_num]) ;
302 	uart_rx_byte_index[uart_num]++;
303 	uart_rx_byte_index[uart_num] &= 0x03 ;
304 	return rx_data;
305 }
306 
307 /**
308  * @brief     This function serves to judge if the transmission of uart is done.
309  * @param[in] uart_num - UART0 or UART1.
310  * @return    return the tx status.
311  * -          0:tx is done     1:tx isn't done
312  */
uart_tx_is_busy(uart_num_e uart_num)313 unsigned char uart_tx_is_busy(uart_num_e uart_num)
314 {
315      return ( (reg_uart_status2(uart_num) & FLD_UART_TX_DONE) ? 0 : 1) ;
316 }
317 
318 /**
319  * @brief     This function serves to send uart0 data by halfword with not DMA method.
320  * @param[in] uart_num - UART0 or UART1.
321  * @param[in] data  - the data to be send.
322  * @return    none
323  */
uart_send_hword(uart_num_e uart_num,unsigned short data)324 void uart_send_hword(uart_num_e uart_num, unsigned short data)
325 {
326 	static unsigned char uart_tx_hword_index[2]={0};
327 
328 	while(uart_get_txfifo_num(uart_num)>6);
329 
330 	reg_uart_data_hword_buf(uart_num, uart_tx_hword_index[uart_num]) = data;
331 	uart_tx_hword_index[uart_num]++ ;
332 	uart_tx_hword_index[uart_num] &= 0x01 ;
333 }
334 
335 /**
336  * @brief     This function serves to send data by word with not DMA method.
337  * @param[in] uart_num - UART0 or UART1.
338  * @param[in] data - the data to be send.
339  * @return    none
340  */
uart_send_word(uart_num_e uart_num,unsigned int data)341 void uart_send_word(uart_num_e uart_num, unsigned int data)
342 {
343 	while (uart_get_txfifo_num(uart_num)>4);
344 	reg_uart_data_word_buf(uart_num) = data;
345 
346 }
347 
348 /**
349  * @brief     This function serves to set the RTS pin's level manually.
350  * @param[in] uart_num - UART0 or UART1.
351  * @param[in] polarity - set the output of RTS pin(only for manual mode).
352  * @return    none
353  */
uart_set_rts_level(uart_num_e uart_num,unsigned char polarity)354 void uart_set_rts_level(uart_num_e uart_num, unsigned char polarity)
355 {
356     if (polarity) {
357     	reg_uart_ctrl2(uart_num) |= FLD_UART_RTS_MANUAL_V;
358     }
359     else {
360     	reg_uart_ctrl2(uart_num) &= (~FLD_UART_RTS_MANUAL_V);
361     }
362 }
363 
364 /**
365  *	@brief		This function serves to set pin for UART0 cts function .
366  *	@param[in]  cts_pin -To set cts pin.
367  *	@return		none
368  */
uart_set_cts_pin(uart_cts_pin_e cts_pin)369 void uart_set_cts_pin(uart_cts_pin_e cts_pin)
370 {
371 	unsigned char val = 0;
372 	unsigned char mask = 0xff;
373 	if(cts_pin == UART0_CTS_PA1)
374 	{
375 		mask= (unsigned char)~(BIT(2)|BIT(3));
376 		val = BIT(2);
377 	}
378 	else if(cts_pin == UART0_CTS_PB6)
379 	{
380 		mask = (unsigned char)~(BIT(4)|BIT(5));
381 		val = BIT(5);
382 		reg_gpio_pad_mul_sel|=BIT(0);
383 	}
384 	else if(cts_pin == UART0_CTS_PD0)
385 	{
386 		mask = (unsigned char)~(BIT(0)|BIT(1));
387 		val = 0;
388 	}
389 	else if(cts_pin == UART1_CTS_PC4)
390 	{
391 		mask= (unsigned char)~(BIT(0)|BIT(1));
392 		val = BIT(1);
393 		reg_gpio_pad_mul_sel|=BIT(0);
394 	}
395 	else if(cts_pin == UART1_CTS_PD4)
396 	{
397 		mask = (unsigned char)~(BIT(0)|BIT(1));
398 		val = 0;
399 	}
400 	else if(cts_pin == UART1_CTS_PE1)
401 	{
402 		mask = (unsigned char)~(BIT(2)|BIT(3));
403 		val = BIT(2);
404 	}
405 	reg_gpio_func_mux(cts_pin)=(reg_gpio_func_mux(cts_pin)& mask)|val;
406 	gpio_function_dis(cts_pin);
407 }
408 
409 /**
410  *	@brief		This function serves to set pin for UART0 rts function .
411  *	@param[in]  rts_pin - To set rts pin.
412  *	@return		none
413  */
uart_set_rts_pin(uart_rts_pin_e rts_pin)414 void uart_set_rts_pin(uart_rts_pin_e rts_pin)
415 {
416 	unsigned char val = 0;
417 	unsigned char mask = 0xff;
418 	if(rts_pin == UART0_RTS_PA2)
419 	{
420 		mask= (unsigned char)~(BIT(4)|BIT(5));
421 		val = BIT(4);
422 	}
423 	else if(rts_pin == UART0_RTS_PB4)
424 	{
425 		mask = (unsigned char)~(BIT(0)|BIT(1));
426 		val = BIT(1);
427 		reg_gpio_pad_mul_sel|=BIT(0);
428 	}
429 	else if(rts_pin == UART0_RTS_PD1)
430 	{
431 		mask = (unsigned char)~(BIT(2)|BIT(3));
432 		val = 0;
433 	}
434 	else if(rts_pin == UART1_RTS_PC5)
435 	{
436 		mask= (unsigned char)~(BIT(2)|BIT(3));
437 		val = BIT(3);
438 		reg_gpio_pad_mul_sel|=BIT(0);
439 	}
440 	else if(rts_pin == UART1_RTS_PD5)
441 	{
442 		mask = (unsigned char)~(BIT(2)|BIT(3));
443 		val = 0;
444 	}
445 	else if(rts_pin == UART1_RTS_PE3)
446 	{
447 		mask = (unsigned char)~(BIT(6)|BIT(7));
448 		val = BIT(6);
449 	}
450 	reg_gpio_func_mux(rts_pin)=(reg_gpio_func_mux(rts_pin)& mask)|val;
451 	gpio_function_dis(rts_pin);
452 }
453 
454 /**
455 * @brief      This function serves to select pin for UART module.
456 * @param[in]  tx_pin  - the pin to send data.
457 * @param[in]  rx_pin  - the pin to receive data.
458 * @return     none
459 */
uart_set_pin(uart_tx_pin_e tx_pin,uart_rx_pin_e rx_pin)460 void uart_set_pin(uart_tx_pin_e tx_pin,uart_rx_pin_e rx_pin)
461 {
462 	gpio_set_up_down_res(tx_pin, GPIO_PIN_PULLUP_10K);
463 	gpio_set_up_down_res(rx_pin, GPIO_PIN_PULLUP_10K);
464 	uart_set_fuc_pin(tx_pin,rx_pin);//set tx and rx pin
465 	gpio_input_en(tx_pin);
466 	gpio_input_en(rx_pin);
467 }
468 
469 /**
470 * @brief      This function serves to set rtx pin for UART module.
471 * @param[in]  rx_pin  - the rtx pin need to set.
472 * @return     none
473 */
uart_set_rtx_pin(uart_rx_pin_e rx_pin)474 void uart_set_rtx_pin(uart_rx_pin_e rx_pin)
475 {
476 	unsigned char val = 0;
477  	unsigned char mask = 0xff;
478 	gpio_set_up_down_res(rx_pin, GPIO_PIN_PULLUP_10K);
479 	if(rx_pin == UART0_RX_PA4)
480 	{
481 	 	mask= (unsigned char)~(BIT(1)|BIT(0));
482 	 	val = BIT(0);
483 	}
484 	else if(rx_pin == UART0_RX_PB3)
485 	{
486 	 	mask = (unsigned char)~(BIT(7)|BIT(6));
487 	 	val = BIT(7);
488 	 	reg_gpio_pad_mul_sel|=BIT(0);
489 	}
490     else if(rx_pin ==UART0_RX_PD3)
491 	{
492 	    mask = (unsigned char)~(BIT(7)|BIT(6));
493 	 	val = 0;
494 	}
495 	else if(rx_pin == UART1_RX_PC7)
496 	{
497 	    mask = (unsigned char)~(BIT(7)|BIT(6));
498 	 	val = BIT(7);
499 	 	reg_gpio_pad_mul_sel|=BIT(0);
500 	}
501 	else if(rx_pin ==  UART1_RX_PD7)
502 	{
503 	 	mask = (unsigned char)~(BIT(7)|BIT(6));
504 	 	val = 0;
505 	}
506 	else if(rx_pin ==  UART1_RX_PE2)
507 	{
508 	    mask = (unsigned char)~(BIT(5)|BIT(4));
509 	    val = BIT(4);
510 	}
511 	reg_gpio_func_mux(rx_pin)=(reg_gpio_func_mux(rx_pin)& mask)|val;
512 	gpio_input_en(rx_pin);
513 	gpio_function_dis(rx_pin);
514 }
515 
516 /**
517 * @brief     This function serves to send data with not DMA method.
518 * @param[in] uart_num - UART0 or UART1.
519 * @param[in] addr     - pointer to the buffer containing data need to send.
520 * @param[in] len      - NDMA transmission length.
521 * @return    1
522 */
uart_send(uart_num_e uart_num,unsigned char * addr,unsigned char len)523 unsigned char uart_send(uart_num_e uart_num, unsigned char * addr, unsigned char len )
524 {
525 	for(unsigned char i=0;i<len;i++)
526 	{
527 		uart_send_byte(uart_num,addr[i]);
528 	}
529 	return 1;
530 }
531 
532 /**
533  * @brief     	This function serves to send data by DMA, this function tell the DMA to get data from the RAM and start.
534  * @param[in]  	uart_num - UART0 or UART1.
535  * @param[in] 	addr     - pointer to the buffer containing data need to send.
536  * @param[in] 	len      - DMA transmission length.The maximum transmission length of DMA is 0xFFFFFC bytes, so dont'n over this length.
537  * @return      1  dma start send.
538  *              0  the length is error.
539  */
uart_send_dma(uart_num_e uart_num,unsigned char * addr,unsigned int len)540 unsigned char uart_send_dma(uart_num_e uart_num, unsigned char * addr, unsigned int len )
541 {
542 	if(len!=0)
543 	{
544 	    uart_clr_tx_done(uart_num);
545 	    dma_set_address(uart_dma_tx_chn[uart_num],(unsigned int)convert_ram_addr_cpu2bus(addr),reg_uart_data_buf_adr(uart_num));
546 	    dma_set_size(uart_dma_tx_chn[uart_num],len,DMA_WORD_WIDTH);
547 	    dma_chn_en(uart_dma_tx_chn[uart_num]);
548 	    return 1;
549 	}
550 	else
551 	{
552 		return 0;
553 	}
554 }
555 
556 /**
557  * @brief     	This function serves to receive data function by DMA, this  function tell the DMA to get data from the uart data fifo.
558  * @param[in]  	uart_num - UART0 or UART1.
559  * @param[in] 	addr     - pointer to the buffer  receive data.
560  * @param[in]   rev_size - the receive length of DMA,The maximum transmission length of DMA is 0xFFFFFC bytes, so dont'n over this length.
561  * @note        1. rev_size must be larger than the data you received actually.
562  *              2. the data length can be arbitrary if less than rev_size.
563  * @return    	none
564  */
uart_receive_dma(uart_num_e uart_num,unsigned char * addr,unsigned int rev_size)565  void uart_receive_dma(uart_num_e uart_num, unsigned char * addr,unsigned int rev_size)
566 {
567 	uart_dma_rev_size = rev_size;
568 	dma_chn_dis(uart_dma_rx_chn[uart_num]);
569 	/*In order to be able to receive data of unknown length(A0 doesn't suppport),the DMA SIZE is set to the longest value 0xffffffff.After entering suspend and wake up, and then continue to receive,
570 	DMA will no longer move data from uart fifo, because DMA thinks that the last transmission was not completed and must disable dma_chn first.modified by minghai,confirmed qiangkai 2020.11.26.*/
571 	dma_set_address(uart_dma_rx_chn[uart_num],reg_uart_data_buf_adr(uart_num),(unsigned int)convert_ram_addr_cpu2bus(addr));
572 	dma_set_size(uart_dma_rx_chn[uart_num], rev_size, DMA_WORD_WIDTH);
573 	dma_chn_en(uart_dma_rx_chn[uart_num]);
574 }
575 
576 /**
577  * @brief     This function serves to get the length of the data that dma received.
578  * @param[in] uart_num - UART0 or UART1.
579  * @param[in] chn      - dma channel.
580  * @return    data length.
581  */
uart_get_dma_rev_data_len(uart_num_e uart_num,dma_chn_e chn)582 unsigned int uart_get_dma_rev_data_len(uart_num_e uart_num,dma_chn_e chn)
583 {
584 	unsigned int data_len=0;
585 	unsigned int buff_data_len = (reg_uart_status1(uart_num)&FLD_UART_RBCNT)%4;
586 	if(buff_data_len==0)
587 	{
588 		data_len=4*((uart_dma_rev_size/4)-reg_dma_size(chn));
589 	}
590 	else
591 	{
592 		data_len=4*((uart_dma_rev_size/4)-reg_dma_size(chn)-1)+buff_data_len;
593 	}
594 	return data_len;
595 }
596 
597  /**
598   * @brief     This function serves to set uart tx_dam channel and config dma tx default.
599   * @param[in] uart_num - UART0 or UART1.
600   * @param[in] chn      - dma channel.
601   * @return    none
602   */
uart_set_tx_dma_config(uart_num_e uart_num,dma_chn_e chn)603  void uart_set_tx_dma_config(uart_num_e uart_num, dma_chn_e chn)
604  {
605 	uart_dma_tx_chn[uart_num]=chn;
606  	dma_config(chn, &uart_tx_dma_config[uart_num]);
607  }
608 
609  /**
610   * @brief     This function serves to set uart rx_dam channel and config dma rx default.
611   * @param[in] uart_num - UART0 or UART1.
612   * @param[in] chn      - dma channel.
613   * @return    none
614   */
uart_set_rx_dma_config(uart_num_e uart_num,dma_chn_e chn)615  void uart_set_rx_dma_config(uart_num_e uart_num, dma_chn_e chn)
616  {
617 	uart_dma_rx_chn[uart_num]=chn;
618  	dma_config(chn, &uart_rx_dma_config[uart_num]);
619  }
620 
621  /**
622   * @brief     UART hardware flow control configuration. Configure CTS.
623   * @param[in] uart_num   - UART0 or UART1.
624   * @param[in] cts_pin    - RTS pin select.
625   * @param[in] cts_parity - when CTS's input equals to select, tx will be stopped.
626   * @return    none
627   */
uart_cts_config(uart_num_e uart_num,uart_cts_pin_e cts_pin,unsigned char cts_parity)628  void uart_cts_config(uart_num_e uart_num,uart_cts_pin_e cts_pin,unsigned char cts_parity)
629  {
630 	uart_set_cts_pin(cts_pin);
631 
632 	gpio_input_en(cts_pin);//enable input
633 
634 	if (cts_parity)
635 	{
636 		reg_uart_ctrl1(uart_num) |= FLD_UART_TX_CTS_POLARITY;
637 	}
638 	else
639 	{
640 		reg_uart_ctrl1(uart_num)  &= (~FLD_UART_TX_CTS_POLARITY);
641 	}
642  }
643 
644  /**
645   * @brief     UART hardware flow control configuration. Configure RTS.
646   * @param[in] uart_num     - UART0 or UART1.
647   * @param[in] rts_pin      - RTS pin select.
648   * @param[in] rts_parity   - whether invert the output of RTS pin(only for auto mode)
649   * @param[in] auto_mode_en - set the mode of RTS(auto or manual).
650   * @return    none
651   */
uart_rts_config(uart_num_e uart_num,uart_rts_pin_e rts_pin,unsigned char rts_parity,unsigned char auto_mode_en)652  void uart_rts_config(uart_num_e uart_num,uart_rts_pin_e rts_pin,unsigned char rts_parity,unsigned char auto_mode_en)
653  {
654 	uart_set_rts_pin(rts_pin);
655 
656 	if (auto_mode_en)
657 	{
658 		reg_uart_ctrl2(uart_num) |= FLD_UART_RTS_MANUAL_M;
659 	}
660 	else {
661 		reg_uart_ctrl2(uart_num) &= (~FLD_UART_RTS_MANUAL_M);
662 	}
663 
664 	if (rts_parity)
665 	{
666 		reg_uart_ctrl2(uart_num) |= FLD_UART_RTS_POLARITY;
667 	}
668 	else
669 	{
670 		reg_uart_ctrl2(uart_num) &= (~FLD_UART_RTS_POLARITY);
671 	}
672  }
673 
674  /**********************************************************************************************************************
675   *                    						local function implementation                                             *
676   *********************************************************************************************************************/
677  /**
678    * @brief     This function is used to look for the prime.if the prime is finded,it will return 1, or return 0.
679    * @param[in] n - the calue to judge.
680    * @return    0 or 1
681    */
uart_is_prime(unsigned int n)682  static unsigned char uart_is_prime(unsigned int n)
683  {
684  	unsigned int i = 5;
685  	if(n <= 3){
686  		return 1; //although n is prime, the bwpc must be larger than 2.
687  	}
688  	else if((n %2 == 0) || (n % 3 == 0)){
689  		return 0;
690  	}
691  	else{
692  		for(i=5;i*i<n;i+=6){
693  			if((n % i == 0)||(n %(i+2))==0){
694  				return 0;
695  			}
696  		}
697  		return 1;
698  	}
699  }
700 
701  /**
702   *	@brief	This function serves to set pin for UART fuction.
703   *	@param  tx_pin - To set TX pin.
704   *	@param  rx_pin - To set RX pin.
705   *	@return	none
706   */
uart_set_fuc_pin(uart_tx_pin_e tx_pin,uart_rx_pin_e rx_pin)707 static void uart_set_fuc_pin(uart_tx_pin_e tx_pin,uart_rx_pin_e rx_pin)
708  {
709  	unsigned char val = 0;
710  	unsigned char mask = 0xff;
711 
712  	if(tx_pin == UART0_TX_PA3)
713  	{
714  		mask= (unsigned char)~(BIT(7)|BIT(6));
715  		val = BIT(6);
716  	}
717  	else if(tx_pin == UART0_TX_PB2)
718  	{
719  		mask = (unsigned char)~(BIT(5)|BIT(4));
720  		val = BIT(5);
721  		reg_gpio_pad_mul_sel|=BIT(0);
722  	}
723  	else if(tx_pin == UART0_TX_PD2)
724  	{
725  		mask = (unsigned char)~(BIT(5)|BIT(4));
726  		val = 0;
727  	}
728  	else if(tx_pin == UART1_TX_PC6)
729  	{
730  		mask = (unsigned char)~(BIT(5)|BIT(4));
731  		val = BIT(5);
732  		reg_gpio_pad_mul_sel|=BIT(0);
733  	}
734  	else if(tx_pin == UART1_TX_PD6)
735  	{
736  		mask = (unsigned char)~(BIT(5)|BIT(4));
737  		val = 0;
738  	}
739  	else if(tx_pin == UART1_TX_PE0)
740  	{
741  		mask = (unsigned char)~(BIT(1)|BIT(0));;
742  		val = BIT(0);
743  	}
744  	reg_gpio_func_mux(tx_pin)=(reg_gpio_func_mux(tx_pin)& mask)|val;
745 
746 
747  	if(rx_pin == UART0_RX_PA4)
748  	{
749  		mask= (unsigned char)~(BIT(1)|BIT(0));
750  		val = BIT(0);
751 
752  	}
753  	else if(rx_pin == UART0_RX_PB3)
754  	{
755  		mask = (unsigned char)~(BIT(7)|BIT(6));
756  		val = BIT(7);
757  		reg_gpio_pad_mul_sel|=BIT(0);
758  	}
759  	else if(rx_pin ==UART0_RX_PD3)
760  	{
761  		mask = (unsigned char)~(BIT(7)|BIT(6));
762  		val = 0;
763  	}
764  	else if(rx_pin == UART1_RX_PC7)
765  	{
766  		mask = (unsigned char)~(BIT(7)|BIT(6));
767  		val = BIT(7);
768  		reg_gpio_pad_mul_sel|=BIT(0);
769  	}
770  	else if(rx_pin ==  UART1_RX_PD7)
771  	{
772  		mask = (unsigned char)~(BIT(7)|BIT(6));
773  		val = 0;
774  	}
775  	else if(rx_pin ==  UART1_RX_PE2)
776  	{
777  		mask = (unsigned char)~(BIT(5)|BIT(4));
778  		val = BIT(4);
779  	}
780  	//note:  setting pad the function  must before  setting no_gpio function, cause it will lead to uart transmit extra one byte data at begin.(confirmed by minghai&sunpeng)
781  	reg_gpio_func_mux(rx_pin)=(reg_gpio_func_mux(rx_pin)& mask)|val;
782 
783  	gpio_function_dis(tx_pin);
784  	gpio_function_dis(rx_pin);
785  }
786