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