rt-thread-official/bsp/nuvoton/libraries/nu_packages/Demo/wormhole_demo.c

326 lines
8.1 KiB
C

/**************************************************************************//**
*
* @copyright (C) 2019 Nuvoton Technology Corp. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2022-10-10 Wayne First version
*
******************************************************************************/
#include <rtthread.h>
#if defined(BSP_USING_WHC)
#include "drv_whc.h"
#include <stdio.h>
#define DBG_ENABLE
#define DBG_LEVEL DBG_LOG
#define DBG_SECTION_NAME "whc.demo"
#define DBG_COLOR
#include <rtdbg.h>
#define USE_WORMHOLE_CHNAME "whc0-0"
typedef enum
{
evCMD_MEM_ALLOCATE,
evCMD_MEM_FREE,
evCMD_MEM_COPY,
evCMD_DEVMEM_WRITE,
evCMD_DEVMEM_READ,
evCMD_MEM_SET
} nu_whc_cmd;
typedef enum
{
evCMD_REQ,
evCMD_RESP,
} nu_whc_cmd_type;
#define CMD_TYPE_Pos 16
#define CMD_TYPE_Msk (3<<CMD_TYPE_Pos)
#define PACK_MSG_CMD(t, x) (((t<<CMD_TYPE_Pos)&CMD_TYPE_Msk)|x)
#define CMD_IS_REQ(m) (((m.u32Cmd&CMD_TYPE_Msk)>>CMD_TYPE_Pos)==evCMD_REQ)
#define CMD_IS_RESP(m) (((m.u32Cmd&CMD_TYPE_Msk)>>CMD_TYPE_Pos)==evCMD_RESP)
typedef struct
{
union
{
nu_whc_msg sMsgBuf;
struct
{
uint32_t u32Cmd;
uint32_t u32Addr0; //Dst, free, allocate, set
uint32_t u32Addr1; //Src, value
uint32_t u32Size;
} msg;
};
} whc_mem;
typedef whc_mem *whc_mem_t;
static struct rt_semaphore tx_sem;
static struct rt_semaphore rx_sem;
static rt_device_t device = RT_NULL;
static rt_err_t whc_tx_complete(rt_device_t dev, void *buffer)
{
return rt_sem_release(&tx_sem);
}
static rt_err_t whc_rx_indicate(rt_device_t dev, rt_size_t size)
{
return rt_sem_release(&rx_sem);
}
static rt_err_t proc_msg(whc_mem_t req, whc_mem_t resp)
{
switch ((nu_whc_cmd)req->msg.u32Cmd)
{
case evCMD_MEM_ALLOCATE:
resp->msg.u32Addr0 = (uint32_t)rt_malloc(req->msg.u32Size);
resp->msg.u32Size = req->msg.u32Size;
resp->msg.u32Cmd = PACK_MSG_CMD(evCMD_RESP, evCMD_MEM_ALLOCATE);
break;
case evCMD_MEM_FREE:
rt_free((void *)req->msg.u32Addr0);
resp->msg.u32Addr0 = (uint32_t)req->msg.u32Addr0;
resp->msg.u32Cmd = PACK_MSG_CMD(evCMD_RESP, evCMD_MEM_FREE);
resp->msg.u32Size = 0;
break;
case evCMD_MEM_COPY:
rt_memcpy((void *)req->msg.u32Addr0, (void *)req->msg.u32Addr1, req->msg.u32Size);
resp->msg.u32Cmd = PACK_MSG_CMD(evCMD_RESP, evCMD_MEM_COPY);
resp->msg.u32Addr0 = (uint32_t)req->msg.u32Addr0;
resp->msg.u32Addr1 = (uint32_t)req->msg.u32Addr1;
resp->msg.u32Size = req->msg.u32Size;
break;
case evCMD_MEM_SET:
rt_memset((void *)req->msg.u32Addr0, (req->msg.u32Addr1 & 0xff), req->msg.u32Size);
resp->msg.u32Cmd = PACK_MSG_CMD(evCMD_RESP, evCMD_MEM_SET);
resp->msg.u32Addr0 = (uint32_t)req->msg.u32Addr0;
resp->msg.u32Addr1 = (uint32_t)(req->msg.u32Addr1 & 0xff);
resp->msg.u32Size = req->msg.u32Size;
break;
case evCMD_DEVMEM_WRITE:
*((vu32 *)req->msg.u32Addr0) = req->msg.u32Addr1;
resp->msg.u32Cmd = PACK_MSG_CMD(evCMD_RESP, evCMD_DEVMEM_WRITE);
resp->msg.u32Addr0 = 0;
resp->msg.u32Addr1 = 0;
resp->msg.u32Size = sizeof(uint32_t);
break;
case evCMD_DEVMEM_READ:
resp->msg.u32Cmd = PACK_MSG_CMD(evCMD_RESP, evCMD_DEVMEM_READ);
resp->msg.u32Addr0 = *((vu32 *)req->msg.u32Addr0);
resp->msg.u32Addr1 = 0;
resp->msg.u32Size = sizeof(uint32_t);
break;
default:
return -RT_ERROR;
}
return -RT_ERROR;
}
static rt_err_t send_msg(whc_mem_t req)
{
if (device)
{
if (sizeof(nu_whc_msg) != rt_device_write(device, 0, req, sizeof(nu_whc_msg)))
{
LOG_E("Failed to send msg.");
return -RT_ERROR;
}
if (-RT_ETIMEOUT == rt_sem_take(&tx_sem, 100))
LOG_E("Timeout cant get ACK.");
}
return RT_EOK;
}
static void whc_daemon(void *parameter)
{
rt_err_t ret;
device = rt_device_find(USE_WORMHOLE_CHNAME);
RT_ASSERT(device);
/* Init semaphores */
ret = rt_sem_init(&tx_sem, "whc_tx", 0, RT_IPC_FLAG_PRIO);
RT_ASSERT(ret == RT_EOK);
ret = rt_sem_init(&rx_sem, "whc_rx", 0, RT_IPC_FLAG_PRIO);
RT_ASSERT(ret == RT_EOK);
/* Set tx complete function */
ret = rt_device_set_tx_complete(device, whc_tx_complete);
RT_ASSERT(ret == RT_EOK);
/* Set rx indicate function */
ret = rt_device_set_rx_indicate(device, whc_rx_indicate);
RT_ASSERT(ret == RT_EOK);
ret = rt_device_open(device, 0);
if (!device)
{
LOG_E("Failed to open %s", USE_WORMHOLE_CHNAME);
return;
}
while (1)
{
if (rt_sem_take(&rx_sem, RT_WAITING_FOREVER) == RT_EOK)
{
nu_whc_msg sNuWhcMsg;
whc_mem_t psWhcMem = (whc_mem_t)&sNuWhcMsg;
if (sizeof(nu_whc_msg) != rt_device_read(device, 0, psWhcMem, sizeof(nu_whc_msg)))
continue;
if (CMD_IS_REQ(psWhcMem->msg))
{
nu_whc_msg sNuWhcMsg_Resp;
proc_msg((whc_mem_t)&sNuWhcMsg, (whc_mem_t)&sNuWhcMsg_Resp);
send_msg((whc_mem_t)&sNuWhcMsg_Resp);
}
else if (CMD_IS_RESP(psWhcMem->msg))
{
LOG_I("Get Resp. 0x%08x 0x%08x 0x%08x %d",
psWhcMem->msg.u32Cmd,
psWhcMem->msg.u32Addr0,
psWhcMem->msg.u32Addr1,
psWhcMem->msg.u32Size);
}
} //if
} //while
}
static int wormhole_app(void)
{
rt_err_t result = 0;
rt_thread_t thread;
thread = rt_thread_create("whcD", whc_daemon, RT_NULL, 2048, 25, 20);
if (thread != RT_NULL)
{
result = rt_thread_startup(thread);
RT_ASSERT(result == RT_EOK);
}
return 0;
}
INIT_COMPONENT_EXPORT(wormhole_app);
void *whc_malloc(uint32_t u32Size)
{
whc_mem sWhcMem;
sWhcMem.msg.u32Cmd = PACK_MSG_CMD(evCMD_REQ, evCMD_MEM_ALLOCATE);
sWhcMem.msg.u32Size = (uint32_t)u32Size;
send_msg(&sWhcMem);
return 0;
}
RTM_EXPORT(whc_malloc);
void *whc_memcpy(void *pvDst, void *pvSrc, uint32_t u32Size)
{
whc_mem sWhcMem;
sWhcMem.msg.u32Cmd = PACK_MSG_CMD(evCMD_REQ, evCMD_MEM_COPY);
sWhcMem.msg.u32Addr0 = (uint32_t)pvDst;
sWhcMem.msg.u32Addr1 = (uint32_t)pvSrc;
sWhcMem.msg.u32Size = (uint32_t)u32Size;
send_msg(&sWhcMem);
return 0;
}
RTM_EXPORT(whc_memcpy);
uint32_t whc_devmem_write(void *pvaddr, uint32_t u32value)
{
whc_mem sWhcMem;
sWhcMem.msg.u32Cmd = PACK_MSG_CMD(evCMD_REQ, evCMD_DEVMEM_WRITE);
sWhcMem.msg.u32Addr0 = (uint32_t)pvaddr;
sWhcMem.msg.u32Addr1 = u32value;
sWhcMem.msg.u32Size = sizeof(uint32_t);
send_msg(&sWhcMem);
return 0;
}
RTM_EXPORT(whc_devmem_write);
uint32_t whc_devmem_read(void *pvaddr)
{
whc_mem sWhcMem;
sWhcMem.msg.u32Cmd = PACK_MSG_CMD(evCMD_REQ, evCMD_DEVMEM_READ);
sWhcMem.msg.u32Addr0 = (uint32_t)pvaddr;
sWhcMem.msg.u32Addr1 = 0;
sWhcMem.msg.u32Size = sizeof(uint32_t);
send_msg(&sWhcMem);
return 0;
}
RTM_EXPORT(whc_devmem_read);
void whc_devmem(int argc, char *argv[])
{
volatile unsigned int u32Addr;
unsigned int value = 0, mode = 0;
if (argc < 2 || argc > 3)
{
goto exit_devmem;
}
if (argc == 3)
{
if (sscanf(argv[2], "0x%x", &value) != 1)
goto exit_devmem;
mode = 1; //Write
}
if (sscanf(argv[1], "0x%x", &u32Addr) != 1)
goto exit_devmem;
else if (u32Addr & (4 - 1))
goto exit_devmem;
if (mode)
{
whc_devmem_write((void *) u32Addr, value);
}
rt_kprintf("0x%08x\n", whc_devmem_read((void *)u32Addr));
return;
exit_devmem:
rt_kprintf("Read: whc_devmem <physical address in hex>\n");
rt_kprintf("Write: whc_devmem <physical address in hex> <value in hex format>\n");
return;
}
MSH_CMD_EXPORT(whc_devmem, dump device registers);
#endif /* #if defined(BSP_USING_HWSEM)*/