/** * 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 #ifdef RT_DEBUG_USING_IO #include #include #include #include #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 ] []\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 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(" The memory address to access\n"); rt_kprintf(" 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 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 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 '%s'\n", argv[optind]); return 0; } if ((iosize == 1 && (req_value & 0xffffff00)) || (iosize == 2 && (req_value & 0xffff0000))) { rt_kprintf(" 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 for access size\n"); return 0; } if ((iosize == 2 && (req_len & 1)) || (iosize == 4 && (req_len & 3))) { rt_kprintf("Badly aligned 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 MSH_CMD_EXPORT_ALIAS(io_mem, io, memory read or write cmd); #endif #endif /* RT_DEBUG_USING_IO */