1 /*
2  * Copyright 2021 QuickLogic
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  * SPDX-License-Identifier: Apache-2.0
17  */
18 
19 #include "core-v-mcu-config.h"
20 #include <string.h>
21 #include "hal_fc_event.h"
22 #include "hal_udma_ctrl_reg_defs.h"
23 #include "hal_udma_uart_reg_defs.h"
24 #include <drv_usart.h>
25 #include <stdint.h>
26 #include "core-v-mcu-config.h"
27 #include "udma_uart_driver.h"
28 #include "rtthread.h"
29 #include "rtdevice.h"
30 #ifdef PKG_USING_FREERTOS_WRAPPER
31 #include <FreeRTOS.h>
32 #include <semphr.h>
33 #include <task.h>
34 #endif
35 
36 #ifdef PKG_USING_FREERTOS_WRAPPER
37 SemaphoreHandle_t  uart_semaphores_rx[N_UART];
38 SemaphoreHandle_t  uart_semaphores_tx[N_UART];
39 #endif
40 
41 char u1buffer[128], u0buffer[128];
42 int u1rdptr, u1wrptr, u0rdptr,u0wrptr;
43 UdmaUart_t *puart0 = (UdmaUart_t*)(UDMA_CH_ADDR_UART);
44 UdmaUart_t *puart1 = (UdmaUart_t*)(UDMA_CH_ADDR_UART + UDMA_CH_SIZE);
45 
46 extern void uart_rx_isr (void *id);
uart_getchar(uint8_t id)47 uint8_t uart_getchar (uint8_t id) {
48 	uint8_t retval;
49 	if (id == 1) {
50 		while (u1rdptr == u1wrptr) ;
51 		retval = u1buffer[u1rdptr++];
52 		u1rdptr &= 0x7f;
53 	}
54 	if (id == 0) {
55 		while (u0rdptr == u0wrptr) ;
56 		retval = u0buffer[u0rdptr++];
57 		u0rdptr &= 0x7f;
58 	}
59 	return retval;
60 }
udma_uart_open(uint8_t uart_id,uint32_t xbaudrate)61 uint16_t udma_uart_open (uint8_t uart_id, uint32_t xbaudrate) {
62 	UdmaUart_t*				puart;
63 	volatile UdmaCtrl_t*		pudma_ctrl = (UdmaCtrl_t*)UDMA_CH_ADDR_CTRL;
64     #ifdef PKG_USING_FREERTOS_WRAPPER
65 	/* See if already initialized */
66 	if (uart_semaphores_rx[uart_id] != NULL || uart_semaphores_tx[uart_id] != NULL) {
67 		return 1;
68 	}
69 	#endif
70 	/* Enable reset and enable uart clock */
71 	pudma_ctrl->reg_rst |= (UDMA_CTRL_UART0_CLKEN << uart_id);
72 	pudma_ctrl->reg_rst &= ~(UDMA_CTRL_UART0_CLKEN << uart_id);
73 	pudma_ctrl->reg_cg |= (UDMA_CTRL_UART0_CLKEN << uart_id);
74 
75 	#ifdef PKG_USING_FREERTOS_WRAPPER
76 	/* Set semaphore */
77 	SemaphoreHandle_t shSemaphoreHandle =NULL;		// FreeRTOS.h has a define for xSemaphoreHandle, so can't use that
78 	shSemaphoreHandle = xSemaphoreCreateBinary();
79 	configASSERT(shSemaphoreHandle);
80 	xSemaphoreGive(shSemaphoreHandle);
81 	uart_semaphores_rx[uart_id] = shSemaphoreHandle;
82 
83 	shSemaphoreHandle = xSemaphoreCreateBinary();
84 	configASSERT(shSemaphoreHandle);
85 	xSemaphoreGive(shSemaphoreHandle);
86 	uart_semaphores_tx[uart_id] = shSemaphoreHandle;
87     #endif
88 	#ifdef PKG_USING_FREERTOS_WRAPPER
89 	/* Set handlers. */
90 	pi_fc_event_handler_set(SOC_EVENT_UART_RX(uart_id), uart_rx_isr, uart_semaphores_rx[uart_id]);
91 	pi_fc_event_handler_set(SOC_EVENT_UDMA_UART_TX(uart_id), NULL, uart_semaphores_tx[uart_id]);
92 	#else
93     user_pi_fc_event_handler_set(SOC_EVENT_UART_RX(uart_id), uart_rx_isr);
94 	#endif
95 	/* Enable SOC events propagation to FC. */
96 	hal_soc_eu_set_fc_mask(SOC_EVENT_UART_RX(uart_id));
97 	hal_soc_eu_set_fc_mask(SOC_EVENT_UDMA_UART_TX(uart_id));
98 
99 	/* configure */
100 	puart = (UdmaUart_t*)(UDMA_CH_ADDR_UART + uart_id * UDMA_CH_SIZE);
101 	puart->uart_setup_b.div = (uint16_t)(5000000/xbaudrate);
102 	puart->uart_setup_b.bits = 3; // 8-bits
103 //	if (uart_id == 0) puart->uart_setup_b.rx_polling_en = 1;
104 //	if (uart_id == 1)
105 	puart->irq_en_b.rx_irq_en = 1;
106 	puart->uart_setup_b.en_tx = 1;
107 	puart->uart_setup_b.en_rx = 1;
108 	puart->uart_setup_b.rx_clean_fifo = 1;
109 
110 	if (uart_id == 1) {
111 		 u1rdptr = 0;
112 	 	 u1wrptr = 0;
113 	}
114 	if (uart_id == 0) {
115 		 u0rdptr = 0;
116 	 	 u0wrptr = 0;
117 	}
118 
119 	return 0;
120 }
121 
122 #ifdef PKG_USING_FREERTOS_WRAPPER
udma_uart_writeraw(uint8_t uart_id,uint16_t write_len,uint8_t * write_buffer)123 uint16_t udma_uart_writeraw(uint8_t uart_id, uint16_t write_len, uint8_t* write_buffer) {
124 	UdmaUart_t*				puart = (UdmaUart_t*)(UDMA_CH_ADDR_UART + uart_id * UDMA_CH_SIZE);
125 	SemaphoreHandle_t shSemaphoreHandle = uart_semaphores_tx[uart_id];
126 	if( xSemaphoreTake( shSemaphoreHandle, 1000000 ) != pdTRUE ) {
127 		return 1;
128 	}
129 
130 	while (puart->status_b.tx_busy) {  // ToDo: Why is this necessary?  Thought the semaphore should have protected
131 	}
132 
133 	puart->tx_saddr = (uint32_t)write_buffer;
134 	puart->tx_size = write_len;
135 	puart->tx_cfg_b.en = 1; //enable the transfer
136 
137 	return 0;
138 }
139 #endif
140 
udma_uart_read(uint8_t uart_id,uint16_t read_len,uint8_t * read_buffer)141 uint16_t udma_uart_read(uint8_t uart_id, uint16_t read_len, uint8_t* read_buffer) {
142 	uint16_t ret = 0;
143 	uint8_t last_char = 0;
144 	UdmaUart_t*				puart = (UdmaUart_t*)(UDMA_CH_ADDR_UART + uart_id * UDMA_CH_SIZE);
145 
146 
147 	while ( (ret < (read_len - 2)) && (last_char != 0xd)) {
148 		if (puart->valid_b.rx_data_valid == 1) {
149 			last_char = (uint8_t)(puart->data_b.rx_data & 0xff);
150 			if (last_char == 0xd)  // if cr add
151 				read_buffer[ret++] = 0xa;  // linefeed
152 			read_buffer[ret++] = last_char;
153 		}
154 	}
155 	read_buffer[ret] = '\0';
156 	return ret--;
157 }
158 
udma_uart_readraw(uint8_t uart_id,uint16_t read_len,uint8_t * read_buffer)159 uint16_t udma_uart_readraw(uint8_t uart_id, uint16_t read_len, uint8_t* read_buffer) {
160 	uint16_t ret = 0;
161 	uint8_t last_char = 0;
162 	UdmaUart_t*				puart = (UdmaUart_t*)(UDMA_CH_ADDR_UART + uart_id * UDMA_CH_SIZE);
163 
164 	while ( ret < read_len ) {
165 		if (puart->valid_b.rx_data_valid == 1) {
166 			last_char = (uint8_t)(puart->data_b.rx_data & 0xff);
167 			read_buffer[ret++] = last_char;
168 		}
169 	}
170 	return ret--;
171 }
172 
udma_uart_getchar(uint8_t uart_id)173 uint8_t udma_uart_getchar(uint8_t uart_id) {
174 	UdmaUart_t*				puart = (UdmaUart_t*)(UDMA_CH_ADDR_UART + uart_id * UDMA_CH_SIZE);
175 
176 	while (puart->valid_b.rx_data_valid == 0) {
177 	}
178 	return (puart->data_b.rx_data & 0xff);
179 }
180 
udma_uart_control(uint8_t uart_id,udma_uart_control_type_t control_type,void * pparam)181 uint16_t udma_uart_control(uint8_t uart_id, udma_uart_control_type_t control_type, void* pparam) {
182 	UdmaUart_t*				puart = (UdmaUart_t*)(UDMA_CH_ADDR_UART + uart_id * UDMA_CH_SIZE);
183 
184 	switch(control_type) {
185 	case kUartDataValid:
186 		if (uart_id == 0)
187 			return !(u0rdptr == u0wrptr);
188 		if (uart_id == 1)
189 			return !(u1rdptr == u1wrptr);
190 		return puart->valid_b.rx_data_valid;
191 	default:
192 		return 0xFFFF;
193 	}
194 	return 0;
195 }
196