| # Usage: |
| # openocd -f openocd-optimus.cfg |
| # (in another window:) |
| # telnet localhost 4444 |
| # |
| # Note: this stops working as soon as Linux boots. I think the MMU breaks it, |
| # perhaps. |
| # |
| |
| source [find interface/olimex-arm-usb-tiny-h.cfg] |
| |
| # Addresses and header offsets for the uLoader and loader (barebox). |
| # Unsigned uLoaders, and both unsigned and signed loaders (bareboxes) have |
| # headers which must be skipped when loading images via JTAG. Signed uLoaders |
| # are only used on devices which have their JTAG locked anyway, so are |
| # irrelevant here. |
| # |
| # Note that there is also a legacy form of unsigned barebox which has no |
| # header. This is not directly supported by this script, but you can just |
| # change the header size here to 0x0. |
| global IRAM_ADDR LOAD_ADDR ULOADER_UNSIGNED_HEADER_SIZE BAREBOX_HEADER_SIZE |
| set IRAM_ADDR 0x83000000 |
| set LOAD_ADDR 0x01000000 |
| set ULOADER_UNSIGNED_HEADER_SIZE 0x38 |
| set BAREBOX_HEADER_SIZE 0x10 |
| |
| reset_config trst_and_srst |
| adapter_khz 1000 |
| |
| # Called automatically at initialization time. |
| # This function will reset the board, so that even if you're in Linux already |
| # (which seems to stop JTAG from working) openocd can take over. |
| proc init_reset { mode } { |
| echo "In init_reset($mode)..." |
| if { $mode == "startup" } { |
| echo "startup mode" |
| jtag_reset 1 1 |
| sleep 1 |
| jtag_reset 0 1 |
| sleep 1 |
| runtest 50 |
| jtag arp_init-reset |
| jtag_reset 0 0 |
| } else { |
| c2k.cpu mww phys 0x904b0000 2 |
| } |
| echo "init_reset done" |
| } |
| proc jtag_init {} { |
| init_reset startup |
| } |
| |
| # the mindspeed c2k "data access port" via jtag. |
| jtag newtap c2k dap \ |
| -expected-id 0x4ba00477 \ |
| -irlen 4 \ |
| -ircapture 0x1 \ |
| -irmask 0xf |
| |
| # the mindspeed c2k's ARM core, via the dap. |
| # If you have a newer version of openocd, you might need to change |
| # "cortex_a8" -> "cortex_a" |
| # NOTE(apenwarr): 0x80110000 is a magic number copied from another config file. |
| # But it's the only one that works. I would have thought the control |
| # registers would be in the normal 0x9xxxxxxx register space but that doesn't |
| # work at all. |
| target create c2k.cpu cortex_a8 \ |
| -chain-position c2k.dap \ |
| -coreid 0 \ |
| -dbgbase 0x80110000 |
| |
| # TODO(apenwarr): this supposedly speeds up flash access, but it's scary. |
| # IRAM_ADDR is the mindspeed CPU's IRAM (internal SRAM) used for booting. |
| # That's the only RAM that will work before configuring the DRAM, ie. |
| # super early after reset. Maybe we should just add some code here to |
| # configure the DRAM though. |
| # c2k.cpu configure \ |
| # -work-area-phys $IRAM_ADDR \ |
| # -work-area-size 65536 |
| |
| # This function lets us reset the CPU without resetting the jtag interface |
| # and disrupting our communications. |
| c2k.cpu configure -event reset-assert { |
| c2k.cpu mww phys 0x904b0000 2 |
| } |
| |
| # Our NOR flash connected via the EXT bus. |
| # NOTE(apenwarr): I think the flash driver is buggy. |
| # Reprogramming the flash seems to only work sometimes. I suggest not |
| # using it; just load a replacement bootloader into RAM instead and use |
| # that for reflashing. |
| flash bank nor0 cfi 0xc0000000 0x04000000 2 2 c2k.cpu |
| |
| # TODO(apenwarr): we'd have to add a new driver in order to flash NAND. |
| # That's probably more work than it's worth. |
| # nand device nand0 orion c2k.cpu 0xcfff0000 |
| |
| # Usage: uloader uloader.bin |
| # Reboots the box and loads uloader.bin into the IRAM, then prepares it to |
| # run. use 'resume' to actually let it run. |
| proc uloader { filename } { |
| global IRAM_ADDR ULOADER_UNSIGNED_HEADER_SIZE |
| |
| reset halt |
| echo "Loading uloader $filename into IRAM..." |
| load_image $filename [expr $IRAM_ADDR - $ULOADER_UNSIGNED_HEADER_SIZE] |
| step $IRAM_ADDR |
| echo "Load completed; stopped at first instruction." |
| } |
| |
| proc _run_uloader {} { |
| global LOAD_ADDR |
| |
| echo "Letting uloader run..." |
| bp $LOAD_ADDR 8 hw |
| resume |
| echo "resumed..." |
| wait_halt |
| rbp $LOAD_ADDR |
| echo "uloader finished." |
| echo "" |
| } |
| |
| proc _loader { filename } { |
| global LOAD_ADDR BAREBOX_HEADER_SIZE |
| |
| echo "Loading loader $filename into DRAM..." |
| load_image $filename [expr $LOAD_ADDR - $BAREBOX_HEADER_SIZE] |
| |
| # NOTE(apenwarr): note sure why, but 'resume' sometimes fails to resume here. |
| # It might have some kind of interaction with the (should be deleted) |
| # hardware breakpoint. step followed by resume works more reliably. |
| step $LOAD_ADDR |
| echo "Load completed; stopped at first instruction." |
| } |
| |
| # Usage: loader barebox.bin |
| # Reboots the box, lets the default uloader execute, then loads the given |
| # barebox into DRAM and prepares it to run. Use 'resume' to actually let |
| # it run. |
| proc loader { filename } { |
| # TODO(apenwarr): Use a post-reset hook to set DRAM timings; skip uloader. |
| reset halt |
| _run_uloader |
| _loader $filename |
| } |
| |
| # Usage: loaders uloader.bin barebox.bin |
| # Reboots the box, loads uloader.bin into IRAM, lets it execute until |
| # it tries to run barebox (presumably after configuring DRAM and GPIOs), |
| # then halts the processor so it can load our own copy of barebox.bin |
| # into DRAM, then runs that. This should allow one-step recovery from |
| # a completely bricked device. |
| # |
| # This prepares the second barebox to run, but doesn't run it. Use 'resume' |
| # to actually let it run. |
| proc loaders { file1 file2 } { |
| # TODO(apenwarr): Use a post-reset hook to set DRAM timings; skip uloader. |
| uloader $file1 |
| _run_uloader |
| _loader $file2 |
| } |
| |
| echo "config finished." |