2014-03-08 05:25:15 +00:00
/ *
2014-01-28 11:21:35 +00:00
STM32 F103 serial bus seems to properly initialize with quite a huge auto - baud range
From 921600 down to 1200 , i don ' t recommend getting any lower then that
Official "specs" are from 115200 to 1200
* /
2013-11-13 09:04:14 +00:00
var STM32 _protocol = function ( ) {
2013-12-10 07:19:18 +00:00
this . hex ; // ref
2014-02-07 21:33:29 +00:00
this . verify _hex ;
2014-03-08 05:25:15 +00:00
2013-11-13 09:04:14 +00:00
this . receive _buffer ;
2014-03-08 05:25:15 +00:00
2013-11-13 09:04:14 +00:00
this . bytes _to _read = 0 ; // ref
this . read _callback ; // ref
2014-03-08 05:25:15 +00:00
2013-11-13 09:04:14 +00:00
this . upload _time _start ;
2014-02-07 21:33:29 +00:00
this . upload _process _alive ;
2014-03-08 05:25:15 +00:00
2013-11-13 09:04:14 +00:00
this . status = {
2014-01-27 22:15:34 +00:00
ACK : 0x79 , // y
2013-11-13 09:04:14 +00:00
NACK : 0x1F
} ;
2014-03-08 05:25:15 +00:00
2013-11-13 09:04:14 +00:00
this . command = {
get : 0x00 , // Gets the version and the allowed commands supported by the current version of the bootloader
get _ver _r _protect _s : 0x01 , // Gets the bootloader version and the Read Protection status of the Flash memory
get _ID : 0x02 , // Gets the chip ID
read _memory : 0x11 , // Reads up to 256 bytes of memory starting from an address specified by the application
go : 0x21 , // Jumps to user application code located in the internal Flash memory or in SRAM
write _memory : 0x31 , // Writes up to 256 bytes to the RAM or Flash memory starting from an address specified by the application
erase : 0x43 , // Erases from one to all the Flash memory pages
extended _erase : 0x44 , // Erases from one to all the Flash memory pages using two byte addressing mode (v3.0+ usart).
write _protect : 0x63 , // Enables the write protection for some sectors
write _unprotect : 0x73 , // Disables the write protection for all Flash memory sectors
readout _protect : 0x82 , // Enables the read protection
readout _unprotect : 0x92 // Disables the read protection
} ;
2014-03-08 05:25:15 +00:00
2013-11-13 09:04:14 +00:00
// Erase (x043) and Extended Erase (0x44) are exclusive. A device may support either the Erase command or the Extended Erase command but not both.
2014-05-07 03:01:08 +00:00
this . available _flash _size = 0 ;
this . page _size = 0 ;
2013-11-13 09:04:14 +00:00
} ;
// no input parameters
2013-12-10 07:19:18 +00:00
STM32 _protocol . prototype . connect = function ( hex ) {
2013-11-13 09:04:14 +00:00
var self = this ;
2013-12-10 07:19:18 +00:00
self . hex = hex ;
2014-03-08 05:25:15 +00:00
2014-06-20 12:29:16 +00:00
var selected _port = String ( $ ( 'div#port-picker #port' ) . val ( ) ) ;
2013-11-14 15:41:09 +00:00
var baud = parseInt ( $ ( 'div#port-picker #baud' ) . val ( ) ) ;
2014-03-08 05:25:15 +00:00
2013-11-13 09:04:14 +00:00
if ( selected _port != '0' ) {
2014-01-27 22:15:34 +00:00
// popular choices - 921600, 460800, 256000, 230400, 153600, 128000, 115200, 57600, 38400, 28800, 19200
2013-12-12 16:10:10 +00:00
var flashing _bitrate ;
2014-03-08 05:25:15 +00:00
2013-11-15 17:03:10 +00:00
switch ( GUI . operating _system ) {
case 'Windows' :
case 'MacOS' :
case 'ChromeOS' :
case 'Linux' :
case 'UNIX' :
2014-01-27 22:15:34 +00:00
flashing _bitrate = 921600 ;
2013-11-15 17:03:10 +00:00
break ;
2014-03-08 05:25:15 +00:00
2013-12-04 13:11:36 +00:00
default :
2013-12-12 16:10:10 +00:00
flashing _bitrate = 115200 ;
2013-11-15 17:03:10 +00:00
}
2014-03-08 05:25:15 +00:00
2013-11-14 15:41:09 +00:00
if ( ! $ ( 'input.updating' ) . is ( ':checked' ) ) {
2014-01-18 11:44:51 +00:00
serial . connect ( selected _port , { bitrate : baud } , function ( openInfo ) {
2014-02-03 09:07:54 +00:00
if ( openInfo ) {
2013-11-14 15:48:37 +00:00
console . log ( 'Sending ascii "R" to reboot' ) ;
2013-11-13 09:04:14 +00:00
2013-11-14 15:41:09 +00:00
// we are connected, disabling connect button in the UI
GUI . connect _lock = true ;
2014-03-08 05:25:15 +00:00
2014-01-28 00:11:37 +00:00
var bufferOut = new ArrayBuffer ( 1 ) ;
var bufferView = new Uint8Array ( bufferOut ) ;
2014-03-08 05:25:15 +00:00
2014-01-28 00:11:37 +00:00
bufferView [ 0 ] = 0x52 ;
2014-03-08 05:25:15 +00:00
2014-01-28 00:11:37 +00:00
serial . send ( bufferOut , function ( ) {
2014-01-18 11:44:51 +00:00
serial . disconnect ( function ( result ) {
2014-03-08 05:25:15 +00:00
if ( result ) {
2014-01-18 11:44:51 +00:00
serial . connect ( selected _port , { bitrate : flashing _bitrate , parityBit : 'even' , stopBits : 'one' } , function ( openInfo ) {
2014-03-08 05:25:15 +00:00
if ( openInfo ) {
2013-11-14 15:41:09 +00:00
self . initialize ( ) ;
2014-02-03 09:07:54 +00:00
} else {
GUI . log ( '<span style="color: red">Failed</span> to open serial port' ) ;
2013-11-14 15:41:09 +00:00
}
} ) ;
2013-11-14 18:16:33 +00:00
} else {
GUI . connect _lock = false ;
2013-11-14 15:41:09 +00:00
}
} ) ;
2014-01-28 00:11:37 +00:00
} ) ;
2014-02-03 09:07:54 +00:00
} else {
GUI . log ( '<span style="color: red">Failed</span> to open serial port' ) ;
2013-11-14 15:41:09 +00:00
}
} ) ;
} else {
2014-01-18 11:44:51 +00:00
serial . connect ( selected _port , { bitrate : flashing _bitrate , parityBit : 'even' , stopBits : 'one' } , function ( openInfo ) {
2014-03-08 05:25:15 +00:00
if ( openInfo ) {
2013-11-14 15:48:37 +00:00
// we are connected, disabling connect button in the UI
GUI . connect _lock = true ;
2014-03-08 05:25:15 +00:00
2013-11-14 15:41:09 +00:00
self . initialize ( ) ;
2014-02-03 09:07:54 +00:00
} else {
GUI . log ( '<span style="color: red">Failed</span> to open serial port' ) ;
2013-11-14 15:41:09 +00:00
}
} ) ;
}
2013-11-13 09:04:14 +00:00
} else {
console . log ( 'Please select valid serial port' ) ;
2014-06-24 12:57:41 +00:00
GUI . log ( '<span style="color: red">Please select valid serial port</span>' ) ;
2013-11-13 09:04:14 +00:00
}
} ;
// initialize certain variables and start timers that oversee the communication
STM32 _protocol . prototype . initialize = function ( ) {
var self = this ;
2014-03-08 05:25:15 +00:00
// reset and set some variables before we start
2013-11-13 09:04:14 +00:00
self . receive _buffer = [ ] ;
self . verify _hex = [ ] ;
2014-03-08 05:25:15 +00:00
2013-11-13 09:04:14 +00:00
self . upload _time _start = microtime ( ) ;
2014-02-07 21:33:29 +00:00
self . upload _process _alive = false ;
2014-03-08 05:25:15 +00:00
2013-11-16 12:03:42 +00:00
// reset progress bar to initial state
self . progress _bar _e = $ ( '.progress' ) ;
self . progress _bar _e . val ( 0 ) ;
self . progress _bar _e . removeClass ( 'valid invalid' ) ;
2013-11-13 09:04:14 +00:00
2014-01-18 11:44:51 +00:00
serial . onReceive . addListener ( function ( info ) {
self . read ( info ) ;
} ) ;
2014-03-08 05:25:15 +00:00
2013-11-13 09:04:14 +00:00
GUI . interval _add ( 'STM32_timeout' , function ( ) {
2014-02-07 21:33:29 +00:00
if ( self . upload _process _alive ) { // process is running
self . upload _process _alive = false ;
2013-11-13 09:04:14 +00:00
} else {
console . log ( 'STM32 - timed out, programming failed ...' ) ;
2014-06-24 12:57:41 +00:00
GUI . log ( 'STM32 - timed out, programming: <strong style="color: red">FAILED</strong>' ) ;
2014-03-08 05:25:15 +00:00
2013-11-13 09:04:14 +00:00
// protocol got stuck, clear timer and disconnect
GUI . interval _remove ( 'STM32_timeout' ) ;
2014-03-08 05:25:15 +00:00
2013-11-13 09:04:14 +00:00
// exit
self . upload _procedure ( 99 ) ;
}
2014-06-24 12:57:41 +00:00
} , 2000 ) ;
2014-03-08 05:25:15 +00:00
2013-11-14 15:41:09 +00:00
self . upload _procedure ( 1 ) ;
2013-11-13 09:04:14 +00:00
} ;
// no input parameters
// this method should be executed every 1 ms via interval timer
2014-03-08 05:25:15 +00:00
STM32 _protocol . prototype . read = function ( readInfo ) {
2013-11-13 09:04:14 +00:00
// routine that fills the buffer
2014-01-18 11:44:51 +00:00
var data = new Uint8Array ( readInfo . data ) ;
2014-03-08 05:25:15 +00:00
2014-01-18 11:44:51 +00:00
for ( var i = 0 ; i < data . length ; i ++ ) {
2014-03-08 05:25:15 +00:00
this . receive _buffer . push ( data [ i ] ) ;
2014-01-18 11:44:51 +00:00
}
2014-03-08 05:25:15 +00:00
2013-11-13 09:04:14 +00:00
// routine that fetches data from buffer if statement is true
2014-01-27 22:15:34 +00:00
if ( this . receive _buffer . length >= this . bytes _to _read && this . bytes _to _read != 0 ) {
var data = this . receive _buffer . slice ( 0 , this . bytes _to _read ) ; // bytes requested
this . receive _buffer . splice ( 0 , this . bytes _to _read ) ; // remove read bytes
2014-03-08 05:25:15 +00:00
2014-01-27 22:15:34 +00:00
this . bytes _to _read = 0 ; // reset trigger
2014-03-08 05:25:15 +00:00
2014-01-27 22:15:34 +00:00
this . read _callback ( data ) ;
2013-11-13 09:04:14 +00:00
}
} ;
2014-01-28 03:02:47 +00:00
// we should always try to consume all "proper" available data while using retrieve
2014-01-18 11:44:51 +00:00
STM32 _protocol . prototype . retrieve = function ( n _bytes , callback ) {
2014-01-27 22:15:34 +00:00
if ( this . receive _buffer . length >= n _bytes ) {
// data that we need are there, process immediately
var data = this . receive _buffer . slice ( 0 , n _bytes ) ;
this . receive _buffer . splice ( 0 , n _bytes ) ; // remove read bytes
2014-03-08 05:25:15 +00:00
2014-01-27 22:15:34 +00:00
callback ( data ) ;
} else {
// still waiting for data, add callback
this . bytes _to _read = n _bytes ;
this . read _callback = callback ;
}
2014-01-18 11:44:51 +00:00
} ;
2013-11-13 09:04:14 +00:00
// Array = array of bytes that will be send over serial
// bytes_to_read = received bytes necessary to trigger read_callback
// callback = function that will be executed after received bytes = bytes_to_read
2014-02-07 21:33:29 +00:00
STM32 _protocol . prototype . send = function ( Array , bytes _to _read , callback ) {
// flip flag
this . upload _process _alive = true ;
2014-03-08 05:25:15 +00:00
2013-11-13 09:04:14 +00:00
var bufferOut = new ArrayBuffer ( Array . length ) ;
var bufferView = new Uint8Array ( bufferOut ) ;
2014-03-08 05:25:15 +00:00
2013-11-13 09:04:14 +00:00
// set Array values inside bufferView (alternative to for loop)
bufferView . set ( Array ) ;
2014-03-08 05:25:15 +00:00
2013-11-13 09:04:14 +00:00
// update references
this . bytes _to _read = bytes _to _read ;
2014-01-27 20:37:42 +00:00
this . read _callback = callback ;
2014-03-08 05:25:15 +00:00
2014-01-27 20:37:42 +00:00
// empty receive buffer before next command is out
this . receive _buffer = [ ] ;
2013-11-13 09:04:14 +00:00
// send over the actual data
2014-03-08 05:25:15 +00:00
serial . send ( bufferOut , function ( writeInfo ) { } ) ;
2013-11-13 09:04:14 +00:00
} ;
2014-03-08 05:25:15 +00:00
// val = single byte to be verified
2013-11-13 09:04:14 +00:00
// data = response of n bytes from mcu (array)
// result = true/false
STM32 _protocol . prototype . verify _response = function ( val , data ) {
if ( val != data [ 0 ] ) {
console . log ( 'STM32 Communication failed, wrong response, expected: ' + val + ' received: ' + data [ 0 ] ) ;
2014-06-24 12:57:41 +00:00
GUI . log ( 'STM32 Communication <span style="color: red">failed</span>, wrong response, expected: ' + val + ' received: ' + data [ 0 ] ) ;
2014-03-08 05:25:15 +00:00
2013-11-13 09:04:14 +00:00
// disconnect
this . upload _procedure ( 99 ) ;
2014-03-08 05:25:15 +00:00
2013-11-13 09:04:14 +00:00
return false ;
}
2014-03-08 05:25:15 +00:00
2013-11-13 09:04:14 +00:00
return true ;
} ;
// input = 16 bit value
// result = true/false
STM32 _protocol . prototype . verify _chip _signature = function ( signature ) {
switch ( signature ) {
2013-11-15 15:31:16 +00:00
case 0x412 : // not tested
2013-11-15 15:17:43 +00:00
console . log ( 'Chip recognized as F1 Low-density' ) ;
2013-11-13 09:04:14 +00:00
break ;
case 0x410 :
console . log ( 'Chip recognized as F1 Medium-density' ) ;
2014-05-07 03:01:08 +00:00
this . available _flash _size = 131072 ;
this . page _size = 1024 ;
2013-11-13 09:04:14 +00:00
break ;
2013-11-15 15:31:16 +00:00
case 0x414 : // not tested
2013-11-15 15:17:43 +00:00
console . log ( 'Chip recognized as F1 High-density' ) ;
2013-11-13 09:04:14 +00:00
break ;
2013-11-15 15:31:16 +00:00
case 0x418 : // not tested
2013-11-15 15:17:43 +00:00
console . log ( 'Chip recognized as F1 Connectivity line' ) ;
2013-11-13 09:04:14 +00:00
break ;
2013-11-15 15:31:16 +00:00
case 0x420 : // not tested
2013-11-15 15:17:43 +00:00
console . log ( 'Chip recognized as F1 Medium-density value line' ) ;
2013-11-13 09:04:14 +00:00
break ;
2013-11-15 15:31:16 +00:00
case 0x428 : // not tested
2013-11-15 15:17:43 +00:00
console . log ( 'Chip recognized as F1 High-density value line' ) ;
2013-11-13 09:04:14 +00:00
break ;
2013-11-15 15:31:16 +00:00
case 0x430 : // not tested
2013-11-15 15:17:43 +00:00
console . log ( 'Chip recognized as F1 XL-density value line' ) ;
2013-11-15 15:31:16 +00:00
break ;
case 0x416 : // not tested
console . log ( 'Chip recognized as L1 Medium-density ultralow power' ) ;
break ;
2013-11-15 15:35:36 +00:00
case 0x436 : // not tested
2013-11-15 15:31:16 +00:00
console . log ( 'Chip recognized as L1 High-density ultralow power' ) ;
break ;
2013-11-15 15:35:36 +00:00
case 0x427 : // not tested
2013-11-15 15:31:16 +00:00
console . log ( 'Chip recognized as L1 Medium-density plus ultralow power' ) ;
break ;
2013-11-15 15:35:36 +00:00
case 0x411 : // not tested
2013-11-15 15:31:16 +00:00
console . log ( 'Chip recognized as F2 STM32F2xxxx' ) ;
break ;
2013-11-15 15:35:36 +00:00
case 0x440 : // not tested
2013-11-15 15:31:16 +00:00
console . log ( 'Chip recognized as F0 STM32F051xx' ) ;
break ;
2013-11-15 15:35:36 +00:00
case 0x444 : // not tested
2013-11-15 15:31:16 +00:00
console . log ( 'Chip recognized as F0 STM32F050xx' ) ;
break ;
2013-11-15 15:35:36 +00:00
case 0x413 : // not tested
2013-11-15 15:31:16 +00:00
console . log ( 'Chip recognized as F4 STM32F40xxx/41xxx' ) ;
break ;
2013-11-15 15:35:36 +00:00
case 0x419 : // not tested
2013-11-15 15:31:16 +00:00
console . log ( 'Chip recognized as F4 STM32F427xx/437xx, STM32F429xx/439xx' ) ;
break ;
2013-11-15 15:35:36 +00:00
case 0x432 : // not tested
2013-11-15 15:31:16 +00:00
console . log ( 'Chip recognized as F3 STM32F37xxx, STM32F38xxx' ) ;
break ;
2013-11-15 15:35:36 +00:00
case 0x422 : // not tested
2013-11-15 15:31:16 +00:00
console . log ( 'Chip recognized as F3 STM32F30xxx, STM32F31xxx' ) ;
2013-11-13 09:04:14 +00:00
break ;
2013-12-10 07:53:53 +00:00
}
2014-03-08 05:25:15 +00:00
2014-05-07 03:01:08 +00:00
if ( this . available _flash _size > 0 ) {
if ( this . hex . bytes _total < this . available _flash _size ) {
2013-12-10 07:53:53 +00:00
return true ;
} else {
2014-05-07 03:01:08 +00:00
console . log ( 'Supplied hex is bigger then flash available on the chip, HEX: ' + this . hex . bytes _total + ' bytes, limit = ' + this . available _flash _size + ' bytes' ) ;
2014-03-08 05:25:15 +00:00
2013-11-13 09:04:14 +00:00
return false ;
2013-12-10 07:53:53 +00:00
}
2014-03-08 05:25:15 +00:00
}
2013-12-10 07:53:53 +00:00
console . log ( 'Chip NOT recognized: ' + signature ) ;
2014-03-08 05:25:15 +00:00
2013-12-10 07:53:53 +00:00
return false ;
2013-11-13 09:04:14 +00:00
} ;
// first_array = usually hex_to_flash array
// second_array = usually verify_hex array
// result = true/false
STM32 _protocol . prototype . verify _flash = function ( first _array , second _array ) {
for ( var i = 0 ; i < first _array . length ; i ++ ) {
if ( first _array [ i ] != second _array [ i ] ) {
console . log ( 'Verification failed on byte: ' + i + ' expected: 0x' + first _array [ i ] . toString ( 16 ) + ' received: 0x' + second _array [ i ] . toString ( 16 ) ) ;
return false ;
}
}
2014-03-08 05:25:15 +00:00
2013-11-13 09:04:14 +00:00
console . log ( 'Verification successful, matching: ' + first _array . length + ' bytes' ) ;
2014-03-08 05:25:15 +00:00
2013-11-13 09:04:14 +00:00
return true ;
} ;
// step = value depending on current state of upload_procedure
STM32 _protocol . prototype . upload _procedure = function ( step ) {
var self = this ;
2014-03-08 05:25:15 +00:00
2013-11-13 09:04:14 +00:00
switch ( step ) {
case 1 :
// initialize serial interface on the MCU side, auto baud rate settings
2014-06-24 12:57:41 +00:00
GUI . log ( 'Contacting bootloader ...' ) ;
2013-12-03 20:23:31 +00:00
var send _counter = 0 ;
GUI . interval _add ( 'stm32_initialize_mcu' , function ( ) { // 200 ms interval (just in case mcu was already initialized), we need to break the 2 bytes command requirement
self . send ( [ 0x7F ] , 1 , function ( reply ) {
2014-01-26 23:49:28 +00:00
if ( reply [ 0 ] == 0x7F || reply [ 0 ] == self . status . ACK || reply [ 0 ] == self . status . NACK ) {
2013-12-03 20:23:31 +00:00
GUI . interval _remove ( 'stm32_initialize_mcu' ) ;
console . log ( 'STM32 - Serial interface initialized on the MCU side' ) ;
2014-03-08 05:25:15 +00:00
2013-12-03 20:23:31 +00:00
// proceed to next step
self . upload _procedure ( 2 ) ;
} else {
GUI . interval _remove ( 'stm32_initialize_mcu' ) ;
2014-06-24 12:57:41 +00:00
GUI . log ( 'Communication with bootloader <span style="color: red">failed</span>' ) ;
2014-03-08 05:25:15 +00:00
2013-12-03 20:23:31 +00:00
// disconnect
self . upload _procedure ( 99 ) ;
}
} ) ;
2014-03-08 05:25:15 +00:00
2013-12-03 20:23:31 +00:00
if ( send _counter ++ > 3 ) {
// stop retrying, its too late to get any response from MCU
GUI . interval _remove ( 'stm32_initialize_mcu' ) ;
2013-11-13 09:04:14 +00:00
}
2014-01-28 00:11:37 +00:00
} , 200 , true ) ;
2013-11-13 09:04:14 +00:00
break ;
case 2 :
// get version of the bootloader and supported commands
2014-01-27 22:15:34 +00:00
self . send ( [ self . command . get , 0xFF ] , 2 , function ( data ) { // 0x00 ^ 0xFF
2013-11-13 09:04:14 +00:00
if ( self . verify _response ( self . status . ACK , data ) ) {
2014-01-28 03:02:47 +00:00
self . retrieve ( data [ 1 ] + 1 + 1 , function ( data ) { // data[1] = number of bytes that will follow [– 1 except current and ACKs]
2014-01-27 20:41:32 +00:00
console . log ( 'STM32 - Bootloader version: ' + ( parseInt ( data [ 0 ] . toString ( 16 ) ) / 10 ) . toFixed ( 1 ) ) ; // convert dec to hex, hex to dec and add floating point
2014-03-08 05:25:15 +00:00
2013-11-13 09:04:14 +00:00
// proceed to next step
self . upload _procedure ( 3 ) ;
} ) ;
}
} ) ;
break ;
case 3 :
// get ID (device signature)
self . send ( [ self . command . get _ID , 0xFD ] , 2 , function ( data ) { // 0x01 ^ 0xFF
if ( self . verify _response ( self . status . ACK , data ) ) {
2014-01-28 03:02:47 +00:00
self . retrieve ( data [ 1 ] + 1 + 1 , function ( data ) { // data[1] = number of bytes that will follow [– 1 (N = 1 for STM32), except for current byte and ACKs]
2013-11-13 09:04:14 +00:00
var signature = ( data [ 0 ] << 8 ) | data [ 1 ] ;
console . log ( 'STM32 - Signature: 0x' + signature . toString ( 16 ) ) ; // signature in hex representation
2014-03-08 05:25:15 +00:00
2013-11-13 09:04:14 +00:00
if ( self . verify _chip _signature ( signature ) ) {
// proceed to next step
self . upload _procedure ( 4 ) ;
} else {
// disconnect
self . upload _procedure ( 99 ) ;
}
} ) ;
}
} ) ;
break ;
case 4 :
// erase memory
2014-06-24 12:57:41 +00:00
GUI . log ( 'Erasing ...' ) ;
2014-05-07 06:07:49 +00:00
if ( ! $ ( 'input.erase_chip' ) . is ( ':checked' ) ) {
// EXPERIMENTAL
console . log ( 'Executing local erase (only needed pages)' ) ;
self . send ( [ self . command . erase , 0xBC ] , 1 , function ( reply ) { // 0x43 ^ 0xFF
if ( self . verify _response ( self . status . ACK , reply ) ) {
// the bootloader receives one byte that contains N, the number of pages to be erased – 1
var max _address = self . hex . data [ self . hex . data . length - 1 ] . address + self . hex . data [ self . hex . data . length - 1 ] . bytes - 0x8000000 ;
var erase _pages _n = Math . ceil ( max _address / self . page _size ) ;
var buff = [ ] ;
buff . push ( erase _pages _n - 1 ) ;
var checksum = buff [ 0 ] ;
for ( var i = 0 ; i < erase _pages _n ; i ++ ) {
buff . push ( i ) ;
checksum ^= i ;
2014-05-07 03:01:08 +00:00
}
2014-05-07 06:07:49 +00:00
buff . push ( checksum ) ;
2014-03-08 05:25:15 +00:00
2014-05-07 06:07:49 +00:00
self . send ( buff , 1 , function ( reply ) {
if ( self . verify _response ( self . status . ACK , reply ) ) {
console . log ( 'Erasing: done' ) ;
// proceed to next step
self . upload _procedure ( 5 ) ;
}
} ) ;
}
} ) ;
} else {
console . log ( 'Executing global chip erase' ) ;
self . send ( [ self . command . erase , 0xBC ] , 1 , function ( reply ) { // 0x43 ^ 0xFF
if ( self . verify _response ( self . status . ACK , reply ) ) {
self . send ( [ 0xFF , 0x00 ] , 1 , function ( reply ) {
if ( self . verify _response ( self . status . ACK , reply ) ) {
console . log ( 'Erasing: done' ) ;
// proceed to next step
self . upload _procedure ( 5 ) ;
}
} ) ;
}
} ) ;
}
2013-11-13 09:04:14 +00:00
break ;
case 5 :
// upload
2014-06-24 12:57:41 +00:00
console . log ( 'Writing data ...' ) ;
GUI . log ( 'Flashing ...' ) ;
2014-02-07 21:33:29 +00:00
var blocks = self . hex . data . length - 1 ;
var flashing _block = 0 ;
2014-02-09 15:26:18 +00:00
var address = self . hex . data [ flashing _block ] . address ;
2014-03-08 05:25:15 +00:00
2014-02-07 21:33:29 +00:00
var bytes _flashed = 0 ;
var bytes _flashed _total = 0 ; // used for progress bar
2014-03-08 05:25:15 +00:00
2014-03-29 00:28:27 +00:00
function write ( ) {
2014-02-09 15:26:18 +00:00
if ( bytes _flashed < self . hex . data [ flashing _block ] . bytes ) {
2014-05-07 03:01:08 +00:00
var bytes _to _write = ( ( bytes _flashed + 256 ) <= self . hex . data [ flashing _block ] . bytes ) ? 256 : ( self . hex . data [ flashing _block ] . bytes - bytes _flashed ) ;
2014-03-08 05:25:15 +00:00
2014-02-09 15:26:18 +00:00
// console.log('STM32 - Writing to: 0x' + address.toString(16) + ', ' + bytes_to_write + ' bytes');
2014-03-08 05:25:15 +00:00
2014-02-07 21:33:29 +00:00
self . send ( [ self . command . write _memory , 0xCE ] , 1 , function ( reply ) { // 0x31 ^ 0xFF
if ( self . verify _response ( self . status . ACK , reply ) ) {
// address needs to be transmitted as 32 bit integer, we need to bit shift each byte out and then calculate address checksum
2014-02-09 14:56:06 +00:00
var address _arr = [ ( address >> 24 ) , ( address >> 16 ) , ( address >> 8 ) , address ] ;
var address _checksum = address _arr [ 0 ] ^ address _arr [ 1 ] ^ address _arr [ 2 ] ^ address _arr [ 3 ] ;
2014-03-08 05:25:15 +00:00
2014-02-09 14:56:06 +00:00
self . send ( [ address _arr [ 0 ] , address _arr [ 1 ] , address _arr [ 2 ] , address _arr [ 3 ] , address _checksum ] , 1 , function ( reply ) { // write start address + checksum
2014-02-07 21:33:29 +00:00
if ( self . verify _response ( self . status . ACK , reply ) ) {
var array _out = new Array ( bytes _to _write + 2 ) ; // 2 byte overhead [N, ...., checksum]
array _out [ 0 ] = bytes _to _write - 1 ; // number of bytes to be written (to write 128 bytes, N must be 127, to write 256 bytes, N must be 255)
2014-03-08 05:25:15 +00:00
2014-02-07 21:33:29 +00:00
var checksum = array _out [ 0 ] ;
for ( var i = 0 ; i < bytes _to _write ; i ++ ) {
array _out [ i + 1 ] = self . hex . data [ flashing _block ] . data [ bytes _flashed ] ; // + 1 because of the first byte offset
checksum ^= self . hex . data [ flashing _block ] . data [ bytes _flashed ] ;
2014-03-08 05:25:15 +00:00
2014-02-07 21:33:29 +00:00
bytes _flashed ++ ;
2013-11-13 09:04:14 +00:00
}
2014-02-07 21:33:29 +00:00
array _out [ array _out . length - 1 ] = checksum ; // checksum (last byte in the array_out array)
2014-03-08 05:25:15 +00:00
2014-02-09 15:03:42 +00:00
address += bytes _to _write ;
2014-06-08 20:38:58 +00:00
bytes _flashed _total += bytes _to _write ;
2014-02-07 21:33:29 +00:00
self . send ( array _out , 1 , function ( reply ) {
if ( self . verify _response ( self . status . ACK , reply ) ) {
2014-02-09 15:26:18 +00:00
// update progress bar
self . progress _bar _e . val ( bytes _flashed _total / ( self . hex . bytes _total * 2 ) * 100 ) ;
2014-03-08 05:25:15 +00:00
2014-02-07 21:33:29 +00:00
// flash another page
write ( ) ;
}
} ) ;
}
} ) ;
}
} ) ;
2014-02-09 15:26:18 +00:00
} else {
// move to another block
if ( flashing _block < blocks ) {
flashing _block ++ ;
2014-03-08 05:25:15 +00:00
2014-02-09 15:26:18 +00:00
address = self . hex . data [ flashing _block ] . address ;
bytes _flashed = 0 ;
2014-03-08 05:25:15 +00:00
2014-02-09 15:26:18 +00:00
write ( ) ;
} else {
// all blocks flashed
console . log ( 'Writing: done' ) ;
2014-03-08 05:25:15 +00:00
2014-02-09 15:26:18 +00:00
// proceed to next step
self . upload _procedure ( 6 ) ;
}
2014-02-07 21:33:29 +00:00
}
2014-03-29 00:28:27 +00:00
}
2014-03-08 05:25:15 +00:00
2014-02-07 21:33:29 +00:00
// start writing
write ( ) ;
2013-11-13 09:04:14 +00:00
break ;
case 6 :
// verify
2014-06-24 12:57:41 +00:00
console . log ( 'Verifying data ...' ) ;
GUI . log ( 'Verifying ...' ) ;
2014-02-07 21:33:29 +00:00
var blocks = self . hex . data . length - 1 ;
var reading _block = 0 ;
2014-02-09 15:26:18 +00:00
var address = self . hex . data [ reading _block ] . address ;
2014-03-08 05:25:15 +00:00
2014-02-07 21:33:29 +00:00
var bytes _verified = 0 ;
var bytes _verified _total = 0 ; // used for progress bar
2014-03-08 05:25:15 +00:00
2014-02-07 21:33:29 +00:00
// initialize arrays
for ( var i = 0 ; i <= blocks ; i ++ ) {
self . verify _hex . push ( [ ] ) ;
}
2014-03-08 05:25:15 +00:00
2014-03-29 00:28:27 +00:00
function reading ( ) {
2014-02-09 15:26:18 +00:00
if ( bytes _verified < self . hex . data [ reading _block ] . bytes ) {
2014-05-07 03:01:08 +00:00
var bytes _to _read = ( ( bytes _verified + 256 ) <= self . hex . data [ reading _block ] . bytes ) ? 256 : ( self . hex . data [ reading _block ] . bytes - bytes _verified ) ;
2014-03-08 05:25:15 +00:00
2014-02-09 15:26:18 +00:00
// console.log('STM32 - Reading from: 0x' + address.toString(16) + ', ' + bytes_to_read + ' bytes');
2014-03-08 05:25:15 +00:00
2014-02-09 15:26:18 +00:00
self . send ( [ self . command . read _memory , 0xEE ] , 1 , function ( reply ) { // 0x11 ^ 0xFF
if ( self . verify _response ( self . status . ACK , reply ) ) {
var address _arr = [ ( address >> 24 ) , ( address >> 16 ) , ( address >> 8 ) , address ] ;
var address _checksum = address _arr [ 0 ] ^ address _arr [ 1 ] ^ address _arr [ 2 ] ^ address _arr [ 3 ] ;
2014-03-08 05:25:15 +00:00
2014-02-09 15:26:18 +00:00
self . send ( [ address _arr [ 0 ] , address _arr [ 1 ] , address _arr [ 2 ] , address _arr [ 3 ] , address _checksum ] , 1 , function ( reply ) { // read start address + checksum
if ( self . verify _response ( self . status . ACK , reply ) ) {
var bytes _to _read _n = bytes _to _read - 1 ;
2014-03-08 05:25:15 +00:00
2014-02-09 15:26:18 +00:00
self . send ( [ bytes _to _read _n , ( ~ bytes _to _read _n ) & 0xFF ] , 1 , function ( reply ) { // bytes to be read + checksum XOR(complement of bytes_to_read_n)
if ( self . verify _response ( self . status . ACK , reply ) ) {
self . retrieve ( bytes _to _read , function ( data ) {
for ( var i = 0 ; i < data . length ; i ++ ) {
self . verify _hex [ reading _block ] . push ( data [ i ] ) ;
}
2014-03-08 05:25:15 +00:00
2014-02-09 15:26:18 +00:00
address += bytes _to _read ;
bytes _verified += bytes _to _read ;
bytes _verified _total += bytes _to _read ;
2014-03-08 05:25:15 +00:00
2014-02-09 15:26:18 +00:00
// update progress bar
2014-03-08 05:25:15 +00:00
self . progress _bar _e . val ( ( self . hex . bytes _total + bytes _verified _total ) / ( self . hex . bytes _total * 2 ) * 100 ) ;
2014-02-09 15:26:18 +00:00
// verify another page
reading ( ) ;
} ) ;
}
} ) ;
}
} ) ;
}
} ) ;
} else {
2014-02-07 21:33:29 +00:00
// move to another block
if ( reading _block < blocks ) {
reading _block ++ ;
2014-03-08 05:25:15 +00:00
2014-02-09 15:03:42 +00:00
address = self . hex . data [ reading _block ] . address ;
2014-02-07 21:33:29 +00:00
bytes _verified = 0 ;
2014-03-08 05:25:15 +00:00
2014-02-07 21:33:29 +00:00
reading ( ) ;
} else {
// all blocks read, verify
2014-03-08 05:25:15 +00:00
2014-02-07 21:33:29 +00:00
var verify = true ;
for ( var i = 0 ; i <= blocks ; i ++ ) {
verify = self . verify _flash ( self . hex . data [ i ] . data , self . verify _hex [ i ] ) ;
2014-03-08 05:25:15 +00:00
2014-02-07 21:33:29 +00:00
if ( ! verify ) break ;
}
2014-03-08 05:25:15 +00:00
2014-02-07 21:33:29 +00:00
if ( verify ) {
console . log ( 'Programming: SUCCESSFUL' ) ;
2014-06-24 12:57:41 +00:00
GUI . log ( 'Programming: <strong style="color: green">SUCCESSFUL</strong>' ) ;
2014-03-08 05:25:15 +00:00
2014-02-07 21:33:29 +00:00
// update progress bar
self . progress _bar _e . addClass ( 'valid' ) ;
2014-03-08 05:25:15 +00:00
2014-02-07 21:33:29 +00:00
// proceed to next step
2014-03-08 05:25:15 +00:00
self . upload _procedure ( 7 ) ;
2014-02-07 21:33:29 +00:00
} else {
console . log ( 'Programming: FAILED' ) ;
2014-06-24 12:57:41 +00:00
GUI . log ( 'Programming: <strong style="color: red">FAILED</strong>' ) ;
2014-03-08 05:25:15 +00:00
2014-02-07 21:33:29 +00:00
// update progress bar
self . progress _bar _e . addClass ( 'invalid' ) ;
2014-03-08 05:25:15 +00:00
2014-02-07 21:33:29 +00:00
// disconnect
2014-03-08 05:25:15 +00:00
self . upload _procedure ( 99 ) ;
2014-02-07 21:33:29 +00:00
}
2013-11-13 09:04:14 +00:00
}
2014-02-07 21:33:29 +00:00
}
2014-03-29 00:28:27 +00:00
}
2014-03-08 05:25:15 +00:00
2014-02-07 21:33:29 +00:00
// start reading
reading ( ) ;
2013-11-13 09:04:14 +00:00
break ;
case 7 :
// go
// memory address = 4 bytes, 1st high byte, 4th low byte, 5th byte = checksum XOR(byte 1, byte 2, byte 3, byte 4)
2014-02-07 21:33:29 +00:00
console . log ( 'Sending GO command: 0x8000000' ) ;
2013-11-13 09:04:14 +00:00
self . send ( [ self . command . go , 0xDE ] , 1 , function ( reply ) { // 0x21 ^ 0xFF
if ( self . verify _response ( self . status . ACK , reply ) ) {
2014-02-07 21:33:29 +00:00
var gt _address = 0x8000000 ;
2013-11-16 18:14:34 +00:00
var address = [ ( gt _address >> 24 ) , ( gt _address >> 16 ) , ( gt _address >> 8 ) , gt _address ] ;
2013-11-15 15:17:43 +00:00
var address _checksum = address [ 0 ] ^ address [ 1 ] ^ address [ 2 ] ^ address [ 3 ] ;
2014-03-08 05:25:15 +00:00
2013-11-15 15:17:43 +00:00
self . send ( [ address [ 0 ] , address [ 1 ] , address [ 2 ] , address [ 3 ] , address _checksum ] , 1 , function ( reply ) {
2013-11-13 09:04:14 +00:00
if ( self . verify _response ( self . status . ACK , reply ) ) {
// disconnect
self . upload _procedure ( 99 ) ;
}
} ) ;
}
} ) ;
break ;
case 99 :
// disconnect
GUI . interval _remove ( 'STM32_timeout' ) ; // stop STM32 timeout timer (everything is finished now)
2014-03-08 05:25:15 +00:00
2014-02-07 21:33:29 +00:00
console . log ( 'Script finished after: ' + ( microtime ( ) - self . upload _time _start ) . toFixed ( 4 ) + ' seconds' ) ;
2014-03-08 05:25:15 +00:00
2013-11-13 09:04:14 +00:00
// close connection
2014-01-18 11:44:51 +00:00
serial . disconnect ( function ( result ) {
2013-11-13 09:04:14 +00:00
if ( result ) { // All went as expected
} else { // Something went wrong
}
2014-03-08 05:25:15 +00:00
2014-03-28 23:59:39 +00:00
PortUsage . reset ( ) ;
2013-11-13 09:04:14 +00:00
// unlocking connect button
GUI . connect _lock = false ;
} ) ;
break ;
}
} ;
// initialize object
var STM32 = new STM32 _protocol ( ) ;