private void EraseDeploymentSectors(string devicePath, Firmware upgradeFirmware) { STDfuDevice device = new STDfuDevice(devicePath); // TODO: make sure we are in DFU mode; if we are in app mode (runtime) then we need to detach and re-enumerate. // get our total deployment sectors count List <uint> allSectorBaseAddresses = new List <uint>(); foreach (Firmware.FirmwareRegion region in upgradeFirmware.FirmwareRegions) { if (region.Name.ToUpper() == "DEPLOYMENT") { allSectorBaseAddresses.AddRange(region.SectorBaseAddresses); } } // erase each sector for (int iSector = 0; iSector < allSectorBaseAddresses.Count; iSector++) { if (!device.EraseSector(allSectorBaseAddresses[iSector])) { throw new Exception("Could not erase sector."); } _updateWorker.ReportProgress((int)((((double)iSector + 1) / (double)allSectorBaseAddresses.Count) * 100)); } //// step 4: restart board //device.SetAddressPointer(0x08000001); // NOTE: for thumb2 instructinos, we added 1 to the "base address". Otherwise our board will not restart properly. //// leave DFU mode. //device.LeaveDfuMode(); }
private void EraseAndUploadDevice(string devicePath, Firmware upgradeFirmware, double startProgressPercent, double operationTotalProgressPercent) { double localProgressPercent = 0.0; STDfuDevice device = new STDfuDevice(devicePath); // TODO: make sure we are in DFU mode; if we are in app mode (runtime) then we need to detach and re-enumerate. // get our total sectors and block counts List <uint> allSectorBaseAddresses = new List <uint>(); uint totalBlockCount = 0; foreach (Firmware.FirmwareRegion region in upgradeFirmware.FirmwareRegions) { allSectorBaseAddresses.AddRange(region.SectorBaseAddresses); if (region.Filename != null) { System.IO.StreamReader streamReader = new System.IO.StreamReader(upgradeFirmware.FolderPath + "\\" + region.Filename); string hexFileString = streamReader.ReadToEnd(); streamReader.Dispose(); byte[] hexFileBytes = SrecHexEncoding.GetBytes(hexFileString, region.BaseAddress); totalBlockCount += (uint)Math.Ceiling((double)hexFileBytes.Length / (double)device.BlockTransferSize); } } // erase each sector for (int iSector = 0; iSector < allSectorBaseAddresses.Count; iSector++) { if (!device.EraseSector(allSectorBaseAddresses[iSector])) { throw new Exception("Could not erase sector."); } localProgressPercent = (((double)iSector + 1) / (double)allSectorBaseAddresses.Count) * 0.5; _updateWorker.ReportProgress(CalculateWorkerProgress(localProgressPercent, startProgressPercent, operationTotalProgressPercent)); } // do "read unprotect" //Debug.Print("Unprotecting all sectors, erasing..."); //Debug.Print("operation " + (stdfuDeviceReadUnprotect() ? "SUCCESS" : "FAILED")); //// do mass erase //Debug.Print("erasing all sectors..."); //Debug.Print("operation " + (device.EraseAllSectors() ? "SUCCESS" : "FAILED")); //localProgressPercent = 0.3; // now flash the board! ushort blockSize = device.BlockTransferSize; ushort completedBlocks = 0; foreach (Firmware.FirmwareRegion region in upgradeFirmware.FirmwareRegions) { if (region.Filename != null) { System.IO.StreamReader streamReader = new System.IO.StreamReader(upgradeFirmware.FolderPath + "\\" + region.Filename); string hexFileString = streamReader.ReadToEnd(); streamReader.Dispose(); byte[] hexFileBytes = SrecHexEncoding.GetBytes(hexFileString, region.BaseAddress); // set our download address pointer if (device.SetAddressPointer(region.BaseAddress) == false) { throw new Exception("Could not set base address for flash operation."); } // write blocks to the board and verify; we must have already erased our sectors before this point for (ushort index = 0; index <= (hexFileBytes.Length / blockSize); index++) { // write block to the board byte[] buffer = new byte[Math.Min(hexFileBytes.Length - (index * blockSize), blockSize)]; Array.Copy(hexFileBytes, index * blockSize, buffer, 0, buffer.Length); bool success = device.WriteMemoryBlock(index, buffer); if (!success) { throw new Exception("Write failed."); } // verify written block byte[] verifyBuffer = new byte[buffer.Length]; success = device.ReadMemoryBlock(index, verifyBuffer); if (!success || !buffer.SequenceEqual(verifyBuffer)) { throw new Exception("Verify failed."); } completedBlocks++; localProgressPercent = 0.5 + (((double)(completedBlocks + 1) / (double)totalBlockCount) * 0.5); _updateWorker.ReportProgress(CalculateWorkerProgress(localProgressPercent, startProgressPercent, operationTotalProgressPercent)); } } } // step 4: restart board device.SetAddressPointer(0x08000001); // NOTE: for thumb2 instructinos, we added 1 to the "base address". Otherwise our board will not restart properly. // leave DFU mode. device.LeaveDfuMode(); }
public bool ReadSettings(out byte productID, out byte[] macAddress, out byte otpSlotsFree) { macAddress = new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; // default to empty address otpSlotsFree = 0; // default to "no slots free" productID = 0; STDfuDevice device; try { device = new STDfuDevice(_devicePath); } catch { return(false); } try { // set pointer to the OTP memory space bool success = device.SetAddressPointer(0x1FFF7800); if (!success) { return(false); } // request the first 32 bytes of OTP; this will contain our board type and MAC address // OTP format: {unused, boardType, macAddress5, macAddress4, macAddress3, macAddress2, macAddress1, macAddress0} // NOTE: the first eight bytes are the data; if those bytes are all 0x00 then the next step of eight bytes are the data. Repeat up to 4 tries total to retrieve data. // netduino plus 2 //byte[] otpConfiguration = new byte[32] { 0xFF, 0x05, 0x5C, 0x86, 0x4A, 0x00, 0xD0, 0x05, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; // netduino plus 2 -- no MAC //byte[] otpConfiguration = new byte[32] { 0xFF, 0x05, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; // netduino 2 //byte[] otpConfiguration = new byte[32] { 0xFF, 0x06, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; // netduino go //byte[] otpConfiguration = new byte[32] { 0xFF, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; //device.WriteMemoryBlock(0, otpConfiguration); byte[] otpConfiguration = new byte[32]; success = device.ReadMemoryBlock(0, otpConfiguration); if (!success) { return(false); } int iConfiguration; for (iConfiguration = 0; iConfiguration < TOTAL_OTP_SLOTS; iConfiguration++) { bool configurationIsEmpty = true; // make sure that the configuration is not all 0xFF for (int iConfigurationByteCheck = 0; iConfigurationByteCheck < CONFIGURATION_SIZE; iConfigurationByteCheck++) { if (otpConfiguration[(iConfiguration * CONFIGURATION_SIZE) + iConfigurationByteCheck] != 0xFF) { configurationIsEmpty = false; } } bool configurationValid = false; if (!configurationIsEmpty) { for (int iConfigurationByteCheck = 0; iConfigurationByteCheck < CONFIGURATION_SIZE; iConfigurationByteCheck++) { if (otpConfiguration[(iConfiguration * CONFIGURATION_SIZE) + iConfigurationByteCheck] != 0) { configurationValid = true; } } // make sure that the leading byte is 0xFF if (otpConfiguration[(iConfiguration * CONFIGURATION_SIZE) + 0] != 0xFF) { configurationValid = false; } } else { otpSlotsFree = (byte)(TOTAL_OTP_SLOTS - iConfiguration); break; } if (configurationValid) { productID = otpConfiguration[(iConfiguration * CONFIGURATION_SIZE) + 1]; Array.Copy(otpConfiguration, (iConfiguration * CONFIGURATION_SIZE) + 2, macAddress, 0, 6); otpSlotsFree = (byte)(TOTAL_OTP_SLOTS - iConfiguration - 1); break; } } } finally { device.Dispose(); } return(true); }
public bool WriteSettings(byte productID, byte[] macAddress) { // validate arguments if (productID == 0xFF) { throw new ArgumentOutOfRangeException("productID"); } if (macAddress == null || macAddress.Length != 6) { throw new ArgumentOutOfRangeException("macAddress"); } STDfuDevice device = new STDfuDevice(_devicePath); try { // set pointer to the OTP memory space device.SetAddressPointer(0x1FFF7800); // request the first 32 bytes of OTP; this will contain our board type and MAC address // OTP format: {unused, boardType, macAddress5, macAddress4, macAddress3, macAddress2, macAddress1, macAddress0} // NOTE: the first eight bytes are the data; if those bytes are all 0x00 then the next set of eight bytes are the data. Repeat up to 4 tries total to retrieve data. // netduino plus 2 //byte[] otpConfiguration = new byte[32] { 0xFF, 0x05, 0x5C, 0x86, 0x4A, 0x00, 0xD0, 0x05, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; // netduino plus 2 -- no MAC //byte[] otpConfiguration = new byte[32] { 0xFF, 0x05, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; // netduino 2 //byte[] otpConfiguration = new byte[32] { 0xFF, 0x06, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; // netduino go //byte[] otpConfiguration = new byte[32] { 0xFF, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; byte[] otpConfiguration = new byte[32]; device.ReadMemoryBlock(0, otpConfiguration); // now determine which slot is our current slot int otpCurrentSlot = -1; // -1 = no slot used yet byte otpSlotsFree = 0; // default to "no slots free" int iConfiguration; for (iConfiguration = 0; iConfiguration < TOTAL_OTP_SLOTS; iConfiguration++) { bool configurationIsEmpty = true; // make sure that the configuration is not all 0xFF for (int iConfigurationByteCheck = 0; iConfigurationByteCheck < CONFIGURATION_SIZE; iConfigurationByteCheck++) { if (otpConfiguration[(iConfiguration * CONFIGURATION_SIZE) + iConfigurationByteCheck] != 0xFF) { configurationIsEmpty = false; } } bool configurationValid = false; if (!configurationIsEmpty) { for (int iConfigurationByteCheck = 0; iConfigurationByteCheck < CONFIGURATION_SIZE; iConfigurationByteCheck++) { if (otpConfiguration[(iConfiguration * CONFIGURATION_SIZE) + iConfigurationByteCheck] != 0) { configurationValid = true; } } // make sure that the leading byte is 0xFF if (otpConfiguration[(iConfiguration * CONFIGURATION_SIZE) + 0] != 0xFF) { configurationValid = false; } } else { otpSlotsFree = (byte)(TOTAL_OTP_SLOTS - iConfiguration); otpCurrentSlot = iConfiguration; break; } if (configurationValid) { otpSlotsFree = (byte)(TOTAL_OTP_SLOTS - iConfiguration - 1); otpCurrentSlot = iConfiguration; break; } } // if we don't have any slots available, return false if (otpCurrentSlot == -1) { return(false); } // create our configuration (8 bytes) byte[] deviceConfiguration = new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; deviceConfiguration[1] = productID; Array.Copy(macAddress, 0, deviceConfiguration, 2, macAddress.Length); // determine if we can re-use the current OTP block. If our new settings set any bits to "1" then we will copy to the next configuration slot. for (iConfiguration = otpCurrentSlot; iConfiguration < TOTAL_OTP_SLOTS; iConfiguration++) { byte[] newOtpConfiguration = new byte[otpConfiguration.Length]; Array.Copy(otpConfiguration, newOtpConfiguration, otpConfiguration.Length); Array.Copy(deviceConfiguration, 0, newOtpConfiguration, iConfiguration * CONFIGURATION_SIZE, deviceConfiguration.Length); // fill all previous slots with zeros (so they are marked as unused) for (int i = 0; i < iConfiguration * CONFIGURATION_SIZE; i++) { newOtpConfiguration[i] = 0; } bool slotCanBeUsed = true; // find out if we can write the new configuration in this slot (because it's either empty or we are only setting bits in a used region to 0s) for (int i = 0; i < deviceConfiguration.Length; i++) { byte oldOtpConfigurationByte = otpConfiguration[(iConfiguration * CONFIGURATION_SIZE) + i]; byte newOtpConfigurationByte = newOtpConfiguration[(iConfiguration * CONFIGURATION_SIZE) + i]; if ((oldOtpConfigurationByte & newOtpConfigurationByte) != newOtpConfigurationByte) { // new configuration byte cannot be set by turning "1" bits to "0" bits. slotCanBeUsed = false; } } if (slotCanBeUsed) { return(device.WriteMemoryBlock(0, newOtpConfiguration)); } } } finally { device.Dispose(); } // if we get here, we could not find a slot to write the configuration. return(false); }