#!/usr/bin/env ruby require "serialport.so" require "optparse" port_baud = 115200 port_path = "/dev/ttyUSB0" terminal_mode = false verbose = false check = false ############################################################################# # Extend SerialPort class with bootloader communication class SerialPort BOOT_SIG = "**soc-lm32/bootloader**" def put_uint32(i) putc( (i >> 24) & 0xff ) putc( (i >> 16) & 0xff ) putc( (i >> 8) & 0xff ) putc( (i >> 0) & 0xff ) end def download(addr, size) a = Array.new(size) putc 'd' put_uint32 addr put_uint32 size size.times do |i| a[i] = getc end return a end def upload(addr, data) putc 'u' put_uint32 addr put_uint32 data.length data.each do |c| putc c end end def find_bootloader(max_tries = 32) old_timeout = read_timeout read_timeout = 500 count = 0; begin count = count + 1 if (count == max_tries) then raise "Bootloader (#{BOOT_SIG}) not not found" end putc '\r' l = gets end while l.nil? or not l.index( BOOT_SIG ) read_timeout = old_timeout end end ############################################################################# # Main opts = OptionParser.new do |o| o.banner = "Usage: upload [options] " o.on( "-b", "--baud BAUDRATE", Integer, "Serial port baudrate (default: #{port_baud})" ) do |baud| port_baud = baud end o.on( "-s", "--serial SERIALPORT", "Path to serial port (default: #{port_path})" ) do |port| port_path = port end o.on( "-v", "--verbose", "Be verbose and show serial I/O" ) do verbose = true end o.on( "-t", "--terminal", "Switch to terminal mode after upload" ) do terminal_mode = true end o.on( "-c", "--check", "Check RAM after upload and verify everything is correct" ) do check = true end o.on_tail( "-h", "--help", "Display this help message" ) do puts o exit 0 end end # Check arguments, open serial port and file begin opts.parse!(ARGV) raise "SREC file argument missing" if ARGV.length != 1; file_path = ARGV[0] uploadFile = File.open( file_path, "r" ) raise "Could not SREC file." if not uploadFile; fileSize = File.size( file_path ) port = SerialPort.new(port_path, port_baud, 8, 1, SerialPort::NONE) raise "Could not open serial port." if not port; rescue => e STDERR.puts "\nERROR: #{e.message}" STDERR.puts STDERR.puts opts STDERR.puts exit 1 end begin STDOUT.sync = true print "Looking for soc-lm32 bootloader..." port.find_bootloader puts "found." data = Array.new(0x2000).map do |e| e = 0x23 end port.upload(0x40000000, data ); # ist_data = port.download(0x40000000, 0x2000) #p ist_data # read SREC file startAddress = nil print "Uploading SREC file..." uploadFile.each_line do |line| line.chomp! if line[0..1] == "S7" then startAddress = line[4..11].hex end if line[0..1] == "S3" then count = line[2..3].hex addr = line[4..11].hex dat = line[12..-3] cksum = line[-2..-1].hex count = count - 5 data = Array.new( count ) count.times do |i| data[i] = ( dat[ (2*i) .. (2*i+1) ] ).hex end port.upload(addr, data) if verbose then print " [0x%08x] " % addr data.each do |e| print " %02x" % e; end puts else print "." end end end puts "done." if check then print "verifieing RAM content..." uploadFile.seek(0) uploadFile.each_line do |line| printf "." line.chomp! if line[0..1] == "S3" then count = line[2..3].hex addr = line[4..11].hex dat = line[12..-3] chsum = line[-2..-1].hex count = count/2 - 1 soll_data = Array.new( count ) count.times do |i| soll_data[i] = ( dat[ (2*i) .. (2*i+1) ] ).hex end ist_data = port.download(addr, count) count.times do |i| if soll_data[i] != ist_data[i] then puts "0x%08x: 0x%02x <-> 0x%02x" % [addr+i, soll_data[i], ist_data[i]] end end end end puts "done." end if not startAddress.nil? then puts "Jumping to start address 0x%08x." % startAddress port.putc 'g' port.put_uint32 startAddress end if terminal_mode puts "------ entering terminal mode ------" while true do a = select( [port, STDIN], nil, nil ); STDOUT.putc(port.getc) if a[0].include?( port ) port.putc(STDIN.getc) if a[0].include?( STDIN ) end end ensure uploadFile.close unless uploadFile.nil? port.close unless port.nil? end