/*** putEeprom ** ** Parameters: ** eeprom - pointer to flash memory acting as emulated eeprom ** address - location to be written ** data - data to be written ** ** Return Value: ** Returns true or false wether the operation was successful ** or not. ** ** Errors: ** none ** ** Description: ** Searches through emulated eeprom for valid address then ** invalidates that location and writes the address and data ** to a new unused location. */ BOOL putEeprom(eeSeg * eeprom, uint32_t address, uint8_t data) { eeSeg tempSeg; int i; uint32_t nextAvalible; //Check if address exists for(i=0; i < _EEPROM_PAGE_SIZE; i++) { //Check if eeSeg is valid and address matches if(getValid(eeprom[i]) && !getTaken(eeprom[i]) && getAddress(eeprom[i]) == address) { //If data is same do nothing if(data == getData(eeprom[i])) { return fTrue; } //If data is different invalidate eeSeg else { tempSeg = eeprom[i]; tempSeg.temp.valid = 0; NVMWriteWord((void*)&eeprom[i],tempSeg.data); // If data is 0xFF return if(data == 0xFF) { return fTrue; } } } //If empty eeSeg found save location and break else if(getValid(eeprom[i]) && getTaken(eeprom[i])) { nextAvalible = i; break; } } //If I == max size no valid segments exist if(i == _EEPROM_PAGE_SIZE) { return fFalse; } //Pack address with data and write to flash tempSeg = pack(address,data); NVMWriteWord((void*)&eeprom[i],tempSeg.data); return fTrue; }
// return true on success, else false bool FlashWrite(uint32_t wordOffset, uint32_t value) { if (FLASH_BLOCK_SIZE_BYTES / 4 <= wordOffset) return false; // out of bounds uint32_t * ptr = (void*)FlashData; ptr += wordOffset; void * physicalAddress = VirtualToPhysicalAddress(ptr); // try writing twice, and check the value each try if (NVMWriteWord(physicalAddress, value) != 0 || *ptr != value) { if (NVMWriteWord(physicalAddress, value) != 0 || *ptr != value) { return false; } } return true; }
void writeWordFlash(uint32_t address,uint32_t data){ if (address >= StartAppVectPhysical && (address < EndAppVectPhysical)){ NVMWriteWord((uint32_t*)address, data); if ((*(int *)(address|0x80000000)) != data){ println_E("FAULT read did not match write on address: ");prHEX32(address,ERROR_PRINT); eraseFlash(); callBootloaderReset(); } }else{ println_E("FAULT can not reach address: ");prHEX32(address,ERROR_PRINT); } }
/**************************************************************************** Function: void WriteBlock(BOOT_REGION *entry, BYTE *buffer) Description: This routine will write the instructions within the buffer to the program memory address range. Precondition: The number of bytes within *buffer will fit the entire range given by *entry *entry is word aligned byte addresses Parameters: BOOT_REGION *entry - The address range that we will write to BYTE *buffer - A pointer to the buffer that holds the instructions we will be writing Returns: None ***************************************************************************/ void WriteBlock(BOOT_REGION *entry, BYTE *buffer) { DWORD_VAL data; DWORD address; // Iterate through region for(address = entry->addressStart; address < entry->addressEnd; address += 4) { // Byte pointer might not be word aligned, so read per byte to get 32-bit value (little endian) data.byte.LB = *buffer++; data.byte.HB = *buffer++; data.byte.UB = *buffer++; data.byte.MB = *buffer++; NVMWriteWord( (void *)address, data.Val ); // Write 4-byte word } }
/*** getBuffer ** ** Parameters: ** eeprom - pointer to flash memory acting as emulated eeprom ** buffer - pointer to buffer ** ** Return Value: ** Returns true or false wether the operation was successful ** or not. ** ** Errors: ** none ** ** Description: ** Searches through buffer and writes all non 0xFF values to ** to eeprom using the index as the address */ void getBuffer(eeSeg * eeprom, uint8_t * buffer) { eeSeg tempSeg; uint8_t tempData; int i; //Cycle through buffer for(i=0; i < _EEPROM_PAGE_SIZE; i++) { //If data in buffer does not equal 0xFF write to flash if(buffer[i] != 0xFF) { tempData = buffer[i]; tempSeg = pack(i, tempData); NVMWriteWord((void*)&eeprom[i],tempSeg.data); } } }
/******************************************************************** * Function: main() * * Precondition: * * Input: None. * * Output: None. * * Side Effects: None. * * Overview: Main entry function. If there is a trigger or * if there is no valid application, the device * stays in firmware upgrade mode. * * * Note: None. ********************************************************************/ INT main(void) { UINT pbClk; UINT bSoftResetFlag = 0; // Setup configuration pbClk = SYSTEMConfig(SYS_FREQ, SYS_CFG_WAIT_STATES | SYS_CFG_PCACHE); InitLED(); TRISBbits.TRISB15 = 1;//test bSoftResetFlag = *(unsigned int *)(NVM_DATA); if(bSoftResetFlag == 1) { NVMErasePage((void*)NVM_DATA); NVMWriteWord((void*)(NVM_DATA), (unsigned int)0x00); } // Enter firmware upgrade mode if there is a trigger or if the application is not valid if(bSoftResetFlag == 1 || CheckTrigger() || !ValidAppPresent()) { // Initialize the transport layer - UART/USB/Ethernet TRANS_LAYER_Init(pbClk); while(!FRAMEWORK_ExitFirmwareUpgradeMode()) // Be in loop till framework recieves "run application" command from PC { // Enter firmware upgrade mode. // Be in loop, looking for commands from PC TRANS_LAYER_Task(); // Run Transport layer tasks FRAMEWORK_FrameWorkTask(); // Run frame work related tasks (Handling Rx frame, process frame and so on) // Blink LED (Indicates the user that bootloader is running). BlinkLED(); } // Close trasnport layer. TRANS_LAYER_Close(); } // No trigger + valid application = run application. JumpToApp(); return 0; }
/***************************************************************************** * * exoHAL_WriteMetaItem * * \param buffer - string buffer containing info to write to meta; len - * size of string in bytes; offset - offset from base of meta * location to store the item * * \return None * * \brief Stores information to the NV meta structure * *****************************************************************************/ void exoHAL_WriteMetaItem(unsigned char * buffer, unsigned char len, int offset) { int i; DWORD address = EXOMETA_ADDR + offset; DWORD input_tmp; if (len % 2 > 0) len += 1; for(i = 0; i < len;) { input_tmp = (buffer[i + 3] << 24 & 0xff000000) | (buffer[i + 2] << 16 & 0xff0000) | (buffer[i + 1] << 8 & 0xff00) | (buffer[i] & 0xff); i += 4; NVMWriteWord((void *)(address), input_tmp); address += 4; } return; }
void DoSerial() // Serial Processing of any input data { char c; uint8 i; if(Serial2Available()) { SerialConnected=1; // Client has connected so we can now send stuff.. (Set until POR as we dont have the equivelent for a disconnect) c = Serial2Read(); if(c==3) // 3. Raw image test (focus setup etc) { while(c!=1 && c!=9) { OC_COUNT(ON); AquireImage(); Serial2Write(3); Serial2Write(99); for(i=0; i<128; i++) Serial2Write(RawData[i]); Serial2Write(99); DelayMicroseconds(100000); if(Serial2Available()) c = Serial2Read(); } } if(c==4) // 4. end processing { PowerSaveSleep(); // END! while(1); } if(c==5) // 5. Send fixed (NVM) settings { Serial2Write(5); Serial2Write(99); Serial2Write(Tmin); Serial2Write(algorithm); Serial2Write(cap); Serial2Write(neck); Serial2Write(SampleRate>>8); Serial2Write(SampleRate); Serial2Write(RejOnTime>>8); Serial2Write(RejOnTime); Serial2Write(tollerance); } if(c==6) SendCounters();// 6. Send current settings if(c==7) // 7. Receive new settings temporary until reset or permanent if written to NVM { Tmin=Serial2Read(); algorithm=Serial2Read(); cap=Serial2Read(); neck=Serial2Read(); SampleRate=Serial2Read()<<8 + Serial2Read(); RejOnTime=Serial2Read()<<8 + Serial2Read(); tollerance=Serial2Read(); NVMChanged=1; Serial2Write(7); } if(c==8 && NVMChanged) // 8. Save to NVM { if( (void*)(NVMPtr+8) >= NVM_END) // used all the flash page so we have to erase whole page and start again (will never happen seriously!) { NVMErasePage(NVM_START); NVMPtr = NVM_START; } // Each variable is stored as a 32 bit integer which is the minimum size programable to flash NVMPtr will always be set at next free FLASH slot after POR or a write NVMWriteWord( (void*) (NVMPtr++) , Tmin ); NVMWriteWord( (void*) (NVMPtr++) , algorithm ); NVMWriteWord( (void*) (NVMPtr++) , cap ); NVMWriteWord( (void*) (NVMPtr++) , neck ); NVMWriteWord( (void*) (NVMPtr++) , SampleRate ); NVMWriteWord( (void*) (NVMPtr++) , RejOnTime); NVMWriteWord( (void*) (NVMPtr++) , tollerance); NVMChanged = 0; // All good so unflag change Serial2Write(8); } if(c==9) SoftReset(); // 9. RESET Sensor! }
/* This function overrides the normal _weak_ _generic_exception_handler which is defined in the C32 User's Guide. The _weak_ _generic_exception_handler just does an infinite loop. */ void _general_exception_handler(void) { unsigned long t0 = _CP0_GET_COUNT(); /* Used for NVMOP 6 us Delay */ /* Mask off Mask of the ExcCode Field from the Cause Register Refer to the MIPs M4K Software User's manual */ _excep_code=_CP0_GET_CAUSE() & 0x0000007C >> 2; _excep_addr=_CP0_GET_EPC(); _CP0_SET_STATUS(_CP0_GET_STATUS()&0xFFFFFFE); /* Disable Interrupts */ #ifdef WRITE_EXCEPTION_CAUSE_TO_FLASH /* Store the exception causes in program memory in case the part exhibited the problem in release mode. Gives user a place to start debugging the problem. */ NVMCON = 0x4001; /* set WREN and Word Programing mode */ NVMADDR = EXCEPTION_CAUSE; /* PM Address at which we'll store the */ /* cause register */ NVMDATA = _excep_code; /* wait at least 6 us for LVD start-up assume we're running at max frequency (80 MHz) so we're always safe */ { while (_CP0_GET_COUNT() - t0 < (80/2)*6); } NVMKEY = 0xAA996655; NVMKEY = 0x556699AA; /* unlock sequence */ NVMCONSET = NVMCON_WR; while(NVMCON & NVMCON_WR); /* wait on write to finish */ NVMCON = 0x4001; /* set WREN and Word Programing mode */ NVMADDR = EXCEPTION_ADDR; /* PM Address at which we'll store the */ /* exception address register */ NVMDATA = _excep_addr; /* wait at least 6 us for LVD start-up assume we're running at max frequency (80 MHz) so we're always safe */ { while (_CP0_GET_COUNT() - t0 < (80/2)*6); } NVMKEY = 0xAA996655; NVMKEY = 0x556699AA; /* unlock sequence */ NVMCONSET = NVMCON_WR; while(NVMCON & NVMCON_WR); /* Write the exception cause and address to the part can be read and the cause determined. */ NVMWriteWord((void*)EXCEPTION_CAUSE, _excep_code); NVMWriteWord((void*)EXCEPTION_ADDR, _excep_addr); #endif while (1) { /* Examine _excep_code to identify the type of exception */ /* Examine _excep_addr to find the address that caused the exception */ } }