/*----------------------------------------------------------------------------* * NAME * Nvm_Read * * DESCRIPTION * Read words from the NVM Store after preparing the NVM to be readable. * After the read operation, perform the actions necessary to save power * on NVM. * * Read words starting at the word offset, and store them in the supplied * buffer. * * PARAMETERS * buffer [out] Data read from NVM * length [in] Number of words of data to read * offset [in] Offset from which to start reading, in words * * RETURNS * Nothing *----------------------------------------------------------------------------*/ void Nvm_Read(uint16 *buffer, uint16 length, uint16 offset) { sys_status result; /* Read from NVM. Firmware re-enables the NVM if it is disabled */ result = NvmRead(buffer, length, offset); /* Disable NVM to save power after read operation */ Nvm_Disable(); /* Report panic if NVM read is not successful */ if(sys_status_success != result) { ReportPanic(app_panic_nvm_read); } }
void Nvm_Read(uint16* buffer, uint16 length, uint16 offset) { sys_status result; /* If the NVM has been earlier disabled, firmware automatically enables * NVM before reading from it. */ result = NvmRead(buffer, length, offset); /* Disable NVM to save power after read operation */ Nvm_Disable(); /* PIO2 usage has to be toggled between LED operation and driving the NVM. * So, after the power to EEPROM is disabled, configure PIO2 to Pair LED * back again. */ SetUpPairLED(); if(sys_status_success != result) { ReportPanic(app_panic_nvm_read); } }
/*----------------------------------------------------------------------------* * NAME * readPersistentStore * * DESCRIPTION * This function is used to initialise and read NVM data. * * PARAMETERS * None * * RETURNS * Nothing *----------------------------------------------------------------------------*/ static void readPersistentStore(void) { /* NVM offset for supported services */ uint16 nvm_offset = NVM_MAX_APP_MEMORY_WORDS; uint16 nvm_sanity = 0xffff; /* Read persistent storage to find if the device was last bonded to another * device. If the device was bonded, trigger fast undirected advertisements * by setting the white list for bonded host. If the device was not bonded, * trigger undirected advertisements for any host to connect. */ NvmRead(&nvm_sanity, sizeof(nvm_sanity), NVM_OFFSET_SANITY_WORD); if (nvm_sanity == NVM_SANITY_MAGIC) { /* Read bonded flag from NVM */ NvmRead((uint16 *)&(IS_BONDED), sizeof(IS_BONDED), NVM_OFFSET_BONDED_FLAG); if (IS_BONDED) { /* Bonded host typed BD address will only be stored if bonded flag * is set to TRUE. Read last bonded device address. */ NvmRead((uint16 *)&(CONN_HOST_ADDR), sizeof(TYPED_BD_ADDR_T), NVM_OFFSET_BONDED_ADDR); /* If device is bonded and bonded address is resolvable then read * the bonded device's IRK */ if (GattIsAddressResolvableRandom(&(CONN_HOST_ADDR))) { NvmRead(CONNECTION_IRK, MAX_WORDS_IRK, NVM_OFFSET_SM_IRK); } } else /* Case when we have only written NVM_SANITY_MAGIC to NVM but * didn't get bonded to any host in the last powered session */ { /* Any initialisation can be done here for non-bonded devices */ } /* Read the diversifier associated with the presently bonded/last * bonded device. */ NvmRead(&(LINK_DIVERSIFIER), sizeof(LINK_DIVERSIFIER), NVM_OFFSET_SM_DIV); /* Read GATT data from NVM */ GattReadDataFromNVM(&nvm_offset); } else /* NVM sanity check failed means either the device is being brought up * for the first time or memory has been corrupted in which case * discard the data and start fresh. */ { nvm_sanity = NVM_SANITY_MAGIC; /* Write NVM Sanity word to the NVM */ NvmWrite(&nvm_sanity, sizeof(nvm_sanity), NVM_OFFSET_SANITY_WORD); /* The device will not be bonded as it is coming up for the first time */ IS_BONDED = FALSE; /* Write bonded status to NVM */ NvmWrite((uint16 *)&(IS_BONDED), sizeof(IS_BONDED), NVM_OFFSET_BONDED_FLAG); /* When the application is coming up for the first time after flashing * the image to it, it will not have bonded to any device. So, no LTK * will be associated with it. Hence, set the diversifier to 0. */ LINK_DIVERSIFIER = 0; /* Write the same to NVM. */ NvmWrite(&(LINK_DIVERSIFIER), sizeof(LINK_DIVERSIFIER), NVM_OFFSET_SM_DIV); /* Since device is being brought up first time, it won't be in * bonded state. Following function call will only initialise the NVM * offset of GATT service. */ GattReadDataFromNVM(&nvm_offset); } }
void init_platform_bootloader( void ) { uint32_t BootNvmInfo; OSStatus err; MicoGpioInitialize( BOOT_SEL, INPUT_PULL_UP ); MicoGpioInitialize( MFG_SEL, INPUT_PULL_UP ); #ifdef MICO_ATE_START_ADDRESS MicoGpioInitialize( EasyLink_BUTTON, INPUT_PULL_UP ); #endif /* Check USB-HOST is inserted */ err = MicoGpioInitialize( (mico_gpio_t)USB_DETECT, INPUT_PULL_DOWN ); require_noerr(err, exit); mico_thread_msleep_no_os(2); require_string( MicoGpioInputGet( (mico_gpio_t)USB_DETECT ) == true, exit, "USB device is not inserted" ); //platform_log("USB device inserted"); if( HardwareInit(DEV_ID_USB) ){ FolderOpenByNum(&RootFolder, NULL, 1); FileBrowse(RootFolder.FsContext); } /* Check last firmware update is success or not. */ NvmRead(UPGRADE_NVM_ADDR, (uint8_t*)&BootNvmInfo, 4); if(false == UpgradeFileFound) { if(BootNvmInfo == UPGRADE_SUCC_MAGIC) { /* * boot up check for the last time */ platform_log("[UPGRADE]:upgrade successful completely"); } else if(BootNvmInfo == (uint32_t)UPGRADE_ERRNO_NOERR) { platform_log("[UPGRADE]:no upgrade, boot normallly"); } else if(BootNvmInfo == (uint32_t)UPGRADE_ERRNO_CODBUFDAT) { platform_log("[UPGRADE]:upgrade successful partly, data fail"); } else { platform_log("[UPGRADE]:upgrade error, errno = %d", (int32_t)BootNvmInfo); } } else { if(BootNvmInfo == (uint32_t)UPGRADE_ERRNO_NOERR) { platform_log("[UPGRADE]:found upgrade ball, prepare to boot upgrade"); BootNvmInfo = UPGRADE_REQT_MAGIC; NvmWrite(UPGRADE_NVM_ADDR, (uint8_t*)&BootNvmInfo, 4); //if you want PORRESET to reset GPIO only,uncomment it //GpioPorSysReset(GPIO_RSTSRC_PORREST); NVIC_SystemReset(); while(1);;; } else if(BootNvmInfo == UPGRADE_SUCC_MAGIC) { BootNvmInfo = (uint32_t)UPGRADE_ERRNO_NOERR; NvmWrite(UPGRADE_NVM_ADDR, (uint8_t*)&BootNvmInfo, 4); platform_log("[UPGRADE]:found upgrade ball file for the last time, re-plugin/out, if you want to upgrade again"); } else { platform_log("[UPGRADE]:upgrade error, errno = %d", (int32_t)BootNvmInfo); if( BootNvmInfo == -9 ) { platform_log("[UPGRADE]:Same file, no need to update"); goto exit; } BootNvmInfo = (uint32_t)UPGRADE_ERRNO_NOERR; NvmWrite(UPGRADE_NVM_ADDR, (uint8_t*)&BootNvmInfo, 4); BootNvmInfo = UPGRADE_REQT_MAGIC; NvmWrite(UPGRADE_NVM_ADDR, (uint8_t*)&BootNvmInfo, 4); //if you want PORRESET to reset GPIO only,uncomment it //GpioPorSysReset(GPIO_RSTSRC_PORREST); NVIC_SystemReset(); } } exit: return; }