From 44e1a016a7d24165c7773eeec36356a43b7c7f67 Mon Sep 17 00:00:00 2001 From: Scheiffler Date: Mon, 25 Sep 2023 15:40:39 -0500 Subject: [PATCH 1/3] Update MAX32670 WearLeveling example to use CLI library --- .../include/{cli.h => cmd_table.h} | 30 +- Examples/MAX32670/WearLeveling/include/main.h | 42 --- Examples/MAX32670/WearLeveling/main.c | 274 ++++++++++++--- Examples/MAX32670/WearLeveling/src/cli.c | 313 ------------------ Libraries/CLI/src/cli.c | 2 +- 5 files changed, 228 insertions(+), 433 deletions(-) rename Examples/MAX32670/WearLeveling/include/{cli.h => cmd_table.h} (60%) delete mode 100644 Examples/MAX32670/WearLeveling/include/main.h delete mode 100644 Examples/MAX32670/WearLeveling/src/cli.c diff --git a/Examples/MAX32670/WearLeveling/include/cli.h b/Examples/MAX32670/WearLeveling/include/cmd_table.h similarity index 60% rename from Examples/MAX32670/WearLeveling/include/cli.h rename to Examples/MAX32670/WearLeveling/include/cmd_table.h index 27b08e2039..5f57b241f5 100644 --- a/Examples/MAX32670/WearLeveling/include/cli.h +++ b/Examples/MAX32670/WearLeveling/include/cmd_table.h @@ -31,30 +31,14 @@ * ******************************************************************************/ -#ifndef EXAMPLES_MAX32670_WEARLEVELING_INCLUDE_CLI_H_ -#define EXAMPLES_MAX32670_WEARLEVELING_INCLUDE_CLI_H_ +#ifndef EXAMPLES_MAX32670_WEARLEVELING_INCLUDE_CMD_TABLE_H_ +#define EXAMPLES_MAX32670_WEARLEVELING_INCLUDE_CMD_TABLE_H_ -#include "lfs.h" +#define CMD_TABLE { { "stop", "stop", "Ends the example", handle_stop }, \ + { "read", "read ", "Reads data from a specific location within a file.", handle_read }, \ + { "write", "write (--create) ", "Writes a character string to a specific location within a file.\n If the create flag is included and the file does not exist, the file will\n be created.", handle_write }, \ + { "swl", "swl ", "Stands for \"show wear leveling.\" This command writes to a file\n the specified number of times. Once all writes have completed, the number\n of times each flash page (filesystem block) was written to is printed to\n the terminal. (Writes should be distributed somewhat evenly across many\n filesystem blocks.) This command may take a while to complete. LED0 is\n used as a heartbeat while the command is executing.", handle_swl } }; -/* - * @brief Function to receive next command from the command line. - * - * @param cmd Buffer to store command into. - * @param size Size of the command buffer. - * - * @return The size of the command if successful, otherwise an error code. - */ -int cmd_get(char *cmd, size_t size); -/* - * @brief Function to process command and call appropriate command handler. - * - * @param lfs Pointer to mounted filesystem instance - * @param cmd Buffer containing characters read from the command line. - * @param size Number of characters in the command buffer. - * - * @return E_NO_ERROR if command processed successfully, otherwise an error code. - */ -int cmd_process(lfs_t *lfs, char *cmd, size_t size); -#endif // EXAMPLES_MAX32670_WEARLEVELING_INCLUDE_CLI_H_ +#endif /* EXAMPLES_MAX32670_WEARLEVELING_INCLUDE_CMD_TABLE_H_ */ diff --git a/Examples/MAX32670/WearLeveling/include/main.h b/Examples/MAX32670/WearLeveling/include/main.h deleted file mode 100644 index 7e85286168..0000000000 --- a/Examples/MAX32670/WearLeveling/include/main.h +++ /dev/null @@ -1,42 +0,0 @@ -/****************************************************************************** - * Copyright (C) 2023 Maxim Integrated Products, Inc., All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES - * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Except as contained in this notice, the name of Maxim Integrated - * Products, Inc. shall not be used except as stated in the Maxim Integrated - * Products, Inc. Branding Policy. - * - * The mere transfer of this software does not imply any licenses - * of trade secrets, proprietary technology, copyrights, patents, - * trademarks, maskwork rights, or any other form of intellectual - * property whatsoever. Maxim Integrated Products, Inc. retains all - * ownership rights. - * - ******************************************************************************/ - -#ifndef EXAMPLES_MAX32670_WEARLEVELING_INCLUDE_MAIN_H_ -#define EXAMPLES_MAX32670_WEARLEVELING_INCLUDE_MAIN_H_ - -/***** Definitions *****/ -#define LFS_START_PAGE 32 // First flash memory block used by LFS -#define LFS_PAGE_CNT 16 // Number of flash memory blocks reserved for LFS -#define CMD_MAX_SIZE 256 // Size of the command buffer - -#endif // EXAMPLES_MAX32670_WEARLEVELING_INCLUDE_MAIN_H_ diff --git a/Examples/MAX32670/WearLeveling/main.c b/Examples/MAX32670/WearLeveling/main.c index 5c793043d5..fabf949c88 100644 --- a/Examples/MAX32670/WearLeveling/main.c +++ b/Examples/MAX32670/WearLeveling/main.c @@ -43,75 +43,60 @@ #include #include #include +#include "board.h" #include "cli.h" +#include "cmd_table.h" #include "flash.h" #include "file.h" +#include "led.h" #include "lfs.h" -#include "main.h" #include "mxc_device.h" +#include "uart.h" -/***** Globals *****/ -uint32_t start_block = LFS_START_PAGE; - -const struct lfs_config cfg = { - .context = &start_block, - // block device operations - .read = flash_read, - .prog = flash_write, - .erase = flash_erase, - .sync = flash_sync, - - // block device configuration - .read_size = 1, - .prog_size = 4, - .block_size = MXC_FLASH_PAGE_SIZE, - .block_count = LFS_PAGE_CNT, - .cache_size = 16, - .lookahead_size = 16, - .block_cycles = 500, -}; +/***** Definitions *****/ +#define LFS_START_PAGE 32 // First flash memory block used by LFS +#define LFS_PAGE_CNT 16 // Number of flash memory blocks reserved for LFS -//****************************************************************************** -/** - * @brief Application entry point - * @return Exit code - */ +/***** Function Prototypes *****/ +int handle_stop(int argc, char *argv[]); +int handle_read(int argc, char *argv[]); +int handle_write(int argc, char *argv[]); +int handle_swl(int argc, char *argv[]); +int mount_filesystem(void); + +/***** Global Variables ******/ +const command_t cmd_table[] = CMD_TABLE; // List of commands available to the user +const unsigned int cmd_table_sz = sizeof(cmd_table) / sizeof(command_t); // Number of commands + +lfs_t lfs; // LFS filesystem instance +volatile bool stop_recv = false; // Used to signal whether the example has completed + +/***** Function Definitions *****/ int main(void) { - lfs_t lfs; // File system instance - char cmd_buf[CMD_MAX_SIZE]; - int cmd_len, err; - - printf("\n\n********** Wear Leveling Example **********\n"); - - // mount the filesystem - printf("Mounting the filesystem...\n"); - err = lfs_mount(&lfs, &cfg); - - // reformat if we can't mount the filesystem - // this should only happen on the first boot - if (err) { - printf("Filesystem is invalid, formatting...\n"); - lfs_format(&lfs, &cfg); - err = lfs_mount(&lfs, &cfg); - } + int err; - if (!err) { - printf("Filesystem is mounted! Ready for commands.\n"); - } else { - printf("Unable to initialize file system!\n"); - return E_BAD_STATE; + printf("\n\n*************** Wear Leveling Example ***************\n"); + + printf("Mounting the file system...\n"); + + if ((err = mount_filesystem()) != E_NO_ERROR) { + printf("Unable to mount file system!\n"); + return err; } - // Continue to receive and process commands until 'stop' command received - while (err != E_SHUTDOWN) { - printf("\ncmd> "); - fflush(stdout); + printf("File system is mounted!\n\n"); + while(MXC_UART_GetActive(MXC_UART_GET_UART(CONSOLE_UART))) {} - cmd_len = cmd_get(cmd_buf, CMD_MAX_SIZE); - err = cmd_process(&lfs, cmd_buf, cmd_len); + // Initialize command-line interface + if (MXC_CLI_Init(MXC_UART_GET_UART(CONSOLE_UART), cmd_table, cmd_table_sz) != E_NO_ERROR) { + printf("Unable to initialize the command-line interface.\n"); + return E_BAD_STATE; } + // CLI running in the background. Continue to receive and process commands until 'stop' command received + while (!stop_recv) {} + // release any resources we were using lfs_unmount(&lfs); printf("\nFilesystem resources released.\n"); @@ -119,3 +104,184 @@ int main(void) printf("Example complete!\n"); return E_NO_ERROR; } + +//****************************************************************************** +int handle_stop(int argc, char *argv[]) +{ + stop_recv = true; + return E_NO_ERROR; +} + +//****************************************************************************** +int handle_read(int argc, char *argv[]) +{ + // Check for invalid arguments + if (argc != 4 || argv == NULL) { + printf("Invalid command. Aborting file read.\n"); + return E_NULL_PTR; + } + + lfs_file_t file; + char data[MAX_FILE_READ_SIZE]; + + // Assign CLI arguments to appropriate variables + char *filename = argv[1]; + int num = atoi(argv[2]); + int pos = atoi(argv[3]); + memset(data, '\0', sizeof(data)); + + // Read data from file + num = file_read(&lfs, &file, filename, data, num, pos); + if (num < LFS_ERR_OK) { + printf("Read failed with error code %d.\n", num); + return num; + } else { + printf("%d bytes were read from %s in filesystem block %d.\n", num, filename, file.block); + } + + // Print data read from file to the terminal + printf("The following string was read from file %s:\n", filename); + + for (int i = 0; i < num; i++) { + printf("%c", data[i]); + } + printf("\n"); + + return E_NO_ERROR; +} + +//****************************************************************************** +int handle_write(int argc, char *argv[]) +{ + // Check for invalid arguments + if (!(argc == 4 || argc == 5) || argv == NULL) { + printf("Invalid command. Aborting file write.\n"); + return E_INVALID; + } + + lfs_file_t file; + char *filename; + char *data; + int pos, err; + bool create; + + // Parse remainder of the arguments based on whether not create flag was passed + if (argc == 5 && memcmp(argv[1], "--create", sizeof("--create") - 1) == 0) { + // Create flag passed, next argument is filename + create = true; + filename = argv[2]; + data = argv[3]; + pos = atoi(argv[4]); + } else if (argc == 4) { + // create flag not passed + create = false; + filename = argv[1]; + data = argv[2]; + pos = atoi(argv[3]); + } else { + printf("Invalid command. Aborting file write.\n"); + return E_BAD_PARAM; + } + + // Write data to the file + err = file_write(&lfs, &file, filename, data, strlen(data), pos, create); + if (err < LFS_ERR_OK) { + printf("Write failed with error code %d.\n", err); + } else { + printf("%d bytes were written to %s in filesystem block %d.\n", err, filename, file.block); + } + + return err; +} + +//****************************************************************************** +int handle_swl(int argc, char *argv[]) +{ + // Check for invalid arguments + if (argc != 2 || argv == NULL) { + printf("Invalid command format. Aborting swl.\n"); + return E_INVALID; + } + + int num_writes, err; + int hit_count[LFS_PAGE_CNT] = { 0 }; + + // Assign CLI arguments to appropriate variables + num_writes = atoi(argv[1]); + + //Set up dummy arguments + char filename[] = "swl_test_file"; + char data[] = "show_littlefs_wear_leveling"; // Length of this string must exceed lfs.cache_size + lfs_file_t file; + + // Write to the test file the specified number of writes and + // track how many times each flash page is written to + for (int i = 0; i < num_writes; i++) { + // Do next write + err = file_write(&lfs, &file, filename, data, strlen(data), 0, true); + if (err < LFS_ERR_OK) { + printf("Failed to write to test file. Aborting \"swl\" command.\n"); + return err; + } + + // Increment the hit count + if (file.block >= 0 && file.block < LFS_PAGE_CNT) { + hit_count[file.block]++; + } + + // Heartbeat, this loop can take a while if num_writes is large + if (i % 50 == 0) { + LED_Toggle(0); + } + } + + // Print results + printf("All writes have completed. Here are the results:\n"); + for (int i = 0; i < LFS_PAGE_CNT; i++) { + printf("Block %d was written to %d times.\n", i, hit_count[i]); + } + printf("\n"); + + return E_NO_ERROR; +} + +//****************************************************************************** +int mount_filesystem(void) +{ + int err; + uint32_t start_block = LFS_START_PAGE; + const struct lfs_config cfg = { + .context = &start_block, + // block device operations + .read = flash_read, + .prog = flash_write, + .erase = flash_erase, + .sync = flash_sync, + + // block device configuration + .read_size = 1, + .prog_size = 4, + .block_size = MXC_FLASH_PAGE_SIZE, + .block_count = LFS_PAGE_CNT, + .cache_size = 16, + .lookahead_size = 16, + .block_cycles = 500, + }; + + // mount the file system + err = lfs_mount(&lfs, &cfg); + + // reformat if we can't mount the filesystem + // this should only happen on the first boot + if (err) { + printf("Filesystem is invalid, formatting...\n"); + lfs_format(&lfs, &cfg); + err = lfs_mount(&lfs, &cfg); + } + + if (err) { + return E_BAD_STATE; + } + + return err; +} diff --git a/Examples/MAX32670/WearLeveling/src/cli.c b/Examples/MAX32670/WearLeveling/src/cli.c deleted file mode 100644 index 4284b92cd8..0000000000 --- a/Examples/MAX32670/WearLeveling/src/cli.c +++ /dev/null @@ -1,313 +0,0 @@ -/****************************************************************************** - * Copyright (C) 2023 Maxim Integrated Products, Inc., All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES - * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Except as contained in this notice, the name of Maxim Integrated - * Products, Inc. shall not be used except as stated in the Maxim Integrated - * Products, Inc. Branding Policy. - * - * The mere transfer of this software does not imply any licenses - * of trade secrets, proprietary technology, copyrights, patents, - * trademarks, maskwork rights, or any other form of intellectual - * property whatsoever. Maxim Integrated Products, Inc. retains all - * ownership rights. - * - ******************************************************************************/ - -#include -#include -#include -#include -#include "board.h" -#include "cli.h" -#include "file.h" -#include "led.h" -#include "main.h" -#include "mxc_device.h" -#include "mxc_errors.h" -#include "uart.h" - -/********************************************************************************/ -/******************************* Private Functions ******************************/ -/********************************************************************************/ - -/***** Handler Functions *****/ -static int help_CmdHandler(void) -{ - // Print command descriptions - printf("\nThe available commands are:\n"); - printf(" * help\n"); - printf(" Description: Prints out list of available commands.\n"); - printf(" Usage: help\n\n"); - printf(" * stop\n"); - printf(" Description: Ends the example.\n"); - printf(" Usage: stop\n\n"); - printf(" * read\n"); - printf(" Description: Reads data from a specific location within a file. If\n"); - printf(" the read is successful, the data read is printed to the\n"); - printf(" terminal.\n"); - printf(" Usage: read \n\n"); - printf(" * write\n"); - printf(" Description: Writes a character string to a specific location within\n"); - printf(" a file.\n"); - printf(" Usage: write (--create) \n"); - printf(" Options:\n"); - printf(" --create: Creates file if it does not already exist.\n"); - printf(" * swl\n"); - printf(" Description: Stands for \"show wear leveling\". Writes to a file the\n"); - printf(" specified number of times. Once all writes have completed,\n"); - printf(" the number of times each flash page (filesystem block)\n"); - printf(" was written to is printed to the terminal. This command may\n"); - printf(" take a while to complete. LED0 is used as a heartbeat while\n"); - printf(" the command is executing.\n"); - printf(" Usage: swl \n\n"); - - return E_NO_ERROR; -} - -static int stop_CmdHandler(void) -{ - return E_SHUTDOWN; -} - -static int read_CmdHandler(lfs_t *lfs, char *args) -{ - // Check for invalid arguments - if (lfs == NULL || args == NULL) { - printf("Invalid argument string. Read failed.\n"); - return E_NULL_PTR; - } - - char *save_ptr = args; - - // Parse arguments sting - strtok_r(args, " ", &save_ptr); - char *filename = strtok_r(NULL, " ", &save_ptr); - char *str_num_bytes = strtok_r(NULL, " ", &save_ptr); - char *str_pos = strtok_r(NULL, "\r\n", &save_ptr); - char data[MAX_FILE_READ_SIZE]; - lfs_file_t file; - - memset(data, '\0', sizeof(data)); - - // Convert arguments to integers - int num = atoi(str_num_bytes); - int pos = atoi(str_pos); - - // Read data from file - num = file_read(lfs, &file, filename, data, num, pos); - if (num < LFS_ERR_OK) { - printf("Read failed with error code %d.\n", num); - return num; - } else { - printf("%d bytes were read from %s in filesystem block %d.\n", num, filename, file.block); - } - - // Print data read from file to the terminal - printf("The following string was read from file %s:\n", filename); - - for (int i = 0; i < num; i++) { - printf("%c", data[i]); - } - printf("\n"); - - return E_NO_ERROR; -} - -static int write_CmdHandler(lfs_t *lfs, char *args) -{ - // Check for invalid arguments - if (lfs == NULL) { - printf("Invalid filesystem instance. Write failed.\n"); - return E_NULL_PTR; - } else if (args == NULL) { - printf("Invalid argument string. Write failed.\n"); - return E_INVALID; - } - - lfs_file_t file; - char *create_fl; - char *filename; - char *data; - char *str_pos; - int pos, err; - bool create; - char *save_ptr = args; - - // Parse arguments - strtok_r(args, " ", &save_ptr); - create_fl = strtok_r(NULL, " ", &save_ptr); - - // Parse remainder of the arguments based on whether not create flag was passed - if (memcmp(create_fl, "--create", sizeof("--create") - 1) == 0) { - // Create flag passed, next argument is filename - create = true; - filename = strtok_r(NULL, " ", &save_ptr); - data = strtok_r(NULL, " ", &save_ptr); - str_pos = strtok_r(NULL, "\r\n", &save_ptr); - } else { - // create flag not passed, last argument parsed was file name - create = false; - filename = create_fl; - data = strtok_r(NULL, " ", &save_ptr); - str_pos = strtok_r(NULL, "\r\n", &save_ptr); - } - - // Convert position to an integer value - pos = atoi(str_pos); - - // Write data to the file - err = file_write(lfs, &file, filename, data, strlen(data), pos, create); - if (err < LFS_ERR_OK) { - printf("Write failed with error code %d.\n", err); - } else { - printf("%d bytes were written to %s in filesystem block %d.\n", err, filename, file.block); - } - - return err; -} - -static int swl_CmdHandler(lfs_t *lfs, char *args) -{ - // Check for invalid arguments - if (lfs == NULL) { - printf("Invalid filesystem instance. Write failed.\n"); - return E_NULL_PTR; - } else if (args == NULL) { - printf("Invalid argument string. Write failed.\n"); - return E_INVALID; - } - - char *save_ptr = args; - char *str_num_writes; - int num_writes, err; - int hit_count[LFS_PAGE_CNT] = { 0 }; - - // Parse argument string - strtok_r(args, " ", &save_ptr); - str_num_writes = strtok_r(NULL, "\r\n", &save_ptr); - num_writes = atoi(str_num_writes); - - //Set up dummy arguments - char filename[] = "swl_test_file"; - char data[] = "show_littlefs_wear_leveling"; // Length of this string must exceed lfs.cache_size - lfs_file_t file; - - // Write to the test file the specified number of writes and - // track how many times each flash page is written to - for (int i = 0; i < num_writes; i++) { - // Do next write - err = file_write(lfs, &file, filename, data, strlen(data), 0, true); - if (err < LFS_ERR_OK) { - printf("Failed to write to test file. Aborting \"swl\" command.\n"); - return err; - } - - // Increment the hit count - if (file.block >= 0 && file.block < LFS_PAGE_CNT) { - hit_count[file.block]++; - } - - // Heartbeat, this loop can take a while if num_writes is large - if (i % 50 == 0) { - LED_Toggle(0); - } - } - - // Print results - printf("All writes have completed. Here are the results:\n"); - for (int i = 0; i < LFS_PAGE_CNT; i++) { - printf("Block %d was written to %d times.\n", i, hit_count[i]); - } - printf("\n"); - - return E_NO_ERROR; -} - -/********************************************************************************/ -/******************************* Public Functions *******************************/ -/********************************************************************************/ -int cmd_get(char *cmd, size_t size) -{ - if (cmd == NULL) { - return E_NULL_PTR; - } else if (size < 0) { - return E_BAD_PARAM; - } - - bool eoc = false; - int num_recv = 0; - int next_ch; - - while (!eoc) { - // Read character from RX FIFO, wait here until 1 is available - while ((next_ch = MXC_UART_ReadCharacter(MXC_UART_GET_UART(CONSOLE_UART))) < E_NO_ERROR) {} - MXC_UART_WriteCharacter(MXC_UART_GET_UART(CONSOLE_UART), next_ch); //Echo - if (next_ch == 0x08) { // backspace - if (num_recv != 0) { - num_recv--; - } - } else { // Store character - cmd[num_recv++] = (char)next_ch; - } - - // if buffer full or EOC received, exit loop - if (num_recv == size || next_ch == '\r' || next_ch == '\n') { - eoc = true; - } - } - - return num_recv; -} - -int cmd_process(lfs_t *lfs, char *cmd, size_t size) -{ - // Check for invalid parameters - if (lfs == NULL || cmd == NULL) { - return E_NULL_PTR; - } else if (size <= 0) { - return E_BAD_PARAM; - } - - // Parse out command and argument strings - int err = E_INVALID; - - // Call appropriate command handler for valid commands - if (memcmp(cmd, "help", sizeof("help") - 1) == 0) { - // Process help command - err = help_CmdHandler(); - } else if (memcmp(cmd, "stop", sizeof("stop") - 1) == 0) { - // Process stop command - err = stop_CmdHandler(); - } else if (memcmp(cmd, "read", sizeof("read") - 1) == 0) { - // Process file read command - err = read_CmdHandler(lfs, cmd); - } else if (memcmp(cmd, "write", sizeof("write") - 1) == 0) { - // Process file write command - err = write_CmdHandler(lfs, cmd); - } else if (memcmp(cmd, "swl", sizeof("swl") - 1) == 0) { - // Process show wear leveling command - err = swl_CmdHandler(lfs, cmd); - } - - memset(cmd, '\0', size); - - return err; -} diff --git a/Libraries/CLI/src/cli.c b/Libraries/CLI/src/cli.c index 008e2aa8bf..b73ee6574d 100644 --- a/Libraries/CLI/src/cli.c +++ b/Libraries/CLI/src/cli.c @@ -252,7 +252,7 @@ int handle_help(int argc, char *argv[]) for (int i = 0; i < command_table_sz; i++) { printf("\n%s:\n", command_table[i].cmd); printf(" Usage: %s\n", command_table[i].usage); - printf(" Description: %s\n\n", command_table[i].description); + printf(" Description: %s\n", command_table[i].description); } return E_NO_ERROR; From bbf268456635d7eab6990e5d479b02231723ee84 Mon Sep 17 00:00:00 2001 From: Scheiffler Date: Mon, 25 Sep 2023 16:51:37 -0500 Subject: [PATCH 2/3] Update MAx32670 WearLeveling example to use new CLI library (pt. 2) --- Examples/MAX32670/WearLeveling/README.md | 84 ++++++++-------- .../MAX32670/WearLeveling/include/cmd_table.h | 8 +- Examples/MAX32670/WearLeveling/main.c | 96 ++++++++----------- 3 files changed, 88 insertions(+), 100 deletions(-) diff --git a/Examples/MAX32670/WearLeveling/README.md b/Examples/MAX32670/WearLeveling/README.md index 9e42ee7e0a..3130d65e0c 100644 --- a/Examples/MAX32670/WearLeveling/README.md +++ b/Examples/MAX32670/WearLeveling/README.md @@ -6,7 +6,7 @@ Below is a list of the supported commands: * help: Prints out the list of available commands and describes how each command is used. * stop: Ends the example. * read: Reads data from a file and prints it to the terminal. -* write: Writes data to a file and can optionally create the file to write to if it does not already exist. +* write: Writes a characterstring to a file * swl: Stands for "show wear leveling". This command performs a specified number of writes (passed as an argument on the command line) to a test file and prints out the number of times each filesystem block was written to. Users should see the writes occur somewhat evenly across most filesystem blocks. Enter "help" in the command line to see more details on the usage of each of the commands including what arguments/options need to be specified to successfully execute each command. @@ -34,54 +34,50 @@ Universal instructions on building, flashing, and debugging this project can be The Console UART of the device will output these messages: ``` -********** Wear Leveling Example ********** -Mounting the filesystem... -C:/MaximSDK/Libraries/littlefs/lfs.c:1224:error: Corrupted dir pair at {0x0, 0x1} +*************** Wear Leveling Example *************** +Mounting the file system... +littlefs/lfs.c:1224:error: Corrupted dir pair at {0x0, 0x1} Filesystem is invalid, formatting... -Filesystem is mounted! Ready for commands. - -cmd> help - -The available commands are: - * help - Description: Prints out list of available commands. - Usage: help - - * stop - Description: Ends the example. - Usage: stop - - * read - Description: Reads data from a specific location within a file. If - the read is successful, the data read is printed to the - terminal. - Usage: read - - * write - Description: Writes a character string to a specific location within - a file. - Usage: write (--create) - Options: - --create: Creates file if it does not already exist. - * swl - DDescription: Stands for "show wear leveling". Writes to a file the - specified number of times. Once all writes have completed, - the number of times each flash page (filesystem block) - was written to is printed to the terminal. This command may - take a while to complete. LED0 is used as a heartbeat while - the command is executing. - Usage: swl - - -cmd> write --create demo_file thisisanexampledatastringtowritetodemofile 0 +File system is mounted! + +CLI Initialized! Enter 'help' to see a list of available commands. + +$ help +help + +stop: + Usage: stop + Description: Ends the example + +read: + Usage: read + Description: Reads data from a specific location within a file. + +write: + Usage: write + Description: Writes a character string to a specific location within a file. + +swl: + Usage: swl + Description: Stands for "show wear leveling." This command writes to a file + the specified number of times. Once all writes have completed, the number + of times each flash page (filesystem block) was written to is printed to + the terminal. (Writes should be distributed somewhat evenly across many + filesystem blocks.) This command may take a while to complete. LED0 is + used as a heartbeat while the command is executing. + +$ write demo_file thisisanexampledatastringtowritetodemofile 0 +write demo_file thisisanexampledatastringtowritetodemofile 0 42 bytes were written to demo_file in filesystem block 6. -cmd> read demo_file 42 0 +$ read demo_file 42 0 +read demo_file 42 0 42 bytes were read from demo_file in filesystem block 6. The following string was read from file demo_file: thisisanexampledatastringtowritetodemofile -cmd> swl 1000 +$ swl 1000 +swl 1000 All writes have completed. Here are the results: Block 0 was written to 0 times. Block 1 was written to 0 times. @@ -101,8 +97,10 @@ Block 14 was written to 83 times. Block 15 was written to 83 times. -cmd> stop +$ stop +stop +$ Filesystem resources released. Example complete! ``` diff --git a/Examples/MAX32670/WearLeveling/include/cmd_table.h b/Examples/MAX32670/WearLeveling/include/cmd_table.h index 5f57b241f5..177fca4849 100644 --- a/Examples/MAX32670/WearLeveling/include/cmd_table.h +++ b/Examples/MAX32670/WearLeveling/include/cmd_table.h @@ -36,9 +36,13 @@ #define CMD_TABLE { { "stop", "stop", "Ends the example", handle_stop }, \ { "read", "read ", "Reads data from a specific location within a file.", handle_read }, \ - { "write", "write (--create) ", "Writes a character string to a specific location within a file.\n If the create flag is included and the file does not exist, the file will\n be created.", handle_write }, \ + { "write", "write ", "Writes a character string to a specific location within a file.\n If the create flag is included and the file does not exist, the file will\n be created.", handle_write }, \ { "swl", "swl ", "Stands for \"show wear leveling.\" This command writes to a file\n the specified number of times. Once all writes have completed, the number\n of times each flash page (filesystem block) was written to is printed to\n the terminal. (Writes should be distributed somewhat evenly across many\n filesystem blocks.) This command may take a while to complete. LED0 is\n used as a heartbeat while the command is executing.", handle_swl } }; - +#define FILENAME_POS 1 +#define NUM_WRITES_POS 1 +#define NUM_BYTES_POS 2 +#define DATA_POS 2 +#define LOCATION_POS 3 #endif /* EXAMPLES_MAX32670_WEARLEVELING_INCLUDE_CMD_TABLE_H_ */ diff --git a/Examples/MAX32670/WearLeveling/main.c b/Examples/MAX32670/WearLeveling/main.c index fabf949c88..ba6e8911a5 100644 --- a/Examples/MAX32670/WearLeveling/main.c +++ b/Examples/MAX32670/WearLeveling/main.c @@ -62,12 +62,9 @@ int handle_stop(int argc, char *argv[]); int handle_read(int argc, char *argv[]); int handle_write(int argc, char *argv[]); int handle_swl(int argc, char *argv[]); -int mount_filesystem(void); +int mount_filesystem(lfs_t *filesystem, const struct lfs_config *cfg); /***** Global Variables ******/ -const command_t cmd_table[] = CMD_TABLE; // List of commands available to the user -const unsigned int cmd_table_sz = sizeof(cmd_table) / sizeof(command_t); // Number of commands - lfs_t lfs; // LFS filesystem instance volatile bool stop_recv = false; // Used to signal whether the example has completed @@ -78,9 +75,33 @@ int main(void) printf("\n\n*************** Wear Leveling Example ***************\n"); + // Create command table (defined cmd_table.h) + const command_t cmd_table[] = CMD_TABLE; + const unsigned int cmd_table_sz = sizeof(cmd_table) / sizeof(command_t); + + // Initialize LFS configuration variables + uint32_t start_block = LFS_START_PAGE; + const struct lfs_config cfg = { + .context = &start_block, + // block device operations + .read = flash_read, + .prog = flash_write, + .erase = flash_erase, + .sync = flash_sync, + + // block device configuration + .read_size = 1, + .prog_size = 4, + .block_size = MXC_FLASH_PAGE_SIZE, + .block_count = LFS_PAGE_CNT, + .cache_size = 16, + .lookahead_size = 16, + .block_cycles = 500, + }; + printf("Mounting the file system...\n"); - if ((err = mount_filesystem()) != E_NO_ERROR) { + if ((err = mount_filesystem(&lfs, &cfg)) != E_NO_ERROR) { printf("Unable to mount file system!\n"); return err; } @@ -125,9 +146,9 @@ int handle_read(int argc, char *argv[]) char data[MAX_FILE_READ_SIZE]; // Assign CLI arguments to appropriate variables - char *filename = argv[1]; - int num = atoi(argv[2]); - int pos = atoi(argv[3]); + char *filename = argv[FILENAME_POS]; + int num = atoi(argv[NUM_BYTES_POS]); + int pos = atoi(argv[LOCATION_POS]); memset(data, '\0', sizeof(data)); // Read data from file @@ -154,37 +175,20 @@ int handle_read(int argc, char *argv[]) int handle_write(int argc, char *argv[]) { // Check for invalid arguments - if (!(argc == 4 || argc == 5) || argv == NULL) { + if (argc != 4 || argv == NULL) { printf("Invalid command. Aborting file write.\n"); return E_INVALID; } + // Assign CLI arguments to appropriate variables lfs_file_t file; - char *filename; - char *data; - int pos, err; - bool create; - - // Parse remainder of the arguments based on whether not create flag was passed - if (argc == 5 && memcmp(argv[1], "--create", sizeof("--create") - 1) == 0) { - // Create flag passed, next argument is filename - create = true; - filename = argv[2]; - data = argv[3]; - pos = atoi(argv[4]); - } else if (argc == 4) { - // create flag not passed - create = false; - filename = argv[1]; - data = argv[2]; - pos = atoi(argv[3]); - } else { - printf("Invalid command. Aborting file write.\n"); - return E_BAD_PARAM; - } + char *filename = argv[FILENAME_POS];; + char *data = argv[DATA_POS]; + int pos = atoi(argv[LOCATION_POS]); + int err; // Write data to the file - err = file_write(&lfs, &file, filename, data, strlen(data), pos, create); + err = file_write(&lfs, &file, filename, data, strlen(data), pos, true); if (err < LFS_ERR_OK) { printf("Write failed with error code %d.\n", err); } else { @@ -207,7 +211,7 @@ int handle_swl(int argc, char *argv[]) int hit_count[LFS_PAGE_CNT] = { 0 }; // Assign CLI arguments to appropriate variables - num_writes = atoi(argv[1]); + num_writes = atoi(argv[NUM_WRITES_POS]); //Set up dummy arguments char filename[] = "swl_test_file"; @@ -246,37 +250,19 @@ int handle_swl(int argc, char *argv[]) } //****************************************************************************** -int mount_filesystem(void) +int mount_filesystem(lfs_t *filesystem, const struct lfs_config *cfg) { int err; - uint32_t start_block = LFS_START_PAGE; - const struct lfs_config cfg = { - .context = &start_block, - // block device operations - .read = flash_read, - .prog = flash_write, - .erase = flash_erase, - .sync = flash_sync, - - // block device configuration - .read_size = 1, - .prog_size = 4, - .block_size = MXC_FLASH_PAGE_SIZE, - .block_count = LFS_PAGE_CNT, - .cache_size = 16, - .lookahead_size = 16, - .block_cycles = 500, - }; // mount the file system - err = lfs_mount(&lfs, &cfg); + err = lfs_mount(filesystem, cfg); // reformat if we can't mount the filesystem // this should only happen on the first boot if (err) { printf("Filesystem is invalid, formatting...\n"); - lfs_format(&lfs, &cfg); - err = lfs_mount(&lfs, &cfg); + lfs_format(filesystem, cfg); + err = lfs_mount(filesystem, cfg); } if (err) { From f973cf3789168e2c3fb2707361ece7e0cc1ff28a Mon Sep 17 00:00:00 2001 From: Jacob-Scheiffler Date: Tue, 26 Sep 2023 20:25:29 +0000 Subject: [PATCH 3/3] clang-format bot reformatting. --- .../MAX32670/WearLeveling/include/cmd_table.h | 14 ++++-- Examples/MAX32670/WearLeveling/main.c | 48 ++++++++++--------- 2 files changed, 35 insertions(+), 27 deletions(-) diff --git a/Examples/MAX32670/WearLeveling/include/cmd_table.h b/Examples/MAX32670/WearLeveling/include/cmd_table.h index 177fca4849..eba3ad3e99 100644 --- a/Examples/MAX32670/WearLeveling/include/cmd_table.h +++ b/Examples/MAX32670/WearLeveling/include/cmd_table.h @@ -34,10 +34,16 @@ #ifndef EXAMPLES_MAX32670_WEARLEVELING_INCLUDE_CMD_TABLE_H_ #define EXAMPLES_MAX32670_WEARLEVELING_INCLUDE_CMD_TABLE_H_ -#define CMD_TABLE { { "stop", "stop", "Ends the example", handle_stop }, \ - { "read", "read ", "Reads data from a specific location within a file.", handle_read }, \ - { "write", "write ", "Writes a character string to a specific location within a file.\n If the create flag is included and the file does not exist, the file will\n be created.", handle_write }, \ - { "swl", "swl ", "Stands for \"show wear leveling.\" This command writes to a file\n the specified number of times. Once all writes have completed, the number\n of times each flash page (filesystem block) was written to is printed to\n the terminal. (Writes should be distributed somewhat evenly across many\n filesystem blocks.) This command may take a while to complete. LED0 is\n used as a heartbeat while the command is executing.", handle_swl } }; +#define CMD_TABLE \ + { { "stop", "stop", "Ends the example", handle_stop }, \ + { "read", "read ", \ + "Reads data from a specific location within a file.", handle_read }, \ + { "write", "write ", \ + "Writes a character string to a specific location within a file.\n If the create flag is included and the file does not exist, the file will\n be created.", \ + handle_write }, \ + { "swl", "swl ", \ + "Stands for \"show wear leveling.\" This command writes to a file\n the specified number of times. Once all writes have completed, the number\n of times each flash page (filesystem block) was written to is printed to\n the terminal. (Writes should be distributed somewhat evenly across many\n filesystem blocks.) This command may take a while to complete. LED0 is\n used as a heartbeat while the command is executing.", \ + handle_swl } }; #define FILENAME_POS 1 #define NUM_WRITES_POS 1 diff --git a/Examples/MAX32670/WearLeveling/main.c b/Examples/MAX32670/WearLeveling/main.c index ba6e8911a5..31ccd5423a 100644 --- a/Examples/MAX32670/WearLeveling/main.c +++ b/Examples/MAX32670/WearLeveling/main.c @@ -102,17 +102,17 @@ int main(void) printf("Mounting the file system...\n"); if ((err = mount_filesystem(&lfs, &cfg)) != E_NO_ERROR) { - printf("Unable to mount file system!\n"); - return err; + printf("Unable to mount file system!\n"); + return err; } printf("File system is mounted!\n\n"); - while(MXC_UART_GetActive(MXC_UART_GET_UART(CONSOLE_UART))) {} + while (MXC_UART_GetActive(MXC_UART_GET_UART(CONSOLE_UART))) {} // Initialize command-line interface if (MXC_CLI_Init(MXC_UART_GET_UART(CONSOLE_UART), cmd_table, cmd_table_sz) != E_NO_ERROR) { - printf("Unable to initialize the command-line interface.\n"); - return E_BAD_STATE; + printf("Unable to initialize the command-line interface.\n"); + return E_BAD_STATE; } // CLI running in the background. Continue to receive and process commands until 'stop' command received @@ -129,7 +129,7 @@ int main(void) //****************************************************************************** int handle_stop(int argc, char *argv[]) { - stop_recv = true; + stop_recv = true; return E_NO_ERROR; } @@ -182,10 +182,12 @@ int handle_write(int argc, char *argv[]) // Assign CLI arguments to appropriate variables lfs_file_t file; - char *filename = argv[FILENAME_POS];; + char *filename = argv[FILENAME_POS]; + { + } char *data = argv[DATA_POS]; int pos = atoi(argv[LOCATION_POS]); - int err; + int err; // Write data to the file err = file_write(&lfs, &file, filename, data, strlen(data), pos, true); @@ -202,7 +204,7 @@ int handle_write(int argc, char *argv[]) int handle_swl(int argc, char *argv[]) { // Check for invalid arguments - if (argc != 2 || argv == NULL) { + if (argc != 2 || argv == NULL) { printf("Invalid command format. Aborting swl.\n"); return E_INVALID; } @@ -252,22 +254,22 @@ int handle_swl(int argc, char *argv[]) //****************************************************************************** int mount_filesystem(lfs_t *filesystem, const struct lfs_config *cfg) { - int err; + int err; - // mount the file system - err = lfs_mount(filesystem, cfg); + // mount the file system + err = lfs_mount(filesystem, cfg); - // reformat if we can't mount the filesystem - // this should only happen on the first boot - if (err) { - printf("Filesystem is invalid, formatting...\n"); - lfs_format(filesystem, cfg); - err = lfs_mount(filesystem, cfg); - } + // reformat if we can't mount the filesystem + // this should only happen on the first boot + if (err) { + printf("Filesystem is invalid, formatting...\n"); + lfs_format(filesystem, cfg); + err = lfs_mount(filesystem, cfg); + } - if (err) { - return E_BAD_STATE; - } + if (err) { + return E_BAD_STATE; + } - return err; + return err; }