ARM microcontroller development Some notes about developing software for ARM microcontrollers on linux, more specifically: - Atmel AT91SAM7 (ARM7TDMI) - OpenOCD - Olimex ARM-USB-OCD Entry: ARM JTAG Date: Thu Aug 19 17:50:41 CEST 2010 With my recent experience using gdb + gdbserver on an Atmel AT91SAM7 using a closed Segger JLink[4] interface I'm wondering what tools I should get to be able to use all full open source chain. 1. How to get my ET-ARM STAMP LPC2110[1] board to work with JTAG? I.e. how does the plugin board[2] connect to the stamp board? 2. What JTAG interface to use to get maximum support from OpenOCD[3]? What are the different JTAG features some have and some don't? How do all the pieces fit together? (uC JTAG + gdbserver). Olimex[5] has several. 3. Can this work on a DIP-package small uC? Probably not PIC as it has an incompatible proprietary debugging interface (one reason to stop using it..), but maybe AVR? I can only find AVR32 links.. Does AVR8 have JTAG actually[6]? First I wonder, is there a natural way to map a 2-way serial byte stream to a JTAG stream? JTAG is SPI, right? Then: is there any monitor code running on the target to support JTAG/gdbserver functionality that is not implemented in hardware? Ok, the basic idea as explained in Dominic Rath's thesis[8]. On-chip debugging allows external control over the uC as opposed to sub-based debugging which would use a monitor and some kind of interrupt mechanis, i.e. a serial port. ARM7 and ARM9 have halt mode debugging, where the core is completely stopped. Both cores support 2 comparators that allow to break on instruction fetches or data access. Disadvantage of stub-based programming for flash uC is setting of breakpoints (as opposed to code in RAM). HW debug can set hardware breakpoints. [1] http://www.futurlec.com/ET-ARM_Stamp.shtml [2] http://www.futurlec.com/ET-ARM_Stamp_Board.shtml [3] http://openocd.berlios.de/web/ [4] http://www.segger.com/cms/jlink.html [5] http://olimex.com/dev/index.html [6] http://www.scienceprog.com/build-your-own-avr-jtagice-clone/ [7] http://sourceforge.net/apps/mediawiki/urjtag/index.php?title=Main_Page [8] http://openocd.berlios.de/thesis.pdf Entry: JTAG for LPC2119 Date: Fri Aug 20 16:59:45 CEST 2010 dir signal pin port -------------------- <- TRST 20 1.31 <- TMS 52 1.30 <- TCK 56 1.29 <- TDI 60 1.28 -> TDO 64 1.27 -> RTCK 24 1.26 Entry: OpenOCD on Olimex ARM-USB-OCD Date: Wed Sep 15 14:47:30 CEST 2010 # Starting with "apt-get install openocd" I get openocd which seems to # support the FT2232 (see openocd -c interface_list). # Scripts are relative to /usr/share/openocd/ in my install. # This also seems to have config support for an the Olimex SAM7-EX256 # board[3]. scripts/board/olimex_sam7_ex256.cfg # The script only sources this script: scripts/target/sam7x256.cfg # I have the SAM7-H256 board[2] connected, so it should just work. # For the programmer Olimex ARM-USB-OCD it seems these scripts are used: scripts/interface/olimex-arm-usb-ocd-h.cfg scripts/interface/olimex-arm-usb-ocd.cfg # To use these scripts (had to use sudo -> need to fix perms). $ cd /usr/share/openocd/scripts $ openocd --file interface/arm-usb-ocd.cfg --file target/sam7x256.cfg Open On-Chip Debugger 0.4.0 (2010-02-23-16:59) Licensed under GNU GPL v2 For bug reports, read http://openocd.berlios.de/doc/doxygen/bugs.html srst_only srst_pulls_trst srst_gates_jtag srst_open_drain Info : clock speed 6000 kHz Info : JTAG tap: sam7x256.cpu tap/device found: 0x3f0f0f0f (mfg: 0x787, part: 0xf0f0, ver: 0x3) Info : Embedded ICE version 1 Info : sam7x256.cpu: hardware has 2 breakpoint/watchpoint units # The default port is 3333. $ arm-eabi-gdb (gdb) target remote localhost:3333 Remote debugging using localhost:3333 0x00000000 in ?? () # Now the `monitor' command can be used. (gdb) monitor help # for output see [4] # Trying to upload the code gives this: (gdb) load Loading section .text, size 0x14595 lma 0x1000000 Load failed # The OpenOCD output gives: Warn : memory write caused data abort (address: 0x01000000, size: 0x4, count: 0xf24) # It seems to be writing to Flash as if it were RAM. My guess is that # gdb also needs to be told where things are. # The gdbinitscript I have for the Segger JTAG / gdbserver just talks # to the monitor (gdbserver) giving it some non-standard commands to # enable flash writing. (gdb) monitor flash list {name at91sam7 base 1048576 size 262144 bus_width 4 chip_width 0} (gdb) monitor flash banks #0: at91sam7 at 0x00100000, size 0x00040000, buswidth 4, chipwidth 0 # Ah, maybe it's protected memory? (gdb) monitor flash info 0 #0 : at91sam7 at 0x00100000, size 0x00040000, buswidth 4, chipwidth 0 # 0: 0x00000000 (0x4000 16kB) protected # 1: 0x00004000 (0x4000 16kB) protected # 2: 0x00008000 (0x4000 16kB) not protected # 3: 0x0000c000 (0x4000 16kB) not protected # 4: 0x00010000 (0x4000 16kB) not protected # 5: 0x00014000 (0x4000 16kB) not protected # 6: 0x00018000 (0x4000 16kB) not protected # 7: 0x0001c000 (0x4000 16kB) not protected # 8: 0x00020000 (0x4000 16kB) not protected # 9: 0x00024000 (0x4000 16kB) not protected # 10: 0x00028000 (0x4000 16kB) not protected # 11: 0x0002c000 (0x4000 16kB) not protected # 12: 0x00030000 (0x4000 16kB) not protected # 13: 0x00034000 (0x4000 16kB) not protected # 14: 0x00038000 (0x4000 16kB) not protected # 15: 0x0003c000 (0x4000 16kB) not protected at91sam7 driver information: Chip is AT91SAM7S256 Cidr: 0x270b0941 | Arch: 0x0070 | Eproc: ARM7TDMI | Version: 0x001 | Flashsize: 0x00040000 Master clock (estimated): 48054 KHz | External clock: 18432 KHz Pagesize: 256 bytes | Lockbits(16): 2 0x0003 | Pages in lock region: 128 Securitybit: 0 | Nvmbits(2): 0 0x0 # Switching off protection of the first two sectors: (gdb) mon flash protect 0 0 1 off cleared protection for sectors 0 through 1 on flash bank 0 # Something fishy.. The "flash info 0" command says the flash is at # 0x00100000, while I'm trying to load it at 0x01000000? # Do the SAM7S256 and SAM7S512 use different memory maps? No. # Why is lma set to 0x01000000? The error message also says that's # the address with a write error. # OK, that was stupid. It was a linux/i386 elf. Fixing that: (gdb) load Loading section .rom_vectors, size 0x40 lma 0x100000 Loading section .text, size 0x1805c lma 0x100040 Loading section .rodata, size 0x2084 lma 0x11809c Loading section .got, size 0x23c lma 0x11a120 Loading section .data, size 0xcec lma 0x11a35c Start address 0x100040, load size 110664 Transfer rate: 5 KB/sec, 10060 bytes/write. (gdb) # Then stepping through the code works, and is quite fast too. # Breakpoints work up to 2. My original app code for SAM7X512 does # eventuall hang on the SAM7X256. It freezes somewhere in HAL config. # Let's see if upload speed can be set a bit higher. It doesn't seem # to be the JTAG speed (at 6MHz). Something else causes only 5Kb/sec # transfer rate. Seems I'm not the only one with the problem[5] on # this hardware. # Using fast memory access (slow is potentially safer?) it does seem # to work a bit faster: 5 -> 9 kB/sec. (gdb) monitor arm7_9 fast_memory_access enable [1] http://www.openhardware.net/Embedded_ARM/OpenOCD_JTAG/ [2] http://www.olimex.com/dev/sam7-h256.html [3] http://www.olimex.com/dev/sam7-ex256.html [4] entry://20100915-174237 [5] https://lists.berlios.de/pipermail/openocd-development/2010-July/015961.html Entry: monitor help Date: Wed Sep 15 17:42:37 CEST 2010 add_help_text command_name helptext_string Add new command help text; Command can be multiple tokens. (command valid any time) add_usage_text command_name usage_string Add new command usage text; command can be multiple tokens. (command valid any time) arm ARM command group (command valid any time) arm core_state ['arm'|'thumb'] display/change ARM core state arm disassemble address [count ['thumb']] disassemble instructions arm mcr cpnum op1 CRn op2 CRm value write coprocessor register arm mrc cpnum op1 CRn op2 CRm read coprocessor register arm reg display ARM core registers arm7_9 arm7/9 specific commands (command valid any time) arm7_9 dbgrq ['enable'|'disable'] use EmbeddedICE dbgrq instead of breakpoint for target halt requests (command valid any time) arm7_9 dcc_downloads ['enable'|'disable'] use DCC downloads for larger memory writes (command valid any time) arm7_9 fast_memory_access ['enable'|'disable'] use fast memory accesses instead of slower but potentially safer accesses (command valid any time) arm7_9 semihosting ['enable'|'disable'] activate support for semihosting operations at91sam7 at91sam7 flash command group (command valid any time) at91sam7 gpnvm bitnum ('set'|'clear') set or clear one General Purpose Non-Volatile Memory (gpnvm) bit bp [address length ['hw']] list or set hardware or software breakpoint command core command group (introspection) (command valid any time) command mode [command_name ...] Returns the command modes allowed by a command:'any', 'config', or 'exec'. If no command isspecified, returns the current command mode. Returns 'unknown' if an unknown command is given. Command can be multiple tokens. (command valid any time) command type command_name [...] Returns the type of built-in command:'native', 'simple', 'group', or 'unknown'. Command can be multiple tokens. (command valid any time) debug_level number Sets the verbosity level of debugging output. 0 shows errors only; 1 adds warnings; 2 (default) adds other info; 3 adds debugging. (command valid any time) drscan tap_name [num_bits value]* ['-endstate' state_name] Execute Data Register (DR) scan for one TAP. Other TAPs must be in BYPASS mode. dump_image filename address size etm Emebdded Trace Macrocell command group (command valid any time) exit exit telnet session fast_load loads active fast load image to current target - mainly for profiling purposes fast_load_image filename address ['bin'|'ihex'|'elf'|'s19'] [min_address [max_length]] Load image into server memory for later use by fast_load; primarily for profiling (command valid any time) find print full path to file according to OpenOCD search rules (command valid any time) flash NOR flash command group (command valid any time) flash banks Display table with information about flash banks. (command valid any time) flash erase_address ['pad'] address length Erase flash sectors starting at address and continuing for length bytes. If 'pad' is specified, data outside that range may also be erased: the start address may be decreased, and length increased, so that all of the first and last sectors are erased. flash erase_check bank_id Check erase state of all blocks in a flash bank. flash erase_sector bank_id first_sector_num last_sector_num Erase a range of sectors in a flash bank. flash fillb address value n Fill n bytes with 8-bit value, starting at word address. (No autoerase.) flash fillh address value n Fill n halfwords with 16-bit value, starting at word address. (No autoerase.) flash fillw address value n Fill n words with 32-bit value, starting at word address. (No autoerase.) flash info bank_id Print information about a flash bank. flash list Returns a list of details about the flash banks. (command valid any time) flash probe bank_id Identify a flash bank. flash protect bank_id first_sector [last_sector|'last'] ('on'|'off') Turn protection on or off for a range of sectors in a given flash bank. flash protect_check bank_id Check protection state of all blocks in a flash bank. flash write_bank bank_id filename offset Write binary data from file to flash bank, starting at specified byte offset from the beginning of the bank. flash write_image [erase] [unlock] filename [offset [file_type]] Write an image to flash. Optionally first unprotect and/or erase the region to be used. Allow optional offset from beginning of bank (defaults to zero) flush_count Returns the number of times the JTAG queue has been flushed. gdb_breakpoint_override ('hard'|'soft'|'disable') Display or specify type of breakpoint to be used by gdb 'break' commands. (command valid any time) gdb_port [port_num] Display or specify base port on which to listen for incoming GDB connections. No arguments reports GDB port; zero disables. (command valid any time) gdb_sync next stepi will return immediately allowing GDB to fetch register state without affecting target state (command valid any time) halt [milliseconds] request target to halt, then wait up to the specifiednumber of milliseconds (default 5) for it to complete help [command_name] Show full command help; command can be multiple tokens. (command valid any time) init Initializes configured targets and servers. Changes command mode from CONFIG to EXEC. Unless 'noinit' is called, this command is called automatically at the end of startup. (command valid any time) interface_list List all built-in interfaces (command valid any time) irscan [tap_name instruction]* ['-endstate' state_name] Execute Instruction Register (DR) scan. The specified opcodes are put into each TAP's IR, and other TAPs are put in BYPASS. jtag perform jtag tap actions (command valid any time) jtag arp_init Validates JTAG scan chain against the list of declared TAPs using just the four standard JTAG signals. (command valid any time) jtag arp_init-reset Uses TRST and SRST to try resetting everything on the JTAG scan chain, then performs 'jtag arp_init'. (command valid any time) jtag cget tap_name '-event' event_name Return any Tcl handler for the specified TAP event. jtag configure tap_name '-event' event_name handler Provide a Tcl handler for the specified TAP event. jtag drscan tap_name [num_bits value]* ['-endstate' state_name] Execute Data Register (DR) scan for one TAP. Other TAPs must be in BYPASS mode. jtag flush_count Returns the number of times the JTAG queue has been flushed. jtag init initialize jtag scan chain (command valid any time) jtag interface Returns the name of the currently selected interface. (command valid any time) jtag names Returns list of all JTAG tap names. (command valid any time) jtag pathmove start_state state1 [state2 [state3 ...]] Move JTAG state machine from current state (start_state) to state1, then state2, state3, etc. jtag tapdisable tap_name Try to disable the specified TAP using the 'tap-disable' TAP event. jtag tapenable tap_name Try to enable the specified TAP using the 'tap-enable' TAP event. jtag tapisenabled tap_name Returns a Tcl boolean (0/1) indicating whether the TAP is enabled (1) or not (0). jtag_khz [khz] With an argument, change to the specified maximum jtag speed. Pass 0 to require adaptive clocking. With or without argument, display current setting. (command valid any time) jtag_nsrst_assert_width [milliseconds] delay after asserting srst in ms (command valid any time) jtag_nsrst_delay [milliseconds] delay after deasserting srst in ms (command valid any time) jtag_ntrst_assert_width [milliseconds] delay after asserting trst in ms (command valid any time) jtag_ntrst_delay [milliseconds] delay after deasserting trst in ms (command valid any time) jtag_rclk [fallback_speed_khz] With an argument, change to to use adaptive clocking if possible; else to use the fallback speed. With or without argument, display current setting. (command valid any time) jtag_reset trst_active srst_active Set reset line values. Value '1' is active, value '0' is inactive. load_image filename address ['bin'|'ihex'|'elf'|'s19'] [min_address] [max_length] log_output file_name redirect logging to a file (default: stderr) (command valid any time) mdb ['phys'] address [count] display memory bytes mdh ['phys'] address [count] display memory half-words mdw ['phys'] address [count] display memory words mflash mflash command group (command valid any time) mwb ['phys'] address value [count] write memory byte mwh ['phys'] address value [count] write memory half-word mww ['phys'] address value [count] write memory word nand NAND flash command group (command valid any time) nand drivers lists available NAND drivers (command valid any time) ocd_array2mem arrayname bitwidth address count convert a TCL array to memory locations and write the 8/16/32 bit values ocd_mem2array arrayname bitwidth address count read 8/16/32 bit memory and return as a TCL array for script processing pathmove start_state state1 [state2 [state3 ...]] Move JTAG state machine from current state (start_state) to state1, then state2, state3, etc. pld programmable logic device commands (command valid any time) poll ['on'|'off'] poll target state; or reconfigure background polling power_restore Overridable procedure run when power restore is detected. Runs 'reset init' by default. (command valid any time) profile profiling samples the CPU PC rbp address remove breakpoint reg [(register_name|register_number) [value]] display or set a register; with no arguments, displays all registers and their values reset [run|halt|init] Reset all targets into the specified mode.Default reset mode is run, if not given. reset_config [none|trst_only|srst_only|trst_and_srst] [srst_pulls_trst|trst_pulls_srst|combined|separate] [srst_gates_jtag|srst_nogate] [trst_push_pull|trst_open_drain] [srst_push_pull|srst_open_drain] configure JTAG reset behavior (command valid any time) reset_nag ['enable'|'disable'] Nag after each reset about options that could have been enabled to improve performance. (command valid any time) resume [address] resume target execution from current PC or address runtest num_cycles Move to Run-Test/Idle, and issue TCK for num_cycles. rwp address remove watchpoint sam7x256.cpu target command group (command valid any time) sam7x256.cpu arm ARM command group (command valid any time) sam7x256.cpu arm7_9 arm7/9 specific commands (command valid any time) sam7x256.cpu arp_examine used internally for reset processing sam7x256.cpu arp_halt used internally for reset processing sam7x256.cpu arp_halt_gdb used internally for reset processing to halt GDB sam7x256.cpu arp_poll used internally for reset processing sam7x256.cpu arp_reset used internally for reset processing sam7x256.cpu arp_waitstate used internally for reset processing sam7x256.cpu array2mem arrayname bitwidth address count Writes Tcl array of 8/16/32 bit numbers to target memory sam7x256.cpu cget target_attribute returns the specified target attribute (command valid any time) sam7x256.cpu curstate displays the current state of this target sam7x256.cpu etm Emebdded Trace Macrocell command group (command valid any time) sam7x256.cpu eventlist displays a table of events defined for this target sam7x256.cpu invoke-event event_name invoke handler for specified event sam7x256.cpu mdb address [count] Display target memory as 8-bit bytes sam7x256.cpu mdh address [count] Display target memory as 16-bit half-words sam7x256.cpu mdw address [count] Display target memory as 32-bit words sam7x256.cpu mem2array arrayname bitwidth address count Loads Tcl array of 8/16/32 bit numbers from target memory sam7x256.cpu mwb address data [count] Write byte(s) to target memory sam7x256.cpu mwh address data [count] Write 16-bit half-word(s) to target memory sam7x256.cpu mww address data [count] Write 32-bit word(s) to target memory scan_chain print current scan chain configuration (command valid any time) script filename of OpenOCD script (tcl) to run (command valid any time) shutdown shut the server down (command valid any time) sleep milliseconds ['busy'] Sleep for specified number of milliseconds. "busy" will busy wait instead (avoid this). (command valid any time) soft_reset_halt halt the target and do a soft reset srst_deasserted Overridable procedure run when srst deassert is detected. Runs 'reset init' by default. (command valid any time) step [address] step one instruction from current PC or address svf filename ['quiet'] Runs a SVF file. target_request target request command group (command valid any time) target_request debugmsgs ['enable'|'charmsg'|'disable'] display and/or modify reception of debug messages from target targets [target] change current default target (one parameter) or prints table of all targets (no parameters) (command valid any time) telnet_port [port_num] Specify port on which to listen for incoming telnet connections. No arguments reports telnet port; zero disables. (command valid any time) test_image filename [offset [type]] tms_sequence ['short'|'long'] Display or change what style TMS sequences to use for JTAG state transitions: short (default) or long. Only for working around JTAG bugs. (command valid any time) trace trace command group trace history ['clear'|size] display trace history, clear history or set size trace point ['clear'|address] display trace points, clear list of trace points, or add new tracepoint at address usage [command_name] Show basic command usage; command can be multiple tokens. (command valid any time) verify_image filename [offset [type]] verify_ircapture ['enable'|'disable'] Display or assign flag controlling whether to verify values captured during Capture-IR. (command valid any time) verify_jtag ['enable'|'disable'] Display or assign flag controlling whether to verify values captured during IR and DR scans. (command valid any time) version show program version (command valid any time) virt2phys virtual_address translate a virtual address into a physical address (command valid any time) wait_halt [milliseconds] wait up to the specified number of milliseconds (default 5) for a previously requested halt wp [address length [('r'|'w'|'a') value [mask]]] list (no params) or create watchpoints xsvf (tapname|'plain') filename ['virt2'] ['quiet'] Runs a XSVF file. If 'virt2' is given, xruntest counts are interpreted as TCK cycles rather than as microseconds. Without the 'quiet' option, all comments, retries, and mismatches will be reported. Entry: Segger JLink OpenOCD Date: Thu Sep 16 09:59:14 CEST 2010 Seems to be Supported [1]. Actually, I need the Atmel SAM-ICE, which is restricted to Atmel devices[2][3]. The SAM-ICE is cheaper ($104 at DigiKey). The standard J-Link is 248 Euro. [1] https://lists.berlios.de/pipermail/openocd-development/2010-August/016312.html [2] http://www.segger.com/cms/j-link-oem-versions.html [3] http://www.atmel.com/dyn/products/tools_card.asp?tool_id=3892 Entry: Armpit scheme on Olimex SAM7-H256 Date: Sun Sep 26 22:15:15 CEST 2010 To build (see script in root dir) arm-eabi-as -mcpu=arm7tdmi armpit_00.0225.s -o a.o arm-eabi-ld -Map bin/armpit_00.0225_SAM7_H256.map --script armpit_build_link -o a.elf a.o To program: Use the following OpenOCD command. Note that the offset is necessary because the elf starts at 0. This is in contrast to the eCos elfs that start at the correct flash base address. flash write_image erase /opt/src/armpit/a.elf 0x100000 elf UPDATE: It flashes and seems to run fine, stepping in gdb. However I do have some config wrong because I don't see any console activity on DBGU and there is no virtual serial port popping up either.. [1] http://www.olimex.com/dev/sam7-h256.html [2] http://armpit.sourceforge.net/ Entry: Olimex stuff Date: Tue Sep 28 14:57:12 CEST 2010 I got some eCos app loaded and running, but I can't set breakpoints. This worked before: Unable to set 32 bit software breakpoint at address 001001f8 - check that memory is read/writable This seems to work: (gdb) monitor gdb_breakpoint_override hard Entry: gdbserver Date: Wed Oct 13 11:34:58 CEST 2010 I still don't have a proper way to reset the olimes ocd/at91 combination such that "load, continue" will work. What seems to work is to: - quit gdb, quit OpenOCD - unplug everything (programmer + board) - start OpenOCD, start gdb, reset, load The following init sequence seems to work a bit: target remote :3333 monitor poll monitor reset init monitor sleep 500 ### needed for gdb 6.8 and higher set mem inaccessible-by-default off monitor flash probe 0 monitor gdb_breakpoint_override hard monitor arm7_9 dcc_downloads enable # monitor arm7_9 fast_memory_access enable Some remarks: * The target needs to be halted before you can do anyting like uploading and setting breakpoints. * Why doesn't the program entry point change after `load'? On the Segger J-Link this seems to work just fine. * Reset seems to work, but it doesn't halt the target. Fix: use `soft_reset_halt'. // This is not initialized properly on Olimex board ?? // const char bytes[] = {1,2,3,1,2,3,1,2,3,1,2,3}; Entry: OpenOCD getting started Date: Thu Nov 11 13:16:05 EST 2010 As I forget this every time: 1. start ocd, i.e. like in [1]. 2. start gdb for arm and connect with the "target remote localhost 3333" connect. 3. initialize the arm chip, i.e. halt + init stack. steps 2. and 3. are best bundled in a script such as [2] cd ~/ecos/build/demo /opt/xc/arm9/bin/arm-linux-gnu-gdb -x ~/ecos/bin/eCos.gdb demo [1] http://zwizwa.be/darcs/pool/bin/ocd.SAM7-H256 [2] http://zwizwa.be/darcs/ecos/bin/eCos.gdb Entry: More OpenOCD Date: Thu Nov 11 14:14:25 EST 2010 A minefield. One thing is sure: target needs reset before `load', and I get different behaviour depending on the JTAG clock speed. Set to 300kHz or less, a "halt reset" will work, higher it doesn't always. Let's play a bit more. [1] http://www.mail-archive.com/openocd-development@lists.berlios.de/msg13435.html Entry: OpenOCD current Date: Thu Nov 11 14:23:40 EST 2010 git clone git://repo.or.cz/openocd.git cd openocd ./bootstrap Bootstrap complete. Quick start build instructions: 1. Build Jim Tcl git submodule init git submodule update cd jimtcl ./configure --with-jim-ext=nvp make make install 2. Configure ./configure --enable-maintainer-mode .... ./configure --enable-maintainer-mode --enable-ft2232_libftdi This one seems to work better. Playing it a bit more it seems to be "mon reset init" that doesn't work properly when JTAG clock is fast. Conclusion: it seems to work +- reliably when JTAG clock is set to a slow rate (i.e. 100-300 kHz) before "reset init" is invoked. Entry: LPC2119 ET-ARM STAMP Date: Sat Jul 11 15:30:55 CEST 2009 The getting started document mentions the "LPC2000 flash utility" which can be downloaded[3] from Philips (NXP) website. There is a linux utilities here[4][6]. Forum[5]. In order to get this to work convieniently, it's probably best to make a motherboard which is connected using a USBSERIAL 3.3V cable, and cut out the MAX3232 serial port. Have to wait for the Futurlec order. [1] http://www.ett.co.th [2] http://www.ett.co.th/prod2009/ET-ARM/ET_ARM_STAMP_ADUC7024.html [3] http://www.nxp.com/files/products/standard/microcontrollers/utilities/lpc2000_flash_utility.zip [4] http://www.pjrc.com/arm/lpc2k_pgm/ [5] http://tech.groups.yahoo.com/group/lpc2000/ [6] http://kroy.hu/lpc2k/ Entry: Setting up AT91SAM7S-EK + Olimex ARM-USB-OCD Date: Wed Feb 2 12:22:38 EST 2011 The Olimex ARM-USB-OCD has a RS232 port which can be plugged to the Atmel AT91SAM7S-EK (AT9). It is an FTDI2232C: Feb 2 12:26:50 zoo kernel: [4894878.109218] usb 1-4.4.4: new full speed USB device using ehci_hcd and address 35 Feb 2 12:26:50 zoo kernel: [4894878.226327] usb 1-4.4.4: New USB device found, idVendor=15ba, idProduct=0003 Feb 2 12:26:50 zoo kernel: [4894878.226330] usb 1-4.4.4: New USB device strings: Mfr=1, Product=2, SerialNumber=0 Feb 2 12:26:50 zoo kernel: [4894878.226393] usb 1-4.4.4: Product: Olimex OpenOCD JTAG Feb 2 12:26:50 zoo kernel: [4894878.226395] usb 1-4.4.4: Manufacturer: Olimex Feb 2 12:26:50 zoo kernel: [4894878.229669] usb 1-4.4.4: Ignoring serial port reserved for JTAG Feb 2 12:26:50 zoo kernel: [4894878.232305] ftdi_sio 1-4.4.4:1.1: FTDI USB Serial Device converter detected Feb 2 12:26:50 zoo kernel: [4894878.232333] usb 1-4.4.4: Detected FT2232C Feb 2 12:26:50 zoo kernel: [4894878.232348] usb 1-4.4.4: Number of endpoints 2 Feb 2 12:26:50 zoo kernel: [4894878.232350] usb 1-4.4.4: Endpoint 1 MaxPacketSize 64 Feb 2 12:26:50 zoo kernel: [4894878.232352] usb 1-4.4.4: Endpoint 2 MaxPacketSize 64 Feb 2 12:26:50 zoo kernel: [4894878.232355] usb 1-4.4.4: Setting MaxPacketSize 64 Feb 2 12:26:50 zoo kernel: [4894878.233289] usb 1-4.4.4: FTDI USB Serial Device converter now attached to ttyUSB2 To identify usb serial ports I have a small script[1][2] that resides in /lib/udev and tries to provide a unique name for the device. The OCD doesn't seem to expose a serial number, so i'm generating a tty name based on the idVendor idProduct info, which then becomes /dev/tty-15ba0003 which I've linked to /dev/ttyOCD. Out of the box, the AT91 doesn't seem to produce any serial output, at least not at 9600 baud. Starting the OpenOCD script[3] I used for the other SAM7 board seems to work: tom@zoo:~/bin$ ./ocd.SAM7-H256 #!/bin/bash cat $0 SCRIPTS=/usr/local/share/openocd/scripts exec openocd \ --file $SCRIPTS/interface/arm-usb-ocd.cfg \ --file $SCRIPTS/target/sam7x256.cfg \ --file $0.cfg \ "$@" Open On-Chip Debugger 0.5.0-dev-00586-gc62fb3f (2010-11-11-14:30) Licensed under GNU GPL v2 For bug reports, read http://openocd.berlios.de/doc/doxygen/bugs.html Info : only one transport option; autoselect 'jtag' srst_only srst_pulls_trst srst_gates_jtag srst_open_drain 300 kHz dcc downloads are enabled fast memory access is enabled force hard breakpoints Info : clock speed 300 kHz Info : JTAG tap: sam7x256.cpu tap/device found: 0x3f0f0f0f (mfg: 0x787, part: 0xf0f0, ver: 0x3) Info : Embedded ICE version 1 Info : sam7x256.cpu: hardware has 2 breakpoint/watchpoint units Info : JTAG tap: sam7x256.cpu tap/device found: 0x3f0f0f0f (mfg: 0x787, part: 0xf0f0, ver: 0x3) Warn : srst pulls trst - can not reset into halted mode. Issuing halt after reset. target state: halted target halted in Thumb state due to debug-request, current mode: Supervisor cpsr: 0x40000033 pc: 0x000007f4 I spent some time in november getting the other ARM board setup after my move. That took some time: I had to work around an issue by setting the clock slower before reset, then setting faster before load. See [3][4]. Next: get something running on the arm board. So I got something to run + output to the serial port (DBGU 9600 baud). However, only 2 or 3 times this worked, after that I no longer get any signal on the debug port. Also measured on the analog scope. I'm able to single-step code on the ARM, but breakpoints (actually I tried the "next" command) don't work reliably. My guess is there's a bug with the OpenOCD somewhere. Let's see if there are any config issues I should be aware of. I've upgraded OpenOCD to git tag 75cdbff5aa93d93e414cb22d413f41fb38a076bb. After power cylcing the board and the OCD it seems to work again. When using just `load' and `continue' everything seems to work just fine. Using `reset' (see eCos.gdb) messes things up for good. [1] http://zwizwa.be/darcs/pool/bin/ttyUSB_id [2] entry://../pool/20101231-230904 [3] entry://20101111-142340 [4] http://zwizwa.be/darcs/ecos/bin/eCos.gdb Entry: AT91SAM7 devices Date: Mon Feb 7 14:08:57 EST 2011 SAM7S : 64 pins http://www.atmel.com/dyn/products/devices.asp?category_id=163&family_id=605&subfamily_id=1586&source=left_nav SAM7X : 100 pins http://www.atmel.com/dyn/products/devices.asp?category_id=163&family_id=605&subfamily_id=1724&source=left_nav Flash RAM ------------------------- SAM7S256 256K 64K SAM7S512 512K 64K SAM7X256 256K 64K SAM7X512 512K 128K Entry: AT91SAM7-EK expansion header Date: Tue Feb 8 09:12:16 EST 2011 To what does the numbering on the expansion header correspond? There are numbers 0-31 and AD4-AD7. Looking at the data sheet these are probably the PA PIO numbers not package pin numbers. That seems to be corrected. AD4-AD7 are dedicated pins while AD0-AD3 are mapped to PA17-PA20. For SPI there is: perA perB ------------------ PA11 NPCS0 PWM0 PA12 MISO PWM1 PA13 MOSI PWM2 PA14 SPCK PWM3 Entry: OpenOCD slow? Date: Sat Feb 12 12:12:08 EST 2011 I get 8kb/sec transfer when I upload the image. The reason is probably the Flash write speed, as other JTAG tranfers go very fast. Entry: More robust OCD : USB replug Date: Sun Feb 13 13:14:56 EST 2011 Error: ftdi_write_data: usb bulk write failed Error: couldn't write MPSSE commands to FT2232 Polling target failed, GDB will be halted. Polling again in 6300ms Can we work around that? Also for serial connectors, I see that minicom can detect an unplugged cable and will reconnect properly. Entry: OpenOCD problems target replug Date: Tue Feb 15 09:07:12 EST 2011 When disconnecting the target I get this: Error: Target not halted Error: auto_probe failed Error: Connect failed. Consider setting up a gdb-attach event for the target to prepare target for GDB connect, or use 'gdb_memory_map disable'. Error: attempted 'gdb' connection rejected Restarting OOCD helps. Entry: OpenOCD hardware breakpoing issues Date: Tue Feb 15 12:26:21 EST 2011 Another issue: sometimes gdb seems to loose the pedals when it won't issue `thbreak' or `next' correctly. Maybe the hardware breakpoint management gets messed up? Error: could not add breakpoint Is there a way to list the hardware breakpoints? Yes: mon bp That doesn't seem to list anything though. I get the following error message: Error: address + size wrapped(0xfffffffe, 0x00000004) To list the gdb-known breakpoints: (gdb) info breakpoints Num Type Disp Enb Address What 7 hw breakpoint del y 0x00101498 in demo at /home/tom/ubidata-tom/src/spi/spi.c:339 Something's not right. Exiting OCD does solve the problem. It seems that the "reset" command doesn't really perform a full reset. Is there a way to reset everything, just as it would be done at init? My current workaround is to use a "while sleep 1; do ... ; done" loop around oocd, and invoke "mon shutdown" from gdb, followed by a reconnect. Entry: ocd over network problem Date: Wed Mar 23 13:14:54 EDT 2011 On localhost works fine: requesting target halt and executing a soft reset target state: halted target halted in ARM state due to debug-request, current mode: Supervisor cpsr: 0x600000d3 pc: 0x00000000 - Loading /home/tom/priv/git-private/ubidata/dbb_trailer/build/out/arm_tom/test-blockmanager Loading section .rom_vectors, size 0x40 lma 0x100000 Loading section .text, size 0x2cc34 lma 0x100040 Loading section .rodata, size 0x198c lma 0x12cc74 Loading section .data, size 0x7b4 lma 0x12e600 Start address 0x100040, load size 191924 Transfer rate: 10 KB/sec, 12794 bytes/write. - Done. - Continuing. Same from other host, either using tunneling or direct TCP connection the speed is something like 195 KB/sec and it doesn't seem to upload properly. ? Entry: openocd OLIMEX OCD-USB-EW Date: Mon May 16 14:36:32 CEST 2011 --enable-arm-jtag-ew Entry: OpenOCD on the AT91 Date: Sat May 28 12:14:09 CEST 2011 It's slow and I don't know why. Setting debug loglevel gives this as the main programming loop: Debug: 15414 145857 target.c:1652 target_write_u32(): address: 0xffffff64, value: 0x5a03d801 Debug: 15415 145857 embeddedice.c:502 embeddedice_write_reg(): 0: 0x00000004 Debug: 15416 145857 embeddedice.c:502 embeddedice_write_reg(): 0: 0x00000005 Debug: 15417 145873 at91sam7.c:353 at91sam7_flash_command(): Flash command: 0x5a03d801, flash bank: 1, page number: 984 Debug: 15418 145874 arm7_9_common.c:2270 arm7_9_read_memory(): address: 0xffffff68, size: 0x00000004, count: 0x00000001 Debug: 15420 145889 target.c:1575 target_read_u32(): address: 0xffffff68, value: 0x00000401 Debug: 15421 145889 at91sam7.c:328 at91sam7_wait_status_busy(): status[0]: 0x401 Debug: 15422 145889 at91sam7.c:1102 at91sam7_write(): Write flash bank:0 page number:984 Debug: 15423 145889 embeddedice.c:502 embeddedice_write_reg(): 0: 0x00000004 Debug: 15424 145889 embeddedice.c:502 embeddedice_write_reg(): 0: 0x00000005 So what we see here is that the flash command 0x5a03d801 goes to register 0xffffff64. Looking at the data sheet this is a block of 256 registers called MC (memory controller) at 0xffffff00, which is documented in section 18 in the AT91SAM7X datasheet. At offset 60 and 70 in this window are two EFCs : embedded Flash Controllers which are documented in section 19. 0x64 : MC_FCR : Memory Controller Flash Command Register 5A 0 3D8 0 1 key page command = WP (write page) The key is the write-protection key, always 0x5A 0x68 : MC_FSR : Memory Controller Flash Status Register bit 0 is the ready bit. -> find out if this causes the delay No it doesn't : that bit is 1 when it's read. Ok, I tried again on the host and I get 7kByte/sec, but it doesn't work properly. Why is this so buggy? I had similar problems a couple of months ago. Is it just that I miss some console messages, or is it electrical? I think it's worth investing some time to see how this actually works, so I can understand the error messages. Entry: gdb cheat sheet Date: Sat May 28 16:34:23 CEST 2011 # List breakpoints info breakpoints # List breakpoints in monitor. This doesn't always show the # breakpoints; it seems GDB will set them at a `continue' command. To # verify, log into OpenOCD using telnet and execute the `bp' command # when gdb is inside a `continue' command. mon bp # List memory map info mem Entry: force hard breakpoints Date: Sat May 28 16:43:42 CEST 2011 dcc downloads are enabled fast memory access is enabled force hard breakpoints Entry: OpenOCD, scripting in tcl Date: Sun May 29 13:57:05 CEST 2011 The thing is: OpenOCD is not only useful for gdb, but another debugger/monitor could be bolted on. It might be a good idea to get to know it a bit better. Cheat sheet # Load 10 bytes (8) from memory at 0xF000 ainto var (arr) and print it # to the console. mem2array arr 8 0xF000 10 puts $arr # The bytes arrive on the OpenOCD console. How to make them go to the # GDB console? # startup.tcl tom@zni:~/git/openocd$ find -name startup.tcl ./src/jtag/startup.tcl ./src/startup.tcl ./src/target/startup.tcl ./src/helper/startup.tcl ./src/server/startup.tcl ./src/flash/startup.tcl [1] http://openocd.berlios.de/doc/html/About-Jim_002dTcl.html [2] http://openocd.berlios.de/doc/html/Tcl-Crash-Course.html#Tcl-Crash-Course Entry: OpenOCD docs Date: Sun May 29 15:00:14 CEST 2011 It would be helpful to read the OpenOCD documentation once, completely. ./configure --enable-maintainer-mode --enable-ft2232_libftdi --enable-doxygen-pdf make -C doc pdf make doxygen (!!! apt-get install doxygen) doc/openocd.pdf doxygen/latex/refman.pdf (1500 pages!) Entry: Python scripting in GDB Date: Sun May 29 15:21:06 CEST 2011 [1] http://sourceware.org/gdb/wiki/PythonGdb [2] http://sourceware.org/gdb/wiki/PythonGdbTutorial Entry: OpenOCD bugs Date: Sun May 29 16:09:57 CEST 2011 I'm trying to get to a reliable workaround for all the bugs I run into. Up to now there hasn't been a simple pattern. This is an attempt to separate multiple bugs + their workaround. * Error: address + size wrapped(0xffffffff, 0x00000004) This is supposed to be a bug in GDB[1]. I have no reliable workaround. * Target not halted, starts running when left alone for a while (i.e. +- 1 hour) Could be WDT? It seems to be seriously messed up. I can't fix it with just software. Warn : srst pulls trst - can not reset into halted mode. Issuing halt after reset. Error: Jazelle debug entry -- BROKEN! Error: Jazelle state handling is BROKEN! target state: halted target halted in Jazelle state due to debug-request, current mode: Supervisor cpsr: 0x61000013 pc: 0x00106a72 requesting target halt and executing a soft reset Error: Jazelle state handling is BROKEN! target state: halted target halted in Jazelle state due to debug-request, current mode: Supervisor cpsr: 0x610000d3 pc: 0x00000000 1000 kHz There are 3 things to reset: - target power - programmer power - OpenOCD Assuming it's not the programmer, it should be possible for OpenOCD to reset the chip, whatever the state it is in. So assume the bug is with OpenOCD and restart it. When I reset just OpenOCD (not the board) I run into the other error: GDB: Cannot find bounds of current function OpenOCD: Error: address + size wrapped(0xffffffff, 0x00000004) Doing "reset" and "continue" a couple of times will eventually pull it back in line. Summary: I managed to reset it: - by re-starting OpenOCD - by fiddling a bit with GDB - did not touch target nor programmer power That should be automatable. [1] http://lists.berlios.de/pipermail/openocd-development/2009-February/004684.html Entry: OpenOCD all zeros Date: Sun May 29 17:01:01 CEST 2011 The following problem was solved by power-cyling the (DBB) board: Open On-Chip Debugger 0.5.0-dev-00886-g6152c29 (2011-05-29-14:08) Licensed under GNU GPL v2 For bug reports, read http://openocd.berlios.de/doc/doxygen/bugs.html Info : only one transport option; autoselect 'jtag' srst_only srst_pulls_trst srst_gates_jtag srst_open_drain Warn : use 'at91sam7s256.cpu' as target identifier, not '0' debug_level: 2 1 kHz dcc downloads are enabled fast memory access is enabled force hard breakpoints adapter_nsrst_delay: 200 jtag_ntrst_delay: 200 Info : clock speed 1 kHz Error: JTAG scan chain interrogation failed: all zeroes Error: Check JTAG interface, timings, target power, etc. Error: Trying to use configured scan chain anyway... Error: at91sam7s256.cpu: IR capture error; saw 0x00 not 0x01 Warn : Bypassing JTAG setup events due to errors Info : Embedded ICE version 0 Error: unknown EmbeddedICE version (comms ctrl: 0x00000000) Info : at91sam7s256.cpu: hardware has 2 breakpoint/watchpoint units debug_level: 1 Error: JTAG scan chain interrogation failed: all zeroes Error: Check JTAG interface, timings, target power, etc. Error: Trying to use configured scan chain anyway... Error: at91sam7s256.cpu: IR capture error; saw 0x00 not 0x01 Warn : Bypassing JTAG setup events due to errors Warn : srst pulls trst - can not reset into halted mode. Issuing halt after reset. Error: timed out while waiting for target halted TARGET: at91sam7s256.cpu - Not halted Runtime Error: ./ocd.SAM7-H256.cfg:38: in procedure 'script' at file "embedded:startup.tcl", line 58 in procedure 'reset' called at file "./ocd.SAM7-H256.cfg", line 38 Entry: OpenOCD errors summary Date: Sun May 29 17:03:55 CEST 2011 TODO: verify the following errors and workarounds. - Error: JTAG scan chain interrogation failed: all zeroes This is solved by a board power-cycle and OpenOCD restart. - Error: Jazelle debug entry -- BROKEN! Restarting OpenOCD then brings it to a state where the following occurs: - Error: address + size wrapped(0xffffffff, 0x00000004) This seems to be a generic error caused by GDB getting confused by what it gets from OpenOCD, or some other GDB-related issue. This is fixable by "nudging", i.e. "reset" + "continue" on the GDB prompt: finally it does seem to run reliably, stepping + breakpoints. Entry: OpenOCD console output to GDB Date: Sun May 29 17:52:15 CEST 2011 Console output to GDB goes through: src/server/gdb_server.c : static int gdb_output_con(struct connection *connection, const char* line); This seems to be only used in: static void gdb_log_callback(void *priv, const char *file, unsigned line, const char *function, const char *string) What I think is going on here is that log_add_callback() adds to some kind of global logging facility. Next is to find out how to "puts" to that. To find a list of commands, do: grep -re ".name = " src/ It seems that "list" is what I'm looking for. Probably a better candidate is "echo", defined in src/command.c : .name = "echo", .handler = jim_echo, .mode = COMMAND_ANY, .help = "Logs a message at \"user\" priority. " "Output message to stdout. " "Option \"-n\" suppresses trailing newline", .usage = "[-n] string", This calls LOG_USER / LOG_USER_N. Entry: AT91SAM7 back channel Date: Sun May 29 19:39:03 CEST 2011 Are the DBGU ports/registers accessible through JTAG in monitor mode? Data sheet SAM7S 12.6.1 * Find out what monitor mode does (as opposed to HALT mode) [1] * What are COMMTX and COMMRX signals. I'm browsing [1] looking for monitor mode at 5.9 and I find debug communication channel (DCC) at 5.8. Maybe that's what I'm looking for. Googling for '"coprocessor 14" openocd' I get [2]. On the ARM side it's just a MCR / MRC instruction. On the host side it's scan chain 2. Is this the same DCC as in "dcc downloads" ? Indeed. This mechanism is already used; I've found some ARM code so it looks like it places some code in RAM to handle the other side. Cool. It has some setup code in arm7_9_common.c and the bulk in embeddedice.c (embeddedice_write_dcc) So this _should_ definitely be workable. How to go about it then? [1] http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0210c/I901036.html [2] http://openocd.berlios.de/doc/html/Architecture-and-Core-Commands.html Entry: Getting debug info from GDB into OpenOCD Date: Mon May 30 10:13:22 CEST 2011 I have a memory buffer that I would like to inspect with some kind of script. I have the option to use the (distorted) gdb scripting language, or to use jim tcl on the OpenOCD side. For the latter, I wonder how to translate symbols from GDB and pass them to the "monitor" command. The default behaviour is just to pass anything after the monitor command verbatim, not dereferencing variables. It's probably best to just write the scripts in GDB. Entry: OpenOCD still unreliable Date: Mon May 30 18:40:17 CEST 2011 I'm getting closer to +- reliable operation. However, once in a couple I get this: stepi ignored. GDB will now fetch the register state from the target. A couple of stepi commands (3) right after "reset init" seem to solve this problem. Entry: More OpenOCD errors Date: Mon May 30 19:40:20 CEST 2011 Error: Target not halted Error: auto_probe failed Error: Connect failed. Consider setting up a gdb-attach event for the target to prepare target for GDB connect, or use 'gdb_memory_map disable'. Error: attempted 'gdb' connection rejected It doesn't recover from that. This (I assume) is because of the board/firmware bug that causes sporadic resets. Fix OpenOCD so it restarts whenever this happens. Let's try to restart manually: Error: JTAG scan chain interrogation failed: all zeroes Error: Check JTAG interface, timings, target power, etc. Error: Trying to use configured scan chain anyway... Error: at91sam7s256.cpu: IR capture error; saw 0x00 not 0x01 Warn : Bypassing JTAG setup events due to errors Info : Embedded ICE version 0 Error: unknown EmbeddedICE version (comms ctrl: 0x00000000) Info : at91sam7s256.cpu: hardware has 2 breakpoint/watchpoint units Reason: board power failure. Entry: OpenOCD ARM DCC debug channel Date: Fri Jun 3 17:09:35 CEST 2011 [1] http://openocd.berlios.de/doc/html/Architecture-and-Core-Commands.html Entry: OpenOCD again Date: Tue Jun 7 23:47:34 CEST 2011 Now using the SAM7S Atmel EK, I get a problem at startup. This is right after halt. The mmw is the first write that resets the device. Also if I leave it at 3000 khz, gdb doesn't want to connect. tom@zni:~/ecos-build/bin$ ./ocd.SAM7 Open On-Chip Debugger 0.5.0-dev-00886-g6152c29 (2011-05-29-14:26) Licensed under GNU GPL v2 For bug reports, read http://openocd.berlios.de/doc/doxygen/bugs.html Info : only one transport option; autoselect 'jtag' srst_only srst_pulls_trst srst_gates_jtag srst_open_drain Warn : use 'at91sam7s256.cpu' as target identifier, not '0' debug_level: 2 100 kHz dcc downloads are enabled fast memory access is enabled force hard breakpoints adapter_nsrst_delay: 200 jtag_ntrst_delay: 200 Info : clock speed 100 kHz Info : JTAG tap: at91sam7s256.cpu tap/device found: 0x3f0f0f0f (mfg: 0x787, part: 0xf0f0, ver: 0x3) Info : Embedded ICE version 1 Info : at91sam7s256.cpu: hardware has 2 breakpoint/watchpoint units debug_level: 1 100 kHz Warn : srst pulls trst - can not reset into halted mode. Issuing halt after reset. target state: halted target halted in ARM state due to debug-request, current mode: Abort cpsr: 0x200000d7 pc: 0x000006e8 requesting target halt and executing a soft reset target state: halted target halted in ARM state due to debug-request, current mode: Supervisor cpsr: 0x200000d3 pc: 0x00000000 Warn : memory write caused data abort (address: 0xfffffd00, size: 0x4, count: 0x1) in procedure 'mww' 3000 kHz receiving debug messages from current target charmsg Checking: /usr/local/share/openocd/scripts/target/at91sam7sx.cfg target create $_TARGETNAME arm7tdmi -endian $_ENDIAN -chain-position $_TARGETNAME -variant arm7tdmi $_TARGETNAME configure -event reset-init { soft_reset_halt # RSTC_CR : Reset peripherals mww 0xfffffd00 0xa5000004 # disable watchdog mww 0xfffffd44 0x00008000 # enable user reset mww 0xfffffd08 0xa5000001 # CKGR_MOR : enable the main oscillator mww 0xfffffc20 0x00000601 sleep 10 # CKGR_PLLR: 96.1097 MHz mww 0xfffffc2c 0x00481c0e sleep 10 # PMC_MCKR : MCK = PLL / 2 ~= 48 MHz mww 0xfffffc30 0x00000007 sleep 10 # MC_FMR: flash mode (FWS=1,FMCN=73) mww 0xffffff60 0x00490100 sleep 100 } Pfff.. If I remove the "reset init" in the startup script, it seems to come up just fine. Maybe that never really worked properly? I don't remember. One thing is clear: it doesn't like 3000 kHz. I thought it went faster.. If I switch to 1000 khz, it seems to work. So, again a buch of problems that are too confusing for me to see what is actually going on. I got it working on the Ubi board but the EK is borked again. Now I do an upload at 3000 kHz and that works: (gdb) mon jtag_khz 3000 3000 kHz (gdb) load Loading section .rom_vectors, size 0x40 lma 0x100000 Loading section .text, size 0x28db8 lma 0x100040 Loading section .rodata, size 0x7930 lma 0x128df8 Loading section .data, size 0x1044 lma 0x130728 Start address 0x100040, load size 202604 Transfer rate: 8 KB/sec, 13506 bytes/write. Let's try 6000: seems to work too. This is weird... Do flash uploads actually talk to the processor or directly to the flash? Maybe it's time to start paying attention to the CPSR. I see several different states: 0x600000d3 (normal) 0x200000d3 0x200000d7 0x400000d3 Let's summarize: - uploads do work at 6000 kHz if the state is ok - "reset init" is not reliable: mww error immediately after soft_reset_halt Crap.. can't add comments after a line in jim tcl! Ha.. removing the soft_reset_halt in the init routine make the data abort error go away. Entry: OpenOCD reset-init event Date: Wed Jun 8 01:31:26 CEST 2011 So, it looks like the trouble from last post is mostly that "soft_reset_halt" is called inside the reset-init event handler in the at91sam7sx.cfg file. Removing it makes it behave better. Comparing it with the at91sam7x256.cfg file there is also no "soft_reset_halt". [1] http://openocd.berlios.de/doc/html/Config-File-Guidelines.html Entry: AT91SAM7 setup from scratch Date: Sun Jun 12 18:05:17 CEST 2011 I've been using eCos up to now. How to work on the bare metal? This is the program I'm trying to run, residing in the file sam7.S main: nop nop nop b main Here's the contents of the makefile: all: sam7.elf clean: rm -rf *~ *.o *.elf CC = arm-eabi-gcc -mcpu=arm7tdmi -O0 -g LD = arm-eabi-gcc -mno-thumb-interwork -mcpu=arm7tdmi -Wl,-static -g -nostdlib OBJDUMP = arm-eabi-objdump %.o: %.S $(CC) -o $@ -c $< %.elf: %.o %.ld $(LD) -T$*.ld -o $@ $*.o %.dump: %.elf $(OBJDUMP) -h $< I'm using the following linker script which places everything in RAM. SECTIONS { . = 0x200000; .text : { *(.text) } .data : { *(.data) } .bss : { *(.bss) } } Compiling this to arm7.elf and loading with gdb enables me to step through the code if I use: set $pc = 0x200000 Next is to set the reset vector and maybe put it in flash? Though RAM seems a lot more convenient if it fits.. Let's peek in the eCos code to see what vectors.o looks like: 0 .text 00000564 1 .data 000001d8 2 .bss 00001310 3 .vectors 00000040 4 .fixed_vectors 00000140 It will place the .vectors at the start of rom. So where is that section defined? packages/hal/arm/arch/current/src/vectors.S It seems that this space contains instructions either as branch or direct pc load, but not addresses. #ifdef CYGSEM_HAL_ROM_RESET_USES_JUMP // Assumption: ROM code has these vectors at the hardware reset address. // A simple jump removes any address-space dependencies [i.e. safer] b reset_vector // 0x00 #else ldr pc,.reset_vector // 0x00 #endif Always difficult to see what is an ARM-ism, and what is an AT91-ism. Looks like for arm the vectors are always code. I'm not sure if they are always at 0 though.. I seem to have found some info online about an LPC that starts somewhere else, in Flash. Some more info [1][2]. For linker docs see [3]. [1] http://sourceware.org/ml/ecos-discuss/1999-10/msg00087.html [2] http://sourceware.org/ml/ecos-discuss/1999-10/msg00095.html [3] http://www.delorie.com/gnu/docs/binutils/ld_9.html Entry: ARM instruction set Date: Sun Jun 12 19:47:26 CEST 2011 Rules of thumb (har har): - Destination register is leftmost, operands rightmost. - Immediates need pound sign # - The 0xFFFFFFFF word is an invalid instruction [1] http://infocenter.arm.com/help/topic/com.arm.doc.qrc0001m/QRC0001_UAL.pdf Entry: arm asm/dasm Date: Thu Jun 16 18:27:05 CEST 2011 For Staapl it might be intersting to try to figure out how to convert between binary and assembler using objdump. This works: arm-eabi-objdump -b binary -m arm -D foo Here -D is used instead of -d, because apparently the raw binary data is interpreted to be in .data segement. Maybe it's simpler to convert bin to .o with all data in the .text segment: arm-eabi-objcopy -I binary -O elf32-littlearm -B arm --rename-section .data=.text foo foo.o But that doesn't set the CODE attribute that are in ordinary binaries, but the DATA attribute is set. Note that renaming happens after setting flags. arm-eabi-objcopy -I binary -O elf32-littlearm -B arm --rename-section .data=.text --set-section-flags .data=code foo foo.o To make it less confusing it seems better to reorder the flags, though that doesn't change functionality arm-eabi-objcopy \ -I binary -O elf32-littlearm -B arm \ --set-section-flags .data=code \ --rename-section .data=.text foo foo.o Entry: $pc not reset after soft_reset_halt Date: Wed Jun 22 02:29:57 CEST 2011 Is this because of GDB? I.e GDB's cache of the register values gets out of sync with the machine? Note that "mon reg" does seem to give the correct values. (gdb) mon soft_reset_halt requesting target halt and executing a soft reset target state: halted target halted in ARM state due to debug-request, current mode: Supervisor cpsr: 0x200000d3 pc: 0x00000000 (gdb) info registers r0 0x0 0 r1 0x6f 111 r2 0x204714 2115348 r3 0x10000002 268435458 r4 0x2006a8 2098856 r5 0x13 19 r6 0x20388c 2111628 r7 0x1d 29 r8 0x20384c 2111564 r9 0x200750 2099024 r10 0x2006e0 2098912 r11 0x20384c 2111564 r12 0x2008d8 2099416 sp 0x203800 0x203800 lr 0x1143a4 1131428 pc 0x11e4a8 0x11e4a8 fps 0x0 0 cpsr 0x20000013 536870931 It happened again on a stepi. Indeed it seems to be just that gdb's idea of the registers gets messed up, so it will set them according to a previously saved state before stepping. The following is the OpenOCD debug output when stepping after a soft_reset_halt. The PC is supposed to be at 0, but somehow it gets set at 0x001100f0 which was the state before soft_reset_halt. The problem does not go away with restarting gdb. Restarting OpenOCD however does fix it. Debug: 56656 3980801 gdb_server.c:2201 gdb_input_inner(): received packet: 's' Debug: 56657 3980801 target.c:1062 target_call_event_callbacks(): target event 7 (gdb-start) Debug: 56658 3980801 gdb_server.c:1455 gdb_step_continue_packet(): - Debug: 56659 3980801 gdb_server.c:1475 gdb_step_continue_packet(): step Debug: 56660 3980801 arm7_9_common.c:2270 arm7_9_read_memory(): address: 0x00000000, size: 0x00000004, count: 0x00000001 Debug: 56661 3980811 target.c:1605 target_read_u32(): address: 0x00000000, value: 0xe59ff018 Debug: 56662 3980811 arm7_9_common.c:2270 arm7_9_read_memory(): address: 0x00000020, size: 0x00000004, count: 0x00000001 Debug: 56663 3980822 target.c:1605 target_read_u32(): address: 0x00000020, value: 0x001100f0 Debug: 56664 3980822 arm7_9_common.c:1615 arm7_9_restore_context(): - Debug: 56665 3980822 arm7_9_common.c:1638 arm7_9_restore_context(): examining Supervisor mode Debug: 56666 3980822 arm7_9_common.c:1652 arm7_9_restore_context(): examining dirty reg: r0 Debug: 56667 3980822 arm7_9_common.c:1652 arm7_9_restore_context(): examining dirty reg: r1 Debug: 56668 3980822 arm7_9_common.c:1652 arm7_9_restore_context(): examining dirty reg: r2 Debug: 56669 3980822 arm7_9_common.c:1652 arm7_9_restore_context(): examining dirty reg: r3 Debug: 56670 3980822 arm7_9_common.c:1652 arm7_9_restore_context(): examining dirty reg: r4 Debug: 56671 3980822 arm7_9_common.c:1652 arm7_9_restore_context(): examining dirty reg: r5 Debug: 56672 3980822 arm7_9_common.c:1652 arm7_9_restore_context(): examining dirty reg: r6 Debug: 56673 3980822 arm7_9_common.c:1652 arm7_9_restore_context(): examining dirty reg: r7 Debug: 56674 3980822 arm7_9_common.c:1652 arm7_9_restore_context(): examining dirty reg: r8 Debug: 56675 3980822 arm7_9_common.c:1652 arm7_9_restore_context(): examining dirty reg: r9 Debug: 56676 3980822 arm7_9_common.c:1652 arm7_9_restore_context(): examining dirty reg: r10 Debug: 56677 3980822 arm7_9_common.c:1652 arm7_9_restore_context(): examining dirty reg: r11 Debug: 56678 3980822 arm7_9_common.c:1652 arm7_9_restore_context(): examining dirty reg: r12 Debug: 56679 3980822 arm7_9_common.c:1652 arm7_9_restore_context(): examining dirty reg: pc Debug: 56680 3980822 arm7_9_common.c:1652 arm7_9_restore_context(): examining dirty reg: cpsr Debug: 56681 3980822 arm7_9_common.c:1704 arm7_9_restore_context(): writing register 0 mode Supervisor with value 0xffffffff Debug: 56682 3980822 arm7_9_common.c:1704 arm7_9_restore_context(): writing register 1 mode Supervisor with value 0xffffffff Debug: 56683 3980822 arm7_9_common.c:1704 arm7_9_restore_context(): writing register 2 mode Supervisor with value 0xffffffff Debug: 56684 3980822 arm7_9_common.c:1704 arm7_9_restore_context(): writing register 3 mode Supervisor with value 0xffffffff Debug: 56685 3980822 arm7_9_common.c:1704 arm7_9_restore_context(): writing register 4 mode Supervisor with value 0xffffffff Debug: 56686 3980822 arm7_9_common.c:1704 arm7_9_restore_context(): writing register 5 mode Supervisor with value 0xffffffff Debug: 56687 3980822 arm7_9_common.c:1704 arm7_9_restore_context(): writing register 6 mode Supervisor with value 0xffffffff Debug: 56688 3980822 arm7_9_common.c:1704 arm7_9_restore_context(): writing register 7 mode Supervisor with value 0xffffffff Debug: 56689 3980822 arm7_9_common.c:1704 arm7_9_restore_context(): writing register 8 mode Supervisor with value 0xffffffff Debug: 56690 3980822 arm7_9_common.c:1704 arm7_9_restore_context(): writing register 9 mode Supervisor with value 0xffffffff Debug: 56691 3980822 arm7_9_common.c:1704 arm7_9_restore_context(): writing register 10 mode Supervisor with value 0xffffffff Debug: 56692 3980822 arm7_9_common.c:1704 arm7_9_restore_context(): writing register 11 mode Supervisor with value 0xffffffff Debug: 56693 3980822 arm7_9_common.c:1704 arm7_9_restore_context(): writing register 12 mode Supervisor with value 0xffffffff Debug: 56694 3980822 arm7_9_common.c:1638 arm7_9_restore_context(): examining Supervisor mode Debug: 56695 3980822 arm7_9_common.c:1652 arm7_9_restore_context(): examining dirty reg: pc Debug: 56696 3980822 arm7_9_common.c:1638 arm7_9_restore_context(): examining Supervisor mode Debug: 56697 3980822 arm7_9_common.c:1652 arm7_9_restore_context(): examining dirty reg: pc Debug: 56698 3980822 arm7_9_common.c:1638 arm7_9_restore_context(): examining Supervisor mode Debug: 56699 3980823 arm7_9_common.c:1652 arm7_9_restore_context(): examining dirty reg: sp_svc Debug: 56700 3980823 arm7_9_common.c:1652 arm7_9_restore_context(): examining dirty reg: lr_svc Debug: 56701 3980823 arm7_9_common.c:1652 arm7_9_restore_context(): examining dirty reg: pc Debug: 56702 3980823 arm7_9_common.c:1704 arm7_9_restore_context(): writing register 13 mode Supervisor with value 0xffffffff Debug: 56703 3980823 arm7_9_common.c:1704 arm7_9_restore_context(): writing register 14 mode Supervisor with value 0xffffffff Debug: 56704 3980823 arm7_9_common.c:1638 arm7_9_restore_context(): examining Supervisor mode Debug: 56705 3980823 arm7_9_common.c:1652 arm7_9_restore_context(): examining dirty reg: pc Debug: 56706 3980823 arm7_9_common.c:1638 arm7_9_restore_context(): examining Supervisor mode Debug: 56707 3980823 arm7_9_common.c:1652 arm7_9_restore_context(): examining dirty reg: pc Debug: 56708 3980823 arm7_9_common.c:1738 arm7_9_restore_context(): writing cpsr with value 0x200000d3 Debug: 56709 3980823 arm7tdmi.c:414 arm7tdmi_write_xpsr(): xpsr: 200000d3, spsr: 0 Debug: 56710 3980823 arm7_9_common.c:1748 arm7_9_restore_context(): writing PC with value 0x00000000 Debug: 56711 3980823 embeddedice.c:501 embeddedice_write_reg(): 9: 0xffffffff Debug: 56712 3980823 embeddedice.c:501 embeddedice_write_reg(): 11: 0xffffffff Debug: 56713 3980823 embeddedice.c:501 embeddedice_write_reg(): 12: 0x00000100 Debug: 56714 3980823 embeddedice.c:501 embeddedice_write_reg(): 13: 0x00000077 Debug: 56715 3980823 embeddedice.c:501 embeddedice_write_reg(): 16: 0x00000000 Debug: 56716 3980823 embeddedice.c:501 embeddedice_write_reg(): 17: 0x00000000 Debug: 56717 3980823 embeddedice.c:501 embeddedice_write_reg(): 19: 0xffffffff Debug: 56718 3980823 embeddedice.c:501 embeddedice_write_reg(): 20: 0x00000000 Debug: 56719 3980823 embeddedice.c:501 embeddedice_write_reg(): 21: 0x000000f7 Debug: 56720 3980823 target.c:1062 target_call_event_callbacks(): target event 4 (resumed) Debug: 56721 3980849 embeddedice.c:501 embeddedice_write_reg(): 9: 0x00000003 Debug: 56722 3980849 embeddedice.c:501 embeddedice_write_reg(): 11: 0xffffffff Debug: 56723 3980849 embeddedice.c:501 embeddedice_write_reg(): 12: 0x00000000 Debug: 56724 3980849 embeddedice.c:501 embeddedice_write_reg(): 13: 0x000000f7 Debug: 56725 3980849 embeddedice.c:501 embeddedice_write_reg(): 16: 0x00000000 Debug: 56726 3980849 embeddedice.c:501 embeddedice_write_reg(): 17: 0x00000000 Debug: 56727 3980849 embeddedice.c:501 embeddedice_write_reg(): 19: 0x00000000 Debug: 56728 3980849 embeddedice.c:501 embeddedice_write_reg(): 21: 0x00000000 Debug: 56729 3980849 embeddedice.c:501 embeddedice_write_reg(): 20: 0x00000000 Debug: 56730 3980849 embeddedice.c:501 embeddedice_write_reg(): 0: 0x00000005 Debug: 56731 3980849 embeddedice.c:501 embeddedice_write_reg(): 12: 0x00000000 Debug: 56732 3980851 arm7_9_common.c:1410 arm7_9_debug_entry(): target entered debug from ARM state Debug: 56733 3980866 armv4_5.c:397 arm_set_cpsr(): set CPSR 0x200000d3: Supervisor mode, ARM state Debug: 56734 3980866 arm7_9_common.c:1438 arm7_9_debug_entry(): target entered debug state in Supervisor mode Debug: 56735 3980866 arm7_9_common.c:1460 arm7_9_debug_entry(): r0: 0xffffffff Debug: 56736 3980866 arm7_9_common.c:1460 arm7_9_debug_entry(): r1: 0xffffffff Debug: 56737 3980866 arm7_9_common.c:1460 arm7_9_debug_entry(): r2: 0xffffffff Debug: 56738 3980866 arm7_9_common.c:1460 arm7_9_debug_entry(): r3: 0xffffffff Debug: 56739 3980866 arm7_9_common.c:1460 arm7_9_debug_entry(): r4: 0xffffffff Debug: 56740 3980866 arm7_9_common.c:1460 arm7_9_debug_entry(): r5: 0xffffffff Debug: 56741 3980866 arm7_9_common.c:1460 arm7_9_debug_entry(): r6: 0xffffffff Debug: 56742 3980866 arm7_9_common.c:1460 arm7_9_debug_entry(): r7: 0xffffffff Debug: 56743 3980866 arm7_9_common.c:1460 arm7_9_debug_entry(): r8: 0xffffffff Debug: 56744 3980866 arm7_9_common.c:1460 arm7_9_debug_entry(): r9: 0xffffffff Debug: 56745 3980866 arm7_9_common.c:1460 arm7_9_debug_entry(): r10: 0xffffffff Debug: 56746 3980866 arm7_9_common.c:1460 arm7_9_debug_entry(): r11: 0xffffffff Debug: 56747 3980866 arm7_9_common.c:1460 arm7_9_debug_entry(): r12: 0xffffffff Debug: 56748 3980866 arm7_9_common.c:1460 arm7_9_debug_entry(): r13: 0xffffffff Debug: 56749 3980866 arm7_9_common.c:1460 arm7_9_debug_entry(): r14: 0xffffffff Debug: 56750 3980866 arm7_9_common.c:1460 arm7_9_debug_entry(): r15: 0x001100f0 Debug: 56751 3980866 arm7_9_common.c:1468 arm7_9_debug_entry(): entered debug state at PC 0x1100f0 Debug: 56752 3980870 target.c:1062 target_call_event_callbacks(): target event 2 (gdb-halt) Debug: 56753 3980870 target.c:1062 target_call_event_callbacks(): target event 3 (halted) Debug: 56754 3980870 target.c:1062 target_call_event_callbacks(): target event 8 (gdb-end) Debug: 56755 3980870 arm7_9_common.c:2121 arm7_9_step(): target stepped Debug: 56756 3980872 gdb_server.c:2201 gdb_input_inner(): received packet: 'g' Debug: 56757 3980873 gdb_server.c:2201 gdb_input_inner(): received packet: 'm1100f0,4' Debug: 56758 3980873 gdb_server.c:1278 gdb_read_memory_packet(): addr: 0x001100f0, len: 0x00000004 Debug: 56759 3980873 target.c:1443 target_read_buffer(): reading buffer of 4 byte at 0x001100f0 Debug: 56760 3980873 arm7_9_common.c:2270 arm7_9_read_memory(): address: 0x001100f0, size: 0x00000004, count: 0x00000001 Debug: 56761 3980885 gdb_server.c:2201 gdb_input_inner(): received packet: 'mffffffff,4' Debug: 56762 3980885 gdb_server.c:1278 gdb_read_memory_packet(): addr: 0xffffffff, len: 0x00000004 Debug: 56763 3980885 target.c:1443 target_read_buffer(): reading buffer of 4 byte at 0xffffffff Error: 56764 3980885 target.c:1460 target_read_buffer(): address + size wrapped(0xffffffff, 0x00000004) Using only OpenOCD commands, the we get the following weirdness: (gdb) mon reg pc 0 pc (/32): 0x00000000 (gdb) mon step target state: halted target halted in ARM state due to single-step, current mode: Supervisor cpsr: 0x200000d3 pc: 0x001100f0 Entry: ARM assembler cheat sheet Date: Wed Jun 22 03:17:19 CEST 2011 - destination register is on the left - s suffix means "update condition flags", i.e. and vs. ands [1] http://infocenter.arm.com/help/topic/com.arm.doc.qrc0001m/QRC0001_UAL.pdf Entry: AT91SAM7S slow_reset init/halt work again Date: Wed Jun 22 04:11:41 CEST 2011 With openocd e7c611deeac63e585eb61d6c4cdb54d078c2c579 the previous trouble[1] I had with reset not working properly seem to be resolved. However, it does seem to need the slow_reset. [1] entry://20110607-234734 Entry: Reset to 0x110070 : warm_reset Date: Thu Jun 23 13:34:12 CEST 2011 I find that when I call soft_reset_halt, the PC gets reset to 0x110070, which in my current eCos setup is warm_reset. It would be strange that this is a coincidence. So how does GDB know how to set that address? Entry: OpenOCD: reset halt vs. reset init Date: Thu Jun 23 13:37:11 CEST 2011 If the target under debug gets switched off while a debug setting is running, issuing a "reset halt" isn't enough. I verfied this and I got faulty JTAG communication, but "poll" did work. After "reset init" things are back to normal. (gdb) mon slow_reset halt 100 kHz srst pulls trst - can not reset into halted mode. Issuing halt after reset. target state: halted target halted in ARM state due to debug-request, current mode: Supervisor cpsr: 0x200000d3 pc: 0x00005bb8 1000 kHz (gdb) mon poll background polling: on TAP: at91sam7s256.cpu (enabled) target state: halted target halted in ARM state due to debug-request, current mode: Supervisor cpsr: 0x200000d3 pc: 0x00005bb8 (gdb) vstepi Bad value '00000001' captured during DR or IR scan: check_value: 0x00000009 check_mask: 0x00000009 JTAG error while reading cpsr Bad value '00000001' captured during DR or IR scan: check_value: 0x00000009 check_mask: 0x00000009 JTAG error while reading cpsr Couldn't calculate PC of next instruction, current opcode was 0x00000000 0x00005bb8 in ?? () 0x5bb0: andeq r0, r0, r0 0x5bb4: andeq r0, r0, r0 => 0x5bb8: andeq r0, r0, r0 0x5bbc: andeq r0, r0, r0 0x5bc0: andeq r0, r0, r0 0x5bc4: andeq r0, r0, r0 0x5bc8: andeq r0, r0, r0 0x5bcc: andeq r0, r0, r0 0x5bd0: andeq r0, r0, r0 0x5bd4: andeq r0, r0, r0 Entry: AT91SAM7 and reset Date: Thu Jun 23 13:53:25 CEST 2011 Some notes about using OpenOCD on the AT91SAM7 platform. These notes reflect behaviour with a recent OpenOCD git version and using the ARM-USB-OCD programmer. 1. Lower clock when requesting a reset. I can get a reliable reset when I lower the clock to 100kHz. Higher than that gives problems. Other commands give no problems if ARM clock is set to fast. Flash is independent of ARM. 2. The AT91SAM7 can't reset in halt, which means that it _will_ execute code in Flash before any JTAG debugger can halt the chip. Therefore it's best to use soft_reset_halt whenever possible and use "reset init" only when JTAG gets out of sync, i.e. when target is power-cycled. Entry: gdb can't connect if target error Date: Thu Jun 23 14:21:52 CEST 2011 It might be best to modify such that gdb is allowed to connect such that it can issue a "mon reset init" command. Error: Target not halted Error: auto_probe failed Error: Connect failed. Consider setting up a gdb-attach event for the target to prepare target for GDB connect, or use 'gdb_memory_map disable'. Error: attempted 'gdb' connection rejected That error is printed in server.c when (abstractly) ->new_connection() fails. The implementation of that function is in gdb_server.c : static int gdb_new_connection(struct connection *connection); The cause seems to be this: Connect must fail if the memory map can't be set up correctly. Maybe this should trigger some retry somewhere? To switch off memory map[1]: gdb_memory_map disable but of course you can't do this from the gdb side.. Some more info about that particular patch here[2]. So it's probably not a good idea to start prodding there, but to use the `gdb-attach' event instead. [1] http://www.amontec.com/openocd/doc/GDB-and-OpenOCD.html [2] http://www.mail-archive.com/openocd-development@lists.berlios.de/msg13048.html [3] entry://20110624-000503 Entry: stepi ignored. GDB will now fetch the register state from the target. Date: Thu Jun 23 14:35:35 CEST 2011 I read in the code, and it seems that this is a workaround in OpenOCD: stepi ignored. GDB will now fetch the register state from the target. Before I needed to work around that workaround by adding a harmless "stepi" instruction to cancel the ignored stepi. So what is this about really? From gdbserver.c: } else if ((packet[0] == 's') && gdb_con->sync) { /* Hmm..... when you issue a continue in GDB, then a "stepi" is * sent by GDB first to OpenOCD, thus defeating the check to * make only the single stepping have the sync feature... */ nostep = true; LOG_WARNING("stepi ignored. GDB will now fetch the register state from the target."); } gdb_con->sync = false; Entry: arm.run Date: Thu Jun 23 14:39:51 CEST 2011 #!/bin/bash # --- config GDB=arm-eabi-gdb-7.2 OPENOCD_HOST=openocd OPENOCD_PORT=3333 # --- code [ -z "$1" ] && echo "usage: $0 " && exit 1 ELF=$1 # ELF=/home/tom/dbb_trailer/build/out/arm/test-blockmanager # LOAD_COMMAND=load CMD=`mktemp` cat<>$CMD # Load file for debugging symbols file $ELF # Connect to OpenOCD target remote $OPENOCD_HOST:$OPENOCD_PORT # Flash the file if requested. echo Flashing...\n $LOAD_COMMAND # Reset target monitor slow_reset init # Give a couple of harmless instruction step commands starting from # the boot vector. The first stepi is a workaround for this: # # stepi ignored. GDB will now fetch the register state from the target. # # which is a GDB bug workaround in OpenOCD, preventing the app from # starting on a "continue". The subsequent ones are a workaround for # an old sync problem that seems to have disappeared. stepi stepi stepi # Run until the test is done thbreak cyg_test_exit continue # Cleanup & exit shell rm $CMD quit EOF exec $GDB --command=$CMD Entry: OpenOCD hacking Date: Thu Jun 23 14:47:31 CEST 2011 - add some exit mechanism to allow for a full restart - "stepi ignored" - gdb can't connect if probe fails (fixed: use gdb-attach -> reset init) - what determines the PC after load/reset? (ELF has entry point set) Entry: ARM ELF Entry point Date: Thu Jun 23 21:31:46 CEST 2011 It looks like load sets the entry point. I.e. for my app the PC is set to 0x110040. Where is that data stored? Using readelf it can be retrieved: $ arm-eabi-readelf -h ELF Header: Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 Class: ELF32 Data: 2's complement, little endian Version: 1 (current) OS/ABI: UNIX - System V ABI Version: 0 Type: EXEC (Executable file) Machine: ARM Version: 0x1 Entry point address: 0x110040 Start of program headers: 52 (bytes into file) Start of section headers: 981516 (bytes into file) Flags: 0x4000002, has entry point, Version4 EABI Size of this header: 52 (bytes) Size of program headers: 32 (bytes) Number of program headers: 2 Size of section headers: 40 (bytes) Number of section headers: 21 Section header string table index: 18 According to [1] it's at the start of the file even: $ hd example-format |head -n 2 00000000 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 |.ELF............| 00000010 02 00 28 00 01 00 00 00 40 00 11 00 34 00 00 00 |..(.....@...4...| ^^^^^^^^^^^ [1] http://vx.netlux.org/lib/static/vdat/tuunix02.htm Entry: OpenOCD gdb-attach event Date: Fri Jun 24 00:05:03 CEST 2011 # Reset target when gdb connects. OpenOCD disconnects when a memory # map is requested and it can't provide it because target comm is not # setup correctly. at91sam7s256.cpu configure -event gdb-attach { echo "Reset on gdb-attach." slow_reset init } [1] http://openocd.berlios.de/doc/html/CPU-Configuration.html Entry: Cannot access memory at address 0xffffffff Date: Fri Jun 24 00:55:12 CEST 2011 I get this error after many commands, including "set $pc = 0". Seems to be because GDB requests that address. I don't know where it comes from. When an image file is loaded it doesn't seem to be a problem. Switching on debug_level 3, the correct operation is: Debug: 167 336068 gdb_server.c:2201 gdb_input_inner(): received packet: 'g' Debug: 168 336068 gdb_server.c:2201 gdb_input_inner(): received packet: 'm0,4' Debug: 169 336068 gdb_server.c:1278 gdb_read_memory_packet(): addr: 0x00000000, len: 0x00000004 Debug: 170 336068 target.c:1443 target_read_buffer(): reading buffer of 4 byte at 0x00000000 Debug: 171 336068 arm7_9_common.c:2270 arm7_9_read_memory(): address: 0x00000000, size: 0x00000004, count: 0x00000001 Actually this skips the register set operation, probably because the $pc is already set to 0. A register set looks like this: Debug: 241 552998 gdb_server.c:2201 gdb_input_inner(): received packet: 'Pf=00000000' Debug: 242 552998 gdb_server.c:1198 gdb_set_register_packet(): - However, when there is no image loaded, GDB tries to read from 0xFFFFFFFF. Debug: 567 761913 gdb_server.c:2201 gdb_input_inner(): received packet: 'mffffffff,1' Debug: 568 761913 gdb_server.c:1278 gdb_read_memory_packet(): addr: 0xffffffff, len: 0x00000001 Debug: 569 761913 target.c:1443 target_read_buffer(): reading buffer of 1 byte at 0xffffffff Debug: 570 761913 arm7_9_common.c:2270 arm7_9_read_memory(): address: 0xffffffff, size: 0x00000001, count: 0x00000001 Debug: 571 761916 gdb_server.c:2201 gdb_input_inner(): received packet: 'g' Debug: 572 761916 gdb_server.c:2201 gdb_input_inner(): received packet: 'm0,4' Debug: 573 761916 gdb_server.c:1278 gdb_read_memory_packet(): addr: 0x00000000, len: 0x00000004 Debug: 574 761916 target.c:1443 target_read_buffer(): reading buffer of 4 byte at 0x00000000 Debug: 575 761916 arm7_9_common.c:2270 arm7_9_read_memory(): address: 0x00000000, size: 0x00000004, count: 0x00000001 Debug: 576 761918 gdb_server.c:2201 gdb_input_inner(): received packet: 'mffffffff,1' Debug: 577 761918 gdb_server.c:1278 gdb_read_memory_packet(): addr: 0xffffffff, len: 0x00000001 Debug: 578 761918 target.c:1443 target_read_buffer(): reading buffer of 1 byte at 0xffffffff Debug: 579 761918 arm7_9_common.c:2270 arm7_9_read_memory(): address: 0xffffffff, size: 0x00000001, count: 0x00000001 Entry: gdb and low-level debugging Date: Fri Jun 24 15:04:14 CEST 2011 Seems that GDB is really a source debugger. I.e. the "disassemble" command can't be used on bare code. For that you need the "x" examine command, i.e. "x/10i $pc" will examine 10 units of data at $pc and interpret them as instructions. The next problem I ran into is setting breakpoints at raw instructions instead of symbolic labels. Just using "break" or "thbreak" doesn't work. Actually it does, it just needs some special syntax[1] (mnemonic: code is a dereferenced code pointer). break *0x0000f000 ( Related remark: it's possible to save current breakpoint configuration as a script. See "help breakpoints". ) [1] http://people.cs.uchicago.edu/~bomb154/154/maclabs/gdblab.html Entry: gdb variable to register mapping Date: Fri Jun 24 17:02:43 CEST 2011 Is it possible to print the variable->register mapping in gdb? Entry: ARM calling conventions Date: Fri Jun 24 18:56:56 CEST 2011 r0-r3 arguments + return value r4-r11 local variables (callee must save) r12 scratch r13 sp r14 lr r15 pc [1] http://en.wikipedia.org/wiki/Calling_convention#ARM Entry: Arm and alginment Date: Fri Jun 24 20:27:36 CEST 2011 It's imperative to properly align data storage on ARM. A normal STR instruction needs 4-byte align, STRH[1] needs 2-bytes align and STRB needs 2-byte. Note that it's very easy to make mistakes against this when you start liberally casting void pointers to other types. I spent a couple of hours tracking down an obscure error that happened only in optimized code. Granted, it took so long to find because eCos data exception handling just ignored the error, and that stepping through the optimized code was nearly impossible due to heavy inlining (spaghetti-izing). [1] http://www.rz.uni-karlsruhe.de/rz/docs/VTune/reference/INST_STRH.htm arm7_9 dcc_downloads enable arm7_9 fast_memory_access enable Entry: OpenOCD slow? How to fix? Date: Mon Jun 27 16:23:00 CEST 2011 [1] https://lists.berlios.de/pipermail/openocd-development/2011-June/019747.html Entry: urjtag Date: Mon Jun 27 16:33:31 CEST 2011 Another JTAG project[1]. [1] http://urjtag.org/ Entry: ARM-USB-OCD-H Date: Mon Aug 22 10:54:59 CEST 2011 I'm using a ARM-USB-OCD which is detected: Aug 22 10:55:45 zni kernel: [4122071.964298] usb 3-5.3: new full speed USB device using ehci_hcd and address 19 Aug 22 10:55:45 zni kernel: [4122072.063273] usb 3-5.3: New USB device found, idVendor=15ba, idProduct=0003 Aug 22 10:55:45 zni kernel: [4122072.063275] usb 3-5.3: New USB device strings: Mfr=1, Product=2, SerialNumber=0 Aug 22 10:55:45 zni kernel: [4122072.063278] usb 3-5.3: Product: Olimex OpenOCD JTAG Aug 22 10:55:45 zni kernel: [4122072.063279] usb 3-5.3: Manufacturer: Olimex Aug 22 10:55:45 zni kernel: [4122072.067085] usb 3-5.3: Ignoring serial port reserved for JTAG Aug 22 10:55:45 zni kernel: [4122072.071532] ftdi_sio 3-5.3:1.1: FTDI USB Serial Device converter detected Aug 22 10:55:45 zni kernel: [4122072.071565] usb 3-5.3: Detected FT2232C Aug 22 10:55:45 zni kernel: [4122072.071567] usb 3-5.3: Number of endpoints 2 Aug 22 10:55:45 zni kernel: [4122072.071569] usb 3-5.3: Endpoint 1 MaxPacketSize 64 Aug 22 10:55:45 zni kernel: [4122072.071570] usb 3-5.3: Endpoint 2 MaxPacketSize 64 Aug 22 10:55:45 zni kernel: [4122072.071571] usb 3-5.3: Setting MaxPacketSize 64 Aug 22 10:55:45 zni kernel: [4122072.071935] usb 3-5.3: FTDI USB Serial Device converter now attached to ttyUSB2 Plugging in the identically looking ARM-USB-OCD-H however gives: Aug 22 10:56:34 zni kernel: [4122120.341738] usb 3-5.3: new high speed USB device using ehci_hcd and address 20 Aug 22 10:56:34 zni kernel: [4122120.438456] usb 3-5.3: New USB device found, idVendor=15ba, idProduct=002b Aug 22 10:56:34 zni kernel: [4122120.438458] usb 3-5.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3 Aug 22 10:56:34 zni kernel: [4122120.438461] usb 3-5.3: Product: Olimex OpenOCD JTAG ARM-USB-OCD-H Aug 22 10:56:34 zni kernel: [4122120.438462] usb 3-5.3: Manufacturer: Olimex Aug 22 10:56:34 zni kernel: [4122120.438464] usb 3-5.3: SerialNumber: OLU9Z1AU Looks like my kernel is too old. Can't upgrade now, so let's just patch the current version. /opt/src/linux-2.6.33.7-rt29/drivers/usb/serial: ftdi_so_ids.h: #define OLIMEX_ARM_USB_OCD_H_PID 0x002b ftdi_sio.c: { USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_H_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, With this, and after setting the correct permissions (udev) it worked. Had to use gcc-4.4 to compile my kernel though: 2.6.33.7-rt29 [1] https://lkml.org/lkml/2011/3/9/347 Entry: eCos boot Date: Mon Aug 22 11:53:11 CEST 2011 => 0x0: ldr pc, [pc, #24] ; 0x20 0x4: ldr pc, [pc, #24] ; 0x24 0x8: ldr pc, [pc, #24] ; 0x28 0xc: ldr pc, [pc, #24] ; 0x2c This loads pc with the contents of vectors stored at the addresses mentioned in the comments. Why is the offset #24? The reason is processor pipeline[1]. The pc is always 8 bytes ahead. [1] http://www.keil.com/forum/16417/ Entry: Loading core files on ARM target Date: Wed Jan 4 19:03:30 EST 2012 wget http://ftp.gnu.org/gnu/gdb/gdb-7.3.1.tar.bz2 tar xf gdb-7.3.1.tar.bz2 mkdir -p gdb-7.3.1/build/arm-eabi cd gdb-7.3.1/build/arm-eabi ../../configure --target=arm-eabi make sudo cp gdb/gdb /usr/local/bin/arm-eabi-gdb-7.3.1 ./gdb/corefile.c:77: if (core_target == NULL) error (_("GDB can't read core files on this machine."));