add script to dump and flash NXP LPC 1313 over UART ISP
This commit is contained in:
parent
8c26edf3bf
commit
0c447df7b0
|
@ -0,0 +1,149 @@
|
|||
#!/usr/bin/env ruby
|
||||
# encoding: utf-8
|
||||
# ruby: 1.9.1
|
||||
# this script will use the LPC1300 UART ISP protocol to read/write memory
|
||||
# the protocol is specified in AN11229
|
||||
require 'serialport'
|
||||
|
||||
DEBUG = false
|
||||
|
||||
# open serial port
|
||||
@serial = SerialPort.open("/dev/ttyUSB0",{ baud: 9600, databits: 8, parity: SerialPort::NONE, stop_bit: 1, flow_control: SerialPort::SOFT})
|
||||
$/ = "\r\n"
|
||||
|
||||
# send a non ISP command
|
||||
# used for configuring ISP
|
||||
# returns response
|
||||
def simple_command(command)
|
||||
puts "< "+command if DEBUG
|
||||
@serial.puts command
|
||||
line = @serial.gets.chomp
|
||||
if line.start_with? command then
|
||||
line = line[(command.length)..-1]
|
||||
line.gsub!(/^\r?\n?/,'')
|
||||
end
|
||||
puts "> "+line if DEBUG
|
||||
return line
|
||||
end
|
||||
|
||||
# send ISP command
|
||||
# returns return code
|
||||
def isp_command(command)
|
||||
rc = simple_command(command).to_i
|
||||
return rc
|
||||
end
|
||||
|
||||
# read memory (size byte at address)
|
||||
# returns raw memory
|
||||
# does not support multiple line
|
||||
def read_memory(address,size)
|
||||
return nil if size>44 # maximal 44 bytes (1 line) supported
|
||||
raise "reading memory failed" unless isp_command("R #{address} #{size}")==0
|
||||
data = @serial.gets.chomp.unpack("u*")[0] # memory read, UU encoded
|
||||
checksum = @serial.gets.chomp.to_i # checksum, addition
|
||||
sum = 0
|
||||
data.bytes {|b| sum += b }
|
||||
#puts data.bytes.to_a.collect {|b| "%02x" % b }*" "
|
||||
raise "wrong checksum" unless checksum==sum
|
||||
@serial.puts "OK"
|
||||
return data
|
||||
end
|
||||
|
||||
# write one page (256 bytes) of raw data to flash at address
|
||||
def write_flash_page(address,data)
|
||||
raise "data size is not one page (256 bytes): #{data.bytesize}" unless data.bytesize==256
|
||||
raise "address #{address} is not page aligned (256 bytes)" unless address%256==0
|
||||
ram_addr = 0x10001000 # where to copy in RAM
|
||||
rc = isp_command("W #{ram_addr} #{data.bytesize}")
|
||||
raise "can't write to RAM (error: #{rc})" unless rc==0
|
||||
(256/32).times do |i|
|
||||
@serial.puts [data.byteslice(i*32,32)].pack("u*")
|
||||
end
|
||||
checksum = 0
|
||||
data.bytes.to_a.each {|b| checksum += b }
|
||||
@serial.puts checksum.to_s
|
||||
line = @serial.gets.chomp
|
||||
raise "writing flash failed (error: #{line})" unless line=="OK"
|
||||
raise "preparing memory failed" unless isp_command("P 0 7")==0
|
||||
rc = isp_command("C #{address} #{ram_addr} #{data.bytesize}")
|
||||
raise "copying RAM to flash failed (error: #{rc})" unless rc==0
|
||||
end
|
||||
|
||||
# test for ISP
|
||||
raise "ISP not detected" unless simple_command("?")=="Synchronized"
|
||||
raise "ISP not detected" unless simple_command("Synchronized")=="OK"
|
||||
puts "ISP detected"
|
||||
|
||||
# set internal frequency
|
||||
raise "can't set frequency" unless simple_command("12000")=="OK"
|
||||
|
||||
# disable echo
|
||||
raise "can't disable echo" unless isp_command("A 0")==0
|
||||
|
||||
# read part ID
|
||||
parts = {}
|
||||
parts["742543403"] = "LPC1311FHN33"
|
||||
parts["742395947"] = "LPC1313FHN33"
|
||||
parts["742395947"] = "LPC1313FBD48"
|
||||
parts["1023492139"] = "LPC1342FHN33"
|
||||
parts["1023492139"] = "LPC1342FBD48"
|
||||
parts["1023410219"] = "LPC1343FHN33"
|
||||
parts["1023410219"] = "LPC1343FBD48"
|
||||
parts["404131883"] = "LPC1311FHN33/01"
|
||||
parts["405803051"] = "LPC1313FHN33/01"
|
||||
parts["405803051"] = "LPC1313FBD48/01"
|
||||
raise "reading part ID failed" unless isp_command("J")==0
|
||||
id = @serial.gets.chomp
|
||||
part = parts[id]
|
||||
if part then
|
||||
puts "part: #{part}"
|
||||
else
|
||||
puts "part ID: #{id} (unknown part)"
|
||||
end
|
||||
|
||||
# read boot code version
|
||||
raise "reading boot version failed" unless isp_command("K")==0
|
||||
version1 = @serial.gets.chomp
|
||||
version2 = @serial.gets.chomp
|
||||
puts "boot version: #{version2}.#{version1}"
|
||||
|
||||
# read UID
|
||||
raise "reading UID failed" unless isp_command("N")==0
|
||||
uid1 = @serial.gets.chomp
|
||||
uid2 = @serial.gets.chomp
|
||||
uid3 = @serial.gets.chomp
|
||||
uid4 = @serial.gets.chomp
|
||||
puts "UID: #{uid1} #{uid2} #{uid3} #{uid4}"
|
||||
|
||||
# read memory
|
||||
puts "dumping flash"
|
||||
file = File.open("lpcdump.raw","w")
|
||||
size = 32 # number of byte to read (1 UU line can hold 61 char = 45 bytes, every 20 lines on checksum is sent)
|
||||
(32*1024/size).times do |offset|
|
||||
data = read_memory(offset*size,size)
|
||||
file.write data
|
||||
end
|
||||
file.close
|
||||
puts "dumped in #{file.path}"
|
||||
|
||||
# unlock firmware to write flash
|
||||
raise "unlocking failed" unless isp_command("U 23130")==0
|
||||
|
||||
puts "erasing sector"
|
||||
rc = isp_command("P 0 1")
|
||||
raise "preparing failed (error: #{rc})" unless rc==0
|
||||
rc = isp_command("E 0 1")
|
||||
raise "erasing failed (error: #{rc})" unless rc==0
|
||||
|
||||
# write firmware
|
||||
puts "flashing"
|
||||
file = File.open("firmware/PS2000/96230036_PS2000_P2R_212.bin","r")
|
||||
size = 256 # page size (number of byte to write)
|
||||
(file.size/size).times do |i|
|
||||
write_flash_page(i*size,file.read(size))
|
||||
end
|
||||
rest = file.size%size
|
||||
if rest>0 then
|
||||
write_flash_page(file.size-rest,file.read(rest)+("\xff".force_encoding("ASCII-8BIT")*(size-rest)))
|
||||
end
|
||||
puts "wrote #{file.size} bytes"
|
Loading…
Reference in New Issue