sflash_write.tcl 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407
  1. #
  2. # Copyright (C) <2019-2021>
  3. # <Cypress Semiconductor Corporation (an Infineon company)>
  4. #
  5. ###############################################################################
  6. #
  7. # sflash_write.tcl
  8. #
  9. # This TCL OpenOCD script runs on a PC and communicates with the embedded
  10. # sflash_write app to allow the PC to write data into a serial flash chip
  11. # attached to the target processor
  12. #
  13. # Usage example:
  14. #
  15. # source [find mfg_spi_flash/write_sflash.tcl]
  16. # sflash_init "BCMUSI11-SDIO-debug"
  17. # sflash_write_file "example.bin" 0x10 "BCMUSI11-SDIO-debug" 1
  18. # shutdown
  19. #
  20. ###############################################################################
  21. # CHIP_RAM_START must be supplied by target specific TCL script
  22. set MemoryStart $CHIP_RAM_START
  23. ###############################################################################
  24. #
  25. # These variables must match the ones in Apps/waf/sflash_write/sflash_write.c
  26. #
  27. # They rely on the linker script placing the data_config_area_t and
  28. # data_transfer_area_t structures at the start of RAM
  29. #
  30. ###############################################################################
  31. # This must match data_config_area_t
  32. set entry_address_loc [expr {$MemoryStart + 0x00} ]
  33. set stack_address_loc [expr {$MemoryStart + 0x04} ]
  34. set buffer_size_loc [expr {$MemoryStart + 0x08} ]
  35. # This must match data_transfer_area_t
  36. set data_size_loc [expr {$MemoryStart + 0x0C} ]
  37. set dest_address_loc [expr {$MemoryStart + 0x10} ]
  38. set command_loc [expr {$MemoryStart + 0x14} ]
  39. set result_loc [expr {$MemoryStart + 0x18} ]
  40. set data_loc [expr {$MemoryStart + 0x1C} ]
  41. # These must match the MFG_SPI_FLASH_COMMAND defines
  42. set COMMAND_INITIAL_VERIFY 0x01
  43. set COMMAND_ERASE 0x02
  44. set COMMAND_WRITE 0x04
  45. set COMMAND_POST_WRITE_VERIFY 0x08
  46. set COMMAND_VERIFY_CHIP_ERASURE 0x10
  47. set COMMAND_WRITE_DCT 0x20
  48. set COMMAND_READ 0x40
  49. set COMMAND_WRITE_ERASE_IF_NEEDED 0x80
  50. # These must match the mfg_spi_flash_result_t enum
  51. set RESULT(0xffffffff) "In Progress"
  52. set RESULT(4294967295) "In Progress"
  53. set RESULT(0) "OK"
  54. set RESULT(1) "Erase Failed"
  55. set RESULT(2) "Verify after write failed"
  56. set RESULT(3) "Size too big for buffer"
  57. set RESULT(4) "Size too big for chip"
  58. set RESULT(5) "DCT location not found - has factory reset app been written?"
  59. set RESULT(6) "Error during Write"
  60. set RESULT(7) "Error during Read"
  61. # For handling big single file
  62. set MAX_SINGLE_FILE_SIZE "4194304"
  63. ###############################################################################
  64. # memread32
  65. #
  66. # Helper function that reads a 32 bit value from RAM and returns it
  67. #
  68. # address - the RAM address to read from
  69. ###############################################################################
  70. proc memread32 {address resume_required} {
  71. if { $resume_required == 1 } {
  72. halt
  73. }
  74. set mem [format %d [read_memory $address 32 1]]
  75. if { $resume_required == 1} {
  76. resume
  77. }
  78. return $mem
  79. }
  80. ###############################################################################
  81. # load_image_bin
  82. #
  83. # Loads part of a binary file into RAM
  84. #
  85. # fname - filename of binary image file
  86. # foffset - offset from the start of the binary file where data will be read
  87. # address - the destination RAM address
  88. # length - number of bytes to transfer
  89. ###############################################################################
  90. proc load_image_bin {fname foffset address length } {
  91. # Load data from fname filename at foffset offset to
  92. # target at address. Load at most length bytes.
  93. puts "loadimage address $address foffset $foffset $length"
  94. load_image $fname [expr {$address - $foffset}] bin $address $length
  95. }
  96. proc target_not_supported {} {
  97. puts stderr "Target is not currently supported by sflash_write.tcl"
  98. shutdown
  99. }
  100. proc post_init_43909_setup { } {
  101. reset init
  102. cortex_r4 maskisr on
  103. # Go to Supervisor ARM mode
  104. reg cpsr 0xd3
  105. reg lr 0x0
  106. }
  107. proc post_init_psoc6_setup { } {
  108. reset init
  109. psoc6 reset_halt sysresetreq
  110. # Switch to cm4 since that is target for sflash_write
  111. targets psoc6.cpu.cm4
  112. }
  113. ###############################################################################
  114. # sflash_init
  115. #
  116. # Prepares for writing to serial flashby loading the sflash_write app into
  117. # memory and setting it running.
  118. # This function assumes the following target has already been built:
  119. # waf.sflash_write-NoOS-<PlatBusDebug>
  120. #
  121. # PlatBusDebug - The platform, bus and debug part of the build target
  122. # init4390 - run initialisation for the 4390
  123. ###############################################################################
  124. proc sflash_init { PlatBusDebug init4390 } {
  125. global entry_address_loc
  126. global stack_address_loc
  127. global buffer_size_loc
  128. global entry_address
  129. global stack_address
  130. global buffer_size
  131. init
  132. if { $init4390 == 4390 } {
  133. target_not_supported
  134. } elseif { $init4390 == 43909 } {
  135. post_init_43909_setup
  136. } elseif { $init4390 == 6 } {
  137. post_init_psoc6_setup
  138. }
  139. load_image $PlatBusDebug
  140. set entry_address [memread32 $entry_address_loc 0]
  141. set stack_address [memread32 $stack_address_loc 0]
  142. set buffer_size [memread32 $buffer_size_loc 0]
  143. puts "entry_address= $entry_address"
  144. puts "stack_address= $stack_address"
  145. puts "buffer_size= $buffer_size"
  146. if { $buffer_size == 0 } {
  147. puts "Error: Buffer size read from address $buffer_size_loc on target is zero"
  148. exit -1;
  149. }
  150. # Setup start address
  151. resume $entry_address
  152. }
  153. ###############################################################################
  154. # program_sflash
  155. #
  156. # Executes a serial command by communicating to the sflash_write app
  157. #
  158. # fname - filename of binary image file (if command requires it)
  159. # foffset - offset from the start of the binary file where data will be read (if command requires it)
  160. # dataSize - number of bytes to transfer (if command requires it)
  161. # destaddr - the destination serial flash address (if command requires it)
  162. # cmd - The commmand to execute (see list above)
  163. ###############################################################################
  164. proc program_sflash { filename foffset dataSize destaddr cmd } {
  165. global PlatBusDebug MemoryStart data_size_loc data_loc dest_address_loc command_loc result_loc entry_address RESULT entry_address_loc
  166. halt
  167. # Load the binary data into the RAM
  168. if { ( $dataSize != 0 ) && ( $filename != "" ) } {
  169. load_image_bin $filename $foffset $data_loc $dataSize
  170. }
  171. # Write the details of the data
  172. mww $data_size_loc $dataSize
  173. mww $dest_address_loc $destaddr
  174. mww $result_loc 0xffffffff
  175. # Write the command - This causes the writing to start
  176. mww $command_loc $cmd
  177. resume
  178. set resultval 0xffffffff
  179. set loops 0
  180. while { ($resultval == 0xffffffff) && ( $loops < 1500 ) } {
  181. sleep 100
  182. set resultval [memread32 $result_loc 1]
  183. incr loops
  184. }
  185. puts "****************** Result: $RESULT($resultval)"
  186. if { $resultval != 0 } {
  187. halt
  188. reg
  189. exit -1;
  190. }
  191. }
  192. ###############################################################################
  193. # sflash_write_file
  194. #
  195. # Writes an entire binary image file to a serial flash address
  196. # This function assumes the following target has already been built:
  197. # waf.sflash_write-NoOS-<PlatBusDebug>
  198. #
  199. # filename - filename of binary image file
  200. # destAddress - the destination serial flash address
  201. # PlatBusDebug - The platform, bus and debug part of the build target
  202. # erasechip - If 1, Erase the chip before writing.
  203. # init4390 - run initialisation for the 4390
  204. ###############################################################################
  205. proc sflash_write_file { filename destAddress PlatBusDebug erasechip init4390 } {
  206. global COMMAND_ERASE COMMAND_INITIAL_VERIFY COMMAND_WRITE COMMAND_POST_WRITE_VERIFY buffer_size COMMAND_WRITE_ERASE_IF_NEEDED MAX_SINGLE_FILE_SIZE
  207. sflash_init $PlatBusDebug $init4390
  208. set binDataSize [file size $filename]
  209. set write_command_val [expr {$COMMAND_WRITE_ERASE_IF_NEEDED | $COMMAND_POST_WRITE_VERIFY} ]
  210. set pos 0
  211. # if { $erasechip } {
  212. # puts "Erasing Chip"
  213. # program_sflash $filename $pos 0 $destAddress $erase_command_val
  214. # puts "Chip Erase Done"
  215. # }
  216. if { $binDataSize < $MAX_SINGLE_FILE_SIZE } {
  217. puts "Total write size is $binDataSize."
  218. while { $pos < $binDataSize } {
  219. if { ($binDataSize - $pos) < $buffer_size } {
  220. set writesize [expr {$binDataSize - $pos}]
  221. } else {
  222. set writesize $buffer_size
  223. }
  224. puts "writing $writesize bytes at [expr {$destAddress + $pos}]"
  225. program_sflash $filename $pos $writesize [expr {$destAddress + $pos}] $write_command_val
  226. set pos [expr {$pos + $writesize}]
  227. }
  228. } else {
  229. puts "The file size was too big ($binDataSize), will split it into small size before write to sflash."
  230. set fd_pos 0
  231. set tmpfilename_count 0
  232. ###Read FILE in binary###
  233. set fd_binDataSize $binDataSize
  234. set fd [open $filename rb]
  235. fconfigure $fd -translation binary
  236. while { $fd_pos < $fd_binDataSize } {
  237. if { ($fd_binDataSize - $fd_pos) < $MAX_SINGLE_FILE_SIZE } {
  238. set fd_writesize [expr {$fd_binDataSize - $fd_pos}]
  239. } else {
  240. set fd_writesize $MAX_SINGLE_FILE_SIZE
  241. }
  242. set data [read $fd $fd_writesize]
  243. ###Write data to temp file in binary###
  244. set tmpfilename $filename\_part\_$tmpfilename_count\.txt
  245. set tmp_fd [open $tmpfilename wb]
  246. puts -nonewline $tmp_fd $data
  247. close $tmp_fd
  248. ###Write temp file into sflash###
  249. puts "Partially, write size is $fd_writesize."
  250. set pos 0
  251. while { $pos < $fd_writesize } {
  252. if { ($fd_writesize - $pos) < $buffer_size } {
  253. set writesize [expr {$fd_writesize - $pos}]
  254. } else {
  255. set writesize $buffer_size
  256. }
  257. puts "writing $writesize bytes at [expr {$destAddress + $pos}]"
  258. program_sflash $tmpfilename $pos $writesize [expr {$destAddress + $pos}] $write_command_val
  259. set pos [expr {$pos + $writesize}]
  260. }
  261. file delete $tmpfilename
  262. set destAddress [ expr {$destAddress + $fd_writesize} ]
  263. set fd_pos [expr {$fd_pos + $fd_writesize}]
  264. seek $fd $fd_pos
  265. set tmpfilename_count [expr {$tmpfilename_count + 1}]
  266. }
  267. close $fd
  268. }
  269. }
  270. ###############################################################################
  271. # sflash_read_file
  272. #
  273. # Reads data from a serial flash address
  274. # This function assumes the following target has already been built:
  275. # waf.sflash_write-NoOS-<PlatBusDebug>
  276. #
  277. # filename - output filename for binary image file
  278. # srcAddress - the destination serial flash address
  279. # PlatBusDebug - The platform, bus and debug part of the build target
  280. # length - number of bytes to read
  281. # init4390 - run initialisation for the 4390
  282. ###############################################################################
  283. proc sflash_read_file { filename srcAddress PlatBusDebug length init4390 } {
  284. global COMMAND_ERASE COMMAND_INITIAL_VERIFY COMMAND_WRITE COMMAND_POST_WRITE_VERIFY buffer_size COMMAND_READ data_loc
  285. puts ""
  286. puts "--> save to $filename"
  287. puts "--> SFLASH address $srcAddress"
  288. puts "--> length $length"
  289. puts ""
  290. sflash_init $PlatBusDebug $init4390
  291. set temp_file [file dirname $filename]
  292. append temp_file "/temp.bin"
  293. # open the output file and set into binary mode
  294. set fd_out [open $filename "wb"]
  295. fconfigure $fd_out -translation binary
  296. set read_command_val [expr {$COMMAND_READ} ]
  297. set pos 0
  298. while { $pos < $length } {
  299. if { ($length - $pos) < $buffer_size } {
  300. set readsize [expr {$length - $pos}]
  301. } else {
  302. set readsize $buffer_size
  303. }
  304. puts "reading $readsize bytes from [expr {$srcAddress + $pos}]"
  305. program_sflash "" $pos $readsize [expr {$srcAddress + $pos}] $read_command_val
  306. halt
  307. dump_image $temp_file $data_loc $readsize
  308. set fd_in_size [ file size $temp_file ]
  309. puts "temp size: $fd_in_size"
  310. # get the output file position for reporting
  311. set curr_pos [ tell $fd_out ]
  312. # concatenate temp_file to filename
  313. # open temp_file in binary mode and read in the data
  314. set fd_in [open $temp_file "rb"]
  315. fconfigure $fd_in -translation binary
  316. set file_data [read $fd_in ]
  317. close $fd_in
  318. puts -nonewline $fd_out $file_data
  319. flush $fd_out
  320. # get current positioin of output for reporting
  321. seek $fd_out 0 end
  322. set new_pos [ tell $fd_out ]
  323. set written_amount [expr {$new_pos - $curr_pos}]
  324. puts " wrote $written_amount from $curr_pos to $new_pos"
  325. #update the SFLASH read position
  326. set pos [expr {$pos + $readsize}]
  327. }
  328. close $fd_out
  329. file delete $temp_file
  330. }
  331. proc sflash_erase { PlatBusDebug init4390 } {
  332. global COMMAND_ERASE COMMAND_INITIAL_VERIFY COMMAND_WRITE COMMAND_POST_WRITE_VERIFY buffer_size COMMAND_WRITE_ERASE_IF_NEEDED
  333. sflash_init $PlatBusDebug $init4390
  334. set erase_command_val [expr {$COMMAND_ERASE} ]
  335. puts "Erasing Chip"
  336. set start_milliseconds [clock milliseconds]
  337. program_sflash "" 0 0 0 $erase_command_val
  338. set end_milliseconds [clock milliseconds]
  339. puts [format "Chip Erase Done (in %d ms)" [expr {$end_milliseconds - $start_milliseconds}]]
  340. }