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
2014-07-22 12:16:09 +00:00
popular choices - 921600 , 460800 , 256000 , 230400 , 153600 , 128000 , 115200 , 57600 , 38400 , 28800 , 19200
2014-01-28 11:21:35 +00:00
* /
2014-08-09 18:47:07 +00:00
'use strict' ;
2014-01-28 11:21:35 +00:00
2014-08-14 15:00:32 +00:00
var STM32 _protocol = function ( ) {
2014-10-01 13:55:11 +00:00
this . baud ;
2014-07-22 12:16:09 +00:00
this . options = { } ;
2014-10-01 13:55:11 +00:00
this . callback ; // ref
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
2014-10-01 13:55:11 +00:00
STM32 _protocol . prototype . connect = function ( port , baud , hex , options , callback ) {
2013-11-13 09:04:14 +00:00
var self = this ;
2013-12-10 07:19:18 +00:00
self . hex = hex ;
2014-10-01 13:55:11 +00:00
self . baud = baud ;
self . callback = callback ;
2014-03-08 05:25:15 +00:00
2014-08-30 06:59:21 +00:00
// we will crunch the options here since doing it inside initialization routine would be too late
2014-07-22 12:16:09 +00:00
self . options = {
no _reboot : false ,
reboot _baud : false ,
2014-08-30 06:59:21 +00:00
erase _chip : false ,
flash _slowly : false
2014-07-22 12:16:09 +00:00
} ;
2014-03-08 05:25:15 +00:00
2014-07-22 12:16:09 +00:00
if ( options . no _reboot ) {
self . options . no _reboot = true ;
} else {
self . options . reboot _baud = options . reboot _baud ;
}
2014-03-08 05:25:15 +00:00
2014-07-22 12:16:09 +00:00
if ( options . erase _chip ) {
self . options . erase _chip = true ;
}
2014-03-08 05:25:15 +00:00
2014-08-30 06:59:21 +00:00
if ( options . flash _slowly ) {
self . options . flash _slowly = true ;
2014-10-01 13:55:11 +00:00
self . baud = 115200 ;
2014-08-30 06:59:21 +00:00
}
2014-07-22 12:16:09 +00:00
if ( self . options . no _reboot ) {
2014-10-01 13:55:11 +00:00
serial . connect ( port , { bitrate : self . baud , parityBit : 'even' , stopBits : 'one' } , function ( openInfo ) {
2014-07-22 12:16:09 +00:00
if ( openInfo ) {
// we are connected, disabling connect button in the UI
GUI . connect _lock = true ;
2014-03-08 05:25:15 +00:00
2014-07-22 12:16:09 +00:00
self . initialize ( ) ;
} else {
GUI . log ( '<span style="color: red">Failed</span> to open serial port' ) ;
}
} ) ;
2013-11-13 09:04:14 +00:00
} else {
2014-08-14 15:00:32 +00:00
serial . connect ( port , { bitrate : self . options . reboot _baud } , function ( openInfo ) {
2014-07-22 12:16:09 +00:00
if ( openInfo ) {
console . log ( 'Sending ascii "R" to reboot' ) ;
// we are connected, disabling connect button in the UI
GUI . connect _lock = true ;
var bufferOut = new ArrayBuffer ( 1 ) ;
var bufferView = new Uint8Array ( bufferOut ) ;
bufferView [ 0 ] = 0x52 ;
2014-08-14 15:00:32 +00:00
serial . send ( bufferOut , function ( ) {
serial . disconnect ( function ( result ) {
2014-07-22 12:16:09 +00:00
if ( result ) {
2014-10-01 13:55:11 +00:00
serial . connect ( port , { bitrate : self . baud , parityBit : 'even' , stopBits : 'one' } , function ( openInfo ) {
2014-07-22 12:16:09 +00:00
if ( openInfo ) {
self . initialize ( ) ;
} else {
2014-08-30 06:27:24 +00:00
GUI . connect _lock = false ;
2014-07-22 12:16:09 +00:00
GUI . log ( '<span style="color: red">Failed</span> to open serial port' ) ;
}
} ) ;
} else {
GUI . connect _lock = false ;
}
} ) ;
} ) ;
} else {
GUI . log ( '<span style="color: red">Failed</span> to open serial port' ) ;
}
} ) ;
2013-11-13 09:04:14 +00:00
}
} ;
// initialize certain variables and start timers that oversee the communication
2014-08-14 15:00:32 +00:00
STM32 _protocol . prototype . initialize = function ( ) {
2013-11-13 09:04:14 +00:00
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
2014-10-01 13:55:11 +00:00
self . upload _time _start = new Date ( ) . getTime ( ) ;
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-11-11 10:59:12 +00:00
// lock some UI elements TODO needs rework
$ ( 'select[name="release"]' ) . prop ( 'disabled' , true ) ;
2014-08-14 15:00:32 +00:00
serial . onReceive . addListener ( function ( info ) {
2014-01-18 11:44:51 +00:00
self . read ( info ) ;
} ) ;
2014-03-08 05:25:15 +00:00
2014-08-14 15:00:32 +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-08-30 08:30:28 +00:00
$ ( 'span.progressLabel' ) . text ( 'STM32 - timed out, programming: FAILED' ) ;
self . progress _bar _e . addClass ( 'invalid' ) ;
2014-07-16 10:59:12 +00:00
googleAnalytics . sendEvent ( 'Flashing' , 'Programming' , 'timeout' ) ;
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-08-14 15:00:32 +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-08-14 15:00:32 +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-08-14 15:00:32 +00:00
STM32 _protocol . prototype . send = function ( Array , bytes _to _read , callback ) {
2014-02-07 21:33:29 +00:00
// 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-08-14 15:00:32 +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
2014-08-14 15:00:32 +00:00
STM32 _protocol . prototype . verify _response = function ( val , data ) {
2013-11-13 09:04:14 +00:00
if ( val != data [ 0 ] ) {
2014-08-30 06:35:09 +00:00
console . error ( 'STM32 Communication failed, wrong response, expected: ' + val + ' received: ' + data [ 0 ] ) ;
2014-08-30 08:30:28 +00:00
$ ( 'span.progressLabel' ) . text ( 'STM32 Communication failed, wrong response, expected: ' + val + ' received: ' + data [ 0 ] ) ;
self . progress _bar _e . addClass ( 'invalid' ) ;
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
2014-08-14 15:00:32 +00:00
STM32 _protocol . prototype . verify _chip _signature = function ( signature ) {
2013-11-13 09:04:14 +00:00
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
2014-08-14 15:00:32 +00:00
STM32 _protocol . prototype . verify _flash = function ( first _array , second _array ) {
2013-11-13 09:04:14 +00:00
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
2014-08-14 15:00:32 +00:00
STM32 _protocol . prototype . upload _procedure = function ( step ) {
2013-11-13 09:04:14 +00:00
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-08-30 08:30:28 +00:00
$ ( 'span.progressLabel' ) . text ( 'Contacting bootloader ...' ) ;
2014-06-24 12:57:41 +00:00
2013-12-03 20:23:31 +00:00
var send _counter = 0 ;
2014-08-14 15:00:32 +00:00
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 {
2014-08-30 08:30:28 +00:00
$ ( 'span.progressLabel' ) . text ( 'Communication with bootloader failed' ) ;
self . progress _bar _e . addClass ( 'invalid' ) ;
2013-12-03 20:23:31 +00:00
GUI . interval _remove ( 'stm32_initialize_mcu' ) ;
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
2014-07-21 01:48:35 +00:00
console . log ( 'STM32 - no response from bootloader, disconnecting' ) ;
2014-08-30 08:30:28 +00:00
2014-08-31 13:55:12 +00:00
$ ( 'span.progressLabel' ) . text ( 'No response from the bootloader, programming: FAILED' ) ;
2014-08-30 08:30:28 +00:00
self . progress _bar _e . addClass ( 'invalid' ) ;
2013-12-03 20:23:31 +00:00
GUI . interval _remove ( 'stm32_initialize_mcu' ) ;
2014-07-21 01:48:35 +00:00
GUI . interval _remove ( 'STM32_timeout' ) ;
// exit
self . upload _procedure ( 99 ) ;
2013-11-13 09:04:14 +00:00
}
2014-07-21 01:48:35 +00:00
} , 250 , true ) ;
2013-11-13 09:04:14 +00:00
break ;
case 2 :
// get version of the bootloader and supported commands
2014-08-14 15:00:32 +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-08-14 15:00:32 +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)
2014-08-14 15:00:32 +00:00
self . send ( [ self . command . get _ID , 0xFD ] , 2 , function ( data ) { // 0x01 ^ 0xFF
2013-11-13 09:04:14 +00:00
if ( self . verify _response ( self . status . ACK , data ) ) {
2014-08-14 15:00:32 +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-08-30 08:30:28 +00:00
$ ( 'span.progressLabel' ) . text ( 'Erasing ...' ) ;
2014-06-24 12:57:41 +00:00
2014-07-22 12:16:09 +00:00
if ( self . options . erase _chip ) {
console . log ( 'Executing global chip erase' ) ;
2014-08-14 15:00:32 +00:00
self . send ( [ self . command . erase , 0xBC ] , 1 , function ( reply ) { // 0x43 ^ 0xFF
2014-07-22 12:16:09 +00:00
if ( self . verify _response ( self . status . ACK , reply ) ) {
2014-08-14 15:00:32 +00:00
self . send ( [ 0xFF , 0x00 ] , 1 , function ( reply ) {
2014-07-22 12:16:09 +00:00
if ( self . verify _response ( self . status . ACK , reply ) ) {
console . log ( 'Erasing: done' ) ;
// proceed to next step
self . upload _procedure ( 5 ) ;
}
} ) ;
}
} ) ;
} else {
2014-05-07 06:07:49 +00:00
console . log ( 'Executing local erase (only needed pages)' ) ;
2014-08-14 15:00:32 +00:00
self . send ( [ self . command . erase , 0xBC ] , 1 , function ( reply ) { // 0x43 ^ 0xFF
2014-05-07 06:07:49 +00:00
if ( self . verify _response ( self . status . ACK , reply ) ) {
// the bootloader receives one byte that contains N, the number of pages to be erased – 1
2014-08-30 06:26:12 +00:00
var max _address = self . hex . data [ self . hex . data . length - 1 ] . address + self . hex . data [ self . hex . data . length - 1 ] . bytes - 0x8000000 ,
erase _pages _n = Math . ceil ( max _address / self . page _size ) ,
buff = [ ] ,
checksum = erase _pages _n - 1 ;
2014-05-07 06:07:49 +00:00
buff . push ( erase _pages _n - 1 ) ;
2014-08-30 06:26:12 +00:00
2014-05-07 06:07:49 +00:00
for ( var i = 0 ; i < erase _pages _n ; i ++ ) {
buff . push ( i ) ;
checksum ^= i ;
2014-05-07 03:01:08 +00:00
}
2014-08-30 06:26:12 +00:00
2014-05-07 06:07:49 +00:00
buff . push ( checksum ) ;
2014-03-08 05:25:15 +00:00
2014-08-14 15:00:32 +00:00
self . send ( buff , 1 , function ( reply ) {
2014-05-07 06:07:49 +00:00
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 ...' ) ;
2014-08-30 08:30:28 +00:00
$ ( 'span.progressLabel' ) . text ( 'Flashing ...' ) ;
2014-06-24 12:57:41 +00:00
2014-08-30 06:26:12 +00:00
var blocks = self . hex . data . length - 1 ,
flashing _block = 0 ,
address = self . hex . data [ flashing _block ] . address ,
bytes _flashed = 0 ,
bytes _flashed _total = 0 ; // used for progress bar
2014-03-08 05:25:15 +00:00
2014-08-09 18:47:07 +00:00
var write = function ( ) {
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-08-14 15:00:32 +00:00
self . send ( [ self . command . write _memory , 0xCE ] , 1 , function ( reply ) { // 0x31 ^ 0xFF
2014-02-07 21:33:29 +00:00
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-08-14 15:00:32 +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
2014-08-14 15:00:32 +00:00
self . send ( array _out , 1 , function ( reply ) {
2014-02-07 21:33:29 +00:00
if ( self . verify _response ( self . status . ACK , reply ) ) {
// flash another page
write ( ) ;
}
} ) ;
2014-11-15 12:44:12 +00:00
// update progress bar
self . progress _bar _e . val ( Math . round ( bytes _flashed _total / ( self . hex . bytes _total * 2 ) * 100 ) ) ;
2014-02-07 21:33:29 +00:00
}
} ) ;
}
} ) ;
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 ...' ) ;
2014-08-30 08:30:28 +00:00
$ ( 'span.progressLabel' ) . text ( 'Verifying ...' ) ;
2014-06-24 12:57:41 +00:00
2014-08-30 06:26:12 +00:00
var blocks = self . hex . data . length - 1 ,
reading _block = 0 ,
address = self . hex . data [ reading _block ] . address ,
bytes _verified = 0 ,
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-08-09 18:47:07 +00:00
var reading = function ( ) {
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-08-14 15:00:32 +00:00
self . send ( [ self . command . read _memory , 0xEE ] , 1 , function ( reply ) { // 0x11 ^ 0xFF
2014-02-09 15:26:18 +00:00
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-08-14 15:00:32 +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
2014-02-09 15:26:18 +00:00
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-08-14 15:00:32 +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)
2014-02-09 15:26:18 +00:00
if ( self . verify _response ( self . status . ACK , reply ) ) {
2014-08-14 15:00:32 +00:00
self . retrieve ( bytes _to _read , function ( data ) {
2014-02-09 15:26:18 +00:00
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
// verify another page
reading ( ) ;
} ) ;
}
} ) ;
2014-11-15 12:44:12 +00:00
// update progress bar
self . progress _bar _e . val ( Math . round ( ( self . hex . bytes _total + bytes _verified _total ) / ( self . hex . bytes _total * 2 ) * 100 ) ) ;
2014-02-09 15:26:18 +00:00
}
} ) ;
}
} ) ;
} 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-08-30 08:30:28 +00:00
$ ( 'span.progressLabel' ) . text ( 'Programming: SUCCESSFUL' ) ;
2014-07-16 10:59:12 +00:00
googleAnalytics . sendEvent ( 'Flashing' , 'Programming' , 'success' ) ;
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-08-30 08:30:28 +00:00
$ ( 'span.progressLabel' ) . text ( 'Programming: FAILED' ) ;
2014-07-16 10:59:12 +00:00
googleAnalytics . sendEvent ( 'Flashing' , 'Programming' , 'fail' ) ;
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
2014-08-14 15:00:32 +00:00
self . send ( [ self . command . go , 0xDE ] , 1 , function ( reply ) { // 0x21 ^ 0xFF
2013-11-13 09:04:14 +00:00
if ( self . verify _response ( self . status . ACK , reply ) ) {
2014-08-30 06:26:12 +00:00
var gt _address = 0x8000000 ,
address = [ ( gt _address >> 24 ) , ( gt _address >> 16 ) , ( gt _address >> 8 ) , gt _address ] ,
address _checksum = address [ 0 ] ^ address [ 1 ] ^ address [ 2 ] ^ address [ 3 ] ;
2014-03-08 05:25:15 +00:00
2014-08-14 15:00:32 +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
2013-11-13 09:04:14 +00:00
// close connection
2014-08-14 15:00:32 +00:00
serial . disconnect ( function ( result ) {
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 ;
2014-10-01 13:55:11 +00:00
2014-11-11 10:59:12 +00:00
// unlock some UI elements TODO needs rework
$ ( 'select[name="release"]' ) . prop ( 'disabled' , false ) ;
2014-10-01 13:55:11 +00:00
// handle timing
var timeSpent = new Date ( ) . getTime ( ) - self . upload _time _start ;
console . log ( 'Script finished after: ' + ( timeSpent / 1000 ) + ' seconds' ) ;
2014-11-15 12:44:12 +00:00
if ( self . callback ) self . callback ( ) ;
2013-11-13 09:04:14 +00:00
} ) ;
break ;
}
} ;
// initialize object
var STM32 = new STM32 _protocol ( ) ;