150 lines
4.5 KiB
Ruby
Executable File
150 lines
4.5 KiB
Ruby
Executable File
#!/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"
|