Create a gist now

Instantly share code, notes, and snippets.

@marlesan /romwr.rb Secret
Last active Nov 1, 2016

What would you like to do?
EN29F002用ROMライタ PC側書き込みソフト
#! /usr/bin/ruby
=begin
Usage: ruby romwr.rb FILENAME [-d DEVICE] [-s ORIGIN]
FILENAME 書き込むファイルの名前
DEVICE ライタ回路(Arduino)が繋がっているデバイスファイル(未指定だと '/dev/ttyACM0')
ORIGIN 書き込み開始のアドレス(16進数指定/未指定だと 0x0000)
・serialport というgemが必要(serialport が使えるならWindowsでも動くはず…)
・Arduinoのリセットボタンを押してから実行する(逆だと上手くいかない)
・データの終端がアドレス0xffffを超えるような書き込みは不可
・チップを全消去するので部分的な書き込みは不可
=end
require 'serialport'
require 'benchmark'
filename = ARGV[0]
device = '/dev/ttyACM0'
origin = 0x0000
romfile = File.binread(filename)
if i_dev = ARGV.index('-d')
device = ARGV[i_dev + 1]
end
if i_org = ARGV.index('-s')
orgin = ARGV[i_org + 1].to_i(16)
end
if origin + romfile.bytesize - 1 > 0xffff
puts "out of range to write!"
exit
end
SerialPort.open(device, 115200, 8, 1, 0) do |serial|
# Mega2560に通信要求
print 'requesting connection.'
serial.read_timeout = 2000 # 2秒ごとに通信リクエストを送る
serial.flush_input
serial.flush_output
loop do
serial.write('#:')
print '.'
begin
break if serial.readline(':').include?('ack')
rescue EOFError
end
end
# 通信開始
serial.flush_input
serial.flush_output
puts "\nconnected!\n"
print "erasing the chip..."
worktime = Benchmark.realtime do
# チップ消去
serial.print('c;')
serial.read_timeout = 40000 # チップ消去にかかる時間が最大35秒
serial.gets(';')
serial.read_timeout = 2000
end
puts "done in #{worktime} sec."
# 読み書き単位の最大サイズを取得
serial.print("M;")
block_size = serial.gets(';').to_i
# バイナリをROMに書き込む
print "programming the romfile..."
worktime = Benchmark.realtime do
# 開始アドレスを設定
serial.print("a;#{origin};")
serial.gets(';')
addr = origin
# 書き込み処理
begin
(romfile.bytesize / block_size).times do
serial.print('w;')
serial.write(romfile[addr..addr + block_size - 1]);
raise "ProgrammingFailed" if serial.gets(';').include?('failed')
addr += block_size
end
# block_size単位から余った部分の送信
if (remain_size = romfile.bytesize % block_size) > 0
# 余り部分のサイズを読み書き単位に設定
serial.print("b;#{remain_size};")
serial.gets(';')
serial.print('w;')
serial.write(romfile[addr..addr + remain_size - 1]);
raise "ProgrammingFailed" if serial.gets(';').include?('failed')
addr += remain_size
end
rescue RuntimeError
puts "programming failed at #{addr.to_s(16)}H-#{(addr + block_size - 1).to_s(16)}H."
exit
end
end
puts "done in #{worktime} sec."
# ベリファイ用に書き込んだ範囲を読み戻す
readback = ""
print "reading back the romfile to verify..."
worktime = Benchmark.realtime do
# 読み書き単位のサイズを最大値に再設定
serial.print("b;#{block_size};")
serial.gets(';')
# 開始アドレスを設定
serial.print("a;#{origin};")
serial.gets(';')
# 読み込み処理
(romfile.bytesize / block_size).times do
serial.print('R;')
readback += serial.read(block_size)
end
# block_size単位から余った部分の受信
if (remain_size = romfile.bytesize % block_size) > 0
# 余り部分のサイズを読み書き単位に設定
serial.print("b;#{remain_size};")
serial.gets(';')
serial.print('R;')
readback += serial.read(remain_size)
end
end
puts "done in #{worktime} sec."
if romfile == readback
puts "\nSUCCEEDED!!"
else
puts "\nFAILED..."
end
puts "\ndumped the readback image to \"_#{filename}\""
File.binwrite("_#{filename}", readback)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment