123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553 |
- /**
- * Copyright (c) 2017 - 2020, Nordic Semiconductor ASA
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form, except as embedded into a Nordic
- * Semiconductor ASA integrated circuit in a product or a software update for
- * such product, must reproduce the above copyright notice, this list of
- * conditions and the following disclaimer in the documentation and/or other
- * materials provided with the distribution.
- *
- * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
- * contributors may be used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * 4. This software, with or without modification, must only be used with a
- * Nordic Semiconductor ASA integrated circuit.
- *
- * 5. Any software provided in binary form under this license must not be reverse
- * engineered, decompiled, modified and/or disassembled.
- *
- * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
- #include <string.h>
- #include "app_error.h"
- #include "boards.h"
- #include "nrf_cli.h"
- #include "nrf_cli_uart.h"
- #include "nrf_drv_uart.h"
- #include "fds.h"
- #include "nrf_soc.h"
- #include "sdk_config.h"
- #include "fds_example.h"
- #define PRINT_HELP "print records\n" \
- "usage: print all|config"
- #define PRINT_ALL_HELP "print all records\n" \
- "usage: print all"
- #define PRINT_CFG_HELP "print configuration\n" \
- "usage: print config"
- #define WRITE_HELP "write a record\n" \
- "usage: write file_id key \"data\"\n" \
- "- file_id:\tfile ID, in HEX\n" \
- "- key:\trecord key, in HEX\n" \
- "- data:\trecord contents"
- #define DELETE_HELP "delete a record\n" \
- "usage: delete file_id key\n" \
- "- file_id:\tfile ID, in HEX\n" \
- "- key:\trecord key, in HEX\n" \
- #define DELETE_ALL_HELP "delete all records\n" \
- "usage: delete_all" \
- #define UPDATE_HELP "update configuration\n" \
- "usage: update on|off on|off boot_count device_name" \
- #define STAT_HELP "print statistics\n" \
- "usage: stat"
- #define GC_HELP "run garbage collection\n" \
- "usage: gc"
- NRF_CLI_UART_DEF(cli_uart, 0, 64, 16);
- NRF_CLI_DEF(m_cli_uart, "fds example:~$ ", &cli_uart.transport, '\r', 4);
- /* Defined in main.c */
- extern char const * fds_err_str(ret_code_t ret);
- void cli_init(void)
- {
- nrf_drv_uart_config_t uart_config = NRF_DRV_UART_DEFAULT_CONFIG;
- uart_config.pseltxd = TX_PIN_NUMBER;
- uart_config.pselrxd = RX_PIN_NUMBER;
- uart_config.hwfc = NRF_UART_HWFC_DISABLED;
- ret_code_t rc = nrf_cli_init(&m_cli_uart, &uart_config, true, true, NRF_LOG_SEVERITY_INFO);
- APP_ERROR_CHECK(rc);
- }
- void cli_start(void)
- {
- ret_code_t rc = nrf_cli_start(&m_cli_uart);
- APP_ERROR_CHECK(rc);
- }
- void cli_process(void)
- {
- nrf_cli_process(&m_cli_uart);
- }
- static void cli_unknown_param_help(nrf_cli_t const * p_cli,
- char const * p_param,
- char const * p_cmd)
- {
- nrf_cli_fprintf(p_cli,
- NRF_CLI_ERROR,
- "%s: unknown parameter '%s'\n"
- "Try '%s -h' for help.\n",
- p_cmd,
- p_param,
- p_cmd);
- }
- static void cli_wrong_param_count_help(nrf_cli_t const * p_cli, char const * p_cmd)
- {
- nrf_cli_fprintf(p_cli,
- NRF_CLI_ERROR,
- "%s: wrong parameter count.\n"
- "Try '%s -h' for help.\n",
- p_cmd,
- p_cmd);
- }
- static void record_write(nrf_cli_t const * p_cli,
- uint32_t fid,
- uint32_t key,
- void const * p_data,
- uint32_t len)
- {
- fds_record_t const rec =
- {
- .file_id = fid,
- .key = key,
- .data.p_data = p_data,
- .data.length_words = (len + 3) / sizeof(uint32_t)
- };
- nrf_cli_fprintf(p_cli, NRF_CLI_DEFAULT,
- "writing record to flash...\n"
- "file: 0x%x, key: 0x%x, \"%s\", len: %u bytes\n",
- fid, key, p_data, len);
- ret_code_t rc = fds_record_write(NULL, &rec);
- if (rc != NRF_SUCCESS)
- {
- nrf_cli_fprintf(p_cli, NRF_CLI_ERROR,
- "error: fds_record_write() returned %s.\n",
- fds_err_str(rc));
- }
- }
- static void record_update(nrf_cli_t const * p_cli, configuration_t const * p_cfg)
- {
- fds_record_desc_t desc = {0};
- fds_find_token_t ftok = {0};
- if (fds_record_find(CONFIG_FILE, CONFIG_REC_KEY, &desc, &ftok) == NRF_SUCCESS)
- {
- fds_record_t const rec =
- {
- .file_id = CONFIG_FILE,
- .key = CONFIG_REC_KEY,
- .data.p_data = p_cfg,
- .data.length_words = (sizeof(configuration_t) + 3) / sizeof(uint32_t)
- };
- ret_code_t rc = fds_record_update(&desc, &rec);
- if (rc != NRF_SUCCESS)
- {
- nrf_cli_fprintf(p_cli, NRF_CLI_ERROR,
- "error: fds_record_update() returned %s.\n",
- fds_err_str(rc));
- }
- }
- else
- {
- nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, "error: could not find config file.\n");
- }
- }
- static void record_delete(nrf_cli_t const * p_cli, uint32_t fid, uint32_t key)
- {
- fds_find_token_t tok = {0};
- fds_record_desc_t desc = {0};
- nrf_cli_fprintf(p_cli, NRF_CLI_DEFAULT,
- "deleting record...\n"
- "file: 0x%x, key: 0x%x\n",
- fid,
- key);
- if (fds_record_find(fid, key, &desc, &tok) == NRF_SUCCESS)
- {
- ret_code_t rc = fds_record_delete(&desc);
- if (rc != NRF_SUCCESS)
- {
- nrf_cli_fprintf(p_cli, NRF_CLI_ERROR,
- "error: fds_record_delete() returned %s.\n", fds_err_str(rc));
- return;
- }
- nrf_cli_fprintf(p_cli, NRF_CLI_DEFAULT, "record id: 0x%x\n", desc.record_id);
- }
- else
- {
- nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, "error: record not found!\n");
- }
- }
- bool record_delete_next(void)
- {
- fds_find_token_t tok = {0};
- fds_record_desc_t desc = {0};
- if (fds_record_iterate(&desc, &tok) == NRF_SUCCESS)
- {
- ret_code_t rc = fds_record_delete(&desc);
- if (rc != NRF_SUCCESS)
- {
- return false;
- }
- return true;
- }
- else
- {
- /* No records left to delete. */
- return false;
- }
- }
- static void print_cmd(nrf_cli_t const * p_cli, size_t argc, char ** argv)
- {
- if (nrf_cli_help_requested(p_cli))
- {
- nrf_cli_help_print(p_cli, NULL, 0);
- }
- else if (argc != 2)
- {
- cli_wrong_param_count_help(p_cli, "print");
- }
- else
- {
- cli_unknown_param_help(p_cli, argv[1], "print");
- }
- }
- static void print_cfg_cmd(nrf_cli_t const * p_cli, size_t argc, char ** argv)
- {
- fds_record_desc_t desc = {0};
- fds_find_token_t tok = {0};
- while (fds_record_find(CONFIG_FILE, CONFIG_REC_KEY, &desc, &tok) == NRF_SUCCESS)
- {
- ret_code_t rc;
- fds_flash_record_t frec = {0};
- rc = fds_record_open(&desc, &frec);
- switch (rc)
- {
- case NRF_SUCCESS:
- break;
- case FDS_ERR_CRC_CHECK_FAILED:
- nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, "error: CRC check failed!\n");
- continue;
- case FDS_ERR_NOT_FOUND:
- nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, "error: record not found!\n");
- continue;
- default:
- {
- nrf_cli_fprintf(p_cli, NRF_CLI_ERROR,
- "error: unexpecte error %s.\n",
- fds_err_str(rc));
- continue;
- }
- }
- configuration_t * p_cfg = (configuration_t *)(frec.p_data);
- nrf_cli_fprintf(p_cli, NRF_CLI_DEFAULT,
- "config1:\t%s\n"
- "config2:\t%s\n"
- "boot count:\t%u\n"
- "device name:\t%s\n",
- p_cfg->config1_on ? "on" : "off",
- p_cfg->config2_on ? "on" : "off",
- p_cfg->boot_count,
- p_cfg->device_name);
- rc = fds_record_close(&desc);
- APP_ERROR_CHECK(rc);
- }
- }
- static void print_all_cmd(nrf_cli_t const * p_cli, size_t argc, char ** argv)
- {
- fds_find_token_t tok = {0};
- fds_record_desc_t desc = {0};
- nrf_cli_fprintf(p_cli, NRF_CLI_DEFAULT,
- "rec. id\t"
- "\tfile id\t"
- "\trec. key"
- "\tlength\n");
- while (fds_record_iterate(&desc, &tok) != FDS_ERR_NOT_FOUND)
- {
- ret_code_t rc;
- fds_flash_record_t frec = {0};
- rc = fds_record_open(&desc, &frec);
- switch (rc)
- {
- case NRF_SUCCESS:
- break;
- case FDS_ERR_CRC_CHECK_FAILED:
- nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, "error: CRC check failed!\n");
- continue;
- case FDS_ERR_NOT_FOUND:
- nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, "error: record not found!\n");
- continue;
- default:
- {
- nrf_cli_fprintf(p_cli, NRF_CLI_ERROR,
- "error: unexpecte error %s.\n",
- fds_err_str(rc));
- continue;
- }
- }
- uint32_t const len = frec.p_header->length_words * sizeof(uint32_t);
- nrf_cli_fprintf(p_cli, NRF_CLI_DEFAULT,
- " 0x%04x\t"
- "\t 0x%04x\t"
- "\t 0x%04x\t"
- "\t %4u bytes\n",
- frec.p_header->record_id,
- frec.p_header->file_id,
- frec.p_header->record_key,
- len);
- rc = fds_record_close(&desc);
- APP_ERROR_CHECK(rc);
- }
- }
- static void write_cmd(nrf_cli_t const * p_cli, size_t argc, char ** argv)
- {
- if (nrf_cli_help_requested(p_cli))
- {
- nrf_cli_help_print(p_cli, NULL, 0);
- }
- else if (argc != 4)
- {
- cli_wrong_param_count_help(p_cli, "write");
- }
- else
- {
- /* Must be statically allocated, because it is going to be written in flash. */
- static uint8_t m_data[256];
- uint16_t const fid = strtol(argv[1], NULL, 16);
- uint16_t const key = strtol(argv[2], NULL, 16);
- uint32_t const len = strlen(argv[3]) < sizeof(m_data) ?
- strlen(argv[3]) : sizeof(m_data);
- /* Copy data to static variable. */
- memset(m_data, 0x00, sizeof(m_data));
- memcpy(m_data, argv[3], len);
- record_write(p_cli, fid, key, m_data, len);
- }
- }
- static void update_cmd(nrf_cli_t const * p_cli, size_t argc, char ** argv)
- {
- if (nrf_cli_help_requested(p_cli))
- {
- nrf_cli_help_print(p_cli, NULL, 0);
- }
- else if (argc != 5)
- {
- cli_wrong_param_count_help(p_cli, "update");
- }
- else
- {
- /* Must be statically allocated, because it is going to be written in flash. */
- static configuration_t cfg = {0};
- memset(&cfg, 0x00, sizeof(configuration_t));
- cfg.config1_on = !strcmp(argv[1], "on");
- cfg.config2_on = !strcmp(argv[2], "on");
- cfg.boot_count = strtol(argv[3], NULL, 10);
- uint16_t const len = strlen(argv[4]) < sizeof(cfg.device_name) ?
- strlen(argv[4]) : sizeof(cfg.device_name);
- memcpy(cfg.device_name, argv[4], len);
- nrf_cli_fprintf(p_cli, NRF_CLI_DEFAULT,
- "updating configuration: %s, %s, boot_count=%u, device_name=\"%s\"\n",
- cfg.config1_on ? "on" : "off",
- cfg.config2_on ? "on" : "off",
- cfg.boot_count,
- cfg.device_name);
- record_update(p_cli, &cfg);
- }
- }
- static void delete_cmd(nrf_cli_t const * p_cli, size_t argc, char ** argv)
- {
- if (nrf_cli_help_requested(p_cli))
- {
- nrf_cli_help_print(p_cli, NULL, 0);
- }
- else if (argc < 3)
- {
- cli_wrong_param_count_help(p_cli, "delete");
- }
- else
- {
- uint32_t const fid = strtol(argv[1], NULL, 16);
- uint32_t const key = strtol(argv[2], NULL, 16);
- record_delete(p_cli, fid, key);
- }
- }
- static void delete_all_cmd(nrf_cli_t const * p_cli, size_t argc, char ** argv)
- {
- if (nrf_cli_help_requested(p_cli))
- {
- nrf_cli_help_print(p_cli, NULL, 0);
- }
- else if (argc != 1)
- {
- cli_wrong_param_count_help(p_cli, "delete_all");
- }
- else
- {
- delete_all_begin();
- }
- }
- static void stat_cmd(nrf_cli_t const * p_cli, size_t argc, char **argv)
- {
- if (nrf_cli_help_requested(p_cli))
- {
- nrf_cli_help_print(p_cli, NULL, 0);
- }
- else
- {
- /* Print fds_stat(). */
- fds_stat_t stat = {0};
- ret_code_t rc = fds_stat(&stat);
- APP_ERROR_CHECK(rc);
- nrf_cli_fprintf(p_cli, NRF_CLI_DEFAULT,
- "total pages:\t%u\n"
- "total records:\t%u\n"
- "valid records:\t%u\n"
- "dirty records:\t%u\n"
- "largest contig:\t%u\n"
- "freeable words:\t%u (%u bytes)\n",
- stat.pages_available,
- stat.valid_records + stat.dirty_records,
- stat.valid_records,
- stat.dirty_records,
- stat.largest_contig,
- stat.freeable_words,
- stat.freeable_words * sizeof(uint32_t));
- }
- }
- static void gc_cmd(nrf_cli_t const * p_cli, size_t argc, char ** argv)
- {
- ret_code_t rc = fds_gc();
- switch (rc)
- {
- case NRF_SUCCESS:
- break;
- default:
- nrf_cli_fprintf(p_cli, NRF_CLI_ERROR,
- "error: garbage collection returned %s\n", fds_err_str(rc));
- break;
- }
- }
- NRF_CLI_CREATE_STATIC_SUBCMD_SET(m_print)
- {
- NRF_CLI_CMD(all, NULL, PRINT_ALL_HELP, print_all_cmd),
- NRF_CLI_CMD(config, NULL, PRINT_CFG_HELP, print_cfg_cmd),
- NRF_CLI_SUBCMD_SET_END
- };
- NRF_CLI_CMD_REGISTER(print, &m_print, PRINT_HELP, print_cmd);
- NRF_CLI_CMD_REGISTER(write, NULL, WRITE_HELP, write_cmd);
- NRF_CLI_CMD_REGISTER(update, NULL, UPDATE_HELP, update_cmd);
- NRF_CLI_CMD_REGISTER(delete, NULL, DELETE_HELP, delete_cmd);
- NRF_CLI_CMD_REGISTER(delete_all, NULL, DELETE_ALL_HELP, delete_all_cmd);
- NRF_CLI_CMD_REGISTER(gc, NULL, GC_HELP, gc_cmd);
- NRF_CLI_CMD_REGISTER(stat, NULL, STAT_HELP, stat_cmd);
|