luckfox-pico-sdk/sysdrv/source/mcu/rt-thread/bsp/rockchip/common/drivers/io.c
luckfox-eng29 8f34c2760d project:build.sh: Added fastboot support; custom modifications to U-Boot and kernel implemented using patches.
project:cfg:BoardConfig_IPC: Added fastboot BoardConfig file and firmware post-scripts, distinguishing between
the BoardConfigs for Luckfox Pico Pro and Luckfox Pico Max. project:app: Added fastboot_client and rk_smart_door
for quick boot applications; updated rkipc app to adapt to the latest media library. media:samples: Added more
usage examples. media:rockit: Fixed bugs; removed support for retrieving data frames from VPSS. media:isp:
Updated rkaiq library and related tools to support connection to RKISP_Tuner. sysdrv:Makefile: Added support for
compiling drv_ko on Luckfox Pico Ultra W using Ubuntu; added support for custom root filesystem.
sysdrv:tools:board: Updated Buildroot optional mirror sources, updated some software versions, and stored device
tree files and configuration files that undergo multiple modifications for U-Boot and kernel separately.
sysdrv:source:mcu: Used RISC-V MCU SDK with RT-Thread system, mainly for initializing camera AE during quick
boot. sysdrv:source:uboot: Added support for fastboot; added high baud rate DDR bin for serial firmware upgrades.
sysdrv:source:kernel: Upgraded to version 5.10.160; increased NPU frequency for RV1106G3; added support for
fastboot.

Signed-off-by: luckfox-eng29 <eng29@luckfox.com>
2024-10-14 09:47:04 +08:00

249 lines
6.0 KiB
C

/**
* Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd
*
* SPDX-License-Identifier: Apache-2.0
******************************************************************************
* @file io.c
* @author
* @version V0.1
* @date 10-Jun-2019
* @brief read and write memory
*
******************************************************************************
*/
#include <rtthread.h>
#ifdef RT_DEBUG_USING_IO
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include "hal_base.h"
static void usage(void)
{
rt_kprintf("Raw memory i/o utility - $Revision: 1.5 $\n\n");
rt_kprintf("io -v -1|2|4 -r|w [-l <len>] <addr> [<value>]\n\n");
rt_kprintf(" -v Verbose, asks for confirmation\n");
rt_kprintf(" -1|2|4 Sets memory access size in bytes (default byte)\n");
rt_kprintf(" -l <len> Length in bytes of area to access (defaults to\n");
rt_kprintf(" one access, or whole file length)\n");
rt_kprintf(" -r|w Read from or Write to memory (default read)\n");
rt_kprintf(" <addr> The memory address to access\n");
rt_kprintf(" <val> The value to write (implies -w)\n\n");
rt_kprintf("Examples:\n");
rt_kprintf(" io 0x1000 Reads one byte from 0x1000\n");
rt_kprintf(" io 0x1000 0x12 Writes 0x12 to location 0x1000\n");
rt_kprintf(" io -2 -l 8 0x1000 Reads 8 words from 0x1000\n\n");
rt_kprintf("Note access size (-1|2|4) does not apply to file based accesses.\n\n");
}
static void
read_memory(unsigned long phys_addr, uint8_t *addr, int len, int iosize)
{
int i;
while (len)
{
rt_kprintf("%08lx: ", phys_addr);
i = 0;
while (i < 16 && len)
{
switch (iosize)
{
case 1:
rt_kprintf(" %02x", *(uint8_t *)addr);
break;
case 2:
rt_kprintf(" %04x", *(uint16_t *)addr);
break;
case 4:
rt_kprintf(" %08lx", *(uint32_t *)addr);
break;
}
i += iosize;
addr += iosize;
len -= iosize;
}
phys_addr += 16;
rt_kprintf("\n");
}
}
static void
write_memory(uint8_t *addr, int len, int iosize, unsigned long value)
{
switch (iosize)
{
case 1:
while (len)
{
*(uint8_t *)addr = value;
len -= iosize;
addr += iosize;
}
break;
case 2:
while (len)
{
*(uint16_t *)addr = value;
len -= iosize;
addr += iosize;
}
break;
case 4:
while (len)
{
*(uint32_t *)addr = value;
len -= iosize;
addr += iosize;
}
break;
}
}
int io_mem(int argc, char **argv)
{
int req_len = 0, opt;
uint8_t *real_io;
unsigned long req_addr, req_value = 0;
char *endptr;
int memread = 1;
int iosize = 1;
int verbose = 0;
opterr = 0;
optind = 0;
if (argc == 1)
{
usage();
return 0;
}
while ((opt = getopt(argc, argv, "hv124rwl:f:")) > 0)
{
switch (opt)
{
case 'h':
usage();
case 'v':
verbose = 1;
break;
case '1':
case '2':
case '4':
iosize = opt - '0';
break;
case 'r':
memread = 1;
break;
case 'w':
memread = 0;
break;
case 'l':
req_len = strtoul(optarg, &endptr, 0);
if (*endptr)
{
rt_kprintf("Bad <size> value '%s'\n", optarg);
return 0;
}
break;
default:
rt_kprintf("Unknown option: %c\n", opt);
usage();
}
}
if (optind == argc)
{
rt_kprintf("No address given\n");
return 0;
}
req_addr = strtoul(argv[optind], &endptr, 0);
if (*endptr)
{
rt_kprintf("Bad <addr> value '%s'\n", argv[optind]);
return 0;
}
optind++;
if (optind < argc)
memread = 0;
if (!memread && optind == argc)
{
rt_kprintf("No value given for WRITE\n");
return 0;
}
if (!memread)
{
req_value = strtoul(argv[optind], &endptr, 0);
if (*endptr)
{
rt_kprintf("Bad <value> value '%s'\n", argv[optind]);
return 0;
}
if ((iosize == 1 && (req_value & 0xffffff00)) ||
(iosize == 2 && (req_value & 0xffff0000)))
{
rt_kprintf("<value> too large\n");
return 0;
}
optind++;
}
if (optind < argc)
{
rt_kprintf("Too many arguments '%s'...\n", argv[optind]);
return 0;
}
if (!req_len)
req_len = iosize;
if ((iosize == 2 && (req_addr & 1)) ||
(iosize == 4 && (req_addr & 3)))
{
rt_kprintf("Badly aligned <addr> for access size\n");
return 0;
}
if ((iosize == 2 && (req_len & 1)) ||
(iosize == 4 && (req_len & 3)))
{
rt_kprintf("Badly aligned <size> for access size\n");
return 0;
}
if (!verbose)
/* Nothing */;
else if (memread)
rt_kprintf("Request to memread 0x%x bytes from address 0x%08lx\n"
"\tusing %d byte accesses\n",
req_len, req_addr, iosize);
else
rt_kprintf("Request to write 0x%x bytes to address 0x%08lx\n"
"\tusing %d byte accesses of value 0x%0*lx\n",
req_len, req_addr, iosize, iosize * 2, req_value);
real_io = (uint8_t *)req_addr;
if (memread)
read_memory(req_addr, real_io, req_len, iosize);
else
write_memory(real_io, req_len, iosize, req_value);
return 0;
}
#ifdef RT_USING_FINSH
#include <finsh.h>
MSH_CMD_EXPORT_ALIAS(io_mem, io, memory read or write cmd);
#endif
#endif /* RT_DEBUG_USING_IO */