2016-08-18 10:07:46 +00:00
|
|
|
#include "FreeRTOS.h"
|
|
|
|
#include "task.h"
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <sysparam.h>
|
|
|
|
|
|
|
|
#include <espressif/spi_flash.h>
|
2016-08-25 21:11:59 +00:00
|
|
|
#include "espressif/esp_common.h"
|
|
|
|
#include "esp/uart.h"
|
2016-08-18 10:07:46 +00:00
|
|
|
|
|
|
|
#define CMD_BUF_SIZE 5000
|
|
|
|
|
|
|
|
const int status_base = -6;
|
|
|
|
const char *status_messages[] = {
|
|
|
|
"SYSPARAM_ERR_NOMEM",
|
|
|
|
"SYSPARAM_ERR_CORRUPT",
|
|
|
|
"SYSPARAM_ERR_IO",
|
|
|
|
"SYSPARAM_ERR_FULL",
|
|
|
|
"SYSPARAM_ERR_BADVALUE",
|
|
|
|
"SYSPARAM_ERR_NOINIT",
|
|
|
|
"SYSPARAM_OK",
|
|
|
|
"SYSPARAM_NOTFOUND",
|
|
|
|
"SYSPARAM_PARSEFAILED",
|
|
|
|
};
|
|
|
|
|
|
|
|
void usage(void) {
|
|
|
|
printf(
|
|
|
|
"Available commands:\n"
|
|
|
|
" <key>? -- Query the value of <key>\n"
|
|
|
|
" <key>=<value> -- Set <key> to text <value>\n"
|
|
|
|
" <key>:<hexdata> -- Set <key> to binary value represented as hex\n"
|
|
|
|
" dump -- Show all currently set keys/values\n"
|
|
|
|
" reformat -- Reinitialize (clear) the sysparam area\n"
|
2016-08-25 21:11:59 +00:00
|
|
|
" echo-off -- Disable input echo\n"
|
|
|
|
" echo-on -- Enable input echo\n"
|
2016-08-18 10:07:46 +00:00
|
|
|
" help -- Show this help screen\n"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t tty_readline(char *buffer, size_t buf_size, bool echo) {
|
|
|
|
size_t i = 0;
|
|
|
|
int c;
|
|
|
|
|
|
|
|
while (true) {
|
|
|
|
c = getchar();
|
|
|
|
if (c == '\r') {
|
|
|
|
if (echo) putchar('\n');
|
|
|
|
break;
|
|
|
|
} else if (c == '\b' || c == 0x7f) {
|
|
|
|
if (i) {
|
|
|
|
if (echo) printf("\b \b");
|
|
|
|
i--;
|
|
|
|
}
|
|
|
|
} else if (c < 0x20) {
|
|
|
|
/* Ignore other control characters */
|
|
|
|
} else if (i >= buf_size - 1) {
|
|
|
|
if (echo) putchar('\a');
|
|
|
|
} else {
|
|
|
|
buffer[i++] = c;
|
|
|
|
if (echo) putchar(c);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
buffer[i] = 0;
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
|
|
|
void print_text_value(char *key, char *value) {
|
|
|
|
printf(" '%s' = '%s'\n", key, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
void print_binary_value(char *key, uint8_t *value, size_t len) {
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
printf(" %s:", key);
|
|
|
|
for (i = 0; i < len; i++) {
|
|
|
|
if (!(i & 0x0f)) {
|
|
|
|
printf("\n ");
|
|
|
|
}
|
|
|
|
printf(" %02x", value[i]);
|
|
|
|
}
|
|
|
|
printf("\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
sysparam_status_t dump_params(void) {
|
|
|
|
sysparam_status_t status;
|
|
|
|
sysparam_iter_t iter;
|
|
|
|
|
|
|
|
status = sysparam_iter_start(&iter);
|
|
|
|
if (status < 0) return status;
|
|
|
|
while (true) {
|
|
|
|
status = sysparam_iter_next(&iter);
|
|
|
|
if (status != SYSPARAM_OK) break;
|
|
|
|
if (!iter.binary) {
|
|
|
|
print_text_value(iter.key, (char *)iter.value);
|
|
|
|
} else {
|
|
|
|
print_binary_value(iter.key, iter.value, iter.value_len);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
sysparam_iter_end(&iter);
|
|
|
|
|
|
|
|
if (status == SYSPARAM_NOTFOUND) {
|
|
|
|
// This is the normal status when we've reached the end of all entries.
|
|
|
|
return SYSPARAM_OK;
|
|
|
|
} else {
|
|
|
|
// Something apparently went wrong
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t *parse_hexdata(char *string, size_t *result_length) {
|
|
|
|
size_t string_len = strlen(string);
|
|
|
|
uint8_t *buf = malloc(string_len / 2);
|
|
|
|
uint8_t c;
|
|
|
|
int i, j;
|
|
|
|
bool digit = false;
|
|
|
|
|
|
|
|
j = 0;
|
|
|
|
for (i = 0; string[i]; i++) {
|
|
|
|
c = string[i];
|
|
|
|
if (c >= 0x30 && c <= 0x39) {
|
|
|
|
c &= 0x0f;
|
|
|
|
} else if (c >= 0x41 && c <= 0x46) {
|
|
|
|
c -= 0x37;
|
|
|
|
} else if (c >= 0x61 && c <= 0x66) {
|
|
|
|
c -= 0x57;
|
|
|
|
} else if (c == ' ') {
|
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
free(buf);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
if (!digit) {
|
|
|
|
buf[j] = c << 4;
|
|
|
|
} else {
|
|
|
|
buf[j++] |= c;
|
|
|
|
}
|
|
|
|
digit = !digit;
|
|
|
|
}
|
|
|
|
if (digit) {
|
|
|
|
free(buf);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
*result_length = j;
|
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
|
|
|
|
void sysparam_editor_task(void *pvParameters) {
|
|
|
|
char *cmd_buffer = malloc(CMD_BUF_SIZE);
|
|
|
|
sysparam_status_t status;
|
|
|
|
char *value;
|
|
|
|
uint8_t *bin_value;
|
|
|
|
size_t len;
|
|
|
|
uint8_t *data;
|
|
|
|
uint32_t base_addr, num_sectors;
|
2016-08-25 21:11:59 +00:00
|
|
|
bool echo = true;
|
2016-08-18 10:07:46 +00:00
|
|
|
|
|
|
|
if (!cmd_buffer) {
|
|
|
|
printf("ERROR: Cannot allocate command buffer!\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
printf("\nWelcome to the system parameter editor! Enter 'help' for more information.\n\n");
|
|
|
|
|
|
|
|
status = sysparam_get_info(&base_addr, &num_sectors);
|
|
|
|
if (status == SYSPARAM_OK) {
|
|
|
|
printf("[current sysparam region is at 0x%08x (%d sectors)]\n", base_addr, num_sectors);
|
|
|
|
} else {
|
|
|
|
printf("[NOTE: No current sysparam region (initialization problem during boot?)]\n");
|
|
|
|
// Default to the same place/size as the normal system initialization
|
|
|
|
// stuff, so if the user uses this utility to reformat it, it will put
|
|
|
|
// it somewhere the system will find it later
|
|
|
|
num_sectors = DEFAULT_SYSPARAM_SECTORS;
|
|
|
|
base_addr = sdk_flashchip.chip_size - (4 + num_sectors) * sdk_flashchip.sector_size;
|
|
|
|
}
|
|
|
|
while (true) {
|
|
|
|
printf("==> ");
|
2016-08-25 21:11:59 +00:00
|
|
|
len = tty_readline(cmd_buffer, CMD_BUF_SIZE, echo);
|
2016-08-18 10:07:46 +00:00
|
|
|
status = 0;
|
|
|
|
if (!len) continue;
|
|
|
|
if (cmd_buffer[len - 1] == '?') {
|
|
|
|
cmd_buffer[len - 1] = 0;
|
|
|
|
printf("Querying '%s'...\n", cmd_buffer);
|
|
|
|
status = sysparam_get_string(cmd_buffer, &value);
|
|
|
|
if (status == SYSPARAM_OK) {
|
|
|
|
print_text_value(cmd_buffer, value);
|
|
|
|
free(value);
|
|
|
|
} else if (status == SYSPARAM_PARSEFAILED) {
|
|
|
|
// This means it's actually a binary value
|
|
|
|
status = sysparam_get_data(cmd_buffer, &bin_value, &len, NULL);
|
|
|
|
if (status == SYSPARAM_OK) {
|
|
|
|
print_binary_value(cmd_buffer, bin_value, len);
|
|
|
|
free(value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if ((value = strchr(cmd_buffer, '='))) {
|
|
|
|
*value++ = 0;
|
|
|
|
printf("Setting '%s' to '%s'...\n", cmd_buffer, value);
|
|
|
|
status = sysparam_set_string(cmd_buffer, value);
|
|
|
|
} else if ((value = strchr(cmd_buffer, ':'))) {
|
|
|
|
*value++ = 0;
|
|
|
|
data = parse_hexdata(value, &len);
|
|
|
|
if (value) {
|
|
|
|
printf("Setting '%s' to binary data...\n", cmd_buffer);
|
|
|
|
status = sysparam_set_data(cmd_buffer, data, len, true);
|
|
|
|
free(data);
|
|
|
|
} else {
|
|
|
|
printf("Error: Unable to parse hex data\n");
|
|
|
|
}
|
|
|
|
} else if (!strcmp(cmd_buffer, "dump")) {
|
|
|
|
printf("Dumping all params:\n");
|
|
|
|
status = dump_params();
|
|
|
|
} else if (!strcmp(cmd_buffer, "reformat")) {
|
|
|
|
printf("Re-initializing region...\n");
|
|
|
|
status = sysparam_create_area(base_addr, num_sectors, true);
|
|
|
|
if (status == SYSPARAM_OK) {
|
|
|
|
// We need to re-init after wiping out the region we've been
|
|
|
|
// using.
|
|
|
|
status = sysparam_init(base_addr, 0);
|
|
|
|
}
|
2016-08-25 21:11:59 +00:00
|
|
|
} else if (!strcmp(cmd_buffer, "echo-on")) {
|
|
|
|
echo = true;
|
|
|
|
printf("Echo on\n");
|
|
|
|
} else if (!strcmp(cmd_buffer, "echo-off")) {
|
|
|
|
echo = false;
|
|
|
|
printf("Echo off\n");
|
2016-08-18 10:07:46 +00:00
|
|
|
} else if (!strcmp(cmd_buffer, "help")) {
|
|
|
|
usage();
|
|
|
|
} else {
|
|
|
|
printf("Unrecognized command.\n\n");
|
|
|
|
usage();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (status != SYSPARAM_OK) {
|
|
|
|
printf("! Operation returned status: %d (%s)\n", status, status_messages[status - status_base]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void user_init(void)
|
|
|
|
{
|
2016-08-25 21:11:59 +00:00
|
|
|
uart_set_baud(0, 115200);
|
|
|
|
|
2016-08-18 10:07:46 +00:00
|
|
|
xTaskCreate(sysparam_editor_task, (signed char *)"sysparam_editor_task", 512, NULL, 2, NULL);
|
|
|
|
}
|