290 lines
6.5 KiB
C
Executable File
290 lines
6.5 KiB
C
Executable File
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <config.h>
|
|
#include <lib.h>
|
|
#include <timer.h>
|
|
#include <serial.h>
|
|
|
|
|
|
#define CMD_BUFF_LEN 16
|
|
#define REV_BUFF_LEN 128
|
|
|
|
typedef enum {
|
|
CMD_0 = 0,
|
|
CMD_1,
|
|
CMD_2,
|
|
CMD_3,
|
|
CMD_4,
|
|
CMD_5,
|
|
CMD_6,
|
|
CMD_7,
|
|
CMD_8,
|
|
CMD_9,
|
|
CMD_10,
|
|
CMD_11,
|
|
CMD_12,
|
|
CMD_13,
|
|
CMD_14,
|
|
CMD_15,
|
|
CMD_16
|
|
} cmd_len;
|
|
|
|
static void show_help(void)
|
|
{
|
|
puts("usage: \n");
|
|
puts(" help -- show command infomation \n");
|
|
puts(" mw [addr] [value] -- write [value] to [addr] \n");
|
|
puts(" both need be hex and start with 0x or 0X \n");
|
|
puts(" md [addr] [length] -- read from [addr] and print to the console \n");
|
|
puts(" total read [length] bytes data \n");
|
|
puts(" both need be hex and start with 0x or 0X \n");
|
|
}
|
|
|
|
static u32 read_line(u8 *buff, u32 buff_len)
|
|
{
|
|
u32 recv_len = 0;
|
|
char c = 0;
|
|
|
|
while (1) {
|
|
c = getchar();
|
|
if (c == '\n' || c == '\r') {
|
|
serial_putc('\n');
|
|
break;
|
|
}
|
|
if (recv_len < buff_len) {
|
|
serial_putc(c);
|
|
buff[recv_len++] = c;
|
|
} else {
|
|
return FAILURE;
|
|
}
|
|
}
|
|
|
|
if (recv_len < (buff_len - 1)) {
|
|
buff[recv_len + 1] = '\0';
|
|
}
|
|
|
|
return recv_len;
|
|
}
|
|
|
|
/* return value : index is started from 0 */
|
|
static u32 str_get_pos(u8 *buff, u32 buff_len, char c)
|
|
{
|
|
u32 index = 0;
|
|
|
|
for (; index < buff_len; index++) {
|
|
if (c == buff[index]) {
|
|
return index;
|
|
}
|
|
}
|
|
|
|
if (index == buff_len) {
|
|
return index;
|
|
}
|
|
|
|
return FAILURE;
|
|
}
|
|
|
|
/* find the cmd dilived by the space */
|
|
static u32 get_cmd(u8 *cmd, u32 cmd_buff_len, u8 *buff, u32 buff_len)
|
|
{
|
|
u32 cmd_len = 0;
|
|
|
|
/* the cmd is divided by space */
|
|
cmd_len = str_get_pos(buff, buff_len, ' ');
|
|
if (cmd_len == 0 || cmd_len == FAILURE || cmd_len > cmd_buff_len) {
|
|
return FAILURE;
|
|
}
|
|
|
|
for (u32 i = 0; i < cmd_len; i++) {
|
|
cmd[i] = buff[i];
|
|
}
|
|
|
|
if (cmd_len < (cmd_buff_len - 1)) {
|
|
cmd[cmd_len + 1] = '\0';
|
|
}
|
|
|
|
return cmd_len;
|
|
}
|
|
|
|
static u8 char_to_hex(u8 value)
|
|
{
|
|
if((value <= '9') && (value >= '0')) {
|
|
return (value - '0');
|
|
} else if ((value <= 'f') && ((value >= 'a'))) {
|
|
return (value - 'a' + 0x0a);
|
|
} else if ((value <= 'F') && (value >= 'A')) {
|
|
return (value - 'A' + 0x0a);
|
|
} else {
|
|
puts("Data format error!\n");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
static u32 pow_t(u32 v, u32 n)
|
|
{
|
|
u32 value = v;
|
|
|
|
if (n == 0) {
|
|
return 1;
|
|
} else if (n == 1) {
|
|
return v;
|
|
}
|
|
|
|
for (u32 i = 1; i < n; i++) {
|
|
value = value * v;
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
static u32 str_to_hex(u8 *str, u32 str_len)
|
|
{
|
|
u32 hex = 0;
|
|
|
|
for (int i = 0; i < str_len; i++) {
|
|
hex += char_to_hex(str[i]) * pow_t(16, (str_len - i - 1));
|
|
}
|
|
|
|
return hex;
|
|
}
|
|
|
|
static u32 get_params(u8 * buff, u32 buff_Len, u32 *param_len)
|
|
{
|
|
u8 param_s[10];
|
|
|
|
*param_len = get_cmd(param_s, 10, buff, buff_Len);
|
|
if (*param_len < 2 || *param_len == FAILURE) {
|
|
puts("command error, too few params!\n");
|
|
return FAILURE;
|
|
}
|
|
|
|
if (param_s[0] != '0' && (param_s[1] != 'x' || param_s[1] != 'X')) {
|
|
puts("command error, params should start with 0x or 0X\n");
|
|
return FAILURE;
|
|
}
|
|
|
|
return str_to_hex(param_s + 2, *param_len - 2);
|
|
}
|
|
|
|
/*
|
|
* input: [addr] [value]
|
|
*/
|
|
void memory_write(u8 *buff, u32 buff_Len)
|
|
{
|
|
u32 addr_len = 0;
|
|
u32 value_len = 0;
|
|
u32 addr = 0;
|
|
u32 value = 0;
|
|
|
|
/* get address */
|
|
addr = get_params(buff, buff_Len, &addr_len);
|
|
if (addr == FAILURE) {
|
|
return;
|
|
}
|
|
|
|
/* get value */
|
|
value = get_params(buff + addr_len + 1, buff_Len - addr_len - 1, &value_len);
|
|
if (value == FAILURE) {
|
|
return;
|
|
}
|
|
|
|
puts("write address=0x");
|
|
serial_put_hex(addr);
|
|
puts(" value=0x");
|
|
serial_put_hex(value);
|
|
puts("\n");
|
|
|
|
writel(value, addr);
|
|
}
|
|
|
|
/*
|
|
* input: [addr] [length]
|
|
*/
|
|
void memory_read(u8 *buff, u32 buff_Len)
|
|
{
|
|
u32 addr_len = 0;
|
|
u32 length_len = 0;
|
|
u32 addr = 0;
|
|
u32 length = 0;
|
|
u32 value = 0;
|
|
|
|
/* get address */
|
|
addr = get_params(buff, buff_Len, &addr_len);
|
|
if (addr == FAILURE) {
|
|
return;
|
|
}
|
|
|
|
/* get length */
|
|
length = get_params(buff + addr_len + 1, buff_Len - addr_len - 1, &length_len);
|
|
if (length == FAILURE) {
|
|
return;
|
|
}
|
|
|
|
if (length % 4 != 0) {
|
|
puts("error: length should be align with 4\n");
|
|
return;
|
|
}
|
|
|
|
/* read and print */
|
|
for (u32 i = 0; i < length / 4; i++) {
|
|
value = readl(addr + i * 4);
|
|
if (i % 4 == 0) {
|
|
serial_put_hex(addr + i * 4);
|
|
puts(": ");
|
|
}
|
|
serial_put_hex(value);
|
|
puts(" ");
|
|
if (i % 4 == 3) {
|
|
puts("\n");
|
|
}
|
|
}
|
|
|
|
puts("\n");
|
|
}
|
|
|
|
u32 start_shell(void)
|
|
{
|
|
u8 buff[REV_BUFF_LEN];
|
|
u32 recv_len = 0;
|
|
u8 cmd[CMD_BUFF_LEN];
|
|
u32 cmd_len = 0;
|
|
|
|
puts("\n## Micro shell ##\n");
|
|
|
|
/* cmd [param1] [param2] ... */
|
|
while (1) {
|
|
puts("# ");
|
|
memset_s(buff, REV_BUFF_LEN, 0, REV_BUFF_LEN);
|
|
memset_s(cmd, CMD_BUFF_LEN, 0, CMD_BUFF_LEN);
|
|
recv_len = read_line(buff, REV_BUFF_LEN);
|
|
if (recv_len == 0 || recv_len == FAILURE) {
|
|
continue;
|
|
}
|
|
cmd_len = get_cmd(cmd, CMD_BUFF_LEN, buff, recv_len);
|
|
if (cmd_len == FAILURE) {
|
|
continue;
|
|
}
|
|
switch (cmd_len) {
|
|
case CMD_2:
|
|
if (memcmp(cmd, "mw", CMD_2) == SUCCESS) {
|
|
/* mw [addr] [value]; addr and value should start with 0x/0X */
|
|
memory_write(buff + cmd_len + 1, recv_len - cmd_len - 1);
|
|
} else if (memcmp(cmd, "md", CMD_2) == SUCCESS) {
|
|
/* md [addr] [length]; addr and length should start with 0x/0X */
|
|
memory_read(buff + cmd_len + 1, recv_len - cmd_len - 1);
|
|
}
|
|
break;
|
|
case CMD_4:
|
|
if (memcmp(cmd, "help", CMD_4) == SUCCESS) {
|
|
show_help();
|
|
}
|
|
default:
|
|
puts("Unknown command!\n");
|
|
break;
|
|
}
|
|
}
|
|
|
|
return SUCCESS;
|
|
}
|