1
0
Fork 0
mirror of https://github.com/betaflight/betaflight-configurator.git synced 2025-07-19 22:35:17 +03:00

documentation and major cleanup for DFU_DNLOAD

This commit is contained in:
cTn 2014-06-09 23:29:36 +02:00
parent 2a18801315
commit e8fa4e1822

View file

@ -3,6 +3,12 @@
control transfers for communicating control transfers for communicating
recipient is interface recipient is interface
request type is class request type is class
Descriptors seems to be broken in current chrome.usb API implementation (writing this while using canary 37.0.2040.0
General rule to remember is that DFU doesn't like running specific operations while the device isn't in idle state
that being said, it seems that certain level of CLRSTATUS is required before running another type of operation for
example switching from DNLOAD to UPLOAD, etc, clearning the state so device is in dfuIDLE is highly recommended.
*/ */
var STM32DFU_protocol = function() { var STM32DFU_protocol = function() {
@ -171,6 +177,57 @@ STM32DFU_protocol.prototype.controlTransfer = function(direction, request, value
} }
}; };
// routine calling DFU_CLRSTATUS until device is in dfuIDLE state
STM32DFU_protocol.prototype.clearStatus = function(callback) {
var self = this;
function check_status() {
self.controlTransfer('in', self.request.GETSTATUS, 0, 0, 6, 0, function(data) {
if (data[4] == self.state.dfuIDLE) {
callback();
} else {
var delay = data[1] | (data[2] << 8) | (data[3] << 16);
setTimeout(clear_status, delay);
}
});
}
function clear_status() {
self.controlTransfer('out', self.request.CLRSTATUS, 0, 0, 0, 0, function() {
check_status();
});
}
check_status();
};
STM32DFU_protocol.prototype.loadAddress = function(address, callback) {
var self = this;
self.controlTransfer('out', self.request.DNLOAD, 0, 0, 0, [0x21, address, (address >> 8), (address >> 16), (address >> 24)], function() {
self.controlTransfer('in', self.request.GETSTATUS, 0, 0, 6, 0, function(data) {
if (data[4] == self.state.dfuDNBUSY) {
var delay = data[1] | (data[2] << 8) | (data[3] << 16);
setTimeout(function() {
self.controlTransfer('in', self.request.GETSTATUS, 0, 0, 6, 0, function(data) {
if (data[4] == self.state.dfuDNLOAD_IDLE) {
callback();
} else {
console.log('Failed to execure address load');
self.upload_procedure(99);
}
});
}, delay);
} else {
console.log('Failed to request address load');
self.upload_procedure(99);
}
});
});
};
// first_array = usually hex_to_flash array // first_array = usually hex_to_flash array
// second_array = usually verify_hex array // second_array = usually verify_hex array
// result = true/false // result = true/false
@ -192,26 +249,11 @@ STM32DFU_protocol.prototype.upload_procedure = function(step) {
switch (step) { switch (step) {
case 1: case 1:
self.controlTransfer('in', self.request.GETSTATUS, 0, 0, 6, 0, function(data) { self.clearStatus(function() {
if (data[4] == self.state.dfuIDLE) {
self.upload_procedure(3);
} else {
self.upload_procedure(2); self.upload_procedure(2);
}
}); });
break; break;
case 2: case 2:
self.controlTransfer('out', self.request.CLRSTATUS, 0, 0, 0, 0, function() {
self.controlTransfer('in', self.request.GETSTATUS, 0, 0, 6, 0, function(data) {
if (data[4] == self.state.dfuIDLE) {
self.upload_procedure(3);
} else {
// throw some error
}
});
});
break;
case 3:
// full chip erase // full chip erase
console.log('Executing global chip erase'); console.log('Executing global chip erase');
STM32.GUI_status('Erasing'); STM32.GUI_status('Erasing');
@ -226,18 +268,21 @@ STM32DFU_protocol.prototype.upload_procedure = function(step) {
if (data[4] == self.state.dfuDNLOAD_IDLE) { if (data[4] == self.state.dfuDNLOAD_IDLE) {
self.upload_procedure(4); self.upload_procedure(4);
} else { } else {
// throw some error console.log('Failed to execute global chip erase');
self.upload_procedure(99);
} }
}); });
}, delay); }, delay);
} else { } else {
// throw some error console.log('Failed to initiate global chip erase');
self.upload_procedure(99);
} }
}); });
}); });
break; break;
case 4: case 4:
// upload // upload
// we dont need to clear the state as we are already using DFU_DNLOAD
console.log('Writing data ...'); console.log('Writing data ...');
STM32.GUI_status('<span style="color: green">Flashing ...</span>'); STM32.GUI_status('<span style="color: green">Flashing ...</span>');
@ -249,42 +294,22 @@ STM32DFU_protocol.prototype.upload_procedure = function(step) {
var bytes_flashed_total = 0; // used for progress bar var bytes_flashed_total = 0; // used for progress bar
var wBlockNum = 2; // required by DFU var wBlockNum = 2; // required by DFU
function load_write_address() { // start
self.controlTransfer('out', self.request.DNLOAD, 0, 0, 0, [0x21, address, (address >> 8), (address >> 16), (address >> 24)], function() { self.loadAddress(address, write);
self.controlTransfer('in', self.request.GETSTATUS, 0, 0, 6, 0, function(data) {
if (data[4] == self.state.dfuDNBUSY) { // completely normal
var delay = data[1] | (data[2] << 8) | (data[3] << 16);
setTimeout(function() {
self.controlTransfer('in', self.request.GETSTATUS, 0, 0, 6, 0, function(data) {
if (data[4] == self.state.dfuDNLOAD_IDLE) {
write();
} else {
console.log(data);
}
});
}, delay);
} else {
console.log(data);
}
});
});
}
function write() { function write() {
if (bytes_flashed < self.hex.data[flashing_block].bytes) { if (bytes_flashed < self.hex.data[flashing_block].bytes) {
var bytes_to_write = ((bytes_flashed + 2048) <= self.hex.data[flashing_block].bytes) ? 2048 : (self.hex.data[flashing_block].bytes - bytes_flashed); var bytes_to_write = ((bytes_flashed + 2048) <= self.hex.data[flashing_block].bytes) ? 2048 : (self.hex.data[flashing_block].bytes - bytes_flashed);
var data = []; var data_to_flash = self.hex.data[flashing_block].data.slice(bytes_flashed, bytes_flashed + bytes_to_write);
for (var i = 0; i < bytes_to_write; i++) {
data.push(self.hex.data[flashing_block].data[bytes_flashed++]);
}
address += bytes_to_write; address += bytes_to_write;
bytes_flashed += bytes_to_write;
bytes_flashed_total += bytes_to_write; bytes_flashed_total += bytes_to_write;
self.controlTransfer('out', self.request.DNLOAD, wBlockNum++, 0, 0, data, function() { self.controlTransfer('out', self.request.DNLOAD, wBlockNum++, 0, 0, data_to_flash, 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) {
var delay = data[1] | (data[2] << 8) | (data[3] << 16); var delay = data[1] | (data[2] << 8) | (data[3] << 16);
setTimeout(function() { setTimeout(function() {
@ -296,23 +321,27 @@ STM32DFU_protocol.prototype.upload_procedure = function(step) {
// flash another page // flash another page
write(); write();
} else { } else {
// throw some error console.log('Failed to write ' + bytes_to_write + 'bytes to 0x' + address.toString(16));
console.log(data); self.upload_procedure(99);
} }
}); });
}, delay); }, delay);
} else {
console.log('Failed to initiate write ' + bytes_to_write + 'bytes to 0x' + address.toString(16));
self.upload_procedure(99);
}
}); });
}) })
} else { } else {
// move to another block
if (flashing_block < blocks) { if (flashing_block < blocks) {
// move to another block
flashing_block++; flashing_block++;
address = self.hex.data[flashing_block].address; address = self.hex.data[flashing_block].address;
bytes_flashed = 0; bytes_flashed = 0;
wBlockNum = 2; wBlockNum = 2;
load_write_address(); self.loadAddress(address, write);
} else { } else {
// all blocks flashed // all blocks flashed
console.log('Writing: done'); console.log('Writing: done');
@ -322,9 +351,6 @@ STM32DFU_protocol.prototype.upload_procedure = function(step) {
} }
} }
} }
// start
load_write_address();
break; break;
case 5: case 5:
// verify // verify