1 /**************************************************************************//**
2 *
3 * @copyright (C) 2019 Nuvoton Technology Corp. All rights reserved.
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Change Logs:
8 * Date Author Notes
9 * 2022-10-10 Wayne First version
10 *
11 ******************************************************************************/
12
13 #include <rtthread.h>
14
15 #if defined(BSP_USING_WHC)
16
17 #include "drv_whc.h"
18 #include <stdio.h>
19
20 #define DBG_ENABLE
21 #define DBG_LEVEL DBG_LOG
22 #define DBG_SECTION_NAME "whc.demo"
23 #define DBG_COLOR
24 #include <rtdbg.h>
25
26 #define USE_WORMHOLE_CHNAME "whc0-0"
27
28 typedef enum
29 {
30 evCMD_MEM_ALLOCATE,
31 evCMD_MEM_FREE,
32 evCMD_MEM_COPY,
33 evCMD_DEVMEM_WRITE,
34 evCMD_DEVMEM_READ,
35 evCMD_MEM_SET
36 } nu_whc_cmd;
37
38 typedef enum
39 {
40 evCMD_REQ,
41 evCMD_RESP,
42 } nu_whc_cmd_type;
43
44 #define CMD_TYPE_Pos 16
45 #define CMD_TYPE_Msk (3<<CMD_TYPE_Pos)
46 #define PACK_MSG_CMD(t, x) (((t<<CMD_TYPE_Pos)&CMD_TYPE_Msk)|x)
47 #define CMD_IS_REQ(m) (((m.u32Cmd&CMD_TYPE_Msk)>>CMD_TYPE_Pos)==evCMD_REQ)
48 #define CMD_IS_RESP(m) (((m.u32Cmd&CMD_TYPE_Msk)>>CMD_TYPE_Pos)==evCMD_RESP)
49
50 typedef struct
51 {
52 union
53 {
54 nu_whc_msg sMsgBuf;
55 struct
56 {
57 uint32_t u32Cmd;
58 uint32_t u32Addr0; //Dst, free, allocate, set
59 uint32_t u32Addr1; //Src, value
60 uint32_t u32Size;
61 } msg;
62 };
63 } whc_mem;
64 typedef whc_mem *whc_mem_t;
65
66 static struct rt_semaphore tx_sem;
67 static struct rt_semaphore rx_sem;
68 static rt_device_t device = RT_NULL;
69
whc_tx_complete(rt_device_t dev,void * buffer)70 static rt_err_t whc_tx_complete(rt_device_t dev, void *buffer)
71 {
72 return rt_sem_release(&tx_sem);
73 }
74
whc_rx_indicate(rt_device_t dev,rt_size_t size)75 static rt_err_t whc_rx_indicate(rt_device_t dev, rt_size_t size)
76 {
77 return rt_sem_release(&rx_sem);
78 }
79
proc_msg(whc_mem_t req,whc_mem_t resp)80 static rt_err_t proc_msg(whc_mem_t req, whc_mem_t resp)
81 {
82 switch ((nu_whc_cmd)req->msg.u32Cmd)
83 {
84 case evCMD_MEM_ALLOCATE:
85 resp->msg.u32Addr0 = (uint32_t)rt_malloc(req->msg.u32Size);
86 resp->msg.u32Size = req->msg.u32Size;
87 resp->msg.u32Cmd = PACK_MSG_CMD(evCMD_RESP, evCMD_MEM_ALLOCATE);
88 break;
89
90 case evCMD_MEM_FREE:
91 rt_free((void *)req->msg.u32Addr0);
92 resp->msg.u32Addr0 = (uint32_t)req->msg.u32Addr0;
93 resp->msg.u32Cmd = PACK_MSG_CMD(evCMD_RESP, evCMD_MEM_FREE);
94 resp->msg.u32Size = 0;
95 break;
96
97 case evCMD_MEM_COPY:
98 rt_memcpy((void *)req->msg.u32Addr0, (void *)req->msg.u32Addr1, req->msg.u32Size);
99 resp->msg.u32Cmd = PACK_MSG_CMD(evCMD_RESP, evCMD_MEM_COPY);
100 resp->msg.u32Addr0 = (uint32_t)req->msg.u32Addr0;
101 resp->msg.u32Addr1 = (uint32_t)req->msg.u32Addr1;
102 resp->msg.u32Size = req->msg.u32Size;
103 break;
104
105 case evCMD_MEM_SET:
106 rt_memset((void *)req->msg.u32Addr0, (req->msg.u32Addr1 & 0xff), req->msg.u32Size);
107 resp->msg.u32Cmd = PACK_MSG_CMD(evCMD_RESP, evCMD_MEM_SET);
108 resp->msg.u32Addr0 = (uint32_t)req->msg.u32Addr0;
109 resp->msg.u32Addr1 = (uint32_t)(req->msg.u32Addr1 & 0xff);
110 resp->msg.u32Size = req->msg.u32Size;
111 break;
112
113 case evCMD_DEVMEM_WRITE:
114 *((vu32 *)req->msg.u32Addr0) = req->msg.u32Addr1;
115
116 resp->msg.u32Cmd = PACK_MSG_CMD(evCMD_RESP, evCMD_DEVMEM_WRITE);
117 resp->msg.u32Addr0 = 0;
118 resp->msg.u32Addr1 = 0;
119 resp->msg.u32Size = sizeof(uint32_t);
120 break;
121
122 case evCMD_DEVMEM_READ:
123 resp->msg.u32Cmd = PACK_MSG_CMD(evCMD_RESP, evCMD_DEVMEM_READ);
124 resp->msg.u32Addr0 = *((vu32 *)req->msg.u32Addr0);
125 resp->msg.u32Addr1 = 0;
126 resp->msg.u32Size = sizeof(uint32_t);
127 break;
128
129 default:
130 return -RT_ERROR;
131 }
132
133 return -RT_ERROR;
134 }
135
send_msg(whc_mem_t req)136 static rt_err_t send_msg(whc_mem_t req)
137 {
138 if (device)
139 {
140 if (sizeof(nu_whc_msg) != rt_device_write(device, 0, req, sizeof(nu_whc_msg)))
141 {
142 LOG_E("Failed to send msg.");
143 return -RT_ERROR;
144 }
145
146 if (-RT_ETIMEOUT == rt_sem_take(&tx_sem, 100))
147 LOG_E("Timeout cant get ACK.");
148 }
149
150 return RT_EOK;
151 }
152
153
whc_daemon(void * parameter)154 static void whc_daemon(void *parameter)
155 {
156 rt_err_t ret;
157
158 device = rt_device_find(USE_WORMHOLE_CHNAME);
159 RT_ASSERT(device);
160
161 /* Init semaphores */
162 ret = rt_sem_init(&tx_sem, "whc_tx", 0, RT_IPC_FLAG_PRIO);
163 RT_ASSERT(ret == RT_EOK);
164
165 ret = rt_sem_init(&rx_sem, "whc_rx", 0, RT_IPC_FLAG_PRIO);
166 RT_ASSERT(ret == RT_EOK);
167
168 /* Set tx complete function */
169 ret = rt_device_set_tx_complete(device, whc_tx_complete);
170 RT_ASSERT(ret == RT_EOK);
171
172 /* Set rx indicate function */
173 ret = rt_device_set_rx_indicate(device, whc_rx_indicate);
174 RT_ASSERT(ret == RT_EOK);
175
176 ret = rt_device_open(device, 0);
177 if (!device)
178 {
179 LOG_E("Failed to open %s", USE_WORMHOLE_CHNAME);
180 return;
181 }
182
183 while (1)
184 {
185 if (rt_sem_take(&rx_sem, RT_WAITING_FOREVER) == RT_EOK)
186 {
187 nu_whc_msg sNuWhcMsg;
188 whc_mem_t psWhcMem = (whc_mem_t)&sNuWhcMsg;
189
190 if (sizeof(nu_whc_msg) != rt_device_read(device, 0, psWhcMem, sizeof(nu_whc_msg)))
191 continue;
192
193 if (CMD_IS_REQ(psWhcMem->msg))
194 {
195 nu_whc_msg sNuWhcMsg_Resp;
196
197 proc_msg((whc_mem_t)&sNuWhcMsg, (whc_mem_t)&sNuWhcMsg_Resp);
198 send_msg((whc_mem_t)&sNuWhcMsg_Resp);
199 }
200 else if (CMD_IS_RESP(psWhcMem->msg))
201 {
202 LOG_I("Get Resp. 0x%08x 0x%08x 0x%08x %d",
203 psWhcMem->msg.u32Cmd,
204 psWhcMem->msg.u32Addr0,
205 psWhcMem->msg.u32Addr1,
206 psWhcMem->msg.u32Size);
207 }
208
209 } //if
210
211 } //while
212 }
213
wormhole_app(void)214 static int wormhole_app(void)
215 {
216 rt_err_t result = 0;
217 rt_thread_t thread;
218
219 thread = rt_thread_create("whcD", whc_daemon, RT_NULL, 2048, 25, 20);
220 if (thread != RT_NULL)
221 {
222 result = rt_thread_startup(thread);
223 RT_ASSERT(result == RT_EOK);
224 }
225
226 return 0;
227 }
228 INIT_COMPONENT_EXPORT(wormhole_app);
229
whc_malloc(uint32_t u32Size)230 void *whc_malloc(uint32_t u32Size)
231 {
232 whc_mem sWhcMem;
233
234 sWhcMem.msg.u32Cmd = PACK_MSG_CMD(evCMD_REQ, evCMD_MEM_ALLOCATE);
235 sWhcMem.msg.u32Size = (uint32_t)u32Size;
236
237 send_msg(&sWhcMem);
238
239 return 0;
240 }
241 RTM_EXPORT(whc_malloc);
242
whc_memcpy(void * pvDst,void * pvSrc,uint32_t u32Size)243 void *whc_memcpy(void *pvDst, void *pvSrc, uint32_t u32Size)
244 {
245 whc_mem sWhcMem;
246
247 sWhcMem.msg.u32Cmd = PACK_MSG_CMD(evCMD_REQ, evCMD_MEM_COPY);
248 sWhcMem.msg.u32Addr0 = (uint32_t)pvDst;
249 sWhcMem.msg.u32Addr1 = (uint32_t)pvSrc;
250 sWhcMem.msg.u32Size = (uint32_t)u32Size;
251
252 send_msg(&sWhcMem);
253
254 return 0;
255 }
256 RTM_EXPORT(whc_memcpy);
257
258
whc_devmem_write(void * pvaddr,uint32_t u32value)259 uint32_t whc_devmem_write(void *pvaddr, uint32_t u32value)
260 {
261 whc_mem sWhcMem;
262
263 sWhcMem.msg.u32Cmd = PACK_MSG_CMD(evCMD_REQ, evCMD_DEVMEM_WRITE);
264 sWhcMem.msg.u32Addr0 = (uint32_t)pvaddr;
265 sWhcMem.msg.u32Addr1 = u32value;
266 sWhcMem.msg.u32Size = sizeof(uint32_t);
267
268 send_msg(&sWhcMem);
269
270 return 0;
271 }
272 RTM_EXPORT(whc_devmem_write);
273
whc_devmem_read(void * pvaddr)274 uint32_t whc_devmem_read(void *pvaddr)
275 {
276 whc_mem sWhcMem;
277
278 sWhcMem.msg.u32Cmd = PACK_MSG_CMD(evCMD_REQ, evCMD_DEVMEM_READ);
279 sWhcMem.msg.u32Addr0 = (uint32_t)pvaddr;
280 sWhcMem.msg.u32Addr1 = 0;
281 sWhcMem.msg.u32Size = sizeof(uint32_t);
282
283 send_msg(&sWhcMem);
284
285 return 0;
286 }
287 RTM_EXPORT(whc_devmem_read);
288
whc_devmem(int argc,char * argv[])289 void whc_devmem(int argc, char *argv[])
290 {
291 volatile unsigned int u32Addr;
292 unsigned int value = 0, mode = 0;
293
294 if (argc < 2 || argc > 3)
295 {
296 goto exit_devmem;
297 }
298
299 if (argc == 3)
300 {
301 if (rt_sscanf(argv[2], "0x%x", &value) != 1)
302 goto exit_devmem;
303 mode = 1; //Write
304 }
305
306 if (rt_sscanf(argv[1], "0x%x", &u32Addr) != 1)
307 goto exit_devmem;
308 else if (u32Addr & (4 - 1))
309 goto exit_devmem;
310
311 if (mode)
312 {
313 whc_devmem_write((void *) u32Addr, value);
314 }
315 rt_kprintf("0x%08x\n", whc_devmem_read((void *)u32Addr));
316
317 return;
318 exit_devmem:
319 rt_kprintf("Read: whc_devmem <physical address in hex>\n");
320 rt_kprintf("Write: whc_devmem <physical address in hex> <value in hex format>\n");
321 return;
322 }
323 MSH_CMD_EXPORT(whc_devmem, dump device registers);
324
325 #endif /* #if defined(BSP_USING_HWSEM)*/
326