/** ****************************************************************************** * @file menu.c * @author William Xu * @version V2.0.0 * @date 05-Oct-2014 * @brief his file provides the software which contains the main menu routine. * The main menu gives the options of: * - downloading a new binary file, * - uploading internal flash memory, * - executing the binary file already loaded ****************************************************************************** * * The MIT License * Copyright (c) 2014 MXCHIP Inc. * * 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 THE * AUTHORS OR COPYRIGHT HOLDERS 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. ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "mico.h" #include "ymodem.h" #include "platform_config.h" #include "platform_internal.h" #include "StringUtils.h" #include "bootloader.h" #include /* Private typedef -----------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/ #define CMD_STRING_SIZE 128 /* Private macro -------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ extern platform_flash_t platform_flash_peripherals[]; uint8_t tab_1024[1024] = { 0 }; char FileName[FILE_NAME_LENGTH]; char ERROR_STR [] = "\n\r*** ERROR: %s\n\r"; /* ERROR message string in code */ extern char menu[]; extern void getline (char *line, int n); /* input line */ extern void startApplication( uint32_t app_addr ); /* Private function prototypes -----------------------------------------------*/ void SerialDownload(mico_flash_t flash, uint32_t flashdestination, int32_t maxRecvSize); void SerialUpload(mico_flash_t flash, uint32_t flashdestination, char * fileName, int32_t maxRecvSize); /* Private functions ---------------------------------------------------------*/ /** * @brief Analyse a command parameter * @param commandBody: command string address * @param para: The para we are looking for * @param paraBody: A pointer to the buffer to receive the para body. * @param paraBodyLength: The length, in bytes, of the buffer pointed to by the paraBody parameter. * @retval the actual length of the paraBody received, -1 means failed to find this paras */ int findCommandPara(char *commandBody, char *para, char *paraBody, int paraBodyLength) { int i = 0; int k, j; int retval = -1; char para_in_ram[100]; strncpy(para_in_ram, para, 100); for (i = 0; para_in_ram[i] != 0; i++) { /* convert to upper characters */ para_in_ram[i] = toupper(para_in_ram[i]); } i = 0; while(commandBody[i] != 0) { if(commandBody[i] == '-' ){ for(j=i+1, k=0; *(para_in_ram+k)!=0x0; j++, k++ ){ if(commandBody[j] != *(para_in_ram+k)){ break; } } if(*(para+k)!=0x0 || (commandBody[j]!=' '&& commandBody[j]!=0x0)){ /* para not found! */ i++; continue; } retval = 0; for (k = j+1; commandBody[k] == ' '; k++); /* skip blanks */ for(j = 0; commandBody[k] != ' ' && commandBody[k] != 0 && commandBody[k] != '-'; j++, k++){ /* para body found! */ if(paraBody) paraBody[j] = commandBody[k]; retval ++; if( retval == paraBodyLength) goto exit; } goto exit; } i++; } exit: if(paraBody) paraBody[retval] = 0x0; return retval; } /** * @brief Download a file via serial port * @param None * @retval None */ void SerialDownload(mico_flash_t flash, uint32_t flashdestination, int32_t maxRecvSize) { char Number[10] = " "; int32_t Size = 0; printf("Waiting for the file to be sent ... (press 'a' to abort)\r\n"); Size = Ymodem_Receive( &tab_1024[0], flash, flashdestination, maxRecvSize ); if (Size > 0) { printf("\n\n\r Successfully!\n\r\r\n Name: %s", FileName); Int2Str((uint8_t *)Number, Size); printf("\n\r Size: %s Bytes\r\n", Number); } else if (Size == -1) { printf("\n\n\rImage size is higher than memory!\n\r"); } else if (Size == -2) { printf("\n\n\rVerification failed!\r\n"); } else if (Size == -3) { printf("\r\n\nAborted.\r\n"); } else { printf("\n\rReceive failed!\r\n"); } } /** * @brief Upload a file via serial port. * @param None * @retval None */ void SerialUpload(mico_flash_t flash, uint32_t flashdestination, char * fileName, int32_t maxRecvSize) { uint8_t status = 0; uint8_t key; printf("Select Receive File\n\r"); MicoUartRecv( STDIO_UART, &key, 1, MICO_NEVER_TIMEOUT ); if (key == CRC16) { /* Transmit the flash image through ymodem protocol */ status = Ymodem_Transmit(flash, flashdestination, (uint8_t *)fileName, maxRecvSize); if (status != 0) { printf("\n\rError while Transmitting\n\r"); } else { printf("\n\rSuccessfully\n\r"); } } } /** * @brief Display the Main Menu on HyperTerminal * @param None * @retval None */ void Main_Menu(void) { char cmdbuf [CMD_STRING_SIZE] = {0}, cmdname[15] = {0}; /* command input buffer */ int i, j; /* index for command buffer */ char idStr[4], startAddressStr[10], endAddressStr[10], flash_dev_str[4]; int32_t id, startAddress, endAddress; bool inputFlashArea = false; mico_logic_partition_t *partition; mico_flash_t flash_dev; OSStatus err = kNoErr; while (1) { /* loop forever */ printf ("\n\rMXCHIP> "); #if defined __GNUC__ fflush(stdout); #endif getline (&cmdbuf[0], sizeof (cmdbuf)); /* input command line */ for (i = 0; cmdbuf[i] == ' '; i++); /* skip blanks on head */ for (; cmdbuf[i] != 0; i++) { /* convert to upper characters */ cmdbuf[i] = toupper(cmdbuf[i]); } for (i = 0; cmdbuf[i] == ' '; i++); /* skip blanks on head */ for(j=0; cmdbuf[i] != ' '&&cmdbuf[i] != 0; i++,j++) { /* find command name */ cmdname[j] = cmdbuf[i]; } cmdname[j] = '\0'; /***************** Command "0" or "BOOTUPDATE": Update the application *************************/ if(strcmp(cmdname, "BOOTUPDATE") == 0 || strcmp(cmdname, "0") == 0) { partition = MicoFlashGetInfo( MICO_PARTITION_BOOTLOADER ); if (findCommandPara(cmdbuf, "r", NULL, 0) != -1){ printf ("\n\rRead Bootloader...\n\r"); SerialUpload( partition->partition_owner, partition->partition_start_addr, "BootLoaderImage.bin", partition->partition_length ); continue; } printf ("\n\rUpdating Bootloader...\n\r"); err = MicoFlashDisableSecurity( MICO_PARTITION_BOOTLOADER, 0x0, partition->partition_length ); require_noerr( err, exit); SerialDownload( partition->partition_owner, partition->partition_start_addr, partition->partition_length ); } /***************** Command "1" or "FWUPDATE": Update the MICO application *************************/ else if(strcmp(cmdname, "FWUPDATE") == 0 || strcmp(cmdname, "1") == 0) { partition = MicoFlashGetInfo( MICO_PARTITION_APPLICATION ); if (findCommandPara(cmdbuf, "r", NULL, 0) != -1){ printf ("\n\rRead application...\n\r"); SerialUpload( partition->partition_owner, partition->partition_start_addr, "ApplicationImage.bin", partition->partition_length ); continue; } printf ("\n\rUpdating application...\n\r"); err = MicoFlashDisableSecurity( MICO_PARTITION_APPLICATION, 0x0, partition->partition_length ); require_noerr( err, exit); SerialDownload( partition->partition_owner, partition->partition_start_addr, partition->partition_length ); } /***************** Command "2" or "DRIVERUPDATE": Update the RF driver *************************/ else if(strcmp(cmdname, "DRIVERUPDATE") == 0 || strcmp(cmdname, "2") == 0) { partition = MicoFlashGetInfo( MICO_PARTITION_RF_FIRMWARE ); if( partition == NULL ){ printf ("\n\rNo flash memory for RF firmware, exiting...\n\r"); continue; } if (findCommandPara(cmdbuf, "r", NULL, 0) != -1){ printf ("\n\rRead RF firmware...\n\r"); SerialUpload( partition->partition_owner, partition->partition_start_addr, "DriverImage.bin", partition->partition_length ); continue; } printf ("\n\rUpdating RF driver...\n\r"); err = MicoFlashDisableSecurity( MICO_PARTITION_RF_FIRMWARE, 0x0, partition->partition_length ); require_noerr( err, exit); SerialDownload( partition->partition_owner, partition->partition_start_addr, partition->partition_length ); } /***************** Command "3" or "PARAUPDATE": Update the application *************************/ else if(strcmp(cmdname, "PARUPDATE") == 0 || strcmp(cmdname, "3") == 0) { if (findCommandPara(cmdbuf, "id", idStr, 0) != -1){ if(Str2Int((uint8_t *)idStr, &id)==0 && id > 0 && id < MICO_PARTITION_MAX ){ //Found Flash start address printf ("\n\rIllegal start address.\n\r"); continue; } partition = MicoFlashGetInfo( (mico_partition_t)id ); }else{ printf ("\n\rPlease input correct MiCO partition id.\n\r"); continue; } if( findCommandPara(cmdbuf, "e", NULL, 0) != -1 ){ printf( "\n\rErasing %s...\n\r", partition->partition_description ); err = MicoFlashDisableSecurity( (mico_partition_t)id, 0x0, partition->partition_length ); require_noerr( err, exit); MicoFlashErase( (mico_partition_t)id, 0x0, partition->partition_length ); continue; } if (findCommandPara(cmdbuf, "r", NULL, 0) != -1){ printf ( "\n\rRead %s...\n\r", partition->partition_description ); SerialUpload( partition->partition_owner, partition->partition_start_addr, "Image.bin", partition->partition_length ); continue; } printf ("\n\rUpdating %s...\n\r", partition->partition_description ); err = MicoFlashDisableSecurity( (mico_partition_t)id, 0x0, partition->partition_length ); require_noerr( err, exit); SerialDownload( partition->partition_owner, partition->partition_start_addr, partition->partition_length ); } /***************** Command "4" or "FLASHUPDATE": : Update the Flash *************************/ else if(strcmp(cmdname, "FLASHUPDATE") == 0 || strcmp(cmdname, "4") == 0) { if (findCommandPara(cmdbuf, "dev", flash_dev_str, 1) == -1 ){ printf ("\n\rUnkown target type! Exiting...\n\r"); continue; } if(Str2Int((uint8_t *)flash_dev_str, (int32_t *)&flash_dev)==0){ printf ("\n\rDevice Number Err! Exiting...\n\r"); continue; } if( flash_dev >= MICO_FLASH_MAX ){ printf ("\n\rDevice Err! Exiting...\n\r"); continue; } inputFlashArea = false; if (findCommandPara(cmdbuf, "start", startAddressStr, 10) != -1){ if(Str2Int((uint8_t *)startAddressStr, &startAddress)==0){ //Found Flash start address printf ("\n\rIllegal start address.\n\r"); continue; }else{ if (findCommandPara(cmdbuf, "end", endAddressStr, 10) != -1){ //Found Flash end address if(Str2Int((uint8_t *)endAddressStr, &endAddress)==0){ printf ("\n\rIllegal end address.\n\r"); continue; }else{ inputFlashArea = true; } }else{ printf ("\n\rFlash end address not found.\n\r"); continue; } } } if(endAddresspartition_owner == MICO_FLASH_NONE || partition->partition_description == NULL ) continue; printf( "|ID:%d| %11s | Dev:%d | 0x%08lx | 0x%08lx |\r\n", i, partition->partition_description, partition->partition_owner, partition->partition_start_addr, partition->partition_length); } } /***************** Command: Excute the application *************************/ else if(strcmp(cmdname, "BOOT") == 0 || strcmp(cmdname, "6") == 0) { printf ("\n\rBooting.......\n\r"); partition = MicoFlashGetInfo( MICO_PARTITION_APPLICATION ); bootloader_start_app( partition->partition_start_addr ); } /***************** Command: Reboot *************************/ else if(strcmp(cmdname, "REBOOT") == 0 || strcmp(cmdname, "7") == 0) { printf ("\n\rReBooting.......\n\r"); MicoSystemReboot(); break; } else if(strcmp(cmdname, "HELP") == 0 || strcmp(cmdname, "?") == 0) { printf ( menu, MODEL, Bootloader_REVISION, HARDWARE_REVISION ); /* display command menu */ break; } else if(strcmp(cmdname, "") == 0 ) { break; } else{ printf (ERROR_STR, "UNKNOWN COMMAND"); break; } exit: continue; } }