diff --git a/core/include/sysparam.h b/core/include/sysparam.h index 2894302..1407803 100644 --- a/core/include/sysparam.h +++ b/core/include/sysparam.h @@ -169,24 +169,20 @@ sysparam_status_t sysparam_get_info(uint32_t *base_addr, uint32_t *num_sectors); */ sysparam_status_t sysparam_get_data(const char *key, uint8_t **destptr, size_t *actual_length, bool *is_binary); -/** Get the value associate with a key (static buffers only) +/** Get the value associated with a key (static value buffer) * * This performs the same function as sysparam_get_data() but without - * performing any memory allocations. It can thus be used before the heap has - * been configured or in other cases where using the heap would be a problem - * (i.e. in an OOM handler, etc). It requires that the caller pass in a - * suitably sized buffer for the value to be read (if the supplied buffer is - * not large enough, the returned value will be truncated and the full - * required length will be returned in `actual_length`). - * - * NOTE: In addition to being large enough for the value, the supplied buffer - * must also be at least as large as the length of the key being requested. - * If it is not, an error will be returned. + * allocating memory for the result value. It can thus be used before the heap + * has been configured or in other cases where using the heap would be a + * problem (i.e. in an OOM handler, etc). It requires that the caller pass in + * a suitably sized buffer for the value to be read (if the supplied buffer is + * not large enough, the returned value will be truncated and the full required + * length will be returned in `actual_length`). * * @param[in] key Key name (zero-terminated string) - * @param[in] buffer Pointer to a buffer to hold the returned value - * @param[in] buffer_size Length of the supplied buffer in bytes - * @param[out] actual_length pointer to a location to hold the actual length + * @param[in] dest Pointer to a buffer to hold the returned value. + * @param[in] dest_size Length of the supplied buffer in bytes. + * @param[out] actual_length Pointer to a location to hold the actual length * of the data which was associated with the key * (may be NULL). * @param[out] is_binary Pointer to a bool to hold whether the returned @@ -199,7 +195,7 @@ sysparam_status_t sysparam_get_data(const char *key, uint8_t **destptr, size_t * * @retval ::SYSPARAM_ERR_CORRUPT Sysparam region has bad/corrupted data * @retval ::SYSPARAM_ERR_IO I/O error reading/writing flash */ -sysparam_status_t sysparam_get_data_static(const char *key, uint8_t *buffer, size_t buffer_size, size_t *actual_length, bool *is_binary); +sysparam_status_t sysparam_get_data_static(const char *key, uint8_t *dest, size_t dest_size, size_t *actual_length, bool *is_binary); /** Get the string value associated with a key * @@ -231,8 +227,8 @@ sysparam_status_t sysparam_get_string(const char *key, char **destptr); /** Get the int32_t value associated with a key * * This routine can be used if you know that the value in a key will (or at - * least should) be an integer value. It will parse the stored data as a - * number (in standard decimal or "0x" hex notation) and return the result. + * least should) be an int32_t value. This is done without allocating any + * memory. * * Note: If the status result is anything other than ::SYSPARAM_OK, the value * in `result` is not changed. This means it is possible to set a default @@ -251,17 +247,13 @@ sysparam_status_t sysparam_get_string(const char *key, char **destptr); * @retval ::SYSPARAM_ERR_CORRUPT Sysparam region has bad/corrupted data * @retval ::SYSPARAM_ERR_IO I/O error reading/writing flash */ -sysparam_status_t sysparam_get_int(const char *key, int32_t *result); +sysparam_status_t sysparam_get_int32(const char *key, int32_t *result); /** Get the boolean value associated with a key * * This routine can be used if you know that the value in a key will (or at - * least should) be a boolean setting. It will read the specified value as a - * text string and attempt to parse it as a boolean value. - * - * It will recognize the following (case-insensitive) strings: - * * True: "yes", "y", "true", "t", "1" - * * False: "no", "n", "false", "f", "0" + * least should) be a uint8_t binary value. This is done without allocating any + * memory. * * Note: If the status result is anything other than ::SYSPARAM_OK, the value * in `result` is not changed. This means it is possible to set a default @@ -280,13 +272,13 @@ sysparam_status_t sysparam_get_int(const char *key, int32_t *result); * @retval ::SYSPARAM_ERR_CORRUPT Sysparam region has bad/corrupted data * @retval ::SYSPARAM_ERR_IO I/O error reading/writing flash */ -sysparam_status_t sysparam_get_bool(const char *key, bool *result); +sysparam_status_t sysparam_get_int8(const char *key, int8_t *result); /** Set the value associated with a key * * The supplied value can be any data, up to 255 bytes in length. If `value` * is NULL or `value_len` is 0, this is treated as a request to delete any - * current entry matching `key`. + * current entry matching `key`. This is done without allocating any memory. * * If `binary` is true, the data will be considered binary (unprintable) data, * and this will be annotated in the saved entry. This does not affect the @@ -310,7 +302,7 @@ sysparam_status_t sysparam_get_bool(const char *key, bool *result); * @retval ::SYSPARAM_ERR_CORRUPT Sysparam region has bad/corrupted data * @retval ::SYSPARAM_ERR_IO I/O error reading/writing flash */ -sysparam_status_t sysparam_set_data(const char *key, const uint8_t *value, size_t value_len, bool binary); +sysparam_status_t sysparam_set_data(const char *key, uint8_t *value, size_t value_len, bool binary); /** Set a key's value from a string * @@ -329,13 +321,13 @@ sysparam_status_t sysparam_set_data(const char *key, const uint8_t *value, size_ * @retval ::SYSPARAM_ERR_CORRUPT Sysparam region has bad/corrupted data * @retval ::SYSPARAM_ERR_IO I/O error reading/writing flash */ -sysparam_status_t sysparam_set_string(const char *key, const char *value); +sysparam_status_t sysparam_set_string(const char *key, char *value); /** Set a key's value as a number * - * Converts an int32_t value to a decimal number and writes it to the - * specified key. This does the inverse of the sysparam_get_int() - * function. + * Write an int32_t binary value to the specified key. This does the inverse of + * the sysparam_get_int32() function. This is done without allocating any + * memory. * * @param[in] key Key name (zero-terminated string) * @param[in] value Value to set @@ -348,13 +340,13 @@ sysparam_status_t sysparam_set_string(const char *key, const char *value); * @retval ::SYSPARAM_ERR_CORRUPT Sysparam region has bad/corrupted data * @retval ::SYSPARAM_ERR_IO I/O error reading/writing flash */ -sysparam_status_t sysparam_set_int(const char *key, int32_t value); +sysparam_status_t sysparam_set_int32(const char *key, int32_t value); -/** Set a key's value as a boolean (yes/no) string +/** Set a key's value as a number * - * Converts a bool value to a corresponding text string and writes it to the - * specified key. This does the inverse of the sysparam_get_bool() - * function. + * Write an int8_t binary value to the specified key. This does the inverse of + * the sysparam_get_int8() function. This is done without allocating any + * memory. * * Note that if the key already contains a value which parses to the same * boolean (true/false) value, it is left unchanged. @@ -370,7 +362,7 @@ sysparam_status_t sysparam_set_int(const char *key, int32_t value); * @retval ::SYSPARAM_ERR_CORRUPT Sysparam region has bad/corrupted data * @retval ::SYSPARAM_ERR_IO I/O error reading/writing flash */ -sysparam_status_t sysparam_set_bool(const char *key, bool value); +sysparam_status_t sysparam_set_int8(const char *key, int8_t value); /** Begin iterating through all key/value pairs * diff --git a/core/sysparam.c b/core/sysparam.c index 723656f..3ce7f61 100644 --- a/core/sysparam.c +++ b/core/sysparam.c @@ -13,9 +13,6 @@ #include "FreeRTOS.h" #include "semphr.h" -//TODO: make this properly threadsafe -//TODO: reduce stack usage - /* The "magic" value that indicates the start of a sysparam region in flash. */ #define SYSPARAM_MAGIC 0x70524f45 // "EORp" in little-endian @@ -33,11 +30,14 @@ */ #define SCAN_BUFFER_SIZE 8 // words -/* The size of the temporary buffer used for reading back and verifying data - * written to flash. Making this larger will make the write-and-verify - * operation slightly faster, but will use more heap during writes +/* The size in words of the buffer used for reading keys when searching for a + * match, for reading payloads to check if the value has changed, and reading + * back from the flash to verify writes. Will work well if big enough for + * commonly used keys, and must be at least one word. Stack allocated so not too + * large! */ -#define VERIFY_BUF_SIZE 64 +#define BOUNCE_BUFFER_WORDS 3 +#define BOUNCE_BUFFER_SIZE (BOUNCE_BUFFER_WORDS * sizeof(uint32_t)) /* Size of region/entry headers. These should not normally need tweaking (and * will probably require some code changes if they are tweaked). @@ -119,40 +119,37 @@ static struct { /***************************** Internal routines *****************************/ -static inline IRAM sysparam_status_t _do_write(uint32_t addr, const void *data, size_t data_size) { - CHECK_FLASH_OP(sdk_spi_flash_write(addr, (void*) data, data_size)); +static inline sysparam_status_t _do_write(uint32_t addr, const void *data, void *buffer, size_t data_size) { + memcpy(buffer, data, data_size); + CHECK_FLASH_OP(sdk_spi_flash_write(addr, buffer, data_size)); return SYSPARAM_OK; } -static inline IRAM sysparam_status_t _do_verify(uint32_t addr, const void *data, void *buffer, size_t len) { +static inline sysparam_status_t _do_verify(uint32_t addr, const void *data, void *buffer, size_t len) { CHECK_FLASH_OP(sdk_spi_flash_read(addr, buffer, len)); if (memcmp(data, buffer, len)) { return SYSPARAM_ERR_IO; } + return SYSPARAM_OK; } -/*FIXME: Eventually, this should probably be implemented down at the SPI flash library layer, where it can just compare bytes/words straight from the SPI hardware buffer instead of allocating a whole separate temp buffer, reading chunks into that, and then doing a memcmp.. */ -static IRAM sysparam_status_t _write_and_verify(uint32_t addr, const void *data, size_t data_size) { +static sysparam_status_t _write_and_verify(uint32_t addr, const void *data, size_t data_size) { int i; size_t count; sysparam_status_t status = SYSPARAM_OK; - uint8_t *verify_buf = malloc(VERIFY_BUF_SIZE); + uint32_t buf[BOUNCE_BUFFER_WORDS]; - if (!verify_buf) return SYSPARAM_ERR_NOMEM; - do { - status = _do_write(addr, data, data_size); + for (i = 0; i < data_size; i += BOUNCE_BUFFER_SIZE) { + count = min(data_size - i, BOUNCE_BUFFER_SIZE); + status = _do_write(addr + i, data + i, buf, count); if (status != SYSPARAM_OK) break; - for (i = 0; i < data_size; i += VERIFY_BUF_SIZE) { - count = min(data_size - i, VERIFY_BUF_SIZE); - status = _do_verify(addr + i, data + i, verify_buf, count); - if (status != SYSPARAM_OK) { - debug(1, "Flash write (@ 0x%08x) verify failed!", addr); - break; - } + status = _do_verify(addr + i, data + i, buf, count); + if (status != SYSPARAM_OK) { + debug(1, "Flash write (@ 0x%08x) verify failed!", addr); + break; } - } while (false); - free(verify_buf); + } return status; } @@ -297,15 +294,47 @@ static sysparam_status_t _find_entry(struct sysparam_context *ctx, uint16_t matc /** Read the payload from the current entry pointed to by `ctx` */ static inline sysparam_status_t _read_payload(struct sysparam_context *ctx, uint8_t *buffer, size_t buffer_size) { debug(3, "read payload (%d) @ 0x%08x", min(buffer_size, ctx->entry.len), ctx->addr); - CHECK_FLASH_OP(sdk_spi_flash_read(ctx->addr + ENTRY_HEADER_SIZE, (void*) buffer, min(buffer_size, ctx->entry.len))); + uint32_t addr = ctx->addr + ENTRY_HEADER_SIZE; + size_t size = min(buffer_size, ctx->entry.len); + size_t align = (uint32_t)buffer & 3; + if (align) { + // Unaligned buffer, use a bounce buffer to align. + uint32_t bounce[1]; + size_t align_size = min(size, align); + CHECK_FLASH_OP(sdk_spi_flash_read(addr, (void*) bounce, align_size)); + memcpy(buffer, bounce, align_size); + size -= align_size; + addr += align_size; + buffer += align_size; + } + if (size > 0) { + CHECK_FLASH_OP(sdk_spi_flash_read(addr, (void*) buffer, size)); + } + return SYSPARAM_OK; +} + +static inline sysparam_status_t _compare_payload(struct sysparam_context *ctx, uint8_t *value, size_t size) { + debug(3, "compare payload (%d) @ 0x%08x", size, ctx->addr); + if (ctx->entry.len != size) return SYSPARAM_NOTFOUND; + uint32_t *bounce[BOUNCE_BUFFER_WORDS]; + uint32_t addr = ctx->addr + ENTRY_HEADER_SIZE; + int i; + for (i = 0; i < size; i += BOUNCE_BUFFER_SIZE) { + int len = min(size - i, BOUNCE_BUFFER_SIZE); + CHECK_FLASH_OP(sdk_spi_flash_read(addr + i, (void*)bounce, len)); + if (memcmp(value + i, bounce, len)) { + // Mismatch. + return SYSPARAM_NOTFOUND; + } + } return SYSPARAM_OK; } /** Find the entry corresponding to the specified key name */ -static sysparam_status_t _find_key(struct sysparam_context *ctx, const char *key, uint16_t key_len, uint8_t *buffer) { +static sysparam_status_t _find_key(struct sysparam_context *ctx, const char *key, uint16_t key_len) { sysparam_status_t status; - debug(3, "find key: %s", key ? key : "(null)"); + debug(3, "find key len %d: %s", key_len, key ? key : "(null)"); while (true) { // Find the next key entry status = _find_entry(ctx, ENTRY_ID_ANY, false); @@ -316,12 +345,12 @@ static sysparam_status_t _find_key(struct sysparam_context *ctx, const char *key break; } if (ctx->entry.len == key_len) { - status = _read_payload(ctx, buffer, key_len); - if (status < 0) return status; - if (!memcmp(key, buffer, key_len)) { + status = _compare_payload(ctx, (uint8_t *)key, key_len); + if (status == SYSPARAM_OK) { // We have a match break; } + if (status != SYSPARAM_NOTFOUND) return status; debug(3, "entry payload does not match"); } else { debug(3, "key length (%d) does not match (%d)", ctx->entry.len, key_len); @@ -639,70 +668,79 @@ sysparam_status_t sysparam_get_data(const char *key, uint8_t **destptr, size_t * sysparam_status_t status; size_t key_len = strlen(key); uint8_t *buffer; - uint8_t *newbuf; - if (!_sysparam_info.cur_base) return SYSPARAM_ERR_NOINIT; + xSemaphoreTake(_sysparam_info.sem, portMAX_DELAY); - buffer = malloc(key_len + 2); - if (!buffer) return SYSPARAM_ERR_NOMEM; - do { - _init_context(&ctx); - status = _find_key(&ctx, key, key_len, buffer); - if (status != SYSPARAM_OK) break; - - // Find the associated value - status = _find_value(&ctx, ctx.entry.idflags); - if (status != SYSPARAM_OK) break; - - newbuf = realloc(buffer, ctx.entry.len + 1); - if (!newbuf) { - status = SYSPARAM_ERR_NOMEM; - break; - } - buffer = newbuf; - status = _read_payload(&ctx, buffer, ctx.entry.len); - if (status != SYSPARAM_OK) break; - - // Zero-terminate the result, just in case (doesn't hurt anything for - // non-string data, and can avoid nasty mistakes if the caller wants to - // interpret the result as a string). - buffer[ctx.entry.len] = 0; - - *destptr = buffer; - if (actual_length) *actual_length = ctx.entry.len; - if (is_binary) *is_binary = (bool)(ctx.entry.idflags & ENTRY_FLAG_BINARY); - return SYSPARAM_OK; - } while (false); - - free(buffer); if (actual_length) *actual_length = 0; + + if (!_sysparam_info.cur_base) { + status = SYSPARAM_ERR_NOINIT; + goto done; + } + + _init_context(&ctx); + status = _find_key(&ctx, key, key_len); + if (status != SYSPARAM_OK) goto done; + + // Find the associated value + status = _find_value(&ctx, ctx.entry.idflags); + if (status != SYSPARAM_OK) goto done; + + buffer = malloc(ctx.entry.len + 1); + if (!buffer) { + status = SYSPARAM_ERR_NOMEM; + goto done; + } + + status = _read_payload(&ctx, buffer, ctx.entry.len); + if (status != SYSPARAM_OK) { + free(buffer); + goto done; + } + + // Zero-terminate the result, just in case (doesn't hurt anything for + // non-string data, and can avoid nasty mistakes if the caller wants to + // interpret the result as a string). + buffer[ctx.entry.len] = 0; + + *destptr = buffer; + if (actual_length) *actual_length = ctx.entry.len; + if (is_binary) *is_binary = (bool)(ctx.entry.idflags & ENTRY_FLAG_BINARY); + status = SYSPARAM_OK; + + done: + xSemaphoreGive(_sysparam_info.sem); return status; } -sysparam_status_t sysparam_get_data_static(const char *key, uint8_t *buffer, size_t buffer_size, size_t *actual_length, bool *is_binary) { +sysparam_status_t sysparam_get_data_static(const char *key, uint8_t *dest, size_t dest_size, size_t *actual_length, bool *is_binary) { struct sysparam_context ctx; sysparam_status_t status = SYSPARAM_OK; size_t key_len = strlen(key); - if (!_sysparam_info.cur_base) return SYSPARAM_ERR_NOINIT; - - // Supplied buffer must be at least as large as the key, or 2 bytes, - // whichever is larger. - if (buffer_size < max(key_len, 2)) return SYSPARAM_ERR_NOMEM; + xSemaphoreTake(_sysparam_info.sem, portMAX_DELAY); if (actual_length) *actual_length = 0; + if (!_sysparam_info.cur_base) { + status = SYSPARAM_ERR_NOINIT; + goto done; + } + _init_context(&ctx); - status = _find_key(&ctx, key, key_len, buffer); - if (status != SYSPARAM_OK) return status; + status = _find_key(&ctx, key, key_len); + if (status != SYSPARAM_OK) goto done; status = _find_value(&ctx, ctx.entry.idflags); - if (status != SYSPARAM_OK) return status; - status = _read_payload(&ctx, buffer, buffer_size); - if (status != SYSPARAM_OK) return status; + if (status != SYSPARAM_OK) goto done; + status = _read_payload(&ctx, dest, dest_size); + if (status != SYSPARAM_OK) goto done; if (actual_length) *actual_length = ctx.entry.len; if (is_binary) *is_binary = (bool)(ctx.entry.idflags & ENTRY_FLAG_BINARY); - return SYSPARAM_OK; + + done: + xSemaphoreGive(_sysparam_info.sem); + return status; } sysparam_status_t sysparam_get_string(const char *key, char **destptr) { @@ -724,103 +762,65 @@ sysparam_status_t sysparam_get_string(const char *key, char **destptr) { return SYSPARAM_OK; } -sysparam_status_t sysparam_get_int(const char *key, int32_t *result) { - char *buffer; - char *endptr; +sysparam_status_t sysparam_get_int32(const char *key, int32_t *result) { int32_t value; + size_t actual_length; + bool is_binary; sysparam_status_t status; - status = sysparam_get_string(key, &buffer); + status = sysparam_get_data_static(key, (uint8_t *)&value, sizeof(int32_t), + &actual_length, &is_binary); if (status != SYSPARAM_OK) return status; - value = strtol(buffer, &endptr, 0); - if (*endptr) { - // There was extra crap at the end of the string. - free(buffer); + if (!is_binary || actual_length != sizeof(int32_t)) return SYSPARAM_PARSEFAILED; - } - *result = value; - free(buffer); - return SYSPARAM_OK; -} - -sysparam_status_t sysparam_get_bool(const char *key, bool *result) { - char *buffer; - sysparam_status_t status; - - status = sysparam_get_string(key, &buffer); - if (status != SYSPARAM_OK) return status; - do { - if (!strcasecmp(buffer, "y") || - !strcasecmp(buffer, "yes") || - !strcasecmp(buffer, "t") || - !strcasecmp(buffer, "true") || - !strcmp(buffer, "1")) { - *result = true; - break; - } - if (!strcasecmp(buffer, "n") || - !strcasecmp(buffer, "no") || - !strcasecmp(buffer, "f") || - !strcasecmp(buffer, "false") || - !strcmp(buffer, "0")) { - *result = false; - break; - } - status = SYSPARAM_PARSEFAILED; - } while (0); - - free(buffer); return status; } -sysparam_status_t sysparam_set_data(const char *key, const uint8_t *value, size_t value_len, bool is_binary) { +sysparam_status_t sysparam_get_int8(const char *key, int8_t *result) { + int8_t value; + size_t actual_length; + bool is_binary; + sysparam_status_t status; + + status = sysparam_get_data_static(key, (uint8_t *)&value, sizeof(int8_t), + &actual_length, &is_binary); + if (status != SYSPARAM_OK) return status; + if (!is_binary || actual_length != sizeof(int8_t)) + return SYSPARAM_PARSEFAILED; + *result = value; + return status; +} + +sysparam_status_t sysparam_set_data(const char *key, uint8_t *value, size_t value_len, bool is_binary) { struct sysparam_context ctx; struct sysparam_context write_ctx; sysparam_status_t status = SYSPARAM_OK; uint16_t key_len = strlen(key); - uint8_t *buffer; - uint8_t *newbuf; size_t free_space; size_t needed_space; - bool free_value = false; int key_id = -1; uint32_t old_value_addr = 0; uint16_t binary_flag; - if (!_sysparam_info.cur_base) return SYSPARAM_ERR_NOINIT; if (!key_len) return SYSPARAM_ERR_BADVALUE; if (key_len > MAX_KEY_LEN) return SYSPARAM_ERR_BADVALUE; if (value_len > MAX_VALUE_LEN) return SYSPARAM_ERR_BADVALUE; - xSemaphoreTake(_sysparam_info.sem, portMAX_DELAY); - if (!value) value_len = 0; debug(1, "updating value for '%s' (%d bytes)", key, value_len); - if (value_len && ((intptr_t)value & 0x3)) { - // The passed value isn't word-aligned. This will be a problem later - // when calling `sdk_spi_flash_write`, so make a word-aligned copy. - buffer = malloc(value_len); - if (!buffer) { - status = SYSPARAM_ERR_NOMEM; - goto done; - } - memcpy(buffer, value, value_len); - value = buffer; - free_value = true; - } - // Create a working buffer for `_find_key` to use. - buffer = malloc(key_len); - if (!buffer) { - if (free_value) free((void *)value); - status = SYSPARAM_ERR_NOMEM; + + xSemaphoreTake(_sysparam_info.sem, portMAX_DELAY); + + if (!_sysparam_info.cur_base) { + status = SYSPARAM_ERR_NOINIT; goto done; } do { _init_context(&ctx); - status = _find_key(&ctx, key, key_len, buffer); + status = _find_key(&ctx, key, key_len); if (status == SYSPARAM_OK) { // Key already exists, see if there's a current value. key_id = ctx.entry.idflags & ENTRY_MASK_ID; @@ -835,24 +835,17 @@ sysparam_status_t sysparam_set_data(const char *key, const uint8_t *value, size_ if (value_len) { if (old_value_addr) { - if ((ctx.entry.idflags & ENTRY_FLAG_BINARY) == binary_flag && ctx.entry.len == value_len) { + if ((ctx.entry.idflags & ENTRY_FLAG_BINARY) == binary_flag && + ctx.entry.len == value_len) { // Are we trying to write the same value that's already there? - if (value_len > key_len) { - newbuf = realloc(buffer, value_len); - if (!newbuf) { - status = SYSPARAM_ERR_NOMEM; - break; - } - buffer = newbuf; - } - status = _read_payload(&ctx, buffer, value_len); - if (status < 0) break; - if (!memcmp(buffer, value, value_len)) { + status = _compare_payload(&ctx, (uint8_t *)value, value_len); + if (status == SYSPARAM_OK) { // Yup, it's a match! No need to do anything further, // just leave the current value as-is. status = SYSPARAM_OK; break; } + if (status != SYSPARAM_NOTFOUND) goto done; } // Since we will be deleting the old value (if any) make sure @@ -954,39 +947,22 @@ sysparam_status_t sysparam_set_data(const char *key, const uint8_t *value, size_ debug(1, "New addr is 0x%08x (%d bytes remaining)", _sysparam_info.end_addr, _sysparam_info.cur_base + _sysparam_info.region_size - _sysparam_info.end_addr); } while (false); - if (free_value) free((void *)value); - free(buffer); - done: xSemaphoreGive(_sysparam_info.sem); return status; } -sysparam_status_t sysparam_set_string(const char *key, const char *value) { - return sysparam_set_data(key, (const uint8_t *)value, strlen(value), false); +sysparam_status_t sysparam_set_string(const char *key, char *value) { + return sysparam_set_data(key, (uint8_t *)value, strlen(value), false); } -sysparam_status_t sysparam_set_int(const char *key, int32_t value) { - uint8_t buffer[12]; - int len; - - len = snprintf((char *)buffer, 12, "%d", value); - return sysparam_set_data(key, buffer, len, false); +sysparam_status_t sysparam_set_int32(const char *key, int32_t value) { + return sysparam_set_data(key, (uint8_t *)&value, sizeof(value), true); } -sysparam_status_t sysparam_set_bool(const char *key, bool value) { - uint8_t buf[4] = {0xff, 0xff, 0xff, 0xff}; - bool old_value; - - // Don't write anything if the current setting already evaluates to the - // same thing. - if (sysparam_get_bool(key, &old_value) == SYSPARAM_OK) { - if (old_value == value) return SYSPARAM_OK; - } - - buf[0] = value ? 'y' : 'n'; - return sysparam_set_data(key, buf, 1, false); +sysparam_status_t sysparam_set_int8(const char *key, int8_t value) { + return sysparam_set_data(key, (uint8_t *)&value, sizeof(uint8_t), true); } sysparam_status_t sysparam_iter_start(sysparam_iter_t *iter) { @@ -1012,7 +988,6 @@ sysparam_status_t sysparam_iter_start(sysparam_iter_t *iter) { } sysparam_status_t sysparam_iter_next(sysparam_iter_t *iter) { - uint8_t buffer[2]; sysparam_status_t status; size_t required_len; struct sysparam_context *ctx = iter->ctx; @@ -1021,7 +996,7 @@ sysparam_status_t sysparam_iter_next(sysparam_iter_t *iter) { char *newbuf; while (true) { - status = _find_key(ctx, NULL, 0, buffer); + status = _find_key(ctx, NULL, 0); if (status != SYSPARAM_OK) return status; memcpy(&value_ctx, ctx, sizeof(value_ctx)); diff --git a/examples/sysparam_editor/sysparam_editor.c b/examples/sysparam_editor/sysparam_editor.c index 22f6190..539f62a 100644 --- a/examples/sysparam_editor/sysparam_editor.c +++ b/examples/sysparam_editor/sysparam_editor.c @@ -6,6 +6,8 @@ #include #include +#include "espressif/esp_common.h" +#include "esp/uart.h" #define CMD_BUF_SIZE 5000 @@ -30,6 +32,7 @@ void usage(void) { " : -- Set to binary value represented as hex\n" " dump -- Show all currently set keys/values\n" " reformat -- Reinitialize (clear) the sysparam area\n" + " echo -- Toggle input echo\n" " help -- Show this help screen\n" ); } @@ -150,6 +153,7 @@ void sysparam_editor_task(void *pvParameters) { size_t len; uint8_t *data; uint32_t base_addr, num_sectors; + bool echo = true; if (!cmd_buffer) { printf("ERROR: Cannot allocate command buffer!\n"); @@ -171,7 +175,7 @@ void sysparam_editor_task(void *pvParameters) { } while (true) { printf("==> "); - len = tty_readline(cmd_buffer, CMD_BUF_SIZE, true); + len = tty_readline(cmd_buffer, CMD_BUF_SIZE, echo); status = 0; if (!len) continue; if (cmd_buffer[len - 1] == '?') { @@ -214,6 +218,9 @@ void sysparam_editor_task(void *pvParameters) { // using. status = sysparam_init(base_addr, 0); } + } else if (!strcmp(cmd_buffer, "echo")) { + echo = !echo; + printf("Echo: %s\n", echo ? "on" : "off"); } else if (!strcmp(cmd_buffer, "help")) { usage(); } else { @@ -229,5 +236,7 @@ void sysparam_editor_task(void *pvParameters) { void user_init(void) { + uart_set_baud(0, 115200); + xTaskCreate(sysparam_editor_task, (signed char *)"sysparam_editor_task", 512, NULL, 2, NULL); }