mirror of
https://github.com/iNavFlight/inav-configurator.git
synced 2025-07-21 15:25:19 +03:00
Update STM32DFU procedure for H7 support
This commit is contained in:
parent
1d84fa0061
commit
0735671ae6
4 changed files with 471 additions and 243 deletions
|
@ -160,6 +160,88 @@
|
||||||
"message": "Are <strong>udev rules</strong> installed correctly? See docs for instructions"
|
"message": "Are <strong>udev rules</strong> installed correctly? See docs for instructions"
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"stm32UsbDfuNotFound": {
|
||||||
|
"message": "USB DFU not found"
|
||||||
|
},
|
||||||
|
"stm32RebootingToBootloader": {
|
||||||
|
"message": "Initiating reboot to bootloader ..."
|
||||||
|
},
|
||||||
|
"stm32RebootingToBootloaderFailed": {
|
||||||
|
"message": "Rebooting device to bootloader: FAILED"
|
||||||
|
},
|
||||||
|
"stm32TimedOut": {
|
||||||
|
"message": "STM32 - timed out, programming: FAILED"
|
||||||
|
},
|
||||||
|
"stm32WrongResponse": {
|
||||||
|
"message": "STM32 Communication failed, wrong response, expected: $1 (0x$2) received: $3 (0x$4)"
|
||||||
|
},
|
||||||
|
"stm32ContactingBootloader": {
|
||||||
|
"message": "Contacting bootloader ..."
|
||||||
|
},
|
||||||
|
"stm32ContactingBootloaderFailed": {
|
||||||
|
"message": "Communication with bootloader failed"
|
||||||
|
},
|
||||||
|
"stm32ResponseBootloaderFailed": {
|
||||||
|
"message": "No response from the bootloader, programming: FAILED"
|
||||||
|
},
|
||||||
|
"stm32GlobalEraseExtended": {
|
||||||
|
"message": "Executing global chip erase (via extended erase) ..."
|
||||||
|
},
|
||||||
|
"stm32LocalEraseExtended": {
|
||||||
|
"message": "Executing local erase (via extended erase) ..."
|
||||||
|
},
|
||||||
|
"stm32GlobalErase": {
|
||||||
|
"message": "Executing global chip erase ..."
|
||||||
|
},
|
||||||
|
"stm32LocalErase": {
|
||||||
|
"message": "Executing local erase ..."
|
||||||
|
},
|
||||||
|
"stm32InvalidHex": {
|
||||||
|
"message": "Invalid hex"
|
||||||
|
},
|
||||||
|
"stm32Erase": {
|
||||||
|
"message": "Erasing ..."
|
||||||
|
},
|
||||||
|
"stm32Flashing": {
|
||||||
|
"message": "Flashing ..."
|
||||||
|
},
|
||||||
|
"stm32Verifying": {
|
||||||
|
"message": "Verifying ..."
|
||||||
|
},
|
||||||
|
"stm32ProgrammingSuccessful": {
|
||||||
|
"message": "Programming: SUCCESSFUL"
|
||||||
|
},
|
||||||
|
"stm32ProgrammingFailed": {
|
||||||
|
"message": "Programming: FAILED"
|
||||||
|
},
|
||||||
|
"stm32AddressLoadFailed": {
|
||||||
|
"message": "Address load for option bytes sector failed. Very likely due to read protection."
|
||||||
|
},
|
||||||
|
"stm32AddressLoadSuccess": {
|
||||||
|
"message": "Address load for option bytes sector succeeded."
|
||||||
|
},
|
||||||
|
"stm32AddressLoadUnknown": {
|
||||||
|
"message": "Address load for option bytes sector failed with unknown error. Aborting."
|
||||||
|
},
|
||||||
|
"stm32NotReadProtected": {
|
||||||
|
"message": "Read protection not active"
|
||||||
|
},
|
||||||
|
"stm32ReadProtected": {
|
||||||
|
"message": "Board seems read protected. Unprotecting. Do not disconnect/unplug!"
|
||||||
|
},
|
||||||
|
"stm32UnprotectSuccessful": {
|
||||||
|
"message": "Unprotect successful."
|
||||||
|
},
|
||||||
|
"stm32UnprotectUnplug": {
|
||||||
|
"message": "ACTION REQUIRED: Unplug and re-connect flight controller in DFU mode to try flashing again!"
|
||||||
|
},
|
||||||
|
"stm32UnprotectFailed": {
|
||||||
|
"message": "Failed to unprotect board"
|
||||||
|
},
|
||||||
|
"stm32UnprotectInitFailed": {
|
||||||
|
"message": "Failed to initiate unprotect routine"
|
||||||
|
},
|
||||||
|
|
||||||
"noConfigurationReceived": {
|
"noConfigurationReceived": {
|
||||||
"message": "No configuration received within <span style=\"color: red\">10 seconds</span>, communication <span style=\"color: red\">failed</span>"
|
"message": "No configuration received within <span style=\"color: red\">10 seconds</span>, communication <span style=\"color: red\">failed</span>"
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,6 +1,18 @@
|
||||||
/*global $*/
|
/*global $*/
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
function checkChromeRuntimeError() {
|
||||||
|
if (chrome.runtime.lastError) {
|
||||||
|
console.error(
|
||||||
|
`Chrome API Error: ${chrome.runtime.lastError.message}.\n Traced ${
|
||||||
|
new Error().stack
|
||||||
|
}`
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
function constrain(input, min, max) {
|
function constrain(input, min, max) {
|
||||||
|
|
||||||
if (input < min) {
|
if (input < min) {
|
||||||
|
|
|
@ -13,9 +13,9 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var STM32DFU_protocol = function () {
|
var STM32DFU_protocol = function () {
|
||||||
this.callback; // ref
|
this.callback = null;
|
||||||
this.hex; // ref
|
this.hex = null;
|
||||||
this.verify_hex;
|
this.verify_hex = [];
|
||||||
|
|
||||||
this.handle = null; // connection handle
|
this.handle = null; // connection handle
|
||||||
|
|
||||||
|
@ -73,10 +73,13 @@ STM32DFU_protocol.prototype.connect = function (device, hex, options, callback)
|
||||||
self.callback = callback;
|
self.callback = callback;
|
||||||
|
|
||||||
self.options = {
|
self.options = {
|
||||||
erase_chip: false
|
erase_chip: false,
|
||||||
|
exitDfu: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (options.erase_chip) {
|
if (options.exitDfu) {
|
||||||
|
self.options.exitDfu = true;
|
||||||
|
} else if (options.erase_chip) {
|
||||||
self.options.erase_chip = true;
|
self.options.erase_chip = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,9 +88,7 @@ STM32DFU_protocol.prototype.connect = function (device, hex, options, callback)
|
||||||
self.verify_hex = [];
|
self.verify_hex = [];
|
||||||
|
|
||||||
// reset progress bar to initial state
|
// reset progress bar to initial state
|
||||||
self.progress_bar_e = $('.progress');
|
TABS.firmware_flasher.flashingMessage(null, TABS.firmware_flasher.FLASH_MESSAGE_TYPES.NEUTRAL).flashProgress(0);
|
||||||
self.progress_bar_e.val(0);
|
|
||||||
self.progress_bar_e.removeClass('valid invalid');
|
|
||||||
|
|
||||||
chrome.usb.getDevices(device, function (result) {
|
chrome.usb.getDevices(device, function (result) {
|
||||||
if (result.length) {
|
if (result.length) {
|
||||||
|
@ -96,29 +97,16 @@ STM32DFU_protocol.prototype.connect = function (device, hex, options, callback)
|
||||||
self.openDevice(result[0]);
|
self.openDevice(result[0]);
|
||||||
} else {
|
} else {
|
||||||
console.log('USB DFU not found');
|
console.log('USB DFU not found');
|
||||||
GUI.log('USB DFU not found');
|
GUI.log(chrome.i18n.getMessage('stm32UsbDfuNotFound'));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
STM32DFU_protocol.prototype.checkChromeError = function() {
|
|
||||||
if (chrome.runtime.lastError) {
|
|
||||||
if(chrome.runtime.lastError.message)
|
|
||||||
console.log('reporting chrome error: ' + chrome.runtime.lastError.message);
|
|
||||||
else
|
|
||||||
console.log('reporting chrome error: ' + chrome.runtime.lastError);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
STM32DFU_protocol.prototype.openDevice = function (device) {
|
STM32DFU_protocol.prototype.openDevice = function (device) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
chrome.usb.openDevice(device, function (handle) {
|
chrome.usb.openDevice(device, function (handle) {
|
||||||
if(self.checkChromeError()) {
|
if (checkChromeRuntimeError()) {
|
||||||
console.log('Failed to open USB device!');
|
console.log('Failed to open USB device!');
|
||||||
GUI.log(chrome.i18n.getMessage('usbDeviceOpenFail'));
|
GUI.log(chrome.i18n.getMessage('usbDeviceOpenFail'));
|
||||||
if(GUI.operating_system === 'Linux') {
|
if(GUI.operating_system === 'Linux') {
|
||||||
|
@ -139,7 +127,7 @@ STM32DFU_protocol.prototype.closeDevice = function () {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
chrome.usb.closeDevice(this.handle, function closed() {
|
chrome.usb.closeDevice(this.handle, function closed() {
|
||||||
if(self.checkChromeError()) {
|
if (checkChromeRuntimeError()) {
|
||||||
console.log('Failed to close USB device!');
|
console.log('Failed to close USB device!');
|
||||||
GUI.log(chrome.i18n.getMessage('usbDeviceCloseFail'));
|
GUI.log(chrome.i18n.getMessage('usbDeviceCloseFail'));
|
||||||
}
|
}
|
||||||
|
@ -155,14 +143,21 @@ STM32DFU_protocol.prototype.claimInterface = function (interfaceNumber) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
chrome.usb.claimInterface(this.handle, interfaceNumber, function claimed() {
|
chrome.usb.claimInterface(this.handle, interfaceNumber, function claimed() {
|
||||||
if(self.checkChromeError()) {
|
// Don't perform the error check on MacOS at this time as there seems to be a bug
|
||||||
|
// where it always reports the Chrome error "Error claiming interface." even though
|
||||||
|
// the interface is in fact successfully claimed.
|
||||||
|
if (checkChromeRuntimeError() && (GUI.operating_system !== "MacOS")) {
|
||||||
console.log('Failed to claim USB device!');
|
console.log('Failed to claim USB device!');
|
||||||
self.upload_procedure(99);
|
self.cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('Claimed interface: ' + interfaceNumber);
|
console.log('Claimed interface: ' + interfaceNumber);
|
||||||
|
|
||||||
|
if (self.options.exitDfu) {
|
||||||
|
self.leave();
|
||||||
|
} else {
|
||||||
self.upload_procedure(0);
|
self.upload_procedure(0);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -196,8 +191,8 @@ STM32DFU_protocol.prototype.getString = function (index, callback) {
|
||||||
'index': 0, // specifies language
|
'index': 0, // specifies language
|
||||||
'length': 255 // max length to retreive
|
'length': 255 // max length to retreive
|
||||||
}, function (result) {
|
}, function (result) {
|
||||||
if(self.checkChromeError()) {
|
if (checkChromeRuntimeError()) {
|
||||||
console.log('USB transfer failed! ' + result.resultCode);
|
console.log('USB getString failed! ' + result.resultCode);
|
||||||
callback("", result.resultCode);
|
callback("", result.resultCode);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -210,13 +205,13 @@ STM32DFU_protocol.prototype.getString = function (index, callback) {
|
||||||
}
|
}
|
||||||
callback(descriptor, result.resultCode);
|
callback(descriptor, result.resultCode);
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
STM32DFU_protocol.prototype.getInterfaceDescriptors = function (interfaceNum, callback) {
|
STM32DFU_protocol.prototype.getInterfaceDescriptors = function (interfaceNum, callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
chrome.usb.getConfiguration( this.handle, function (config) {
|
chrome.usb.getConfiguration( this.handle, function (config) {
|
||||||
if(self.checkChromeError()) {
|
if (checkChromeRuntimeError()) {
|
||||||
console.log('USB getConfiguration failed!');
|
console.log('USB getConfiguration failed!');
|
||||||
callback([], -200);
|
callback([], -200);
|
||||||
return;
|
return;
|
||||||
|
@ -248,10 +243,10 @@ STM32DFU_protocol.prototype.getInterfaceDescriptors = function (interfaceNum, ca
|
||||||
callback(descriptorStringArray, 0);
|
callback(descriptorStringArray, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
getDescriptorString();
|
getDescriptorString();
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
STM32DFU_protocol.prototype.getInterfaceDescriptor = function (_interface, callback) {
|
STM32DFU_protocol.prototype.getInterfaceDescriptor = function (_interface, callback) {
|
||||||
|
@ -265,8 +260,8 @@ STM32DFU_protocol.prototype.getInterfaceDescriptor = function (_interface, callb
|
||||||
'index': 0,
|
'index': 0,
|
||||||
'length': 18 + _interface * 9
|
'length': 18 + _interface * 9
|
||||||
}, function (result) {
|
}, function (result) {
|
||||||
if(self.checkChromeError()) {
|
if (checkChromeRuntimeError()) {
|
||||||
console.log('USB transfer failed! ' + result.resultCode);
|
console.log('USB getInterfaceDescriptor failed! ' + result.resultCode);
|
||||||
callback({}, result.resultCode);
|
callback({}, result.resultCode);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -286,7 +281,7 @@ STM32DFU_protocol.prototype.getInterfaceDescriptor = function (_interface, callb
|
||||||
|
|
||||||
callback(descriptor, result.resultCode);
|
callback(descriptor, result.resultCode);
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
STM32DFU_protocol.prototype.getFunctionalDescriptor = function (_interface, callback) {
|
STM32DFU_protocol.prototype.getFunctionalDescriptor = function (_interface, callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
@ -299,7 +294,7 @@ STM32DFU_protocol.prototype.getFunctionalDescriptor = function (_interface, call
|
||||||
'index': 0,
|
'index': 0,
|
||||||
'length': 255
|
'length': 255
|
||||||
}, function (result) {
|
}, function (result) {
|
||||||
if(self.checkChromeError()) {
|
if (checkChromeRuntimeError()) {
|
||||||
console.log('USB getFunctionalDescriptor failed! ' + result.resultCode);
|
console.log('USB getFunctionalDescriptor failed! ' + result.resultCode);
|
||||||
callback({}, result.resultCode);
|
callback({}, result.resultCode);
|
||||||
return;
|
return;
|
||||||
|
@ -318,7 +313,7 @@ STM32DFU_protocol.prototype.getFunctionalDescriptor = function (_interface, call
|
||||||
|
|
||||||
callback(descriptor, result.resultCode);
|
callback(descriptor, result.resultCode);
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
STM32DFU_protocol.prototype.getChipInfo = function (_interface, callback) {
|
STM32DFU_protocol.prototype.getChipInfo = function (_interface, callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
@ -329,15 +324,43 @@ STM32DFU_protocol.prototype.getChipInfo = function (_interface, callback) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Keep this for new MCU debugging
|
||||||
|
// console.log('Descriptors: ' + descriptors);
|
||||||
|
|
||||||
var parseDescriptor = function(str) {
|
var parseDescriptor = function(str) {
|
||||||
// F303: "@Internal Flash /0x08000000/128*0002Kg"
|
// F303: "@Internal Flash /0x08000000/128*0002Kg"
|
||||||
// F40x: "@Internal Flash /0x08000000/04*016Kg,01*064Kg,07*128Kg"
|
// F40x: "@Internal Flash /0x08000000/04*016Kg,01*064Kg,07*128Kg"
|
||||||
// F72x: "@Internal Flash /0x08000000/04*016Kg,01*64Kg,03*128Kg"
|
// F72x: "@Internal Flash /0x08000000/04*016Kg,01*64Kg,03*128Kg"
|
||||||
// F74x: "@Internal Flash /0x08000000/04*032Kg,01*128Kg,03*256Kg"
|
// F74x: "@Internal Flash /0x08000000/04*032Kg,01*128Kg,03*256Kg"
|
||||||
|
|
||||||
|
// H750 SPRacing H7 EXST: "@External Flash /0x90000000/998*128Kg,1*128Kg,4*128Kg,21*128Ka"
|
||||||
|
// H750 SPRacing H7 EXST: "@External Flash /0x90000000/1001*128Kg,3*128Kg,20*128Ka" - Early BL firmware with incorrect string, treat as above.
|
||||||
|
|
||||||
|
// H750 Partitions: Flash, Config, Firmware, 1x BB Management block + x BB Replacement blocks)
|
||||||
|
if (str == "@External Flash /0x90000000/1001*128Kg,3*128Kg,20*128Ka") {
|
||||||
|
str = "@External Flash /0x90000000/998*128Kg,1*128Kg,4*128Kg,21*128Ka";
|
||||||
|
}
|
||||||
|
|
||||||
// split main into [location, start_addr, sectors]
|
// split main into [location, start_addr, sectors]
|
||||||
|
|
||||||
var tmp0 = str.replace(/[^\x20-\x7E]+/g, "");
|
var tmp0 = str.replace(/[^\x20-\x7E]+/g, "");
|
||||||
var tmp1 = tmp0.split('/');
|
var tmp1 = tmp0.split('/');
|
||||||
if (tmp1.length != 3 || !tmp1[0].startsWith("@")) {
|
|
||||||
|
// G474 (and may be other G4 variants) returns
|
||||||
|
// "@Option Bytes /0x1FFF7800/01*048 e/0x1FFFF800/01*048 e"
|
||||||
|
// for two banks of options bytes which may be fine in terms of descriptor syntax,
|
||||||
|
// but as this splits into an array of size 5 instead of 3, it induces an length error.
|
||||||
|
// Here, we blindly trim the array length to 3. While doing so may fail to
|
||||||
|
// capture errornous patterns, but it is good to avoid this known and immediate
|
||||||
|
// error.
|
||||||
|
// May need to preserve the second bank if the configurator starts to really
|
||||||
|
// support option bytes.
|
||||||
|
|
||||||
|
if (tmp1.length > 3) {
|
||||||
|
console.log('parseDescriptor: shrinking long descriptor "' + str + '"');
|
||||||
|
tmp1.length = 3;
|
||||||
|
}
|
||||||
|
if (!tmp1[0].startsWith("@")) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
var type = tmp1[0].trim().replace('@', '');
|
var type = tmp1[0].trim().replace('@', '');
|
||||||
|
@ -368,11 +391,6 @@ STM32DFU_protocol.prototype.getChipInfo = function (_interface, callback) {
|
||||||
case 'K':
|
case 'K':
|
||||||
page_size *= 1024;
|
page_size *= 1024;
|
||||||
break;
|
break;
|
||||||
/* case ' ':
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return null;
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sectors.push({
|
sectors.push({
|
||||||
|
@ -390,16 +408,16 @@ STM32DFU_protocol.prototype.getChipInfo = function (_interface, callback) {
|
||||||
'start_address': start_address,
|
'start_address': start_address,
|
||||||
'sectors' : sectors,
|
'sectors' : sectors,
|
||||||
'total_size' : total_size
|
'total_size' : total_size
|
||||||
}
|
};
|
||||||
return memory;
|
return memory;
|
||||||
}
|
};
|
||||||
var chipInfo = descriptors.map(parseDescriptor).reduce(function(o, v, i) {
|
var chipInfo = descriptors.map(parseDescriptor).reduce(function(o, v, i) {
|
||||||
o[v.type.toLowerCase().replace(' ', '_')] = v;
|
o[v.type.toLowerCase().replace(' ', '_')] = v;
|
||||||
return o;
|
return o;
|
||||||
}, {});
|
}, {});
|
||||||
callback(chipInfo, resultCode);
|
callback(chipInfo, resultCode);
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
STM32DFU_protocol.prototype.controlTransfer = function (direction, request, value, _interface, length, data, callback, _timeout) {
|
STM32DFU_protocol.prototype.controlTransfer = function (direction, request, value, _interface, length, data, callback, _timeout) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
@ -424,8 +442,8 @@ STM32DFU_protocol.prototype.controlTransfer = function (direction, request, valu
|
||||||
'length': length,
|
'length': length,
|
||||||
'timeout': timeout
|
'timeout': timeout
|
||||||
}, function (result) {
|
}, function (result) {
|
||||||
if(self.checkChromeError()) {
|
if (checkChromeRuntimeError()) {
|
||||||
console.log('USB transfer failed!');
|
console.log('USB controlTransfer IN failed for request ' + request + '!');
|
||||||
}
|
}
|
||||||
if (result.resultCode) console.log('USB transfer result code: ' + result.resultCode);
|
if (result.resultCode) console.log('USB transfer result code: ' + result.resultCode);
|
||||||
|
|
||||||
|
@ -452,8 +470,8 @@ STM32DFU_protocol.prototype.controlTransfer = function (direction, request, valu
|
||||||
'data': arrayBuf,
|
'data': arrayBuf,
|
||||||
'timeout': timeout
|
'timeout': timeout
|
||||||
}, function (result) {
|
}, function (result) {
|
||||||
if(self.checkChromeError()) {
|
if (checkChromeRuntimeError()) {
|
||||||
console.log('USB transfer failed!');
|
console.log('USB controlTransfer OUT failed for request ' + request + '!');
|
||||||
}
|
}
|
||||||
if (result.resultCode) console.log('USB transfer result code: ' + result.resultCode);
|
if (result.resultCode) console.log('USB transfer result code: ' + result.resultCode);
|
||||||
|
|
||||||
|
@ -488,7 +506,7 @@ STM32DFU_protocol.prototype.clearStatus = function (callback) {
|
||||||
STM32DFU_protocol.prototype.loadAddress = function (address, callback, abort) {
|
STM32DFU_protocol.prototype.loadAddress = function (address, callback, abort) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
self.controlTransfer('out', self.request.DNLOAD, 0, 0, 0, [0x21, address, (address >> 8), (address >> 16), (address >> 24)], function () {
|
self.controlTransfer('out', self.request.DNLOAD, 0, 0, 0, [0x21, address & 0xff, (address >> 8) & 0xff, (address >> 16) & 0xff, (address >> 24) & 0xff], function () {
|
||||||
self.controlTransfer('in', self.request.GETSTATUS, 0, 0, 6, 0, function (data) {
|
self.controlTransfer('in', self.request.GETSTATUS, 0, 0, 6, 0, function (data) {
|
||||||
if (data[4] == self.state.dfuDNBUSY) {
|
if (data[4] == self.state.dfuDNBUSY) {
|
||||||
var delay = data[1] | (data[2] << 8) | (data[3] << 16);
|
var delay = data[1] | (data[2] << 8) | (data[3] << 16);
|
||||||
|
@ -500,7 +518,7 @@ STM32DFU_protocol.prototype.loadAddress = function (address, callback, abort) {
|
||||||
} else {
|
} else {
|
||||||
console.log('Failed to execute address load');
|
console.log('Failed to execute address load');
|
||||||
if(typeof abort === "undefined" || abort) {
|
if(typeof abort === "undefined" || abort) {
|
||||||
self.upload_procedure(99);
|
self.cleanup();
|
||||||
} else {
|
} else {
|
||||||
callback(data);
|
callback(data);
|
||||||
}
|
}
|
||||||
|
@ -509,7 +527,7 @@ STM32DFU_protocol.prototype.loadAddress = function (address, callback, abort) {
|
||||||
}, delay);
|
}, delay);
|
||||||
} else {
|
} else {
|
||||||
console.log('Failed to request address load');
|
console.log('Failed to request address load');
|
||||||
self.upload_procedure(99);
|
self.cleanup();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -539,13 +557,10 @@ STM32DFU_protocol.prototype.upload_procedure = function (step) {
|
||||||
self.getChipInfo(0, function (chipInfo, resultCode) {
|
self.getChipInfo(0, function (chipInfo, resultCode) {
|
||||||
if (resultCode != 0 || typeof chipInfo === "undefined") {
|
if (resultCode != 0 || typeof chipInfo === "undefined") {
|
||||||
console.log('Failed to detect chip info, resultCode: ' + resultCode);
|
console.log('Failed to detect chip info, resultCode: ' + resultCode);
|
||||||
self.upload_procedure(99);
|
self.cleanup();
|
||||||
} else {
|
} else {
|
||||||
if (typeof chipInfo.internal_flash === "undefined") {
|
if (typeof chipInfo.internal_flash !== "undefined") {
|
||||||
console.log('Failed to detect internal flash');
|
// internal flash
|
||||||
self.upload_procedure(99);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.chipInfo = chipInfo;
|
self.chipInfo = chipInfo;
|
||||||
|
|
||||||
self.flash_layout = chipInfo.internal_flash;
|
self.flash_layout = chipInfo.internal_flash;
|
||||||
|
@ -557,7 +572,7 @@ STM32DFU_protocol.prototype.upload_procedure = function (step) {
|
||||||
GUI.log(chrome.i18n.getMessage('dfu_error_image_size',
|
GUI.log(chrome.i18n.getMessage('dfu_error_image_size',
|
||||||
[(self.hex.bytes_total / 1024.0).toFixed(1),
|
[(self.hex.bytes_total / 1024.0).toFixed(1),
|
||||||
(self.available_flash_size / 1024.0).toFixed(1)]));
|
(self.available_flash_size / 1024.0).toFixed(1)]));
|
||||||
self.upload_procedure(99);
|
self.cleanup();
|
||||||
} else {
|
} else {
|
||||||
self.getFunctionalDescriptor(0, function (descriptor, resultCode) {
|
self.getFunctionalDescriptor(0, function (descriptor, resultCode) {
|
||||||
self.transferSize = resultCode ? 2048 : descriptor.wTransferSize;
|
self.transferSize = resultCode ? 2048 : descriptor.wTransferSize;
|
||||||
|
@ -567,20 +582,51 @@ STM32DFU_protocol.prototype.upload_procedure = function (step) {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
} else if (typeof chipInfo.external_flash !== "undefined") {
|
||||||
|
// external flash, flash to the 3rd partition.
|
||||||
|
self.chipInfo = chipInfo;
|
||||||
|
self.flash_layout = chipInfo.external_flash;
|
||||||
|
|
||||||
|
var firmware_partition_index = 2;
|
||||||
|
var firmware_sectors = self.flash_layout.sectors[firmware_partition_index];
|
||||||
|
var firmware_partition_size = firmware_sectors.total_size;
|
||||||
|
|
||||||
|
self.available_flash_size = firmware_partition_size;
|
||||||
|
|
||||||
|
GUI.log(chrome.i18n.getMessage('dfu_device_flash_info', (self.flash_layout.total_size / 1024).toString()));
|
||||||
|
|
||||||
|
if (self.hex.bytes_total > self.available_flash_size) {
|
||||||
|
GUI.log(chrome.i18n.getMessage('dfu_error_image_size',
|
||||||
|
[(self.hex.bytes_total / 1024.0).toFixed(1),
|
||||||
|
(self.available_flash_size / 1024.0).toFixed(1)]));
|
||||||
|
self.cleanup();
|
||||||
|
} else {
|
||||||
|
self.getFunctionalDescriptor(0, function (descriptor, resultCode) {
|
||||||
|
self.transferSize = resultCode ? 2048 : descriptor.wTransferSize;
|
||||||
|
console.log('Using transfer size: ' + self.transferSize);
|
||||||
|
self.clearStatus(function () {
|
||||||
|
self.upload_procedure(2); // no option bytes to deal with
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log('Failed to detect internal or external flash');
|
||||||
|
self.cleanup();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
if (typeof self.chipInfo.option_bytes === "undefined") {
|
if (typeof self.chipInfo.option_bytes === "undefined") {
|
||||||
console.log('Failed to detect option bytes');
|
console.log('Failed to detect option bytes');
|
||||||
self.upload_procedure(99);
|
self.cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
var unprotect = function() {
|
var unprotect = function() {
|
||||||
console.log('Initiate read unprotect');
|
console.log('Initiate read unprotect');
|
||||||
GUI.log('Chip seems read protected. Initiating read unprotect');
|
let messageReadProtected = chrome.i18n.getMessage('stm32ReadProtected');
|
||||||
$('span.progressLabel').text('Board seems read protected. Unprotecting. Do not disconnect/unplug!');
|
GUI.log(messageReadProtected);
|
||||||
self.progress_bar_e.addClass('actionRequired');
|
TABS.firmware_flasher.flashingMessage(messageReadProtected, TABS.firmware_flasher.FLASH_MESSAGE_TYPES.ACTION);
|
||||||
|
|
||||||
self.controlTransfer('out', self.request.DNLOAD, 0, 0, 0, [0x92], function () { // 0x92 initiates read unprotect
|
self.controlTransfer('out', self.request.DNLOAD, 0, 0, 0, [0x92], function () { // 0x92 initiates read unprotect
|
||||||
self.controlTransfer('in', self.request.GETSTATUS, 0, 0, 6, 0, function (data) {
|
self.controlTransfer('in', self.request.GETSTATUS, 0, 0, 6, 0, function (data) {
|
||||||
|
@ -588,11 +634,12 @@ STM32DFU_protocol.prototype.upload_procedure = function (step) {
|
||||||
var delay = data[1] | (data[2] << 8) | (data[3] << 16);
|
var delay = data[1] | (data[2] << 8) | (data[3] << 16);
|
||||||
var total_delay = delay + 20000; // wait at least 20 seconds to make sure the user does not disconnect the board while erasing the memory
|
var total_delay = delay + 20000; // wait at least 20 seconds to make sure the user does not disconnect the board while erasing the memory
|
||||||
var timeSpentWaiting = 0;
|
var timeSpentWaiting = 0;
|
||||||
var incr = 1000; // one sec incements
|
var incr = 1000; // one sec increments
|
||||||
var waitForErase = setInterval(function () {
|
var waitForErase = setInterval(function () {
|
||||||
self.progress_bar_e.val( Math.min(timeSpentWaiting/total_delay,1) * 100);
|
|
||||||
if(timeSpentWaiting < total_delay)
|
TABS.firmware_flasher.flashProgress(Math.min(timeSpentWaiting / total_delay, 1) * 100);
|
||||||
{
|
|
||||||
|
if(timeSpentWaiting < total_delay) {
|
||||||
timeSpentWaiting += incr;
|
timeSpentWaiting += incr;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -600,45 +647,48 @@ STM32DFU_protocol.prototype.upload_procedure = function (step) {
|
||||||
self.controlTransfer('in', self.request.GETSTATUS, 0, 0, 6, 0, function (data, error) { // should stall/disconnect
|
self.controlTransfer('in', self.request.GETSTATUS, 0, 0, 6, 0, function (data, error) { // should stall/disconnect
|
||||||
if(error) { // we encounter an error, but this is expected. should be a stall.
|
if(error) { // we encounter an error, but this is expected. should be a stall.
|
||||||
console.log('Unprotect memory command ran successfully. Unplug flight controller. Connect again in DFU mode and try flashing again.');
|
console.log('Unprotect memory command ran successfully. Unplug flight controller. Connect again in DFU mode and try flashing again.');
|
||||||
GUI.log('Unprotect successful. ACTION REQUIRED: Unplug and re-connect flight controller in DFU mode to try flashing again!');
|
GUI.log(chrome.i18n.getMessage('stm32UnprotectSuccessful'));
|
||||||
$('span.progressLabel').text('ACTION REQUIRED: Unplug and re-connect flight controller in DFU mode to try flashing again!');
|
|
||||||
self.progress_bar_e.val(0);
|
let messageUnprotectUnplug = chrome.i18n.getMessage('stm32UnprotectUnplug');
|
||||||
self.progress_bar_e.addClass('actionRequired');
|
GUI.log(messageUnprotectUnplug);
|
||||||
|
|
||||||
|
TABS.firmware_flasher.flashingMessage(messageUnprotectUnplug, TABS.firmware_flasher.FLASH_MESSAGE_TYPES.ACTION)
|
||||||
|
.flashProgress(0);
|
||||||
|
|
||||||
} else { // unprotecting the flight controller did not work. It did not reboot.
|
} else { // unprotecting the flight controller did not work. It did not reboot.
|
||||||
console.log('Failed to execute unprotect memory command');
|
console.log('Failed to execute unprotect memory command');
|
||||||
GUI.log('Failed to unprotect chip');
|
|
||||||
$('span.progressLabel').text('Failed to unprotect board');
|
GUI.log(chrome.i18n.getMessage('stm32UnprotectFailed'));
|
||||||
self.progress_bar_e.addClass('invalid');
|
TABS.firmware_flasher.flashingMessage(chrome.i18n.getMessage('stm32UnprotectFailed'), TABS.firmware_flasher.FLASH_MESSAGE_TYPES.INVALID);
|
||||||
console.log(data);
|
console.log(data);
|
||||||
self.upload_procedure(99);
|
self.cleanup();
|
||||||
}
|
}
|
||||||
}, 2000); // this should stall/disconnect anyways. so we only wait 2 sec max.
|
}, 2000); // this should stall/disconnect anyways. so we only wait 2 sec max.
|
||||||
}, incr);
|
}, incr);
|
||||||
} else {
|
} else {
|
||||||
console.log('Failed to initiate unprotect memory command');
|
console.log('Failed to initiate unprotect memory command');
|
||||||
GUI.log('Failed to initiate unprotect routine');
|
let messageUnprotectInitFailed = chrome.i18n.getMessage('stm32UnprotectInitFailed');
|
||||||
$('span.progressLabel').text('Failed to initate unprotect');
|
GUI.log(messageUnprotectInitFailed);
|
||||||
self.progress_bar_e.addClass('invalid');
|
TABS.firmware_flasher.flashingMessage(messageUnprotectInitFailed, TABS.firmware_flasher.FLASH_MESSAGE_TYPES.INVALID);
|
||||||
self.upload_procedure(99);
|
self.cleanup();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
var tryReadOB = function() {
|
var tryReadOB = function() {
|
||||||
// the following should fail if read protection is active
|
// the following should fail if read protection is active
|
||||||
self.controlTransfer('in', self.request.UPLOAD, 2, 0, self.chipInfo.option_bytes.total_size, 0, function (ob_data, errcode) {
|
self.controlTransfer('in', self.request.UPLOAD, 2, 0, self.chipInfo.option_bytes.total_size, 0, function (ob_data, errcode) {
|
||||||
if(errcode) {
|
if(errcode) {
|
||||||
console.log('USB transfer error while reading option bytes: ' + errcode1);
|
console.log('USB transfer error while reading option bytes: ' + errcode1);
|
||||||
self.upload_procedure(99);
|
self.cleanup();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self.controlTransfer('in', self.request.GETSTATUS, 0, 0, 6, 0, function (data) {
|
self.controlTransfer('in', self.request.GETSTATUS, 0, 0, 6, 0, function (data) {
|
||||||
if (data[4] == self.state.dfuUPLOAD_IDLE && ob_data.length == self.chipInfo.option_bytes.total_size) {
|
if (data[4] == self.state.dfuUPLOAD_IDLE && ob_data.length == self.chipInfo.option_bytes.total_size) {
|
||||||
console.log('Option bytes read successfully');
|
console.log('Option bytes read successfully');
|
||||||
console.log('Chip does not appear read protected');
|
console.log('Chip does not appear read protected');
|
||||||
GUI.log('Read protection not active');
|
GUI.log(chrome.i18n.getMessage('stm32NotReadProtected'));
|
||||||
// it is pretty safe to continue to erase flash
|
// it is pretty safe to continue to erase flash
|
||||||
self.clearStatus(function() {
|
self.clearStatus(function() {
|
||||||
self.upload_procedure(2);
|
self.upload_procedure(2);
|
||||||
|
@ -655,16 +705,16 @@ STM32DFU_protocol.prototype.upload_procedure = function (step) {
|
||||||
self.controlTransfer('in', self.request.GETSTATUS, 0, 0, 6, 0, function (data) {
|
self.controlTransfer('in', self.request.GETSTATUS, 0, 0, 6, 0, function (data) {
|
||||||
if (data[4] == self.state.dfuDNLOAD_IDLE) {
|
if (data[4] == self.state.dfuDNLOAD_IDLE) {
|
||||||
console.log('Failed to write ob');
|
console.log('Failed to write ob');
|
||||||
self.upload_procedure(99);
|
self.cleanup();
|
||||||
} else {
|
} else {
|
||||||
console.log('Success writing ob');
|
console.log('Success writing ob');
|
||||||
self.upload_procedure(99);
|
self.cleanup();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}, delay);
|
}, delay);
|
||||||
} else {
|
} else {
|
||||||
console.log('Failed to initiate write ob');
|
console.log('Failed to initiate write ob');
|
||||||
self.upload_procedure(99);
|
self.cleanup();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -680,24 +730,24 @@ STM32DFU_protocol.prototype.upload_procedure = function (step) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
var initReadOB = function (loadAddressResponse) {
|
var initReadOB = function (loadAddressResponse) {
|
||||||
// contrary to what is in the docs. Address load should in theory work even if read protection is active
|
// contrary to what is in the docs. Address load should in theory work even if read protection is active
|
||||||
// if address load fails with this specific error though, it is very likely bc of read protection
|
// if address load fails with this specific error though, it is very likely bc of read protection
|
||||||
if(loadAddressResponse[4] == self.state.dfuERROR && loadAddressResponse[0] == self.status.errVENDOR) {
|
if(loadAddressResponse[4] == self.state.dfuERROR && loadAddressResponse[0] == self.status.errVENDOR) {
|
||||||
// read protected
|
// read protected
|
||||||
GUI.log('Address load for option bytes sector failed. Very likely due to read protection.');
|
GUI.log(chrome.i18n.getMessage('stm32AddressLoadFailed'));
|
||||||
self.clearStatus(unprotect);
|
self.clearStatus(unprotect);
|
||||||
return;
|
return;
|
||||||
} else if(loadAddressResponse[4] == self.state.dfuDNLOAD_IDLE) {
|
} else if(loadAddressResponse[4] == self.state.dfuDNLOAD_IDLE) {
|
||||||
console.log('Address load for option bytes sector succeeded.');
|
console.log('Address load for option bytes sector succeeded.');
|
||||||
self.clearStatus(tryReadOB);
|
self.clearStatus(tryReadOB);
|
||||||
} else {
|
} else {
|
||||||
GUI.log('Address load for option bytes sector failed with unknown error. Aborting.');
|
GUI.log(chrome.i18n.getMessage('stm32AddressLoadUnknown'));
|
||||||
self.upload_procedure(99);
|
self.cleanup();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
self.clearStatus(function () {
|
self.clearStatus(function () {
|
||||||
// load address fails if read protection is active unlike as stated in the docs
|
// load address fails if read protection is active unlike as stated in the docs
|
||||||
|
@ -733,12 +783,34 @@ STM32DFU_protocol.prototype.upload_procedure = function (step) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$('span.progressLabel').text('Erasing ...');
|
|
||||||
console.log('Executing local chip erase');
|
if (erase_pages.length === 0) {
|
||||||
|
console.log('Aborting, No flash pages to erase');
|
||||||
|
TABS.firmware_flasher.flashingMessage(chrome.i18n.getMessage('stm32InvalidHex'), TABS.firmware_flasher.FLASH_MESSAGE_TYPES.INVALID);
|
||||||
|
self.cleanup();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TABS.firmware_flasher.flashingMessage(chrome.i18n.getMessage('stm32Erase'), TABS.firmware_flasher.FLASH_MESSAGE_TYPES.NEUTRAL);
|
||||||
|
console.log('Executing local chip erase', erase_pages);
|
||||||
|
|
||||||
var page = 0;
|
var page = 0;
|
||||||
var total_erased = 0; // bytes
|
var total_erased = 0; // bytes
|
||||||
|
|
||||||
|
var erase_page_next = function() {
|
||||||
|
TABS.firmware_flasher.flashProgress((page + 1) / erase_pages.length * 100);
|
||||||
|
page++;
|
||||||
|
|
||||||
|
if(page == erase_pages.length) {
|
||||||
|
console.log("Erase: complete");
|
||||||
|
GUI.log(chrome.i18n.getMessage('dfu_erased_kilobytes', (total_erased / 1024).toString()));
|
||||||
|
self.upload_procedure(4);
|
||||||
|
} else {
|
||||||
|
erase_page();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
var erase_page = function() {
|
var erase_page = function() {
|
||||||
var page_addr = erase_pages[page].page * self.flash_layout.sectors[erase_pages[page].sector].page_size +
|
var page_addr = erase_pages[page].page * self.flash_layout.sectors[erase_pages[page].sector].page_size +
|
||||||
self.flash_layout.sectors[erase_pages[page].sector].start_address;
|
self.flash_layout.sectors[erase_pages[page].sector].start_address;
|
||||||
|
@ -754,27 +826,41 @@ STM32DFU_protocol.prototype.upload_procedure = function (step) {
|
||||||
|
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
self.controlTransfer('in', self.request.GETSTATUS, 0, 0, 6, 0, function (data) {
|
self.controlTransfer('in', self.request.GETSTATUS, 0, 0, 6, 0, function (data) {
|
||||||
if (data[4] == self.state.dfuDNLOAD_IDLE) {
|
|
||||||
// update progress bar
|
|
||||||
self.progress_bar_e.val((page + 1) / erase_pages.length * 100);
|
|
||||||
page++;
|
|
||||||
|
|
||||||
if(page == erase_pages.length) {
|
if (data[4] == self.state.dfuDNBUSY) {
|
||||||
console.log("Erase: complete");
|
|
||||||
GUI.log(chrome.i18n.getMessage('dfu_erased_kilobytes', (total_erased / 1024).toString()));
|
//
|
||||||
self.upload_procedure(4);
|
// H743 Rev.V (probably other H7 Rev.Vs also) remains in dfuDNBUSY state after the specified delay time.
|
||||||
|
// STM32CubeProgrammer deals with behavior with an undocumented procedure as follows.
|
||||||
|
// 1. Issue DFU_CLRSTATUS, which ends up with (14,10) = (errUNKNOWN, dfuERROR)
|
||||||
|
// 2. Issue another DFU_CLRSTATUS which delivers (0,2) = (OK, dfuIDLE)
|
||||||
|
// 3. Treat the current erase successfully finished.
|
||||||
|
// Here, we call clarStatus to get to the dfuIDLE state.
|
||||||
|
//
|
||||||
|
|
||||||
|
console.log('erase_page: dfuDNBUSY after timeout, clearing');
|
||||||
|
|
||||||
|
self.clearStatus(function() {
|
||||||
|
self.controlTransfer('in', self.request.GETSTATUS, 0, 0, 6, 0, function (data) {
|
||||||
|
if (data[4] == self.state.dfuIDLE) {
|
||||||
|
erase_page_next();
|
||||||
|
} else {
|
||||||
|
console.log('Failed to erase page 0x' + page_addr.toString(16) + ' (did not reach dfuIDLE after clearing');
|
||||||
|
self.cleanup();
|
||||||
}
|
}
|
||||||
else
|
});
|
||||||
erase_page();
|
});
|
||||||
|
} else if (data[4] == self.state.dfuDNLOAD_IDLE) {
|
||||||
|
erase_page_next();
|
||||||
} else {
|
} else {
|
||||||
console.log('Failed to erase page 0x' + page_addr.toString(16));
|
console.log('Failed to erase page 0x' + page_addr.toString(16));
|
||||||
self.upload_procedure(99);
|
self.cleanup();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}, delay);
|
}, delay);
|
||||||
} else {
|
} else {
|
||||||
console.log('Failed to initiate page erase, page 0x' + page_addr.toString(16));
|
console.log('Failed to initiate page erase, page 0x' + page_addr.toString(16));
|
||||||
self.upload_procedure(99);
|
self.cleanup();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -788,7 +874,7 @@ STM32DFU_protocol.prototype.upload_procedure = function (step) {
|
||||||
// upload
|
// upload
|
||||||
// we dont need to clear the state as we are already using DFU_DNLOAD
|
// we dont need to clear the state as we are already using DFU_DNLOAD
|
||||||
console.log('Writing data ...');
|
console.log('Writing data ...');
|
||||||
$('span.progressLabel').text('Flashing ...');
|
TABS.firmware_flasher.flashingMessage(chrome.i18n.getMessage('stm32Flashing'), TABS.firmware_flasher.FLASH_MESSAGE_TYPES.NEUTRAL);
|
||||||
|
|
||||||
var blocks = self.hex.data.length - 1;
|
var blocks = self.hex.data.length - 1;
|
||||||
var flashing_block = 0;
|
var flashing_block = 0;
|
||||||
|
@ -817,22 +903,22 @@ STM32DFU_protocol.prototype.upload_procedure = function (step) {
|
||||||
self.controlTransfer('in', self.request.GETSTATUS, 0, 0, 6, 0, function (data) {
|
self.controlTransfer('in', self.request.GETSTATUS, 0, 0, 6, 0, function (data) {
|
||||||
if (data[4] == self.state.dfuDNLOAD_IDLE) {
|
if (data[4] == self.state.dfuDNLOAD_IDLE) {
|
||||||
// update progress bar
|
// update progress bar
|
||||||
self.progress_bar_e.val(bytes_flashed_total / (self.hex.bytes_total * 2) * 100);
|
TABS.firmware_flasher.flashProgress(bytes_flashed_total / (self.hex.bytes_total * 2) * 100);
|
||||||
|
|
||||||
// flash another page
|
// flash another page
|
||||||
write();
|
write();
|
||||||
} else {
|
} else {
|
||||||
console.log('Failed to write ' + bytes_to_write + 'bytes to 0x' + address.toString(16));
|
console.log('Failed to write ' + bytes_to_write + 'bytes to 0x' + address.toString(16));
|
||||||
self.upload_procedure(99);
|
self.cleanup();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}, delay);
|
}, delay);
|
||||||
} else {
|
} else {
|
||||||
console.log('Failed to initiate write ' + bytes_to_write + 'bytes to 0x' + address.toString(16));
|
console.log('Failed to initiate write ' + bytes_to_write + 'bytes to 0x' + address.toString(16));
|
||||||
self.upload_procedure(99);
|
self.cleanup();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
})
|
});
|
||||||
} else {
|
} else {
|
||||||
if (flashing_block < blocks) {
|
if (flashing_block < blocks) {
|
||||||
// move to another block
|
// move to another block
|
||||||
|
@ -851,7 +937,7 @@ STM32DFU_protocol.prototype.upload_procedure = function (step) {
|
||||||
self.upload_procedure(5);
|
self.upload_procedure(5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
// start
|
// start
|
||||||
self.loadAddress(address, write);
|
self.loadAddress(address, write);
|
||||||
|
@ -860,7 +946,7 @@ STM32DFU_protocol.prototype.upload_procedure = function (step) {
|
||||||
case 5:
|
case 5:
|
||||||
// verify
|
// verify
|
||||||
console.log('Verifying data ...');
|
console.log('Verifying data ...');
|
||||||
$('span.progressLabel').text('Verifying ...');
|
TABS.firmware_flasher.flashingMessage(chrome.i18n.getMessage('stm32Verifying'), TABS.firmware_flasher.FLASH_MESSAGE_TYPES.NEUTRAL);
|
||||||
|
|
||||||
var blocks = self.hex.data.length - 1;
|
var blocks = self.hex.data.length - 1;
|
||||||
var reading_block = 0;
|
var reading_block = 0;
|
||||||
|
@ -896,7 +982,7 @@ STM32DFU_protocol.prototype.upload_procedure = function (step) {
|
||||||
bytes_verified_total += bytes_to_read;
|
bytes_verified_total += bytes_to_read;
|
||||||
|
|
||||||
// update progress bar
|
// update progress bar
|
||||||
self.progress_bar_e.val((self.hex.bytes_total + bytes_verified_total) / (self.hex.bytes_total * 2) * 100);
|
TABS.firmware_flasher.flashProgress((self.hex.bytes_total + bytes_verified_total) / (self.hex.bytes_total * 2) * 100);
|
||||||
|
|
||||||
// verify another page
|
// verify another page
|
||||||
read();
|
read();
|
||||||
|
@ -927,46 +1013,54 @@ STM32DFU_protocol.prototype.upload_procedure = function (step) {
|
||||||
|
|
||||||
if (verify) {
|
if (verify) {
|
||||||
console.log('Programming: SUCCESSFUL');
|
console.log('Programming: SUCCESSFUL');
|
||||||
$('span.progressLabel').text('Programming: SUCCESSFUL');
|
|
||||||
|
|
||||||
// update progress bar
|
// update progress bar
|
||||||
self.progress_bar_e.addClass('valid');
|
TABS.firmware_flasher.flashingMessage(chrome.i18n.getMessage('stm32ProgrammingSuccessful'), TABS.firmware_flasher.FLASH_MESSAGE_TYPES.VALID);
|
||||||
|
|
||||||
// proceed to next step
|
// proceed to next step
|
||||||
self.upload_procedure(6);
|
self.leave();
|
||||||
} else {
|
} else {
|
||||||
console.log('Programming: FAILED');
|
console.log('Programming: FAILED');
|
||||||
$('span.progressLabel').text('Programming: FAILED');
|
|
||||||
|
|
||||||
// update progress bar
|
// update progress bar
|
||||||
self.progress_bar_e.addClass('invalid');
|
TABS.firmware_flasher.flashingMessage(chrome.i18n.getMessage('stm32ProgrammingFailed'), TABS.firmware_flasher.FLASH_MESSAGE_TYPES.INVALID);
|
||||||
|
|
||||||
// disconnect
|
// disconnect
|
||||||
self.upload_procedure(99);
|
self.cleanup();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
break;
|
break;
|
||||||
case 6:
|
}
|
||||||
// jump to application code
|
};
|
||||||
var address = self.hex.data[0].address;
|
|
||||||
|
STM32DFU_protocol.prototype.leave = function () {
|
||||||
|
// leave DFU
|
||||||
|
|
||||||
|
const self = this;
|
||||||
|
|
||||||
|
let address;
|
||||||
|
if (self.hex) {
|
||||||
|
address = self.hex.data[0].address;
|
||||||
|
} else {
|
||||||
|
// Assuming we're running off internal flash
|
||||||
|
address = 0x08000000;
|
||||||
|
}
|
||||||
|
|
||||||
self.clearStatus(function () {
|
self.clearStatus(function () {
|
||||||
self.loadAddress(address, leave);
|
self.loadAddress(address, function () {
|
||||||
});
|
// 'downloading' 0 bytes to the program start address followed by a GETSTATUS is used to trigger DFU exit on STM32
|
||||||
|
|
||||||
var leave = function () {
|
|
||||||
self.controlTransfer('out', self.request.DNLOAD, 0, 0, 0, 0, function () {
|
self.controlTransfer('out', self.request.DNLOAD, 0, 0, 0, 0, function () {
|
||||||
self.controlTransfer('in', self.request.GETSTATUS, 0, 0, 6, 0, function (data) {
|
self.controlTransfer('in', self.request.GETSTATUS, 0, 0, 6, 0, function (data) {
|
||||||
self.upload_procedure(99);
|
self.cleanup();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
STM32DFU_protocol.prototype.cleanup = function () {
|
||||||
|
const self = this;
|
||||||
|
|
||||||
break;
|
|
||||||
case 99:
|
|
||||||
// cleanup
|
|
||||||
self.releaseInterface(0);
|
self.releaseInterface(0);
|
||||||
|
|
||||||
GUI.connect_lock = false;
|
GUI.connect_lock = false;
|
||||||
|
@ -975,8 +1069,8 @@ STM32DFU_protocol.prototype.upload_procedure = function (step) {
|
||||||
|
|
||||||
console.log('Script finished after: ' + (timeSpent / 1000) + ' seconds');
|
console.log('Script finished after: ' + (timeSpent / 1000) + ' seconds');
|
||||||
|
|
||||||
if (self.callback) self.callback();
|
if (self.callback) {
|
||||||
break;
|
self.callback();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -545,6 +545,46 @@ TABS.firmware_flasher.initialize = function (callback) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
TABS.firmware_flasher.FLASH_MESSAGE_TYPES = {NEUTRAL : 'NEUTRAL',
|
||||||
|
VALID : 'VALID',
|
||||||
|
INVALID : 'INVALID',
|
||||||
|
ACTION : 'ACTION'};
|
||||||
|
|
||||||
|
TABS.firmware_flasher.flashingMessage = function(message, type) {
|
||||||
|
let self = this;
|
||||||
|
|
||||||
|
let progressLabel_e = $('span.progressLabel');
|
||||||
|
switch (type) {
|
||||||
|
case self.FLASH_MESSAGE_TYPES.VALID:
|
||||||
|
progressLabel_e.removeClass('invalid actionRequired')
|
||||||
|
.addClass('valid');
|
||||||
|
break;
|
||||||
|
case self.FLASH_MESSAGE_TYPES.INVALID:
|
||||||
|
progressLabel_e.removeClass('valid actionRequired')
|
||||||
|
.addClass('invalid');
|
||||||
|
break;
|
||||||
|
case self.FLASH_MESSAGE_TYPES.ACTION:
|
||||||
|
progressLabel_e.removeClass('valid invalid')
|
||||||
|
.addClass('actionRequired');
|
||||||
|
break;
|
||||||
|
case self.FLASH_MESSAGE_TYPES.NEUTRAL:
|
||||||
|
default:
|
||||||
|
progressLabel_e.removeClass('valid invalid actionRequired');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (message != null) {
|
||||||
|
progressLabel_e.html(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
};
|
||||||
|
|
||||||
|
TABS.firmware_flasher.flashProgress = function(value) {
|
||||||
|
$('.progress').val(value);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
TABS.firmware_flasher.cleanup = function (callback) {
|
TABS.firmware_flasher.cleanup = function (callback) {
|
||||||
PortHandler.flush_callbacks();
|
PortHandler.flush_callbacks();
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue