class GdbFlasher::MCU
Public Class Methods
new(connection)
click to toggle source
# File lib/gdbflasher/mcu.rb, line 4 def initialize(connection) @connection = connection @symbol_table = {} helper_hex = File.join HELPERS, helper_name + ".hex" helper_sym = File.join HELPERS, helper_name + ".sym" File.open(helper_sym, "r") do |f| f.each_line do |line| line.rstrip! address, symbol = line.split(" ") @symbol_table[symbol.intern] = address.to_i 16 end end helper = nil File.open(helper_hex, "r") { |f| helper = IHex.load f } connection.reset connection.get_stop_reply helper.segments.each do |segment| connection.write_memory segment.base, segment.data end initialize_environment @connection.insert_breakpoint 0, @symbol_table[:trap], breakpoint_kind call_helper :initialize end
Public Instance Methods
finalize()
click to toggle source
# File lib/gdbflasher/mcu.rb, line 38 def finalize call_helper :finalize @connection.remove_breakpoint 0, @symbol_table[:trap], breakpoint_kind end
program_ihex(ihex, extra = {})
click to toggle source
# File lib/gdbflasher/mcu.rb, line 44 def program_ihex(ihex, extra = {}) sectors = [] sector_actions = [] sector_map = self.class.const_get :SECTORS sector_map.each_index do |i| sector_begin, sector_end = sector_map[i] sector_segment = nil ihex.segments.each do |segment| intersection = segment.intersect sector_begin, sector_end if intersection.size > 0 if sector_segment.nil? sector_segment = IHex::Segment.new sector_segment.base = sector_begin sector_segment.data = blank_byte.chr * (sector_end - sector_begin + 1) sectors << sector_segment end affected_range = intersection.base - sector_begin...intersection.base + intersection.size - sector_begin sector_segment.data[affected_range] = intersection.data end end end if extra[:read_disallowed] sector_actions = [ [ :erase, :program ] ] * sectors.count else puts "Checking sectors" sectors.each do |sector| data = @connection.read_memory sector.base, sector.size if data == sector.data sector_actions << [ ] elsif is_blank(data) sector_actions << [ :program, :verify ] elsif is_blank(sector.data) sector_actions << [ :erase, :verify ] else sector_actions << [ :erase, :program, :verify ] end end end puts "Programming sectors:" sectors.each_index do |i| sector = sectors[i] actions = sector_actions[i] next if actions.empty? sector_id = sector_map.index { |i| i[0] == sector.base } printf " - %08X - %08X: ", sector.base, sector.base + sector.size - 1 actions.each do |action| case action when :erase print "erase, " status = erase sector_id if status != 0 puts "failure!" warn "Unable to erase sector #{sector_id}, vendor-specific error #{status}" return false end when :program print "program, " offset = 0 page_size = @symbol_table[:PAGE_SIZE] buffer = @symbol_table[:page_buffer] while offset < sector.size @connection.write_memory buffer, sector.data[offset...offset + page_size] status = program sector.base + offset if status != 0 puts "failure!" warn "Unable to program page #{(sector.base + offset).to_s 16}, vendor-specific error #{status}" return false end offset += page_size end when :verify print "verify, " data = @connection.read_memory sector.base, sector.size if data != sector.data puts "failure!" warn "Verification of sector #{sector_id} failed." return false end end end print "all ok.\n" end true end
Protected Instance Methods
blank_byte()
click to toggle source
# File lib/gdbflasher/mcu.rb, line 160 def blank_byte 0xFF end
breakpoint_kind()
click to toggle source
# File lib/gdbflasher/mcu.rb, line 180 def breakpoint_kind 4 # ARM breakpoint end
call_helper(func, r0 = 0, r1 = 0, r2 = 0, r3 = 0)
click to toggle source
# File lib/gdbflasher/mcu.rb, line 188 def call_helper(func, r0 = 0, r1 = 0, r2 = 0, r3 = 0) regs = @connection.read_registers regs[0..3] = r0, r1, r2, r3 regs[14] = @symbol_table[:trap] | lr_offset regs[15] = @symbol_table[func] @connection.write_registers regs reply = @connection.continue regs = @connection.read_registers if reply.signal != 0x05 || regs[15] != @symbol_table[:trap] raise "Target stopped by signal #{reply.signal}, PC = #{regs[15].to_s 16}" end regs[0] end
erase(sector_id)
click to toggle source
# File lib/gdbflasher/mcu.rb, line 164 def erase(sector_id) call_helper :erase, sector_id end
initialize_environment()
click to toggle source
# File lib/gdbflasher/mcu.rb, line 176 def initialize_environment end
is_blank(string)
click to toggle source
# File lib/gdbflasher/mcu.rb, line 172 def is_blank(string) string.bytes.all? { |byte| byte == blank_byte } end
lr_offset()
click to toggle source
# File lib/gdbflasher/mcu.rb, line 184 def lr_offset 0 end
program(offset)
click to toggle source
# File lib/gdbflasher/mcu.rb, line 168 def program(offset) call_helper :program, offset end