summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJenna Fox <a@creativepony.com>2012-09-23 22:01:49 +1000
committerJenna Fox <a@creativepony.com>2012-09-23 22:01:49 +1000
commit28b65b95cc1f47a6353e6ede5a4dbee6a36a76e3 (patch)
tree0e1b9bc46045d97dce0a499947bfd0f1b2792831
parent288212e19a9341788772afcc0fb02d8240e5ffcc (diff)
downloadmicronucleus-28b65b95cc1f47a6353e6ede5a4dbee6a36a76e3.tar.gz
micronucleus-28b65b95cc1f47a6353e6ede5a4dbee6a36a76e3.tar.bz2
micronucleus-28b65b95cc1f47a6353e6ede5a4dbee6a36a76e3.zip
getting close to having a working 2.2kb bootloader!
-rw-r--r--commandline/main.c4
-rw-r--r--firmware/dump.rb3
-rw-r--r--firmware/upload.rb110
3 files changed, 115 insertions, 2 deletions
diff --git a/commandline/main.c b/commandline/main.c
index 1639904..725e2ea 100644
--- a/commandline/main.c
+++ b/commandline/main.c
@@ -15,9 +15,9 @@
#include "usbcalls.h"
#define IDENT_VENDOR_NUM 0x16c0
-#define IDENT_VENDOR_STRING "obdev.at"
+#define IDENT_VENDOR_STRING "creativepony.com"
#define IDENT_PRODUCT_NUM 1503
-#define IDENT_PRODUCT_STRING "HIDBoot"
+#define IDENT_PRODUCT_STRING "uBoot"
// extra delays before more USB requests for tiny85 compatibility while chip frozen
// this number could be lower than 16000 - minimum will be greater than 9000 (erase and write)
diff --git a/firmware/dump.rb b/firmware/dump.rb
new file mode 100644
index 0000000..471d6d4
--- /dev/null
+++ b/firmware/dump.rb
@@ -0,0 +1,3 @@
+`rm temp-dump.bin`
+`avrdude -c usbtiny -p t85 -U flash:r:temp-dump.bin:r`
+puts open('temp-dump.bin').read(30).bytes.to_a.map { |x| x.to_s(16) }.join(' ')
diff --git a/firmware/upload.rb b/firmware/upload.rb
new file mode 100644
index 0000000..7253ef5
--- /dev/null
+++ b/firmware/upload.rb
@@ -0,0 +1,110 @@
+require 'libusb'
+
+# Abstracts access to uBoot avr tiny85 bootloader - can be used only to upload bytes
+class MicroBoot
+ Functions = [
+ :get_info,
+ :write_page,
+ :run_program
+ ]
+
+ # return all thinklets
+ def self.all
+ usb = LIBUSB::Context.new
+ usb.devices.select { |device|
+ device.product == 'uBoot'
+ }.map { |device|
+ self.new(device)
+ }
+ end
+
+ def initialize devref
+ @device = devref
+ end
+
+ def info
+ unless defined? @info
+ result = control_transfer(function: :get_info, dataIn: 5)
+ version, flash_length, page_size, write_sleep = result.unpack('CS>CC')
+
+ @info = {
+ flash_length: flash_length,
+ page_size: page_size,
+ version: version,
+ write_sleep: write_sleep.to_f / 1000.0
+ }
+ end
+ @info
+ end
+
+ # upload a new program
+ def program= bytestring
+ raise "Program too long!" if bytestring.bytesize > info[:flash_length]
+ bytes = bytestring.bytes.to_a
+
+ address = 0
+ bytes.each_slice(info[:page_size]) do |bytes|
+ control_transfer(function: :write_page, wIndex: address, wValue: bytes.length, dataOut: bytes.pack('C*'))
+ sleep(info[:write_sleep])
+ address += bytes.length
+ end
+ end
+
+ def finished
+ control_transfer(function: :run_program)
+ sleep(info[:write_sleep]) # not sure if this is worth having? It's okay if USB fails now...
+
+ @io.close
+ @io = nil
+ end
+
+ protected
+ # raw opened device
+ def io
+ unless @io
+ @io = @device.open
+ end
+
+ @io
+ end
+
+ def control_transfer(opts = {})
+ opts[:bRequest] = Functions.index(opts.delete(:function)) if opts[:function]
+ io.control_transfer({
+ wIndex: 0,
+ wValue: 0,
+ bmRequestType: usb_request_type(opts),
+ timeout: 5000
+ }.merge opts)
+ end
+
+
+
+ def usb_request_type opts
+ c = LIBUSB::Call
+ value = c::RequestTypes[:REQUEST_TYPE_VENDOR] | c::RequestRecipients[:RECIPIENT_DEVICE]
+ value |= c::EndpointDirections[:ENDPOINT_OUT] if opts.has_key? :dataOut
+ value |= c::EndpointDirections[:ENDPOINT_IN] if opts.has_key? :dataIn
+ return value
+ end
+end
+
+puts "Finding devices"
+thinklets = MicroBoot.all
+puts "Found #{thinklets.length} thinklet"
+exit unless thinklets.length > 0
+
+thinklet = thinklets.first
+
+puts "First thinklet: #{thinklet.info.inspect}"
+
+test_data = ("---- Hello World! ----" * 10).encode("BINARY")
+puts "Attempting to write '#{test_data}' to first thinklet's program memory"
+thinklet.program = test_data
+
+puts "That seems to have gone well! Telling thinklet to run program..."
+
+sleep(0.5)
+
+thinklet.finished # let thinklet know it can go do other things now if it likes
+puts "All done!"