diff --git a/Examples/MAX32650/SDHC_FAT/README.md b/Examples/MAX32650/SDHC_FAT/README.md index b9dff00e80..4cea5eefc2 100644 --- a/Examples/MAX32650/SDHC_FAT/README.md +++ b/Examples/MAX32650/SDHC_FAT/README.md @@ -1,6 +1,9 @@ ## Description -This example demonstrates the SDHC FAT Filesystem. The terminal prompts with a list of user-selectable tasks to run on the inserted Micro SD Card. +This example demonstrates formatting and modifying the filesystem on an SD card. + +Use the a terminal window to select the operation(s) to perform on the SD card. + ## Software @@ -21,153 +24,23 @@ Universal instructions on building, flashing, and debugging this project can be ## Expected Output ``` -***** MAX32650 SDHC FAT Filesystem Example ***** +***** 32650 SDHC FAT Filesystem Example ***** Card inserted. Card Initialized. Card type: SDHC -SDHC Ready! -CLI Initialized! Enter 'help' to see a list of available commands. - -$ help -help - -size: - Usage: size - Description: Find the Size of the SD Card and Free Space - - -format: - Usage: format - Description: Format the Card - - -mount: - Usage: mount - Description: Manually Mount Card - - -ls: - Usage: ls - Description: list the contents of the current directory - - -mkdir: - Usage: mkdir - Description: Create a directory - - -file_create: - Usage: file_create - Description: Create a file of random data - - -cd: - Usage: cd - Description: Move into a directory - - -add_data: - Usage: add_data - Description: Add random Data to an Existing File - - -del: - Usage: del - Description: Delete a file - - -fatfs: - Usage: fatfs - Description: Format Card and Run Example of FatFS Operations - - -unmount: - Usage: unmount - Description: Unmount card - - -$ format -format - - -*****THE DRIVE WILL BE FORMATTED IN 5 SECONDS***** -**************PRESS ANY KEY TO ABORT************** - -FORMATTING DRIVE -Drive formatted. -SD card mounted. -SD card unmounted. - -$ size -size -SD card mounted. -Disk Size: 31162880 bytes -Available: 31162848 bytes - -$ mount -mount -SD card mounted. - -$ mkdir Analog_devices -mkdir Analog_devices -Creating directory... -Directory Analog_devices created. - -$ cd Analog_Devices -cd Analog_Devices -Changed to Analog_Devices - -$ file_create ADI 30 -file_create ADI 30 -Creating file ADI with length 30 -File opened! -30 bytes written to file! -File Closed! - -$ add_data ADI 30 -add_data ADI 30 -File opened! -30 bytes written to file -File closed. - -$ ls -ls -Listing Contents of /Analog_devices - -/Analog_devices/ADI - -Finished listing contents - -$ del ADI -del ADI -Deleted file ADI - -$ fatfs -fatfs - - -*****THE DRIVE WILL BE FORMATTED IN 5 SECONDS***** -**************PRESS ANY KEY TO ABORT************** - -FORMATTING DRIVE -Drive formatted. -SD card mounted. -SD card unmounted. -SD card mounted. -SD Card Opened! -File opened! -256 bytes written to file! -File Closed! -Creating Directory... -Renaming File... -Attempting to read back file... -Read Back 256 bytes -Message: dwfl-owoXGcTZ,5z,Sy8lfsNqDGrzio'O6vntRMoWODcIKP!C'y7tF.'W88ZjR81BpiibPhokQfa3w'cvmnr0EgE1MNDIhXKfBJGP6b?0tvHEPK-WNc7yuPdFNL6FPq10',Q,GSf3jSyY?MU0wv'FToTI!ct.E6Q4nbVuavg6h'48D5sR5mcepxf1l!MesddI7aZ9s?KIVnybRwZ.UBJpX1b?5oXP9wLKZcgW-k,gZ5HMIMwAcy!n9S?E57m0zvI -File Closed! - -$ unmount -unmount -SD card unmounted. - -$ +SD clock ratio (at card) 4:1 + +Choose one of the following options: +0. Find the Size of the SD Card and Free Space +1. Format the Card +2. Manually Mount Card +3. List Contents of Current Directory +4. Create a Directory +5. Move into a Directory (cd) +6. Create a File of Random Data +7. Add Random Data to an Existing File +8. Delete a File +9. Format Card and Run Exmaple of FatFS Operations +10. Unmount Card and Quit ``` diff --git a/Examples/MAX32650/SDHC_FAT/include/sdhc_example.h b/Examples/MAX32650/SDHC_FAT/include/sdhc_example.h deleted file mode 100644 index 60c85214c6..0000000000 --- a/Examples/MAX32650/SDHC_FAT/include/sdhc_example.h +++ /dev/null @@ -1,65 +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_MAX32650_SDHC_FAT_INCLUDE_SDHC_EXAMPLE_H_ -#define EXAMPLES_MAX32650_SDHC_FAT_INCLUDE_SDHC_EXAMPLE_H_ - -int sdhc_init(void); - -void generateMessage(unsigned length); - -int mount(); - -int umount(); - -int formatSDHC(); - -int getSize(); - -int ls(); - -int createFile(char *file_name, unsigned int length); - -int appendFile(char *file_name, unsigned int length); - -int mkdir(char *dir_name); - -int cd(char *dir_name); - -int deleteFile(char *file_name); - -int example(); - -void waitCardInserted(); - -#endif // EXAMPLES_MAX32650_SDHC_FAT_INCLUDE_SDHC_EXAMPLE_H_ diff --git a/Examples/MAX32650/SDHC_FAT/include/user-cli.h b/Examples/MAX32650/SDHC_FAT/include/user-cli.h deleted file mode 100644 index f1f92d0350..0000000000 --- a/Examples/MAX32650/SDHC_FAT/include/user-cli.h +++ /dev/null @@ -1,68 +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_MAX32650_SDHC_FAT_INCLUDE_USER_CLI_H_ -#define EXAMPLES_MAX32650_SDHC_FAT_INCLUDE_USER_CLI_H_ - -/* -------------------------------------------------- */ -// GLOBAL VARIABLE -/* -------------------------------------------------- */ -extern const command_t user_commands[]; -extern const unsigned int num_user_commands; - -/* -------------------------------------------------- */ -// FUNCTION PROTOTYPES -/* -------------------------------------------------- */ -int handle_size(int argc, char *argv[]); - -int handle_format(int argc, char *argv[]); - -int handle_mount(int argc, char *argv[]); - -int handle_ls(int argc, char *argv[]); - -int handle_mkdir(int argc, char *argv[]); - -int handle_createfile(int argc, char *argv[]); - -int handle_cd(int argc, char *argv[]); - -int handle_add_data(int argc, char *argv[]); - -int handle_del(int argc, char *argv[]); - -int handle_fatfs(int argc, char *argv[]); - -int handle_unmount(int argc, char *argv[]); - -#endif // EXAMPLES_MAX32650_SDHC_FAT_INCLUDE_USER_CLI_H_ diff --git a/Examples/MAX32650/SDHC_FAT/main.c b/Examples/MAX32650/SDHC_FAT/main.c index eeba6b66b4..4a3f418024 100644 --- a/Examples/MAX32650/SDHC_FAT/main.c +++ b/Examples/MAX32650/SDHC_FAT/main.c @@ -31,45 +31,577 @@ /***** Includes *****/ #include - -#include "board.h" -#include "cli.h" -#include "icc.h" +#include +#include +#include +#include "mxc_device.h" +#include "mxc_sys.h" +#include "mxc_delay.h" #include "mxc_errors.h" -#include "sdhc_example.h" +#include "sdhc_regs.h" +#include "led.h" +#include "tmr.h" #include "uart.h" -#include "user-cli.h" +#include "gpio.h" +#include "sdhc_lib.h" +#include "ff.h" /***** Definitions *****/ #define STRINGIFY(x) #x #define TOSTRING(x) STRINGIFY(x) -/***** Functions *****/ +#define MAXLEN 256 + +/***** Globals *****/ +FATFS *fs; //FFat Filesystem Object +FATFS fs_obj; +FIL file; //FFat File Object +FRESULT err; //FFat Result (Struct) +FILINFO fno; //FFat File Information Object +DIR dir; //FFat Directory Object +TCHAR message[MAXLEN], directory[MAXLEN], cwd[MAXLEN], filename[MAXLEN], volume_label[24], + volume = '0'; +TCHAR *FF_ERRORS[20]; +DWORD clusters_free = 0, sectors_free = 0, sectors_total = 0, volume_sn = 0; +UINT bytes_written = 0, bytes_read = 0, mounted = 0; +BYTE work[4096]; +static char charset[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789,.-#'?!"; +mxc_gpio_cfg_t SDPowerEnablePin = { MXC_GPIO3, MXC_GPIO_PIN_5, MXC_GPIO_FUNC_OUT, MXC_GPIO_PAD_NONE, + MXC_GPIO_VSSEL_VDDIO }; + +/***** FUNCTIONS *****/ + +void generateMessage(unsigned length) +{ + for (int i = 0; i < length; i++) { + /*Generate some random data to put in file*/ + message[i] = charset[rand() % (sizeof(charset) - 1)]; + } +} + +int mount() +{ + fs = &fs_obj; + if ((err = f_mount(fs, "", 1)) != FR_OK) { //Mount the default drive to fs now + printf("Error opening SD card: %s\n", FF_ERRORS[err]); + f_mount(NULL, "", 0); + } else { + printf("SD card mounted.\n"); + mounted = 1; + } + + f_getcwd(cwd, sizeof(cwd)); //Set the Current working directory + + return err; +} + +int umount() +{ + if ((err = f_mount(NULL, "", 0)) != FR_OK) { //Unmount the default drive from its mount point + printf("Error unmounting volume: %s\n", FF_ERRORS[err]); + } else { + printf("SD card unmounted.\n"); + mounted = 0; + } + + return err; +} + +int formatSDHC() +{ + printf("\n\n*****THE DRIVE WILL BE FORMATTED IN 5 SECONDS*****\n"); + printf("**************PRESS ANY KEY TO ABORT**************\n\n"); + MXC_UART_ClearRXFIFO(MXC_UART0); + MXC_TMR_Delay(MXC_TMR0, MXC_DELAY_MSEC(5000)); + if (MXC_UART_GetRXFIFOAvailable(MXC_UART0) > 0) { + return E_ABORT; + } + + printf("FORMATTING DRIVE\n"); + + MKFS_PARM format_options = { .fmt = FM_ANY }; + + if ((err = f_mkfs("", &format_options, work, sizeof(work))) != + FR_OK) { //Format the default drive to FAT32 + printf("Error formatting SD card: %s\n", FF_ERRORS[err]); + } else { + printf("Drive formatted.\n"); + } + + mount(); + + if ((err = f_setlabel("MAXIM")) != FR_OK) { + printf("Error setting drive label: %s\n", FF_ERRORS[err]); + f_mount(NULL, "", 0); + } + + umount(); + + return err; +} + +int getSize() +{ + if (!mounted) { + mount(); + } + + if ((err = f_getfree(&volume, &clusters_free, &fs)) != FR_OK) { + printf("Error finding free size of card: %s\n", FF_ERRORS[err]); + f_mount(NULL, "", 0); + } + + sectors_total = (fs->n_fatent - 2) * fs->csize; + sectors_free = clusters_free * fs->csize; + + printf("Disk Size: %u bytes\n", sectors_total / 2); + printf("Available: %u bytes\n", sectors_free / 2); + + return err; +} + +int ls() +{ + if (!mounted) { + mount(); + } + + printf("Listing Contents of %s - \n", cwd); + + if ((err = f_opendir(&dir, cwd)) == FR_OK) { + while (1) { + err = f_readdir(&dir, &fno); + if (err != FR_OK || fno.fname[0] == 0) + break; + + printf("%s/%s", cwd, fno.fname); + + if (fno.fattrib & AM_DIR) { + printf("/"); + } + + printf("\n"); + } + f_closedir(&dir); + } else { + printf("Error opening directory!\n"); + return err; + } + + printf("\nFinished listing contents\n"); + + return err; +} + +int createFile() +{ + unsigned int length = 128; + + if (!mounted) { + mount(); + } + + printf("Enter the name of the text file: \n"); + scanf("%255s", filename); + printf("Enter the length of the file: (256 max)\n"); + scanf("%d", &length); + printf("Creating file %s with length %d\n", filename, length); + + if ((err = f_open(&file, (const TCHAR *)filename, FA_CREATE_ALWAYS | FA_WRITE)) != FR_OK) { + printf("Error opening file: %s\n", FF_ERRORS[err]); + f_mount(NULL, "", 0); + return err; + } + printf("File opened!\n"); + + generateMessage(length); + + if ((err = f_write(&file, &message, length, &bytes_written)) != FR_OK) { + printf("Error writing file: %s\n", FF_ERRORS[err]); + f_mount(NULL, "", 0); + return err; + } + printf("%d bytes written to file!\n", bytes_written); + + if ((err = f_close(&file)) != FR_OK) { + printf("Error closing file: %s\n", FF_ERRORS[err]); + f_mount(NULL, "", 0); + return err; + } + printf("File Closed!\n"); + return err; +} + +int appendFile() +{ + unsigned int length = 0; + + if (!mounted) { + mount(); + } + + printf("Type name of file to append: \n"); + scanf("%255s", filename); + printf("Type length of random data to append: \n"); + scanf("%d", &length); + + if ((err = f_stat((const TCHAR *)filename, &fno)) == FR_NO_FILE) { + printf("File %s doesn't exist!\n", (const TCHAR *)filename); + return err; + } + if ((err = f_open(&file, (const TCHAR *)filename, FA_OPEN_APPEND | FA_WRITE)) != FR_OK) { + printf("Error opening file %s\n", FF_ERRORS[err]); + return err; + } + printf("File opened!\n"); + + generateMessage(length); + + if ((err = f_write(&file, &message, length, &bytes_written)) != FR_OK) { + printf("Error writing file: %s\n", FF_ERRORS[err]); + return err; + } + printf("%d bytes written to file\n", bytes_written); + + if ((err = f_close(&file)) != FR_OK) { + printf("Error closing file: %s\n", FF_ERRORS[err]); + return err; + } + printf("File closed.\n"); + return err; +} + +int mkdir() +{ + if (!mounted) { + mount(); + } + + printf("Enter directory name: \n"); + scanf("%255s", directory); + + err = f_stat((const TCHAR *)directory, &fno); + if (err == FR_NO_FILE) { + printf("Creating directory...\n"); + + if ((err = f_mkdir((const TCHAR *)directory)) != FR_OK) { + printf("Error creating directory: %s\n", FF_ERRORS[err]); + f_mount(NULL, "", 0); + return err; + } else { + printf("Directory %s created.\n", directory); + } + + } else { + printf("Directory already exists.\n"); + } + return err; +} + +int cd() +{ + if (!mounted) { + mount(); + } + + printf("Directory to change into: \n"); + scanf("%255s", directory); + + if ((err = f_stat((const TCHAR *)directory, &fno)) == FR_NO_FILE) { + printf("Directory doesn't exist (Did you mean mkdir?)\n"); + return err; + } + + if ((err = f_chdir((const TCHAR *)directory)) != FR_OK) { + printf("Error in chdir: %s\n", FF_ERRORS[err]); + f_mount(NULL, "", 0); + return err; + } + + printf("Changed to %s\n", directory); + f_getcwd(cwd, sizeof(cwd)); + + return err; +} + +int delete () +{ + if (!mounted) { + mount(); + } + + printf("File or directory to delete (always recursive!)\n"); + scanf("%255s", filename); + + if ((err = f_stat((const TCHAR *)filename, &fno)) == FR_NO_FILE) { + printf("File or directory doesn't exist\n"); + return err; + } + + if ((err = f_unlink(filename)) != FR_OK) { + printf("Error deleting file\n"); + return err; + } + printf("Deleted file %s\n", filename); + return err; +} + +int example() +{ + unsigned int length = 256; + + if ((err = formatSDHC()) != FR_OK) { + printf("Error Formatting SD Card: %s\n", FF_ERRORS[err]); + return err; + } + + //open SD Card + if ((err = mount()) != FR_OK) { + printf("Error opening SD Card: %s\n", FF_ERRORS[err]); + return err; + } + printf("SD Card Opened!\n"); + + if ((err = f_setlabel("MAXIM")) != FR_OK) { + printf("Error setting drive label: %s\n", FF_ERRORS[err]); + f_mount(NULL, "", 0); + return err; + } + + if ((err = f_getfree(&volume, &clusters_free, &fs)) != FR_OK) { + printf("Error finding free size of card: %s\n", FF_ERRORS[err]); + f_mount(NULL, "", 0); + return err; + } + + if ((err = f_getlabel(&volume, volume_label, &volume_sn)) != FR_OK) { + printf("Error reading drive label: %s\n", FF_ERRORS[err]); + f_mount(NULL, "", 0); + return err; + } + + if ((err = f_open(&file, "0:HelloWorld.txt", FA_CREATE_ALWAYS | FA_WRITE)) != FR_OK) { + printf("Error opening file: %s\n", FF_ERRORS[err]); + f_mount(NULL, "", 0); + return err; + } + printf("File opened!\n"); + + generateMessage(length); + + if ((err = f_write(&file, &message, length, &bytes_written)) != FR_OK) { + printf("Error writing file: %s\n", FF_ERRORS[err]); + f_mount(NULL, "", 0); + return err; + } + printf("%d bytes written to file!\n", bytes_written); + + if ((err = f_close(&file)) != FR_OK) { + printf("Error closing file: %s\n", FF_ERRORS[err]); + f_mount(NULL, "", 0); + return err; + } + printf("File Closed!\n"); + + if ((err = f_chmod("HelloWorld.txt", 0, AM_RDO | AM_ARC | AM_SYS | AM_HID)) != FR_OK) { + printf("Error in chmod: %s\n", FF_ERRORS[err]); + f_mount(NULL, "", 0); + return err; + } + + err = f_stat("MaximSDHC", &fno); + if (err == FR_NO_FILE) { + printf("Creating Directory...\n"); + if ((err = f_mkdir("MaximSDHC")) != FR_OK) { + printf("Error creating directory: %s\n", FF_ERRORS[err]); + f_mount(NULL, "", 0); + return err; + } + } + + printf("Renaming File...\n"); + if ((err = f_rename("0:HelloWorld.txt", "0:MaximSDHC/HelloMaxim.txt")) != + FR_OK) { //cr: clearify 0:file notation + printf("Error moving file: %s\n", FF_ERRORS[err]); + f_mount(NULL, "", 0); + return err; + } + + if ((err = f_chdir("/MaximSDHC")) != FR_OK) { + printf("Error in chdir: %s\n", FF_ERRORS[err]); + f_mount(NULL, "", 0); + return err; + } + + printf("Attempting to read back file...\n"); + if ((err = f_open(&file, "HelloMaxim.txt", FA_READ)) != FR_OK) { + printf("Error opening file: %s\n", FF_ERRORS[err]); + f_mount(NULL, "", 0); + return err; + } + + if ((err = f_read(&file, &message, bytes_written, &bytes_read)) != FR_OK) { + printf("Error reading file: %s\n", FF_ERRORS[err]); + f_mount(NULL, "", 0); + return err; + } + + printf("Read Back %d bytes\n", bytes_read); + printf("Message: "); + printf("%s", message); + printf("\n"); + + if ((err = f_close(&file)) != FR_OK) { + printf("Error closing file: %s\n", FF_ERRORS[err]); + f_mount(NULL, "", 0); + return err; + } + printf("File Closed!\n"); + + //unmount SD Card + //f_mount(fs, "", 0); + if ((err = f_mount(NULL, "", 0)) != FR_OK) { + printf("Error unmounting volume: %s\n", FF_ERRORS[err]); + return err; + } + + return 0; +} + +/******************************************************************************/ int main(void) { - int err; + mxc_sdhc_cfg_t cfg; + + FF_ERRORS[0] = "FR_OK"; + FF_ERRORS[1] = "FR_DISK_ERR"; + FF_ERRORS[2] = "FR_INT_ERR"; + FF_ERRORS[3] = "FR_NOT_READY"; + FF_ERRORS[4] = "FR_NO_FILE"; + FF_ERRORS[5] = "FR_NO_PATH"; + FF_ERRORS[6] = "FR_INVLAID_NAME"; + FF_ERRORS[7] = "FR_DENIED"; + FF_ERRORS[8] = "FR_EXIST"; + FF_ERRORS[9] = "FR_INVALID_OBJECT"; + FF_ERRORS[10] = "FR_WRITE_PROTECTED"; + FF_ERRORS[11] = "FR_INVALID_DRIVE"; + FF_ERRORS[12] = "FR_NOT_ENABLED"; + FF_ERRORS[13] = "FR_NO_FILESYSTEM"; + FF_ERRORS[14] = "FR_MKFS_ABORTED"; + FF_ERRORS[15] = "FR_TIMEOUT"; + FF_ERRORS[16] = "FR_LOCKED"; + FF_ERRORS[17] = "FR_NOT_ENOUGH_CORE"; + FF_ERRORS[18] = "FR_TOO_MANY_OPEN_FILES"; + FF_ERRORS[19] = "FR_INVALID_PARAMETER"; + srand(12347439); + int run = 1, input = -1; printf("\n\n***** " TOSTRING(TARGET) " SDHC FAT Filesystem Example *****\n"); - MXC_ICC_Disable(); + // Enable Power To Card + MXC_GPIO_Config(&SDPowerEnablePin); + MXC_GPIO_OutClr(MXC_GPIO1, SDPowerEnablePin.mask); - if (sdhc_init() != E_NO_ERROR) { - printf("Unable to initialize the SDHC card.\n"); - return E_BAD_STATE; + // Initialize SDHC peripheral + cfg.bus_voltage = MXC_SDHC_Bus_Voltage_3_3; + cfg.block_gap = 0; + cfg.clk_div = + 0x0b0; // Maximum divide ratio, frequency must be >= 400 kHz during Card Identification phase + if (MXC_SDHC_Init(&cfg) != E_NO_ERROR) { + printf("Unable to initialize SDHC driver.\n"); + return 1; } - printf("SDHC Ready!\n"); - while (MXC_UART_GetActive(MXC_UART_GET_UART(CONSOLE_UART))) {} + // wait for card to be inserted + while (!MXC_SDHC_Card_Inserted()) {} + printf("Card inserted.\n"); - // Initialize CLI - if ((err = MXC_CLI_Init(MXC_UART_GET_UART(CONSOLE_UART), user_commands, num_user_commands)) != - E_NO_ERROR) { - return err; + // set up card to get it ready for a transaction + if (MXC_SDHC_Lib_InitCard(10) == E_NO_ERROR) { + printf("Card Initialized.\n"); + } else { + printf("No card response! Remove card, reset EvKit, and try again.\n"); + + return -1; } - // Run CLI - while (1) {} + if (MXC_SDHC_Lib_Get_Card_Type() == CARD_SDHC) { + printf("Card type: SDHC\n"); + } else { + printf("Card type: MMC/eMMC\n"); + } + while (run) { + f_getcwd(cwd, sizeof(cwd)); + + printf("\nChoose one of the following options: \n"); + printf("0. Find the Size of the SD Card and Free Space\n"); + printf("1. Format the Card\n"); + printf("2. Manually Mount Card\n"); + printf("3. List Contents of Current Directory\n"); + printf("4. Create a Directory\n"); + printf("5. Move into a Directory (cd)\n"); + printf("6. Create a File of Random Data\n"); + printf("7. Add Random Data to an Existing File\n"); + printf("8. Delete a File\n"); + printf("9. Format Card and Run Exmaple of FatFS Operations\n"); + printf("10. Unmount Card and Quit\n"); + printf("%s>>", cwd); + + input = -1; + scanf("%d", &input); + printf("%d\n", input); + + err = 0; + + switch (input) { + case 0: + getSize(); + break; + case 1: + formatSDHC(); + break; + case 3: + ls(); + break; + case 6: + createFile(); + break; + case 7: + appendFile(); + break; + case 4: + mkdir(); + break; + case 5: + cd(); + break; + case 9: + example(); + break; + case 10: + umount(); + run = 0; + break; + case 2: + mount(); + break; + case 8: + delete (); + break; + default: + printf("Invalid Selection %d!\n", input); + err = -1; + break; + } + if (err >= 0 && err <= 20) { + printf("Function Returned with code: %d\n", FF_ERRORS[err]); + } else { + printf("Function Returned with code: %d\n", err); + } + MXC_TMR_Delay(MXC_TMR0, MXC_DELAY_MSEC(500)); + } + printf("End of example, please try to read the card.\n"); return 0; } diff --git a/Examples/MAX32650/SDHC_FAT/project.mk b/Examples/MAX32650/SDHC_FAT/project.mk index bc88bd6fd7..19e711ae24 100644 --- a/Examples/MAX32650/SDHC_FAT/project.mk +++ b/Examples/MAX32650/SDHC_FAT/project.mk @@ -22,6 +22,3 @@ SBT=0 LIB_SDHC=1 # Use FatFS R0.15 FATFS_VERSION = ff15 - -# Enable CLI Library -LIB_CLI=1 diff --git a/Examples/MAX32650/SDHC_FAT/src/sdhc_example.c b/Examples/MAX32650/SDHC_FAT/src/sdhc_example.c deleted file mode 100644 index 86fb7ad91e..0000000000 --- a/Examples/MAX32650/SDHC_FAT/src/sdhc_example.c +++ /dev/null @@ -1,537 +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 "board.h" -#include "ff.h" -#include "mxc_delay.h" -#include "mxc_device.h" -#include "sdhc.h" -#include "sdhc_example.h" -#include "sdhc_lib.h" -#include "uart.h" - -/***** Definitions *****/ -#define MAXLEN 256 - -/***** Global Variables *****/ -FATFS *fs; //FFat Filesystem Object -FATFS fs_obj; -FIL file; //FFat File Object -FRESULT err; //FFat Result (Struct) -FILINFO fno; //FFat File Information Object -DIR dir; //FFat Directory Object -TCHAR message[MAXLEN], directory[MAXLEN], cwd[MAXLEN], filename[MAXLEN], volume_label[24], - volume = '0'; -TCHAR *FF_ERRORS[20]; -DWORD clusters_free = 0, sectors_free = 0, sectors_total = 0, volume_sn = 0; -UINT bytes_written = 0, bytes_read = 0, mounted = 0; -BYTE work[4096]; -static char charset[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789,.-#'?!"; -mxc_gpio_cfg_t SDPowerEnablePin = { MXC_GPIO3, MXC_GPIO_PIN_5, MXC_GPIO_FUNC_OUT, MXC_GPIO_PAD_NONE, - MXC_GPIO_VSSEL_VDDIO }; - -// ****************************************************************************** -int sdhc_init(void) -{ - mxc_sdhc_cfg_t cfg; - - FF_ERRORS[0] = "FR_OK"; - FF_ERRORS[1] = "FR_DISK_ERR"; - FF_ERRORS[2] = "FR_INT_ERR"; - FF_ERRORS[3] = "FR_NOT_READY"; - FF_ERRORS[4] = "FR_NO_FILE"; - FF_ERRORS[5] = "FR_NO_PATH"; - FF_ERRORS[6] = "FR_INVLAID_NAME"; - FF_ERRORS[7] = "FR_DENIED"; - FF_ERRORS[8] = "FR_EXIST"; - FF_ERRORS[9] = "FR_INVALID_OBJECT"; - FF_ERRORS[10] = "FR_WRITE_PROTECTED"; - FF_ERRORS[11] = "FR_INVALID_DRIVE"; - FF_ERRORS[12] = "FR_NOT_ENABLED"; - FF_ERRORS[13] = "FR_NO_FILESYSTEM"; - FF_ERRORS[14] = "FR_MKFS_ABORTED"; - FF_ERRORS[15] = "FR_TIMEOUT"; - FF_ERRORS[16] = "FR_LOCKED"; - FF_ERRORS[17] = "FR_NOT_ENOUGH_CORE"; - FF_ERRORS[18] = "FR_TOO_MANY_OPEN_FILES"; - FF_ERRORS[19] = "FR_INVALID_PARAMETER"; - - // Enable Power To Card - MXC_GPIO_Config(&SDPowerEnablePin); - MXC_GPIO_OutClr(MXC_GPIO1, SDPowerEnablePin.mask); - - // Initialize SDHC peripheral - cfg.bus_voltage = MXC_SDHC_Bus_Voltage_3_3; - cfg.block_gap = 0; - cfg.clk_div = - 0x0b0; // Maximum divide ratio, frequency must be >= 400 kHz during Card Identification phase - if (MXC_SDHC_Init(&cfg) != E_NO_ERROR) { - printf("Unable to initialize SDHC driver.\n"); - return 1; - } - - // wait for card to be inserted - while (!MXC_SDHC_Card_Inserted()) {} - printf("Card inserted.\n"); - - // set up card to get it ready for a transaction - if (MXC_SDHC_Lib_InitCard(10) == E_NO_ERROR) { - printf("Card Initialized.\n"); - } else { - printf("No card response! Remove card, reset EvKit, and try again.\n"); - return -1; - } - - if (MXC_SDHC_Lib_Get_Card_Type() == CARD_SDHC) { - printf("Card type: SDHC\n"); - } else { - printf("Card type: MMC/eMMC\n"); - } - - return E_NO_ERROR; -} - -// ****************************************************************************** -void generateMessage(unsigned length) -{ - for (int i = 0; i < length; i++) { - /*Generate some random data to put in file*/ - message[i] = charset[rand() % (sizeof(charset) - 1)]; - } -} - -// ****************************************************************************** -int mount() -{ - fs = &fs_obj; - if ((err = f_mount(fs, "", 1)) != FR_OK) { //Mount the default drive to fs now - printf("Error opening SD card: %s\n", FF_ERRORS[err]); - f_mount(NULL, "", 0); - } else { - printf("SD card mounted.\n"); - mounted = 1; - } - - f_getcwd(cwd, sizeof(cwd)); //Set the Current working directory - - return err; -} - -// ****************************************************************************** -int umount() -{ - if ((err = f_mount(NULL, "", 0)) != FR_OK) { //Unmount the default drive from its mount point - printf("Error unmounting volume: %s\n", FF_ERRORS[err]); - } else { - printf("SD card unmounted.\n"); - mounted = 0; - } - - return err; -} - -// ****************************************************************************** -int formatSDHC() -{ - printf("\n\n*****THE DRIVE WILL BE FORMATTED IN 5 SECONDS*****\n"); - printf("**************PRESS ANY KEY TO ABORT**************\n\n"); - MXC_UART_ClearRXFIFO(MXC_UART_GET_UART(CONSOLE_UART)); - MXC_Delay(MXC_DELAY_SEC(5)); - if (MXC_UART_GetRXFIFOAvailable(MXC_UART_GET_UART(CONSOLE_UART)) > 0) { - return E_ABORT; - } - - printf("FORMATTING DRIVE\n"); - - MKFS_PARM format_options = { .fmt = FM_ANY }; - - if ((err = f_mkfs("", &format_options, work, sizeof(work))) != - FR_OK) { //Format the default drive to FAT32 - printf("Error formatting SD card: %s\n", FF_ERRORS[err]); - } else { - printf("Drive formatted.\n"); - } - - mount(); - - if ((err = f_setlabel("MAXIM")) != FR_OK) { - printf("Error setting drive label: %s\n", FF_ERRORS[err]); - f_mount(NULL, "", 0); - } - - umount(); - - return err; -} - -// ****************************************************************************** -int getSize() -{ - if (!mounted) { - mount(); - } - - if ((err = f_getfree(&volume, &clusters_free, &fs)) != FR_OK) { - printf("Error finding free size of card: %s\n", FF_ERRORS[err]); - f_mount(NULL, "", 0); - } - - sectors_total = (fs->n_fatent - 2) * fs->csize; - sectors_free = clusters_free * fs->csize; - - printf("Disk Size: %u bytes\n", sectors_total / 2); - printf("Available: %u bytes\n", sectors_free / 2); - - return err; -} - -// ****************************************************************************** -int ls() -{ - if (!mounted) { - mount(); - } - - printf("Listing Contents of %s - \n", cwd); - - if ((err = f_opendir(&dir, cwd)) == FR_OK) { - while (1) { - err = f_readdir(&dir, &fno); - if (err != FR_OK || fno.fname[0] == 0) - break; - - printf("%s/%s", cwd, fno.fname); - - if (fno.fattrib & AM_DIR) { - printf("/"); - } - - printf("\n"); - } - f_closedir(&dir); - } else { - printf("Error opening directory!\n"); - return err; - } - - printf("\nFinished listing contents\n"); - - return err; -} - -// ****************************************************************************** -int createFile(char *file_name, unsigned int length) -{ - if (!mounted) { - mount(); - } - - snprintf(filename, MAXLEN, "%s", file_name); - - if (length > MAXLEN) { - printf("Error. File size limit for this example is %d bytes.\n", MAXLEN); - return FR_INVALID_PARAMETER; - } - - printf("Creating file %s with length %d\n", filename, length); - - if ((err = f_open(&file, (const TCHAR *)filename, FA_CREATE_ALWAYS | FA_WRITE)) != FR_OK) { - printf("Error opening file: %s\n", FF_ERRORS[err]); - f_mount(NULL, "", 0); - return err; - } - printf("File opened!\n"); - - generateMessage(length); - - if ((err = f_write(&file, &message, length, &bytes_written)) != FR_OK) { - printf("Error writing file: %s\n", FF_ERRORS[err]); - f_mount(NULL, "", 0); - return err; - } - printf("%d bytes written to file!\n", bytes_written); - - if ((err = f_close(&file)) != FR_OK) { - printf("Error closing file: %s\n", FF_ERRORS[err]); - f_mount(NULL, "", 0); - return err; - } - printf("File Closed!\n"); - - return err; -} - -// ****************************************************************************** -int appendFile(char *file_name, unsigned int length) -{ - if (!mounted) { - mount(); - } - - snprintf(filename, MAXLEN, "%s", file_name); - - if ((err = f_stat((const TCHAR *)filename, &fno)) == FR_NO_FILE) { - printf("File %s doesn't exist!\n", (const TCHAR *)filename); - return err; - } - - if (length > MAXLEN) { - printf("Error. Size limit for this example is %d bytes.\n", MAXLEN); - return FR_INVALID_PARAMETER; - } - - if ((err = f_open(&file, (const TCHAR *)filename, FA_OPEN_APPEND | FA_WRITE)) != FR_OK) { - printf("Error opening file %s\n", FF_ERRORS[err]); - return err; - } - printf("File opened!\n"); - - generateMessage(length); - - if ((err = f_write(&file, &message, length, &bytes_written)) != FR_OK) { - printf("Error writing file: %s\n", FF_ERRORS[err]); - return err; - } - printf("%d bytes written to file\n", bytes_written); - - if ((err = f_close(&file)) != FR_OK) { - printf("Error closing file: %s\n", FF_ERRORS[err]); - return err; - } - printf("File closed.\n"); - - return err; -} - -// ****************************************************************************** -int mkdir(char *dir_name) -{ - if (!mounted) { - mount(); - } - - snprintf(directory, MAXLEN, "%s", dir_name); - - err = f_stat((const TCHAR *)directory, &fno); - if (err == FR_NO_FILE) { - printf("Creating directory...\n"); - - if ((err = f_mkdir((const TCHAR *)directory)) != FR_OK) { - printf("Error creating directory: %s\n", FF_ERRORS[err]); - f_mount(NULL, "", 0); - return err; - } else { - printf("Directory %s created.\n", directory); - } - - } else { - printf("Directory already exists.\n"); - } - - return err; -} - -// ****************************************************************************** -int cd(char *dir_name) -{ - if (!mounted) { - mount(); - } - - snprintf(directory, MAXLEN, "%s", dir_name); - - if ((err = f_stat((const TCHAR *)directory, &fno)) == FR_NO_FILE) { - printf("Directory doesn't exist (Did you mean mkdir?)\n"); - return err; - } - - if ((err = f_chdir((const TCHAR *)directory)) != FR_OK) { - printf("Error in chdir: %s\n", FF_ERRORS[err]); - f_mount(NULL, "", 0); - return err; - } - - printf("Changed to %s\n", directory); - f_getcwd(cwd, sizeof(cwd)); - - return err; -} - -// ****************************************************************************** -int deleteFile(char *file_name) -{ - if (!mounted) { - mount(); - } - - snprintf(filename, MAXLEN, "%s", file_name); - - if ((err = f_stat((const TCHAR *)filename, &fno)) == FR_NO_FILE) { - printf("File or directory doesn't exist\n"); - return err; - } - - if ((err = f_unlink(filename)) != FR_OK) { - printf("Error deleting file\n"); - return err; - } - - printf("Deleted file %s\n", filename); - - return err; -} - -// ****************************************************************************** -int example() -{ - unsigned int length = 256; - - if ((err = formatSDHC()) != FR_OK) { - printf("Error Formatting SD Card: %s\n", FF_ERRORS[err]); - return err; - } - - //open SD Card - if ((err = mount()) != FR_OK) { - printf("Error opening SD Card: %s\n", FF_ERRORS[err]); - return err; - } - printf("SD Card Opened!\n"); - - if ((err = f_setlabel("MAXIM")) != FR_OK) { - printf("Error setting drive label: %s\n", FF_ERRORS[err]); - f_mount(NULL, "", 0); - return err; - } - - if ((err = f_getfree(&volume, &clusters_free, &fs)) != FR_OK) { - printf("Error finding free size of card: %s\n", FF_ERRORS[err]); - f_mount(NULL, "", 0); - return err; - } - - if ((err = f_getlabel(&volume, volume_label, &volume_sn)) != FR_OK) { - printf("Error reading drive label: %s\n", FF_ERRORS[err]); - f_mount(NULL, "", 0); - return err; - } - - if ((err = f_open(&file, "0:HelloWorld.txt", FA_CREATE_ALWAYS | FA_WRITE)) != FR_OK) { - printf("Error opening file: %s\n", FF_ERRORS[err]); - f_mount(NULL, "", 0); - return err; - } - printf("File opened!\n"); - - generateMessage(length); - - if ((err = f_write(&file, &message, length, &bytes_written)) != FR_OK) { - printf("Error writing file: %s\n", FF_ERRORS[err]); - f_mount(NULL, "", 0); - return err; - } - printf("%d bytes written to file!\n", bytes_written); - - if ((err = f_close(&file)) != FR_OK) { - printf("Error closing file: %s\n", FF_ERRORS[err]); - f_mount(NULL, "", 0); - return err; - } - printf("File Closed!\n"); - - if ((err = f_chmod("HelloWorld.txt", 0, AM_RDO | AM_ARC | AM_SYS | AM_HID)) != FR_OK) { - printf("Error in chmod: %s\n", FF_ERRORS[err]); - f_mount(NULL, "", 0); - return err; - } - - err = f_stat("MaximSDHC", &fno); - if (err == FR_NO_FILE) { - printf("Creating Directory...\n"); - if ((err = f_mkdir("MaximSDHC")) != FR_OK) { - printf("Error creating directory: %s\n", FF_ERRORS[err]); - f_mount(NULL, "", 0); - return err; - } - } - - printf("Renaming File...\n"); - if ((err = f_rename("0:HelloWorld.txt", "0:MaximSDHC/HelloMaxim.txt")) != - FR_OK) { //cr: clearify 0:file notation - printf("Error moving file: %s\n", FF_ERRORS[err]); - f_mount(NULL, "", 0); - return err; - } - - if ((err = f_chdir("/MaximSDHC")) != FR_OK) { - printf("Error in chdir: %s\n", FF_ERRORS[err]); - f_mount(NULL, "", 0); - return err; - } - - printf("Attempting to read back file...\n"); - if ((err = f_open(&file, "HelloMaxim.txt", FA_READ)) != FR_OK) { - printf("Error opening file: %s\n", FF_ERRORS[err]); - f_mount(NULL, "", 0); - return err; - } - - if ((err = f_read(&file, &message, bytes_written, &bytes_read)) != FR_OK) { - printf("Error reading file: %s\n", FF_ERRORS[err]); - f_mount(NULL, "", 0); - return err; - } - - printf("Read Back %d bytes\n", bytes_read); - printf("Message: "); - printf("%s", message); - printf("\n"); - - if ((err = f_close(&file)) != FR_OK) { - printf("Error closing file: %s\n", FF_ERRORS[err]); - f_mount(NULL, "", 0); - return err; - } - printf("File Closed!\n"); - - //unmount SD Card - //f_mount(fs, "", 0); - if ((err = f_mount(NULL, "", 0)) != FR_OK) { - printf("Error unmounting volume: %s\n", FF_ERRORS[err]); - return err; - } - - return 0; -} diff --git a/Examples/MAX32650/SDHC_FAT/src/user-cli.c b/Examples/MAX32650/SDHC_FAT/src/user-cli.c deleted file mode 100644 index 94138bbf89..0000000000 --- a/Examples/MAX32650/SDHC_FAT/src/user-cli.c +++ /dev/null @@ -1,181 +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 "cli.h" -#include "mxc_errors.h" -#include "sdhc_example.h" -#include "user-cli.h" - -const command_t user_commands[] = { - { "size", "size", "Find the Size of the SD Card and Free Space", handle_size }, - { "format", "format", "Format the Card", handle_format }, - { "mount", "mount", "Manually Mount Card", handle_mount }, - { "ls", "ls", "list the contents of the current directory", handle_ls }, - { "mkdir", "mkdir ", "Create a directory", handle_mkdir }, - { "file_create", "file_create ", - "Create a file of random data", handle_createfile }, - { "cd", "cd ", "Move into a directory", handle_cd }, - { "add_data", "add_data ", - "Add random Data to an Existing File", handle_add_data }, - { "del", "del ", "Delete a file", handle_del }, - { "fatfs", "fatfs", "Format Card and Run Example of FatFS Operations", handle_fatfs }, - { "unmount", "unmount", "Unmount card", handle_unmount }, -}; - -const unsigned int num_user_commands = sizeof(user_commands) / sizeof(command_t); - -// ****************************************************************************** -int handle_size(int argc, char *argv[]) -{ - if (argc != 1) { - printf("Incorrect usage. Too many parameters.\n"); - return E_INVALID; - } - - return getSize(); -} - -// ****************************************************************************** -int handle_format(int argc, char *argv[]) -{ - if (argc != 1) { - printf("Incorrect usage. Too many parameters.\n"); - return E_INVALID; - } - - return formatSDHC(); -} - -// ****************************************************************************** -int handle_mount(int argc, char *argv[]) -{ - if (argc != 1) { - printf("Incorrect usage. Too many parameters.\n"); - return E_INVALID; - } - - return mount(); -} - -// ****************************************************************************** -int handle_ls(int argc, char *argv[]) -{ - if (argc != 1) { - printf("Incorrect usage. Too many parameters.\n"); - return E_INVALID; - } - - return ls(); -} - -// ****************************************************************************** -int handle_mkdir(int argc, char *argv[]) -{ - if (argc != 2) { - printf("Incorrect usage. Please provide directory name.\n"); - return E_INVALID; - } - - return mkdir(argv[1]); -} - -// ****************************************************************************** -int handle_createfile(int argc, char *argv[]) -{ - if (argc != 3) { - printf("Incorrect usage. Please provide filename and length.\n"); - return E_INVALID; - } - - unsigned int length = atoi(argv[2]); - return createFile(argv[1], length); -} - -// ****************************************************************************** -int handle_cd(int argc, char *argv[]) -{ - if (argc != 2) { - printf("Incorrect usage. Please provide directory name.\n"); - return E_INVALID; - } - - return cd(argv[1]); -} - -// ****************************************************************************** -int handle_add_data(int argc, char *argv[]) -{ - if (argc != 3) { - printf("Incorrect usage. Please provide filename and length.\n"); - return E_INVALID; - } - - unsigned int length = atoi(argv[2]); - return appendFile(argv[1], length); -} - -// ****************************************************************************** -int handle_del(int argc, char *argv[]) -{ - if (argc != 2) { - printf("Incorrect usage. Please provide filename.\n"); - return E_INVALID; - } - - return deleteFile(argv[1]); -} - -// ****************************************************************************** -int handle_fatfs(int argc, char *argv[]) -{ - if (argc != 1) { - printf("Incorrect usage. Too many parameters.\n"); - return E_INVALID; - } - - return example(); -} - -// ****************************************************************************** -int handle_unmount(int argc, char *argv[]) -{ - if (argc != 1) { - printf("Incorrect usage. Too many parameters.\n"); - return E_INVALID; - } - - return umount(); -} diff --git a/Examples/MAX32670/Flash_CLI/CLI-commands.c b/Examples/MAX32670/Flash_CLI/CLI-commands.c new file mode 100644 index 0000000000..97a0494bdf --- /dev/null +++ b/Examples/MAX32670/Flash_CLI/CLI-commands.c @@ -0,0 +1,284 @@ +/* + FreeRTOS V8.2.1 - Copyright (C) 2015 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/* Modified by Maxim Integrated 26-Jun-2015 to quiet compiler warnings */ +#include +#include +#include + +/* FreeRTOS includes. */ +#include "FreeRTOS.h" +#include "task.h" + +/* FreeRTOS+CLI includes. */ +#include "FreeRTOS_CLI.h" +#include "definitions.h" + +#include "mxc_errors.h" + +static char *getParamString(const char *commandString, size_t paramNo) +{ + BaseType_t length; + const char *param = FreeRTOS_CLIGetParameter(commandString, paramNo, &length); + if (!param) + return NULL; + char *buff = (char *)pvPortMalloc(length + 1); + strncpy(buff, param, length); + buff[length] = 0; + return buff; +} + +static BaseType_t prvEraseCommand(char *pcWriteBuffer, size_t xWriteBufferLen, + const char *pcCommandString); + +/* Structure that defines the "echo_parameters" command line command. This +takes a variable number of parameters that the command simply echos back one at +a time. */ +static const CLI_Command_Definition_t xEraseCommand = { + "erase", "\r\nerase: \r\n Erases page in flash being operated on\r\n", + prvEraseCommand, /* The function to run. */ + 0 /* The user can enter any number of commands. */ +}; + +/*-----------------------------------------------------------*/ + +static BaseType_t prvWriteCommand(char *pcWriteBuffer, size_t xWriteBufferLen, + const char *pcCommandString); + +/* Structure that defines the "echo_parameters" command line command. This +takes a variable number of parameters that the command simply echos back one at +a time. */ +static const CLI_Command_Definition_t xWriteCommand = { + "write", + "\r\nwrite : \r\n Writes text string to flash starting at the 32-bit word " + "in the flash page\n specified by \"word offset\" (e.g. word offset=3 -> address offset=0xC,\n " + "word offset=4 -> address offset=0x10)\r\n", + prvWriteCommand, /* The function to run. */ + 2 /* The user can enter any number of commands. */ +}; + +/*-----------------------------------------------------------*/ + +static BaseType_t prvReadCommand(char *pcWriteBuffer, size_t xWriteBufferLen, + const char *pcCommandString); + +/* Structure that defines the "echo_parameters" command line command. This +takes a variable number of parameters that the command simply echos back one at +a time. */ +static const CLI_Command_Definition_t xReadCommand = { + "read", + "\r\nread : \r\n Reads text from flash starting at the 32-bit " + "word in the flash page\n specified by \"word offset\" (e.g. word offset=3 -> address " + "offset=0xC,\n word offset=4 -> address offset=0x10)\r\n", + prvReadCommand, /* The function to run. */ + 2 /* The user can enter any number of commands. */ +}; + +/*-----------------------------------------------------------*/ + +static BaseType_t prvCRCCommand(char *pcWriteBuffer, size_t xWriteBufferLen, + const char *pcCommandString); + +/* Structure that defines the "echo_parameters" command line command. This +takes a variable number of parameters that the command simply echos back one at +a time. */ +static const CLI_Command_Definition_t xCRCCommand = { + "crc", "\r\ncrc: \r\n Calculates CRC of entire flash page\r\n", + prvCRCCommand, /* The function to run. */ + 0 /* The user can enter any number of commands. */ +}; +/*-----------------------------------------------------------*/ + +void vRegisterCLICommands(void) +{ + /* Register all the command line commands defined immediately above. */ + FreeRTOS_CLIRegisterCommand(&xEraseCommand); + FreeRTOS_CLIRegisterCommand(&xWriteCommand); + FreeRTOS_CLIRegisterCommand(&xReadCommand); + FreeRTOS_CLIRegisterCommand(&xCRCCommand); +} +/*-----------------------------------------------------------*/ + +static BaseType_t prvEraseCommand(char *pcWriteBuffer, size_t xWriteBufferLen, + const char *pcCommandString) +{ + /* Remove compile time warnings about unused parameters, and check the + write buffer is not NULL. NOTE - for simplicity, this example assumes the + write buffer length is adequate, so does not check for buffer overflows. */ + (void)pcCommandString; + (void)xWriteBufferLen; + configASSERT(pcWriteBuffer); + if (!check_erased(FLASH_STORAGE_START_ADDR, MXC_FLASH_PAGE_SIZE)) { + portENTER_CRITICAL(); + int retval = MXC_FLC_PageErase(FLASH_STORAGE_START_ADDR); + portEXIT_CRITICAL(); + if (retval != E_NO_ERROR) { + memset(pcWriteBuffer, 0x00, xWriteBufferLen); + snprintf(pcWriteBuffer, xWriteBufferLen, "Erase failed with error %i\r\n", retval); + return pdFALSE; + } + } + memset(pcWriteBuffer, 0x00, xWriteBufferLen); + snprintf(pcWriteBuffer, xWriteBufferLen, "Success\r\n"); + return pdFALSE; +} +/*-----------------------------------------------------------*/ + +static BaseType_t prvWriteCommand(char *pcWriteBuffer, size_t xWriteBufferLen, + const char *pcCommandString) +{ + /* Remove compile time warnings about unused parameters, and check the + write buffer is not NULL. NOTE - for simplicity, this example assumes the + write buffer length is adequate, so does not check for buffer overflows. */ + (void)pcCommandString; + (void)xWriteBufferLen; + configASSERT(pcWriteBuffer); + + const char *pcParameterOffset, *pcParameterText; + + /* Obtain the parameter string. */ + pcParameterOffset = getParamString(pcCommandString, 1); + pcParameterText = getParamString(pcCommandString, 2); + + int offset = atoi(pcParameterOffset); + uint32_t *data = (uint32_t *)pvPortMalloc(strlen(pcParameterText) * 4); + for (int i = 0; i < strlen(pcParameterText); i++) { + data[i] = (uint32_t)pcParameterText[i]; + } + portENTER_CRITICAL(); + int retval = flash_write(FLASH_STORAGE_START_ADDR + offset * 4, strlen(pcParameterText), data); + portEXIT_CRITICAL(); + vPortFree(data); + if (retval != E_NO_ERROR) { + memset(pcWriteBuffer, 0x00, xWriteBufferLen); + snprintf(pcWriteBuffer, xWriteBufferLen, "Write failed with error %i\r\n", retval); + } else { + memset(pcWriteBuffer, 0x00, xWriteBufferLen); + snprintf(pcWriteBuffer, xWriteBufferLen, "Success\r\n"); + } + + return pdFALSE; +} +/*-----------------------------------------------------------*/ + +static BaseType_t prvReadCommand(char *pcWriteBuffer, size_t xWriteBufferLen, + const char *pcCommandString) +{ + /* Remove compile time warnings about unused parameters, and check the + write buffer is not NULL. NOTE - for simplicity, this example assumes the + write buffer length is adequate, so does not check for buffer overflows. */ + (void)pcCommandString; + (void)xWriteBufferLen; + configASSERT(pcWriteBuffer); + + const char *pcParameterOffset, *pcParameterLength; + + /* Obtain the parameter string. */ + pcParameterOffset = getParamString(pcCommandString, 1); + pcParameterLength = getParamString(pcCommandString, 2); + + int offset = atoi(pcParameterOffset); + int length = atoi(pcParameterLength); + uint8_t *data = (uint8_t *)pvPortMalloc(length); + + int retval = flash_read(FLASH_STORAGE_START_ADDR + offset * 4, length, data); + if (retval != E_NO_ERROR) { + memset(pcWriteBuffer, 0x00, xWriteBufferLen); + snprintf(pcWriteBuffer, xWriteBufferLen, "Read failed with error %i\r\n", retval); + } else { + memset(pcWriteBuffer, 0x00, xWriteBufferLen); + snprintf(pcWriteBuffer, xWriteBufferLen, "Success: \r\n"); + strncat(pcWriteBuffer, (char *)data, length); + strncat(pcWriteBuffer, "\r\n", 3); + } + vPortFree(data); + + return pdFALSE; +} +/*-----------------------------------------------------------*/ + +static BaseType_t prvCRCCommand(char *pcWriteBuffer, size_t xWriteBufferLen, + const char *pcCommandString) +{ + /* Remove compile time warnings about unused parameters, and check the + write buffer is not NULL. NOTE - for simplicity, this example assumes the + write buffer length is adequate, so does not check for buffer overflows. */ + (void)pcCommandString; + (void)xWriteBufferLen; + configASSERT(pcWriteBuffer); + + portENTER_CRITICAL(); + uint32_t crc = + calculate_crc((uint32_t *)FLASH_STORAGE_START_ADDR, MXC_FLASH_PAGE_SIZE / sizeof(uint32_t)); + portEXIT_CRITICAL(); + memset(pcWriteBuffer, 0x00, xWriteBufferLen); + snprintf(pcWriteBuffer, xWriteBufferLen, "CRC: 0x%08X\r\n", crc); + return pdFALSE; +} +/*-----------------------------------------------------------*/ diff --git a/Examples/MAX32670/Flash_CLI/FreeRTOSConfig.h b/Examples/MAX32670/Flash_CLI/FreeRTOSConfig.h new file mode 100644 index 0000000000..bccf098f36 --- /dev/null +++ b/Examples/MAX32670/Flash_CLI/FreeRTOSConfig.h @@ -0,0 +1,98 @@ +/****************************************************************************** + * + * Copyright (C) 2022-2023 Maxim Integrated Products, Inc. All Rights Reserved. + * (now owned by Analog Devices, Inc.), + * Copyright (C) 2023 Analog Devices, Inc. All Rights Reserved. This software + * is proprietary to Analog Devices, Inc. and its licensors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + +#ifndef EXAMPLES_MAX32670_FLASH_CLI_FREERTOSCONFIG_H_ +#define EXAMPLES_MAX32670_FLASH_CLI_FREERTOSCONFIG_H_ + +#include +#include "max32670.h" + +/*----------------------------------------------------------- + * Application specific definitions. + * + * These definitions should be adjusted for your particular hardware and + * application requirements. + * + * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE + * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. + * + * See http://www.freertos.org/a00110.html. + *----------------------------------------------------------*/ + +/* CMSIS keeps a global updated with current system clock in Hz */ +#define configCPU_CLOCK_HZ ((uint32_t)IPO_FREQ) + +// #define configUSE_TICKLESS_IDLE 1 + +#define configTICK_RATE_HZ ((portTickType)1000) +#define configRTC_TICK_RATE_HZ (32768) + +#define configTOTAL_HEAP_SIZE ((size_t)(26 * 1024)) + +#define configMINIMAL_STACK_SIZE ((uint16_t)128) + +#define configMAX_PRIORITIES 5 +#define configUSE_PREEMPTION 1 +#define configUSE_IDLE_HOOK 0 +#define configUSE_TICK_HOOK 0 +#define configUSE_CO_ROUTINES 0 +#define configUSE_16_BIT_TICKS 0 +#define configUSE_MUTEXES 1 + +/* Run time and task stats gathering related definitions. */ +#define configUSE_TRACE_FACILITY 1 +#define configUSE_STATS_FORMATTING_FUNCTIONS 1 + +/* Set the following definitions to 1 to include the API function, or zero +to exclude the API function. */ +#define INCLUDE_vTaskPrioritySet 0 +#define INCLUDE_vTaskDelete 0 +#define INCLUDE_vTaskSuspend 1 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_uxTaskPriorityGet 0 +#define INCLUDE_vTaskDelay 1 + +/* # of priority bits (configured in hardware) is provided by CMSIS */ +#define configPRIO_BITS __NVIC_PRIO_BITS + +/* Priority 7, or 255 as only the top three bits are implemented. This is the lowest priority. */ +#define configKERNEL_INTERRUPT_PRIORITY ((unsigned char)7 << (8 - configPRIO_BITS)) + +/* Priority 5, or 160 as only the top three bits are implemented. */ +#define configMAX_SYSCALL_INTERRUPT_PRIORITY ((unsigned char)5 << (8 - configPRIO_BITS)) + +/* Alias the default handler names to match CMSIS weak symbols */ +#define vPortSVCHandler SVC_Handler +#define xPortPendSVHandler PendSV_Handler +#define xPortSysTickHandler SysTick_Handler + +#ifdef configUSE_TICKLESS_IDLE +/* Provide routines for tickless idle pre- and post- processing */ +void vPreSleepProcessing(uint32_t *); +void vPostSleepProcessing(uint32_t); +#define configPRE_SLEEP_PROCESSING(idletime) vPreSleepProcessing(&idletime); +#define configPOST_SLEEP_PROCESSING(idletime) vPostSleepProcessing(idletime); +#endif + +/* FreeRTOS+CLI requires this size to be defined, but we do not use it */ +#define configCOMMAND_INT_MAX_OUTPUT_SIZE 1 + +#endif // EXAMPLES_MAX32670_FLASH_CLI_FREERTOSCONFIG_H_ diff --git a/Examples/MAX32670/Flash_CLI/README.md b/Examples/MAX32670/Flash_CLI/README.md index 1ac0efa8bf..9ede6b8923 100644 --- a/Examples/MAX32670/Flash_CLI/README.md +++ b/Examples/MAX32670/Flash_CLI/README.md @@ -1,6 +1,6 @@ ## Description -This example demonstates various features of the Flash Controller (page erase and write), and how to use the CRC to compute a CRC value. In the terminal window, type the command that you wish to execute. The available commands are "write" (writes a text string to flash), "read" (reads text from flash), "erase" (erases the flash page being operated on) and "crc" (computes the CRC value of the entire flash page.) For more details on how to input these commands, enter "help" in the terminal window. +This example demonstates the CLI commands feature of FreeRTOS, various features of the Flash Controller (page erase and write), and how to use the CRC to compute a CRC value. In the terminal window, type the command that you wish to execute. The available commands are "write" (writes a text string to flash), "read" (reads text from flash), "erase" (erases the flash page being operated on) and "crc" (computes the CRC value of the entire flash page.) For more details on how to input these commands, enter "help" in the terminal window. *** NOTE ***: Attempting to overwrite flash will return error. If you want to overwrite an address you must first erase. @@ -18,12 +18,16 @@ Universal instructions on building, flashing, and debugging this project can be ## Setup ### Required Connections - +If using the Standard EV Kit (EvKit\_V1): - Connect a USB cable between the PC and the CN1 (USB/PWR) connector. -- Select RX0 and TX0 on Headers JP1 and JP3 (UART 0). +- Connect pins JP4(RX_SEL) and JP5(TX_SEL) to RX0 and TX0 header. - Open an terminal application on the PC and connect to the EV kit's console UART at 115200, 8-N-1. -- Close jumper JP1 (LED1 EN). -- Close jumper JP2 (LED2 EN). +- Close jumper JP2 (LED0 EN). +- Close jumper JP3 (LED1 EN). + +If using the Featherboard (FTHR\_Apps\_P1): +- Connect a USB cable between the PC and the J4 (USB/PWR) connector. +- Open an terminal application on the PC and connect to the board's console UART at 115200, 8-N-1. ## Expected Output @@ -32,71 +36,72 @@ The Console UART of the device will output these messages: ``` *************** Flash Control CLI Example *************** -This example demonstrates various features of the Flash Controller -(page erase and write), and how to use the CRC to compute the -CRC value of an array. Enter commands in the terminal window. +This example demonstrates the CLI commands feature of FreeRTOS, various features +of the Flash Controller (page erase and write), and how to use the CRC to +compute the CRC value of an array. Enter commands in the terminal window. -CLI Initialized! Enter 'help' to see a list of available commands. +Starting FreeRTOS scheduler. -$ help +Enter 'help' to view a list of available commands. +cmd> help help -write: - Usage: write - Description: Writes text string to flash starting at the 32-bit word in the - flash page specified by "word offset" (e.g. word offset=3 -> address - offset=0xC, word offset=4 -> address offset=0x10) +help: + Lists all the registered commands + erase: - Usage: erase - Description: Erases page in flash being operated on + Erases page in flash being operated on + +write : + Writes text string to flash starting at the 32-bit word in the flash page + specified by "word offset" (e.g. word offset=3 -> address offset=0xC, + word offset=4 -> address offset=0x10) -read: - Usage: read - Description: Reads text from flash starting at the 32-bit word in the flash - page specified by "word offset" (e.g. word offset=3 -> address offset=0xC, - word offset=4 -> address offset=0x10) +read : + Reads text from flash starting at the 32-bit word in the flash page + specified by "word offset" (e.g. word offset=3 -> address offset=0xC, + word offset=4 -> address offset=0x10) crc: - Usage: crc - Description: Calculates CRC of entire flash page + Calculates CRC of entire flash page -$ erase +cmd> erase erase Success -$ crc +cmd> crc crc CRC: 0x4BD6CBCA -$ write 23 DEADBEEF +cmd> write 23 DEADBEEF write 23 DEADBEEF -Write addr 0x1005E05C: D -Write addr 0x1005E060: E -Write addr 0x1005E064: A -Write addr 0x1005E068: D -Write addr 0x1005E06C: B -Write addr 0x1005E070: E -Write addr 0x1005E074: E -Write addr 0x1005E078: F +Write addr 0x1007E05C: D +Write addr 0x1007E060: E +Write addr 0x1007E064: A +Write addr 0x1007E068: D +Write addr 0x1007E06C: B +Write addr 0x1007E070: E +Write addr 0x1007E074: E +Write addr 0x1007E078: F Success -$ crc +cmd> crc crc CRC: 0xA61BF020 -$ read 23 8 +cmd> read 23 8 read 23 8 -Read addr 0x1005E05C: D -Read addr 0x1005E060: E -Read addr 0x1005E064: A -Read addr 0x1005E068: D -Read addr 0x1005E06C: B -Read addr 0x1005E070: E -Read addr 0x1005E074: E -Read addr 0x1005E078: F +Read addr 0x1007E05C: D +Read addr 0x1007E060: E +Read addr 0x1007E064: A +Read addr 0x1007E068: D +Read addr 0x1007E06C: B +Read addr 0x1007E070: E +Read addr 0x1007E074: E +Read addr 0x1007E078: F Success: DEADBEEF -$ +cmd> ``` \ No newline at end of file diff --git a/Examples/MAX32670/Flash_CLI/definitions.h b/Examples/MAX32670/Flash_CLI/definitions.h index 48ae104a5e..0b14749b39 100644 --- a/Examples/MAX32670/Flash_CLI/definitions.h +++ b/Examples/MAX32670/Flash_CLI/definitions.h @@ -22,53 +22,24 @@ #ifndef EXAMPLES_MAX32670_FLASH_CLI_DEFINITIONS_H_ #define EXAMPLES_MAX32670_FLASH_CLI_DEFINITIONS_H_ -/***** Definitions *****/ -// Internal storage flash memory page (the last page) -#define FLASH_STORAGE_PAGE_NO (MXC_FLASH_MEM_SIZE / MXC_FLASH_PAGE_SIZE - 1) +#include "flc.h" -// Internal storage start address -#define FLASH_STORAGE_START_ADDR MXC_FLASH_PAGE_ADDR(FLASH_STORAGE_PAGE_NO) +#define VERBOSE_LOGGING -#define POLY 0xEDB88320 // CRC Polynomial +#ifdef VERBOSE_LOGGING +#define LOGV(...) printf(__VA_ARGS__) +#else +#define LOGV(...) +#endif -// CLI command table -// clang-format off -#define CMD_TABLE { { "write", \ - "write ", \ - "Writes text string to flash starting at the 32-bit word in the\n" \ - " flash page specified by \"word offset\" (e.g. word offset=3 -> address\n" \ - " offset=0xC, word offset=4 -> address offset=0x10)", \ - handle_write }, \ - { "erase", \ - "erase", \ - "Erases page in flash being operated on", \ - handle_erase }, \ - { "read", \ - "read ", \ - "Reads text from flash starting at the 32-bit word in the flash\n" \ - " page specified by \"word offset\" (e.g. word offset=3 -> address offset=0xC,\n" \ - " word offset=4 -> address offset=0x10)", \ - handle_read }, \ - { "crc", \ - "crc", \ - "Calculates CRC of entire flash page", \ - handle_crc } } -// clang-format on +#define FLASH_STORAGE_PAGE_NO \ + (MXC_FLASH_MEM_SIZE / MXC_FLASH_PAGE_SIZE - \ + 1) ///< Internal storage flash memory page (the last page) +#define FLASH_STORAGE_START_ADDR \ + MXC_FLASH_PAGE_ADDR(FLASH_STORAGE_PAGE_NO) ///< Internal storage start address -#define WORD_OFFSET_POS 1 -#define DATA_POS 2 -#define LENGTH_POS 2 - -/***** Function Prototypes *****/ -// Command handler functions -int handle_write(int argc, char *argv[]); -int handle_read(int argc, char *argv[]); -int handle_erase(int argc, char *argv[]); -int handle_crc(int argc, char *argv[]); - -// Command helper functions -int flash_verify(uint32_t address, uint32_t length, uint32_t *data); -int check_mem(uint32_t startaddr, uint32_t length, uint32_t data); +int flash_write(uint32_t startaddr, uint32_t length, uint32_t *data); +int flash_read(uint32_t startaddr, uint32_t length, uint8_t *data); int check_erased(uint32_t startaddr, uint32_t length); - +uint32_t calculate_crc(uint32_t *array, uint32_t length); #endif // EXAMPLES_MAX32670_FLASH_CLI_DEFINITIONS_H_ diff --git a/Examples/MAX32670/Flash_CLI/main.c b/Examples/MAX32670/Flash_CLI/main.c index 993d78e71a..7b5c79be7e 100644 --- a/Examples/MAX32670/Flash_CLI/main.c +++ b/Examples/MAX32670/Flash_CLI/main.c @@ -29,232 +29,332 @@ /***** Includes *****/ #include #include -#include #include +#include +#include "FreeRTOS.h" +#include "FreeRTOS_CLI.h" #include "board.h" -#include "cli.h" #include "crc.h" #include "definitions.h" -#include "ecc_regs.h" +#include "dma.h" #include "flc.h" +#include "gcr_regs.h" #include "icc.h" +#include "mxc_assert.h" +#include "mxc_delay.h" +#include "mxc_device.h" +#include "nvic_table.h" +#include "semphr.h" +#include "task.h" #include "uart.h" +#include "ecc_regs.h" -/***** Functions *****/ -int main(void) -{ - printf("\n\n*************** Flash Control CLI Example ***************\n"); - printf("\nThis example demonstrates various features of the Flash Controller"); - printf("\n(page erase and write), and how to use the CRC to compute the"); - printf("\nCRC value of an array. Enter commands in the terminal window.\n\n"); +/* FreeRTOS+CLI */ +void vRegisterCLICommands(void); - while (MXC_UART_GetActive(MXC_UART_GET_UART(CONSOLE_UART))) {} +/* Task IDs */ +TaskHandle_t cmd_task_id; - MXC_ECC->en = 0; // Disable ECC on Flash, ICC, and SRAM +/* Stringification macros */ +#define STRING(x) STRING_(x) +#define STRING_(x) #x - // Set up CLI command table - const command_t cmd_table[] = CMD_TABLE; - const unsigned int cmd_table_sz = sizeof(cmd_table) / sizeof(command_t); +/* Console ISR selection */ +#if (CONSOLE_UART == 0) +#define UARTx_IRQHandler UART0_IRQHandler +#define UARTx_IRQn UART0_IRQn - // Initialize CLI - if (MXC_CLI_Init(MXC_UART_GET_UART(CONSOLE_UART), cmd_table, cmd_table_sz) != E_NO_ERROR) { - printf("Failed to initialize command-line interface.\n"); - return E_BAD_STATE; - } +#elif (CONSOLE_UART == 1) +#define UARTx_IRQHandler UART1_IRQHandler +#define UARTx_IRQn UART1_IRQn +#else +#error "Please update ISR macro for UART CONSOLE_UART" +#endif +mxc_uart_regs_t *ConsoleUART = MXC_UART_GET_UART(CONSOLE_UART); - // Run CLI - while (1) {} +/* Array sizes */ +#define CMD_LINE_BUF_SIZE 80 +#define OUTPUT_BUF_SIZE 512 +#define POLY 0xEDB88320 + +/***** Functions *****/ + +/* =| UART0_IRQHandler |====================================== + * + * This function overrides the weakly-declared interrupt handler + * in system_max326xx.c and is needed for asynchronous UART + * calls to work properly + * + * =========================================================== + */ +void UARTx_IRQHandler(void) +{ + MXC_UART_AsyncHandler(ConsoleUART); } -// ***************************************************************************** -// ********************* Command Handler Functions ***************************** -// ***************************************************************************** -int handle_write(int argc, char *argv[]) +/* =| vCmdLineTask_cb |====================================== + * + * Callback on asynchronous reads to wake the waiting command + * processor task + * + * =========================================================== + */ +void vCmdLineTask_cb(mxc_uart_req_t *req, int error) { - int err, i = 0; - uint32_t data[MXC_FLASH_PAGE_SIZE / 4]; + BaseType_t xHigherPriorityTaskWoken; - // Check for an invalid command - if (argc != 3 || argv == NULL) { - printf("Invalid command format. Aborting flash write.\n"); - return E_BAD_PARAM; + /* Wake the task */ + xHigherPriorityTaskWoken = pdFALSE; + vTaskNotifyGiveFromISR(cmd_task_id, &xHigherPriorityTaskWoken); + portYIELD_FROM_ISR(xHigherPriorityTaskWoken); +} + +/* =| vCmdLineTask |====================================== + * + * The command line task provides a prompt on the serial + * interface and takes input from the user to evaluate + * via the FreeRTOS+CLI parser. + * + * NOTE: FreeRTOS+CLI is part of FreeRTOS+ and has + * different licensing requirements. Please see + * http://www.freertos.org/FreeRTOS-Plus for more information + * + * ======================================================= + */ +void vCmdLineTask(void *pvParameters) +{ + unsigned char tmp; + unsigned int index; /* Index into buffer */ + unsigned int x; + int uartReadLen; + char buffer[CMD_LINE_BUF_SIZE]; /* Buffer for input */ + char output[OUTPUT_BUF_SIZE]; /* Buffer for output */ + BaseType_t xMore; + mxc_uart_req_t async_read_req; + + memset(buffer, 0, CMD_LINE_BUF_SIZE); + index = 0; + + /* Register available CLI commands */ + vRegisterCLICommands(); + + /* Enable UARTx interrupt */ + NVIC_ClearPendingIRQ(UARTx_IRQn); + NVIC_DisableIRQ(UARTx_IRQn); + NVIC_SetPriority(UARTx_IRQn, 1); + NVIC_EnableIRQ(UARTx_IRQn); + + /* Async read will be used to wake process */ + async_read_req.uart = ConsoleUART; + async_read_req.rxData = &tmp; + async_read_req.rxLen = 1; + async_read_req.txData = NULL; + async_read_req.txLen = 0; + async_read_req.callback = vCmdLineTask_cb; + + printf("\nEnter 'help' to view a list of available commands.\n"); + printf("cmd> "); + fflush(stdout); + + while (1) { + while (MXC_UART_ReadyForSleep(ConsoleUART)) {} + + /* Register async read request */ + if (MXC_UART_TransactionAsync(&async_read_req) != E_NO_ERROR) { + printf("Error registering async request. Command line unavailable.\n"); + vTaskDelay(portMAX_DELAY); + } + /* Hang here until ISR wakes us for a character */ + ulTaskNotifyTake(pdTRUE, portMAX_DELAY); + + /* Check that we have a valid character */ + if (async_read_req.rxCnt > 0) { + /* Process character */ + do { + if (tmp == 0x08) { + /* Backspace */ + if (index > 0) { + index--; + printf("\x08 \x08"); + } + fflush(stdout); + } else if (tmp == 0x03) { + /* ^C abort */ + index = 0; + printf("^C"); + printf("\ncmd> "); + fflush(stdout); + } else if ((tmp == '\r') || (tmp == '\n')) { + printf("\r\n"); + /* Null terminate for safety */ + buffer[index] = 0x00; + /* Evaluate */ + do { + xMore = FreeRTOS_CLIProcessCommand(buffer, output, OUTPUT_BUF_SIZE); + /* If xMore == pdTRUE, then output buffer contains no null + * termination, so we know it is OUTPUT_BUF_SIZE. If pdFALSE, we can + * use strlen. + */ + for (x = 0; x < (xMore == pdTRUE ? OUTPUT_BUF_SIZE : strlen(output)); x++) { + putchar(*(output + x)); + } + } while (xMore != pdFALSE); + /* New prompt */ + index = 0; + printf("\ncmd> "); + fflush(stdout); + } else if (index < CMD_LINE_BUF_SIZE) { + putchar(tmp); + buffer[index++] = tmp; + fflush(stdout); + } else { + /* Throw away data and beep terminal */ + putchar(0x07); + fflush(stdout); + } + uartReadLen = 1; + /* If more characters are ready, process them here */ + + if (ConsoleUART->status & MXC_F_UART_STATUS_RX_EM) { // Prevent dropping characters + MXC_Delay(500); + } + } while ((MXC_UART_GetRXFIFOAvailable(MXC_UART_GET_UART(CONSOLE_UART)) > 0) && + (MXC_UART_Read(ConsoleUART, (uint8_t *)&tmp, &uartReadLen) == 0)); + } } +} - // Get command-line arguments - int startaddr = FLASH_STORAGE_START_ADDR + atoi(argv[WORD_OFFSET_POS]) * 4; - char *text = argv[DATA_POS]; +//****************************************************************************** +int flash_verify(uint32_t address, uint32_t length, uint32_t *data) +{ + volatile uint32_t *ptr; - // Convert character string to uint32_t since we must write flash in 32-bit words - for (int i = 0; i < strlen(text); i++) { - data[i] = (uint32_t)text[i]; + for (ptr = (uint32_t *)address; ptr < (uint32_t *)(address + length); ptr++, data++) { + if (*ptr != *data) { + printf("Verify failed at 0x%x (0x%x != 0x%x)\n", (unsigned int)ptr, (unsigned int)*ptr, + (unsigned int)*data); + return E_UNKNOWN; + } } + return E_NO_ERROR; +} + +//****************************************************************************** +int flash_write(uint32_t startaddr, uint32_t length, uint32_t *data) +{ + int i = 0; + // Check if flash controller is busy if (MXC_FLC0->ctrl & MXC_F_FLC_CTRL_PEND) { return E_BUSY; } - // Check whether the flash we are attempting to write has already been written to - if (!check_erased(startaddr, strlen(text))) { + if (!check_erased(startaddr, length)) { return E_INVALID; } MXC_ICC_Disable(); - // Write each character to flash - for (uint32_t testaddr = startaddr; i < strlen(text); testaddr += 4, i++) { + for (uint32_t testaddr = startaddr; i < length; testaddr += 4) { // Write a word - err = MXC_FLC_Write(testaddr, 4, &data[i]); - if (err != E_NO_ERROR) { - printf("Failure in writing a word : error %i addr: 0x%08x\n", err, testaddr); - return err; + int error_status = MXC_FLC_Write(testaddr, 4, &data[i]); + LOGV("Write addr 0x%08X: %c\r\n", testaddr, data[i]); + if (error_status != E_NO_ERROR) { + printf("Failure in writing a word : error %i addr: 0x%08x\n", error_status, testaddr); + return error_status; } - - printf("Write addr 0x%08X: %c\r\n", testaddr, data[i]); + i++; } MXC_ICC_Enable(); - // Verify the flash write was successful - err = flash_verify(startaddr, strlen(text), data); - if (err != E_NO_ERROR) { - printf("Write failed with error %i\n", err); - } else { - printf("Success\n"); - } - - return E_NO_ERROR; + return flash_verify(startaddr, length, data); } // ***************************************************************************** -int handle_read(int argc, char *argv[]) +int flash_read(uint32_t startaddr, uint32_t length, uint8_t *data) { - uint32_t addr; - uint8_t data[MXC_FLASH_PAGE_SIZE / 4]; - - // Check for an invalid command - if (argc != 3 || argv == NULL) { - printf("Invalid command format. Aborting flash read.\n"); - return E_BAD_PARAM; - } - - // Get command-line arguments - int startaddr = FLASH_STORAGE_START_ADDR + atoi(argv[WORD_OFFSET_POS]) * 4; - int length = atoi(argv[LENGTH_POS]); - - // Initialize data buffer - memset(data, 0x0, sizeof(data)); - - // Read requested characters from flash for (int i = 0; i < length; i++) { - addr = startaddr + i * 4; + uint32_t addr = startaddr + i * 4; data[i] = *(uint32_t *)addr; - if (data[i] == 0xFF) { - printf("Read addr 0x%08X: %s\n", addr, "empty"); + LOGV("Read addr 0x%08X: %s\r\n", addr, "empty"); } else { - printf("Read addr 0x%08X: %c\n", addr, data[i]); + LOGV("Read addr 0x%08X: %c\r\n", addr, data[i]); } } - - printf("Success:\n"); - printf("%s\n", (char *)data); - return E_NO_ERROR; } // ***************************************************************************** -int handle_erase(int argc, char *argv[]) +int check_mem(uint32_t startaddr, uint32_t length, uint32_t data) { - int err = E_NO_ERROR; - - // Check for an invalid command - if (argc != 1 || argv == NULL) { - printf("Invalid command format. Aborting flash erase.\n"); - return E_BAD_PARAM; - } + uint32_t *ptr; - // Check whether the flash page is already erased - if (!check_erased(FLASH_STORAGE_START_ADDR, MXC_FLASH_PAGE_SIZE)) { - // Erase flash page if it's not already erased - if ((err = MXC_FLC_PageErase(FLASH_STORAGE_START_ADDR)) != E_NO_ERROR) { - printf("Failed to erase flash page.\n"); - return err; + for (ptr = (uint32_t *)startaddr; ptr < (uint32_t *)(startaddr + length); ptr++) { + if (*ptr != data) { + return 0; } } + return 1; +} - printf("Success\n"); +//****************************************************************************** +int check_erased(uint32_t startaddr, uint32_t length) +{ + return check_mem(startaddr, length, 0xFFFFFFFF); +} - return err; +//****************************************************************************** +void flash_init(void) +{ + MXC_FLC_ClearFlags(0x3); } -// ***************************************************************************** -int handle_crc(int argc, char *argv[]) +//****************************************************************************** +uint32_t calculate_crc(uint32_t *array, uint32_t length) { int err; mxc_crc_req_t req; - // Check for an invalid command - if (argc != 1 || argv == NULL) { - printf("Invalid command format. Aborting CRC compute.\n"); - return E_BAD_PARAM; - } - - // Setup CRC request to calculate CRC value for the entire flash page - req.dataBuffer = (uint32_t *)FLASH_STORAGE_START_ADDR; - req.dataLen = MXC_FLASH_PAGE_SIZE / sizeof(uint32_t); + req.dataBuffer = array; + req.dataLen = length; - // Initialize CRC engine and compute CRC value MXC_CRC_Init(); MXC_CRC_SetPoly(POLY); if ((err = MXC_CRC_Compute(&req)) != E_NO_ERROR) { return err; } - // Print result - printf("CRC: 0x%08X\r\n", req.resultCRC); - - return E_NO_ERROR; + return req.resultCRC; } -// ***************************************************************************** -// ************************* Helper Functions ********************************** -// ***************************************************************************** -int flash_verify(uint32_t address, uint32_t length, uint32_t *data) +//****************************************************************************** +int main(void) { - volatile uint32_t *ptr; + printf("\n\n*************** Flash Control CLI Example ***************\n"); + printf("\nThis example demonstrates the CLI commands feature of FreeRTOS, various features"); + printf("\nof the Flash Controller (page erase and write), and how to use the CRC to"); + printf("\ncompute the CRC value of an array. Enter commands in the terminal window.\n\n"); - // Loop through memory and check whether it matches the data array - for (ptr = (uint32_t *)address; ptr < (uint32_t *)(address + length); ptr++, data++) { - if (*ptr != *data) { - printf("Verify failed at 0x%x (0x%x != 0x%x)\n", (unsigned int)ptr, (unsigned int)*ptr, - (unsigned int)*data); - return E_UNKNOWN; - } - } + MXC_ECC->en = 0; // Disable ECC on Flash, ICC, and SRAM - return E_NO_ERROR; -} + NVIC_SetRAM(); + // Initialize the Flash + flash_init(); -// ***************************************************************************** -int check_mem(uint32_t startaddr, uint32_t length, uint32_t data) -{ - uint32_t *ptr; - - // Loop through memory and check whether it matches the expected data value - for (ptr = (uint32_t *)startaddr; ptr < (uint32_t *)(startaddr + length); ptr++) { - if (*ptr != data) { - return 0; - } + /* Configure task */ + if ((xTaskCreate(vCmdLineTask, (const char *)"CmdLineTask", + configMINIMAL_STACK_SIZE + CMD_LINE_BUF_SIZE + OUTPUT_BUF_SIZE, NULL, + tskIDLE_PRIORITY + 1, &cmd_task_id) != pdPASS)) { + printf("xTaskCreate() failed to create a task.\n"); + } else { + /* Start scheduler */ + printf("Starting FreeRTOS scheduler.\n"); + vTaskStartScheduler(); } - return 1; -} - -//****************************************************************************** -int check_erased(uint32_t startaddr, uint32_t length) -{ - // Check whether flash memory is set to all 1's (erased state) - return check_mem(startaddr, length, 0xFFFFFFFF); + return 0; } diff --git a/Examples/MAX32670/Flash_CLI/project.mk b/Examples/MAX32670/Flash_CLI/project.mk index 569767abf7..b3fecca9c6 100644 --- a/Examples/MAX32670/Flash_CLI/project.mk +++ b/Examples/MAX32670/Flash_CLI/project.mk @@ -13,5 +13,5 @@ # Add your config here! -# Enable the CLI library -LIB_CLI = 1 +# Enable the FreeRTOS library +LIB_FREERTOS=1 \ No newline at end of file diff --git a/Examples/MAX32670/WearLeveling/README.md b/Examples/MAX32670/WearLeveling/README.md index 5a5f5dffe7..9e42ee7e0a 100644 --- a/Examples/MAX32670/WearLeveling/README.md +++ b/Examples/MAX32670/WearLeveling/README.md @@ -6,8 +6,8 @@ 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 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 distributed somewhat evenly across most filesystem blocks. +* write: Writes data to a file and can optionally create the file to write to if it does not already exist. +* 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,50 +34,54 @@ 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 file system... -littlefs/lfs.c:1224:error: Corrupted dir pair at {0x0, 0x1} +********** Wear Leveling Example ********** +Mounting the filesystem... +C:/MaximSDK/Libraries/littlefs/lfs.c:1224:error: Corrupted dir pair at {0x0, 0x1} Filesystem is invalid, formatting... -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 +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 42 bytes were written to demo_file in filesystem block 6. -$ read demo_file 42 0 -read demo_file 42 0 +cmd> 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 -$ swl 1000 -swl 1000 +cmd> swl 1000 All writes have completed. Here are the results: Block 0 was written to 0 times. Block 1 was written to 0 times. @@ -97,10 +101,8 @@ Block 14 was written to 83 times. Block 15 was written to 83 times. -$ stop -stop +cmd> stop -$ Filesystem resources released. Example complete! ``` diff --git a/Examples/MAX32670/WearLeveling/include/cli.h b/Examples/MAX32670/WearLeveling/include/cli.h new file mode 100644 index 0000000000..760373aa72 --- /dev/null +++ b/Examples/MAX32670/WearLeveling/include/cli.h @@ -0,0 +1,48 @@ +/****************************************************************************** + * + * Copyright (C) 2022-2023 Maxim Integrated Products, Inc. All Rights Reserved. + * (now owned by Analog Devices, Inc.), + * Copyright (C) 2023 Analog Devices, Inc. All Rights Reserved. This software + * is proprietary to Analog Devices, Inc. and its licensors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + +#ifndef EXAMPLES_MAX32670_WEARLEVELING_INCLUDE_CLI_H_ +#define EXAMPLES_MAX32670_WEARLEVELING_INCLUDE_CLI_H_ + +#include "lfs.h" + +/* + * @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_ diff --git a/Examples/MAX32670/WearLeveling/include/cmd_table.h b/Examples/MAX32670/WearLeveling/include/cmd_table.h deleted file mode 100644 index a117f0b13f..0000000000 --- a/Examples/MAX32670/WearLeveling/include/cmd_table.h +++ /dev/null @@ -1,48 +0,0 @@ -/****************************************************************************** - * - * Copyright (C) 2022-2023 Maxim Integrated Products, Inc. All Rights Reserved. - * (now owned by Analog Devices, Inc.), - * Copyright (C) 2023 Analog Devices, Inc. All Rights Reserved. This software - * is proprietary to Analog Devices, Inc. and its licensors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - ******************************************************************************/ - -#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 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/include/main.h b/Examples/MAX32670/WearLeveling/include/main.h new file mode 100644 index 0000000000..e8055cc1f6 --- /dev/null +++ b/Examples/MAX32670/WearLeveling/include/main.h @@ -0,0 +1,30 @@ +/****************************************************************************** + * + * Copyright (C) 2022-2023 Maxim Integrated Products, Inc. All Rights Reserved. + * (now owned by Analog Devices, Inc.), + * Copyright (C) 2023 Analog Devices, Inc. All Rights Reserved. This software + * is proprietary to Analog Devices, Inc. and its licensors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + +#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 f713c697a8..e0fed8e6f2 100644 --- a/Examples/MAX32670/WearLeveling/main.c +++ b/Examples/MAX32670/WearLeveling/main.c @@ -31,80 +31,74 @@ #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" -/***** 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 +/***** 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, +}; -/***** 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(lfs_t *filesystem, const struct lfs_config *cfg); - -/***** Global Variables ******/ -lfs_t lfs; // LFS filesystem instance -volatile bool stop_recv = false; // Used to signal whether the example has completed - -/***** Function Definitions *****/ +//****************************************************************************** +/** + * @brief Application entry point + * @return Exit code + */ int main(void) { - int err; + lfs_t lfs; // File system instance + char cmd_buf[CMD_MAX_SIZE]; + int cmd_len, err; - printf("\n\n*************** Wear Leveling Example ***************\n"); + 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); + // mount the filesystem + printf("Mounting the filesystem...\n"); + err = lfs_mount(&lfs, &cfg); - // 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(&lfs, &cfg)) != E_NO_ERROR) { - printf("Unable to mount file system!\n"); - return err; + // 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); } - printf("File system is mounted!\n\n"); - 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"); + if (!err) { + printf("Filesystem is mounted! Ready for commands.\n"); + } else { + printf("Unable to initialize file system!\n"); return E_BAD_STATE; } - // CLI running in the background. Continue to receive and process commands until 'stop' command received - while (!stop_recv) {} + // Continue to receive and process commands until 'stop' command received + while (err != E_SHUTDOWN) { + printf("\ncmd> "); + fflush(stdout); + + cmd_len = cmd_get(cmd_buf, CMD_MAX_SIZE); + err = cmd_process(&lfs, cmd_buf, cmd_len); + } // release any resources we were using lfs_unmount(&lfs); @@ -113,151 +107,3 @@ 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[FILENAME_POS]; - int num = atoi(argv[NUM_BYTES_POS]); - int pos = atoi(argv[LOCATION_POS]); - 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 || argv == NULL) { - printf("Invalid command. Aborting file write.\n"); - return E_INVALID; - } - - // Assign CLI arguments to appropriate variables - lfs_file_t file; - 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, true); - 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[NUM_WRITES_POS]); - - //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(lfs_t *filesystem, const struct lfs_config *cfg) -{ - int err; - - // 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); - } - - if (err) { - return E_BAD_STATE; - } - - return err; -} diff --git a/Examples/MAX32670/WearLeveling/project.mk b/Examples/MAX32670/WearLeveling/project.mk index 3c23870cbe..16e450a8b6 100644 --- a/Examples/MAX32670/WearLeveling/project.mk +++ b/Examples/MAX32670/WearLeveling/project.mk @@ -13,8 +13,4 @@ # Add your config here! -# Enable the LittleFS Library -LIB_LITTLEFS = 1 - -# Enable the CLI Library -LIB_CLI = 1 \ No newline at end of file +LIB_LITTLEFS = 1 \ No newline at end of file diff --git a/Examples/MAX32670/WearLeveling/src/cli.c b/Examples/MAX32670/WearLeveling/src/cli.c new file mode 100644 index 0000000000..488f3413de --- /dev/null +++ b/Examples/MAX32670/WearLeveling/src/cli.c @@ -0,0 +1,301 @@ +/****************************************************************************** + * + * Copyright (C) 2022-2023 Maxim Integrated Products, Inc. All Rights Reserved. + * (now owned by Analog Devices, Inc.), + * Copyright (C) 2023 Analog Devices, Inc. All Rights Reserved. This software + * is proprietary to Analog Devices, Inc. and its licensors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + +#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 bd28a463d5..77be66d5d8 100644 --- a/Libraries/CLI/src/cli.c +++ b/Libraries/CLI/src/cli.c @@ -28,7 +28,6 @@ #include "board.h" #include "cli.h" -#include "mxc_errors.h" #include "nvic_table.h" /* -------------------------------------------------- */ @@ -48,17 +47,6 @@ #define UART_BAUD 115200 #define BUFF_SIZE 1 -// Macro to call MXC_UART_Init function with appropriate parameters -#if (TARGET_NUM == 32520 || TARGET_NUM == 32570 || TARGET_NUM == 32650) -#define UART_INIT(uart) MXC_UART_Init(uart, UART_BAUD) -#elif TARGET_NUM == 32660 -#define UART_INIT(uart) MXC_UART_Init(uart, UART_BAUD, MAP_A) -#elif TARGET_NUM == 32662 -#define UART_INIT(uart) MXC_UART_Init(uart, UART_BAUD, MXC_UART_APB_CLK, MAP_A) -#else -#define UART_INIT(uart) MXC_UART_Init(uart, UART_BAUD, MXC_UART_APB_CLK) -#endif - /* -------------------------------------------------- */ // FUNCTION PROTOTYPES /* -------------------------------------------------- */ @@ -252,7 +240,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", command_table[i].description); + printf(" Description: %s\n\n", command_table[i].description); } return E_NO_ERROR; @@ -302,8 +290,8 @@ int MXC_CLI_Init(mxc_uart_regs_t *uart, const command_t *commands, unsigned int command_table = commands; command_table_sz = num_commands; - // Initialize UART - if ((error = UART_INIT(uart)) != E_NO_ERROR) { + // Initialize Console UART + if ((error = MXC_UART_Init(uart, UART_BAUD, MXC_UART_APB_CLK)) != E_NO_ERROR) { printf("-->Error initializing CLI UART: %d\n", error); return error; }