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 --enable-tui 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.")); Entry: Loading binary code into ram Date: Mon Jun 4 12:24:03 EDT 2012 Basically what I want to do is this: - Load a firmware in Flash - Load some extra code in Flash / RAM that can call into Flash. Entry: Better GDB scripting Date: Tue Jun 5 13:36:24 EDT 2012 I'm finding a lot of interesting things in Staapl about "host RPC", where a very limitied target (small PIC uC) can recursively call code on a host. It would be nice to get this kind of workflow going in GDB. Entry: GDB hooks Date: Tue Jul 31 17:32:32 EDT 2012 I want a simple mechanism to check if a certain breakpoint is hit and if so, execute a function then continue. Entry: OpenOCD Date: Fri Nov 30 15:03:26 EST 2012 Trying again to use OpenOCD on AT91SAM7 board. GIT SHA1 1a8223f28b2a459750b6dd9b867f4cec0c14a515 $ openocd --file interface/arm-usb-ocd.cfg --file target/sam7x256.cfg Entry: AT91SAM7 AIC Date: Wed Dec 12 12:55:57 EST 2012 Source (23.6.3) 0: FIQ pin 1: SIQ system peripheral interrupt lines (system timer, RTC, PMC, MC, ...) 2-31: PID2-PID31: embedded user peripheral / external interrupt lines What's the difference between system/user peripheral? E.g. PIO is a user peripheral. The peripheral identification defined at the product level corresponds to the interrupt source number. For a peripheral table, see 10.2 Registers: (* = E/D or S/C) AIC_SMR source mode register AIC_I*CR interrupt enable/disable command register AIC_I*CR interrupt set/clear command register AIC_IPR interrupt pending AIC_IVR interrupt vector (read signals entry of ISR) AIC_IMR interrupt mask AIC_ISR current interrupt (p158) AIC_CISR nIRQ/nFIQ lines fast forcing AIC_EOICR end of interrupt command register (to signal exit of ISR) AIC_SVRn source vector register n:1-31 (corresponds to AIC_IVR read) The basic idea behind the AIC is to extend the ARM's simple single-interrupt model to a multi-priority interrupt model by running bulk of the ISR routines with arm IRQ enabled. AIC enables fast vectored dispatch to allow for lower interrupt latencies. For such routines, care needs to be taken to complete the AIC entry/exit in each routine. The AIC uses a stack internally to keep track of the current interrupt being served. Entry/exit are marked by r/w of AIC_IVR and AIC_EOICR. [1] http://www.atmel.com/Images/doc6120.pdf Entry: Disassembling raw ARM code Date: Mon Jul 15 10:00:23 EDT 2013 Given a binary, how to get a disassembly dump on the command line? It seems best to split this in 2 scripts: - convert .bin -> arm .elf with .text section - run objdump arm-none-eabi-objcopy --input binary --output elf32-littlearm --binary-architecture arm --rename-section .data=.text in.bin out.elf arm-none-eabi-objdump -D out.elf Entry: at91lib USB Date: Thu Jul 25 17:46:01 EDT 2013 at91lib is low-level without task switching. Caveat: callbacks are invoked from the interrupt handler, so can't call any code that depends on work done in the interrupt handler. Entry: Disable / Enable interrupts Date: Wed Aug 14 14:24:45 EDT 2013 // disable asm("mrs r0, cpsr\n" "orr r0,r0,#0x80\n" "msr cpsr_c,r0\n" "mov r0,#1\n" "bx lr\n"); // enable asm("mrs r0, cpsr\n" "bic r0,r0,#0x80\n" "msr cpsr_c,r0\n" "bx lr\n"); Entry: TI Tiva C Series TM4C123G eval board / EK-TM4C123GXL Date: Sat Aug 17 23:49:24 EDT 2013 Looks like the board[1] has a USB JTAG interface (implemented using a second identical micro!). It seems this is a TI-ICDI supported by openocd. OpenOCD config is here[2]. ./configure \ --enable-maintainer-mode \ --enable-ft2232_libftdi \ --enable-ti-icdi \ --enable-jlink [1] http://www.ti.com/tool/ek-tm4c123gxl [2] http://e2e.ti.com/support/microcontrollers/tiva_arm/f/908/t/279223.aspx Entry: Community ARM uC boards Date: Fri Aug 23 12:48:22 EDT 2013 Time has come for "standard" platforms: - Arduino Due - TI Tiva C Launchpad Arduino is interesting because it has a potential of being a real standard. I'm not a big fan of the IDE for personal use, but at least there is a good patch point into the community as a library provider. The TI launchpad is interesting because it is very cheap, and has embedded JTAG. Downside is that TI software cannot be freely redistributed. Though it does seem to have a eLua port. Entry: uClinux Date: Sun Aug 25 01:11:19 EDT 2013 On a STM32F437[1]? I see.. That board[2] has 16MB PSRAM. Not exactly in the 128kByte range :) An article that deals with the question of why one would want to do that, given that a chip with MMU is not exactly more expensive, and that a M3/M4 is not designed to run over external memory interface [3]. [1] https://www.youtube.com/watch?v=k9kKLjefeHM [2] http://www.emcraft.com/products/224 [3] http://electronicdesign.com/embedded/practical-advice-running-uclinux-cortex-m3m4 Entry: Building Toolchains Date: Fri Aug 30 03:07:31 EDT 2013 - sat https://github.com/esden/summon-arm-toolchain I have one built on 2012-12-5, but according to the above this is no longer under development. It refers to https://launchpad.net/gcc-arm-embedded - crosstool-ng http://crosstool-ng.org/ Trying this now.. Failed: [ERROR] checking for suffix of object files... configure: error: in `/home/tom/ct-ng/.build/arm-unknown-eabi/build/build-cc-core-pass-2/arm-unknown-eabi/libgcc': [ERROR] configure: error: cannot compute suffix of object files: cannot compile [ERROR] make[1]: *** [configure-target-libgcc] Error 1 http://gcc.gnu.org/wiki/FAQ#Configuration_fails_with_.27.27configure:_error:_cannot_compute_suffix_of_object_files:_cannot_compile.27.27._What_is_the_problem.3F /home/tom/ct-ng/.build/arm-unknown-eabi/build/build-cc-core-pass-2/arm-unknown-eabi/libgcc/config.log: conftest.c: In function 'main': conftest.c:12:1: sorry, unimplemented: Thumb-1 hard-float VFP ABI Weird.. Should I pick a different float arch? Linaro has hardfloat thumb? Trying latest.. http://crosstool-ng.org/download/ibot-logs/2012-10-07.html - cortex m4 hardfloat toolchain: https://github.com/prattmic/arm-cortex-m4-hardfloat-toolchain Also recommends to look at gcc-arm-embedded - https://launchpad.net/gcc-arm-embedded GCC dev by ARM employees. It does hardfloat: tom@tx:/tmp$ ~/gcc-arm-embedded/gcc-arm-none-eabi-4_7-2013q2/bin/arm-none-eabi-gcc -O3 -ffast-math -mfpu=vfp -mfloat-abi=hard -mthumb -mcpu=cortex-m4 -c test.c tom@tx:/tmp$ ~/gcc-arm-embedded/gcc-arm-none-eabi-4_7-2013q2/bin/arm-none-eabi-objdump -d test.o test.o: file format elf32-littlearm Disassembly of section .text: 00000000 : 0: eddf 7a02 vldr s15, [pc, #8] ; c 4: ee30 0a27 vadd.f32 s0, s0, s15 8: 4770 bx lr a: bf00 nop c: 42f60000 .word 0x42f60000 So, these options are necessary: -mcpu=cortex-m4 -mthumb enables thumb-2 mode -mfloat-abi=hard since not all M4 have hard float Entry: Paul Stoffregen Date: Tue Sep 3 19:10:13 EDT 2013 http://www.kickstarter.com/profile/paulstoffregen http://www.dorkbotpdx.org/blog/paul http://www.youtube.com/user/PaulStoffregen https://twitter.com/PaulStoffregen Entry: Teensy 3.0 - STM Cortex M4 Date: Wed Sep 4 20:33:21 EDT 2013 No JTAG though.. Too bad. Looks like it's the TI M4 boards are more interesting at this point. http://hackaday.com/2012/09/05/meet-the-teensy-3-0/ Entry: Trying out Tivaware Date: Sat Sep 7 17:12:45 EDT 2013 With arm-none-eabi-* binaries[1] in the path, things seem to work out of the box: $ cd tivaware/examples/boards/ek-tm4c123gxl/freertos_demo $ make $ file gcc/freertos_demo.axf gcc/freertos_demo.axf: ELF 32-bit LSB executable, ARM, version 1 (SYSV), statically linked, not stripped Let's see if there's a simpler example: blinky.c in: $ cd tivaware/examples/boards/ek-tm4c123gxl/blinky It has a very simple main file. Where is the chip startup? Ah, in startup_gcc.c - check linker flag "--entry ResetISR". using blinky.ld, gnu ld links: - blinky.o - startup_gcc.o - libm.a - libc.a - libgcc.a ( Makefile finds libc.a ... using arm-none-eabi-gcc print-file-name=libc.a ) The output .axf is just an ELF. The startup_gcc.c file seems to have the "viral" clause license.. From what I read this is probably not a problem in practice. Startup does: - ISR vector setup (different than ARMv5 ?) - RAM data,bss setup - Float unit setup - main() Let's try to upload it. $ openocd --version Open On-Chip Debugger 0.8.0-dev-00120-gc93d28d-dirty (2013-08-18-00:30) # M-x gdb ~/tm4c/gdb -i=mi /opt/xc/tivaware/examples/boards/ek-tm4c123gxl/blinky/gcc/blinky.axf After fixing some gdb/emacs problems that required updates, it does seem that the "load" command worked as the led is blinking: mon reset mon halt Though there are some problems: - first time around, "load" didn't work - can't write to PC? p $pc $5 = (void (*)()) 0x28f set $pc = 0 p $pc $6 = (void (*)()) 0x1 [1] https://launchpad.net/gcc-arm-embedded Entry: Cortex M4 boot? Date: Sat Sep 7 18:57:58 EDT 2013 Does a M4 boot differently than an ARM 7 TDMI? From [1]: ...the vector table at 0 is actually a table of vectors (pointers), not instructions. The first entry contains the start-up value for the SP register, the second is the reset vector. This allows writing the reset handler directly in C, since the processor sets up the stack. __Vectors DCD __initial_sp ; Top of Stack DCD Reset_Handler ; Reset Handler DCD NMI_Handler ; NMI Handler DCD HardFault_Handler ; Hard Fault Handler DCD MemManage_Handler ; MPU Fault Handler DCD BusFault_Handler ; Bus Fault Handler DCD UsageFault_Handler ; Usage Fault Handler [...more vectors...] [1] http://stackoverflow.com/questions/6139952/what-is-the-booting-process-for-arm Entry: PC odd addresses? Date: Sat Sep 7 19:07:13 EDT 2013 Why are PC addresses odd? It seems this indicates thumb mode. [1] http://stackoverflow.com/questions/15764833/indirect-function-call-uses-odd-address Entry: Cheat sheet Date: Sat Sep 7 19:50:00 EDT 2013 [1] http://infocenter.arm.com/help/topic/com.arm.doc.qrc0001l/QRC0001_UAL.pdf [2] http://simplemachines.it/doc/arm_inst.pdf Entry: Cortex M4 Date: Sat Sep 7 20:44:33 EDT 2013 http://www.eejournal.com/archives/articles/20100223-cortex/ Entry: ARM DSP intrinsics Date: Sun Sep 8 19:48:05 EDT 2013 Goes GCC support this? According to [3] it doesn't. Does LLVM support it? Looks like the general idea is that I'm going to have to do this in asm. Maybe this is a good excuse to learn about register allocation and some other compiler optimization techniques. But first, learn the asm. [1] http://www.iar.com/About/Blog/2012/1/Designing-advanced-DSP-applications/ [2] http://stackoverflow.com/questions/9828567/arm-neon-intrinsics-vs-hand-assembly [3] http://stackoverflow.com/questions/14188262/how-to-enable-intrinsics-in-compiler Entry: Running Cortex-M4 DSP code on QEMU Date: Mon Sep 16 19:50:35 EDT 2013 The Cortex-M4 is not supported directly. However, it seems that the DSP instruction set is supported in ARM mode, at least just using arm-none-eabi-gcc on "qadd r1,r2,r3" produces: 00000000 <.text>: 0: e1031052 qadd r1, r2, r3 As opposed to "-mcpu=cortex-m4 -mthumb" : 00000000 <.text>: 0: fa83 f182 qadd r1, r2, r3 Let's see if qemu in plain arm mode executes the first one. ... DSP instructions were added to the set. These are signified by an "E" in the name of the ARMv5TE and ARMv5TEJ architectures[1]. Qemu supports: $ qemu-system-arm -cpu ? Available CPUs: arm1026 arm1136 arm1136-r2 arm1176 arm11mpcore arm926 arm946 cortex-a15 cortex-a8 cortex-a9 cortex-m3 pxa250 pxa255 pxa260 pxa261 pxa262 pxa270-a0 pxa270-a1 pxa270 pxa270-b0 pxa270-b1 pxa270-c0 pxa270-c5 sa1100 sa1110 ti925t any For GCC it's -mcpu=name: This specifies the name of the target ARM processor. GCC uses this name to determine what kind of instructions it can emit when generating assembly code. Permissible names are: arm2, arm250, arm3, arm6, arm60, arm600, arm610, arm620, arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700, arm700i, arm710, arm710c, arm7100, arm720, arm7500, arm7500fe, arm7tdmi, arm7tdmi-s, arm710t, arm720t, arm740t, strongarm, strongarm110, strongarm1100, strongarm1110, arm8, arm810, arm9, arm9e, arm920, arm920t, arm922t, arm946e-s, arm966e-s, arm968e-s, arm926ej-s, arm940t, arm9tdmi, arm10tdmi, arm1020t, arm1026ej-s, arm10e, arm1020e, arm1022e, arm1136j-s, arm1136jf-s, mpcore, mpcorenovfp, arm1156t2-s, arm1156t2f-s, arm1176jz-s, arm1176jzf-s, cortex-a5, cortex-a7, cortex-a8, cortex-a9, cortex-a15, cortex-r4, cortex-r4f, cortex-r5, cortex-m4, cortex-m3, cortex-m1, cortex-m0, xscale, iwmmxt, iwmmxt2, ep9312, fa526, fa626, fa606te, fa626te, fmp626, fa726te. So, pick the simplest one with an 'E' in it. Don't want an elaborate boot massaging process.. Maybe -cpu=any is good for qemu? So both cortex-a8 and cortex-a9 seem to work in ARM and THUMB mode. [1] http://en.wikipedia.org/wiki/ARM_architecture#DSP_enhancement_instructions Entry: Semihosting exit Date: Mon Sep 16 20:51:14 EDT 2013 Semihisting SYS_EXIT. See [1]. [1] http://lists.nongnu.org/archive/html/qemu-devel/2013-08/msg03889.html Entry: Inline asm Date: Mon Sep 16 21:32:15 EDT 2013 [1] http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html Entry: DSP instructions Date: Mon Sep 16 21:41:51 EDT 2013 saturating and multiply instructions: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0489c/Cihddjgg.html http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0489c/Cihjfeii.html Entry: M0 vs M3 Date: Thu Sep 19 20:25:40 EDT 2013 Asked when someone might need to move to 32bit from 8 or 16bit, York said, “The protocol stack for ZigBee is atrocious on an 8bit core. It is the same with USB and Bluetooth, and if an ADC is 16bit, you are going to want 32bits to manipulate the data without overflowing.” http://www.electronicsweekly.com/news/components/microprocessors-and-dsps/arms-cortex-m0-processor-how-it-works-2009-03/ Entry: Debian on Beagleboard xM Date: Thu Sep 26 18:43:31 EDT 2013 Got debian installed through: http://elinux.org/BeagleBoardDebian 2013-08-26 image Though there are problems when netload gets high: USB gives up. ( Board has ethernet connector setup through USB instead of the SoC. ) Found a couple of references to this: https://groups.google.com/forum/#!topic/beagleboard/ji8SiHrzC2Y How to solve? EDIT: Might just be power supply. I had it powered over USB, but it probably takes more than 500mA. It seems to run fine on a 2A DC adapter. Entry: qemu osmocom Date: Sun Nov 24 08:39:45 EST 2013 http://git.osmocom.org/qemu Trouble with texinfo 5.2, so doing this: ./configure --disable-docs --disable-user --target-list=arm-softmmu In the diff I see no reference to any command line flag that enables this particular machine. What does `machine_init' do? Also patch config-host.mak: Add -lrt to LIBS_QGQ and LIBS remove -Werror from QEMU_CFLAGS compiles.. result is in arm-softmmu/qemu-system-arm now how does that extension work? Start with this: static void cc32_register_types(void) { type_register_static(&cc32_sysc_info); type_register_static(&cc32_flcon_info); } type_init(cc32_register_types) Entry: qemu primer Date: Sun Nov 24 10:23:47 EST 2013 - modules are registered through init functions defined in module.h : #define block_init(function) module_init(function, MODULE_INIT_BLOCK) #define machine_init(function) module_init(function, MODULE_INIT_MACHINE) #define qapi_init(function) module_init(function, MODULE_INIT_QAPI) #define type_init(function) module_init(function, MODULE_INIT_QOM) Probably best to start reading here: http://qemu.weilnetz.de/qemu-tech.html http://wiki.qemu.org/Documentation/GettingStartedDevelopers Starting from the CC32RS512 diff, it might be good to add a memory mapped I/O for debug output. This would give a good idea of how virtual devices work. Relevant calls/macros for the CC32 SYSC emulation: type_init(cc32_register_types) type_register_static(&cc32_sysc_info); cc32_sysc_class_init() DEVICE_CLASS() SYS_BUS_DEVICE_CLASS() cc32_sysc_init cc32_sysc_reset FROM_SYSBUS() qdev_init_gpio_in() sysbus_init_irq() memory_region_init_io() sysbus_init_mmio() container_of() sysbus_create_varargs() / sysbus_create_simple() Datastructures first. static void cc32_sysc_reset(DeviceState *d) { cc32_sysc_state *s = container_of(d, cc32_sysc_state, busdev.qdev); ... } This recovers larger scope for "inlined" C data structures, i.e. find s such that &(s->busdev.qdev) == d This avoids having to store back-pointers. struct cc32_sysc_state { ... SysBusDevice busdev; ... }; struct SysBusDevice { ... DeviceState qdev; ... }; Entry: Qemu minimal build Date: Fri Dec 6 10:09:16 EST 2013 FIXME: Tried a from scratch LXC Debian wheezy VM. Doesn't seem to have the necessary packages.. Minimal build for ARM embedded dev. apt-get install libpixman-1-dev pkg-config libz-dev libglib2.0-dev ./configure --disable-docs --disable-user --target-list=arm-softmmu [1] http://www.linuxforu.com/2011/06/qemu-for-embedded-systems-development-part-1/ Entry: Minimal qemu Date: Fri Dec 6 11:45:25 EST 2013 ## list of things to disable # ./configure --help |grep disable |awk -e '{print $1}' # ./configure --help|grep list ## Don't disable: # --disable-system ./configure --target-list=arm-softmmu \ --audio-drv-list= \ --audio-card-list= \ --disable-debug-tcg \ --disable-sparse \ --disable-strip \ --disable-werror \ --disable-sdl \ --disable-virtfs \ --disable-vnc \ --disable-xen \ --disable-brlapi \ --disable-vnc-tls \ --disable-vnc-sasl \ --disable-vnc-jpeg \ --disable-vnc-png \ --disable-vnc-thread \ --disable-curses \ --disable-curl \ --disable-fdt \ --disable-bluez \ --disable-slirp \ --disable-kvm \ --disable-nptl \ --disable-system \ --disable-user \ --disable-linux-user \ --disable-darwin-user \ --disable-bsd-user \ --disable-guest-base \ --disable-pie \ --disable-uuid \ --disable-vde \ --disable-linux-aio \ --disable-cap-ng \ --disable-attr \ --disable-blobs \ --disable-docs \ --disable-vhost-net \ --disable-spice \ --disable-libiscsi \ --disable-smartcard \ --disable-smartcard-nss \ --disable-usb-redir \ --disable-guest-agent Entry: set $pc = 0 on ARM7TMDI Date: Fri Dec 6 12:58:42 EST 2013 About the ARM pipeline. This is a bit confusing. It's interesting how this confusion has lasted so long.. Up to this point I seem to recall always reading asm code such that the current $pc -- annotated by '=>' in asm dump (e.g. x/10i) -- points to the current instruction. However, the instruction that's executing is actually 3 instructions back. Now the funny thing is that r1 after this: mov r1, pc is 20 (0x14) bytes past the address of the instruction. How is that? The reason might be that qemu is not emulating the ARM7TDMI but is using -cpu arm926 by default. It seems that pc-relative addressing is standardized across designs with different pipeline depths, but register moves are not? 20 bytes is 5 instructions. Is this the 5-stage pipeline? Shouln't it be one byte less in that case? Entry: Adding a register-mapped QEMU device Date: Sat Dec 7 09:50:54 EST 2013 1. Build system Create file hw/zwizwa.c Add a reference to Makefile.target: obj-arm-y += zwizwa.o 2. In .c file, register objects: #include #include "module.h" static void zwizwa_register_types(void) { printf("zwizwa_register_types\n"); } type_init(zwizwa_register_types) 3. Call type_register_static on TypInfo struct #include "module.h" #include "sysbus.h" #include "qemu/object.h" typedef struct { } zwizwa_debug_state; static void zwizwa_debug_class_init(ObjectClass *klass, void *data) { } static TypeInfo zwizwa_debug_info = { .name = "zwizwa-debug", .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(zwizwa_debug_state), .class_init = zwizwa_debug_class_init, }; static void zwizwa_register_types(void) { type_register_static(&zwizwa_debug_info); } type_init(zwizwa_register_types) 4. Implement ObjectClass init method This needs a little explanation of the class system. What I can gather, the hierarchy is: object -> device -> sys-bus-device For this type, there are two methods to register: static int zwizwa_debug_init(SysBusDevice *dev){ return 0; } static void zwizwa_debug_reset(DeviceState *d){ } static void zwizwa_debug_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass); sdc->init = zwizwa_debug_init; dc->reset = zwizwa_debug_reset; } Here DEVICE_CLASS() and SYS_BUS_DEVICE_CLASS() are dynamic casts with type checking: #define DEVICE_CLASS(klass) OBJECT_CLASS_CHECK(DeviceClass, (klass), TYPE_DEVICE) #define TYPE_DEVICE "device" #define OBJECT_CLASS(class) ((ObjectClass *)(class)) #define OBJECT_CLASS_CHECK(class, obj, name) \ ((class *)object_class_dynamic_cast_assert(OBJECT_CLASS(obj), (name))) with object_ function implemented in object.c That file seems to be quite recent: * Copyright IBM, Corp. 2011 * * Authors: * Anthony Liguori * 5. Nested objects From the use of container_of(), it seems that much of QEMU's data structures are organized as composite flat objects (as opposed to objects pointing to other objects). I'm guessing this macro originates in the Linux source[1]. Using a flat representation makes ownership relationships very clear and makes it possible to traverse the structure hierarchy in two directions without extra bookkeeping (e.g. reverse pointers). - down: C structure member dereference - up: container_of(member_ptr, parent_type, member_name) 6. Access to objects in init / reset. static int zwizwa_debug_init(SysBusDevice *dev){ zwizwa_debug_state *s = FROM_SYSBUS(typeof(*s), dev); // ... return 0; } static void zwizwa_debug_reset(DeviceState *d){ zwizwa_debug_state *s = container_of(d, typeof(*s), busdev.qdev); // ... } From the CC32RS512 example, the FROM_SYSBUS macro is used to convert a SysBusDevice pointer to the full object. Note that this is also a container_of() style macro. #define FROM_SYSBUS(type, dev) DO_UPCAST(type, busdev, dev) #define DO_UPCAST(type, field, dev) container_of(dev, type, field) In the FROM_SYSBUS definition, the field name "busdev" is fixed, so we need to make sure we have that in our state structure: typedef struct zwizwa_debug_state { SysBusDevice busdev; } Actually, this seems deprecated[2]: use your own macro based on OBJECT_CHECK() For reset, need to know that this is a device method, so we go up one more in the hierarchy. 7. Implement init / reset. Some relevant calls from the CC32RS512 module: qdev_init_gpio_in() memory_region_init_io() sysbus_init_irq() sysbus_init_mmio() For this example we only use memory mapped io: typedef struct { SysBusDevice busdev; MemoryRegion iomem; } zwizwa_debug_state; static uint64_t zwizwa_debug_read(void *opaque, target_phys_addr_t offset, unsigned size) { return 0; } static void zwizwa_debug_write(void *opaque, target_phys_addr_t offset, uint64_t value, unsigned size) { printf("%08x <- %08x\n", (unsigned int)offset, (unsigned int)value); } static const MemoryRegionOps zwizwa_debug_ops = { .read = zwizwa_debug_read, .write = zwizwa_debug_write, .endianness = DEVICE_NATIVE_ENDIAN, }; static int zwizwa_debug_init(SysBusDevice *dev){ zwizwa_debug_state *s = FROM_SYSBUS(typeof(*s), dev); memory_region_init_io(&s->iomem, &zwizwa_debug_ops, s, "zwizwa-debug", 4); sysbus_init_mmio(dev, &s->iomem); return 0; } 8. Instantiate Called from machine init: sysbus_create_varargs("zwizwa-debug", 0x0FF000, NULL); [1] http://stackoverflow.com/questions/15832301/understanding-container-of-macro-in-linux-kernel [2] http://osdir.com/ml/qemu-devel/2013-07/msg05332.html Entry: QEMU i/o write prob Date: Sat Dec 7 12:26:08 EST 2013 Somehow the code above doesn't work.. Time to trace it. It works from ASM: mov r0, #0x10000 str r0, [r0] But not from GDB: (gdb) set *0x10000 = 123 Weird.. Is this a qemu gdb stub problem? Let's trace it down. In gdbstub.c everything goes through: target_memory_rw_debug() which calls: cpu_memory_rw_debug() in exec.c line 4527 it's because is_ram_rom_romd() returns false Qs: - should is_ram_rom_romd() return true for i/o memory? - why does it return different values for 2 separate calls? -> it doesn't it seems i/o memory is simply excluded in gdbstub Entry: libfdt Date: Sat Dec 7 13:33:55 EST 2013 device tree compiler http://ozlabs.org/~dgibson/ Entry: GDB stepping on qemu VM. Date: Sat Dec 7 14:15:11 EST 2013 Something isn't right... Tried with more recent QEMU and it doesn't seem to have this problem. It executs the instruction at $pc, not the one 3 instructions back It would be interesting to find out on the mailing list what exactly happened here.. Conclusion is that single-stepping an ARM doesn't seem so well-defined! Last merge was: 2012-03-03 5a30d3f19d9c6d135bf7a395a24dc455698d5cf9 That's a lot of patches.. Cursory glance didn't find antying. Hmmm... I wonder if I just disabled it? Entry: Moving to new QEMU Date: Sat Dec 7 15:26:45 EST 2013 Some things have shifted around since 2012-03-03. Probably best to first merge the zwizwa stuff, then merge the CC32RS512. EDIT: zwizwa stuff done. Tried the pipeline thing and now both instructions have pc pointing 2 instructions ahead. Looks like the previous behavior was just a bug. 0x3c : mov r0, pc ; loads 0x44 => 0x40 : ldr r0, [pc] ; 0x48 Entry: Extending QEMU with a new processor target Date: Wed Dec 11 13:14:13 EST 2013 How to do this? Let's dive into the source: target-arm/cpu.c static const ARMCPUInfo arm_cpus[] = { ... { .name = "cortex-m3", .initfn = cortex_m3_initfn, .class_init = arm_v7m_class_init }, ... } CPU types seem to be factored into feature sets: static void cortex_m3_initfn(Object *obj) { ARMCPU *cpu = ARM_CPU(obj); set_feature(&cpu->env, ARM_FEATURE_V7); set_feature(&cpu->env, ARM_FEATURE_M); cpu->midr = 0x410fc231; } To simulate the cortex-m4, I have been using the cortex-a8 for its support of the thumb2 DSP instruction set. Let's trace that down: static void cortex_a8_initfn(Object *obj) { ARMCPU *cpu = ARM_CPU(obj); set_feature(&cpu->env, ARM_FEATURE_V7); set_feature(&cpu->env, ARM_FEATURE_VFP3); set_feature(&cpu->env, ARM_FEATURE_NEON); set_feature(&cpu->env, ARM_FEATURE_THUMB2EE); set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS); cpu->midr = 0x410fc080; cpu->reset_fpsid = 0x410330c0; cpu->mvfr0 = 0x11110222; cpu->mvfr1 = 0x00011100; cpu->ctr = 0x82048004; cpu->reset_sctlr = 0x00c50078; cpu->id_pfr0 = 0x1031; cpu->id_pfr1 = 0x11; cpu->id_dfr0 = 0x400; cpu->id_afr0 = 0; cpu->id_mmfr0 = 0x31100003; cpu->id_mmfr1 = 0x20000000; cpu->id_mmfr2 = 0x01202000; cpu->id_mmfr3 = 0x11; cpu->id_isar0 = 0x00101111; cpu->id_isar1 = 0x12112111; cpu->id_isar2 = 0x21232031; cpu->id_isar3 = 0x11112131; cpu->id_isar4 = 0x00111142; cpu->clidr = (1 << 27) | (2 << 24) | 3; cpu->ccsidr[0] = 0xe007e01a; /* 16k L1 dcache. */ cpu->ccsidr[1] = 0x2007e01a; /* 16k L1 icache. */ cpu->ccsidr[2] = 0xf0000000; /* No L2 icache. */ cpu->reset_auxcr = 2; define_arm_cp_regs(cpu, cortexa8_cp_reginfo); } // target-arm/cpu.h /* If adding a feature bit which corresponds to a Linux ELF * HWCAP bit, remember to update the feature-bit-to-hwcap * mapping in linux-user/elfload.c:get_elf_hwcap(). */ enum arm_features { ARM_FEATURE_VFP, ARM_FEATURE_AUXCR, /* ARM1026 Auxiliary control register. */ ARM_FEATURE_XSCALE, /* Intel XScale extensions. */ ARM_FEATURE_IWMMXT, /* Intel iwMMXt extension. */ ARM_FEATURE_V6, ARM_FEATURE_V6K, ARM_FEATURE_V7, ARM_FEATURE_THUMB2, ARM_FEATURE_MPU, /* Only has Memory Protection Unit, not full MMU. */ ARM_FEATURE_VFP3, ARM_FEATURE_VFP_FP16, ARM_FEATURE_NEON, ARM_FEATURE_THUMB_DIV, /* divide supported in Thumb encoding */ ARM_FEATURE_M, /* Microcontroller profile. */ ARM_FEATURE_OMAPCP, /* OMAP specific CP15 ops handling. */ ARM_FEATURE_THUMB2EE, ARM_FEATURE_V7MP, /* v7 Multiprocessing Extensions */ ARM_FEATURE_V4T, ARM_FEATURE_V5, ARM_FEATURE_STRONGARM, ARM_FEATURE_VAPA, /* cp15 VA to PA lookups */ ARM_FEATURE_ARM_DIV, /* divide supported in ARM encoding */ ARM_FEATURE_VFP4, /* VFPv4 (implies that NEON is v2) */ ARM_FEATURE_GENERIC_TIMER, ARM_FEATURE_MVFR, /* Media and VFP Feature Registers 0 and 1 */ ARM_FEATURE_DUMMY_C15_REGS, /* RAZ/WI all of cp15 crn=15 */ ARM_FEATURE_CACHE_TEST_CLEAN, /* 926/1026 style test-and-clean ops */ ARM_FEATURE_CACHE_DIRTY_REG, /* 1136/1176 cache dirty status register */ ARM_FEATURE_CACHE_BLOCK_OPS, /* v6 optional cache block operations */ ARM_FEATURE_MPIDR, /* has cp15 MPIDR */ ARM_FEATURE_PXN, /* has Privileged Execute Never bit */ ARM_FEATURE_LPAE, /* has Large Physical Address Extension */ ARM_FEATURE_V8, ARM_FEATURE_AARCH64, /* supports 64 bit mode */ }; What I did not find immediately is where these tags are used in the interpretation / compilation.. So let's dive into that first. Where are the instructions defined? Beef seems to be in target-arm/translate.c Lots of functions prefixed "gen_". I guess these are code generators for the individual instructions? They call into "tcg_gen_" prefixed functions, which is the Tiny Code Generator. What are the "disas_" functions? They call into tcg as well. Entry: Qemu ARM IRQ Date: Thu Dec 12 15:29:19 EST 2013 This doesn't work any more: cpu_irq = arm_pic_init_cpu(env); Where to find how this changed? Here's the answer [1]. - pic = arm_pic_init_cpu(s->cpu); s->pic = sysbus_create_varargs("strongarm_pic", 0x90050000, - pic[ARM_PIC_CPU_IRQ], pic[ARM_PIC_CPU_FIQ], NULL); + qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_IRQ), + qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_FIQ), + NULL); So in the CC32RS512 code, this is probably what it needs to be: the cc32-sysc is connected to the 2 ARM interrupts IRQ and FIQ, and the rest of the hardware is connected to the interrupt controller which has 32 interrupts. dev = DEVICE(cpu); dev = sysbus_create_varargs("cc32-sysc", 0x0F0000, qdev_get_gpio_in(dev, ARM_CPU_IRQ), qdev_get_gpio_in(dev, ARM_CPU_FIQ), NULL); for (i = 0; i < 32; i++) { fprintf(stderr, "PIC %d\n", i); pic[i] = qdev_get_gpio_in(dev, i); } [1] http://lists.nongnu.org/archive/html/qemu-devel/2013-08/msg01080.html Entry: Qemu overview Date: Fri Dec 13 10:39:06 EST 2013 High-level and mostly wrong overview of qemu: - Asm code gets translated to TCG code, then compiled to native code or interpreted. - Memory accesses are either based on the RAM/ROM objects, or sysbus objects - sysbus objects have behavior associated to read/write. they also interact with interrupts. - not clear how exactly control flow works for interrupts From [1]: 2.11 Hardware interrupts In order to be faster, QEMU does not check at every basic block if a hardware interrupt is pending. Instead, the user must asynchronously call a specific function to tell that an interrupt is pending. This function resets the chaining of the currently executing basic block. It ensures that the execution will return soon in the main loop of the CPU emulator. Then the main loop can test if the interrupt is pending and handle it. - guest code is called synchronously[2]: ... what matters is that both TCG and KVM allow us to jump into guest code and execute it. Jumping into guest code takes away our control of execution and gives control to the guest. While a thread is running guest code it cannot simultaneously be in the event loop because the guest has (safe) control of the CPU. Typically the amount of time spent in guest code is limited because reads and writes to emulated device registers and other exceptions cause us to leave the guest and give control back to QEMU. In extreme cases a guest can spend an unbounded amount of time without giving up control and this would make QEMU unresponsive. In order to solve the problem of guest code hogging QEMU's thread of control signals are used to break out of the guest. [1] http://ellcc.org/ellcc/share/doc/qemu/qemu-tech.html#Hardware-interrupts [2] http://blog.vmsplice.net/2011/03/qemu-internals-overall-architecture-and.html Entry: Why is there no qemu arm7tdmi emulator? Date: Fri Dec 13 12:02:25 EST 2013 From a brief look at the code, patching together a cpu from feature sets isn't a big amount of work. Maybe have a look at skyeye[1] [1] http://balau82.wordpress.com/2010/09/27/simulating-at91-with-skyeye/ Entry: ARM + high speed usb: SAM3U Date: Sat Mar 22 13:37:26 EDT 2014 [1] http://www.atmel.com/products/microcontrollers/arm/sam3u.aspx Entry: Debian multiarch for cross-compilation Date: Fri Aug 22 21:30:35 CEST 2014 sudo sudo dpkg –-add-architecture armel It seems this only works with libraries. Can't have both cpp-4.9:amd64 and cpp-4.9:armel installed? Is there a way to have this conflict resolved? [1] http://www.lshift.net/blog/2012/06/17/using-debian-multiarch-for-cross-compiling [2] http://lwn.net/Articles/482952/ Entry: emdebian cross compiler Date: Mon Aug 25 18:02:30 CEST 2014 # deb [arch=amd64] http://ftp.uk.debian.org/emdebian/toolchains stable main # deb [arch=amd64] http://ftp.uk.debian.org/emdebian/toolchains testing main apt-get install g++-4.7-arm-linux-gnueabi Entry: Multiarch cross compilers Date: Mon Aug 25 19:46:20 CEST 2014 How to obtain a cross toolchain that works with installed multiarch -dev packages? Prebuilt toolchains are here[2]. Tried, but currently there is a version gcc-4.9 mismatch in sid wrt[2] 4.9.1-9: amd64 4.9.1-8: arm64 armel armhf hppa hurd-i386 i386 kfreebsd-amd64 kfreebsd-i386 mipsel powerpc ppc64 s390x sparc x32 Build one from source? [1] https://wiki.debian.org/MultiarchCrossToolchainBuild [2] http://toolchains.secretsauce.net/ Entry: Old way: emdebian xapt Date: Mon Aug 25 23:22:53 CEST 2014 xapt -a armhf -m libusb-1.0-0-dev libboost-filesystem-dev libpython3.4-dev This still needs a lot of magic with -I flags and -rpath... How to automate? For pratical purposes, I can now compile on target. Maybe best to just wait until the multiarch stuff works. [1] https://wiki.debian.org/EmdebianToolchain Entry: Time to figure out state-of-the-art cross compilers Date: Fri Sep 12 21:47:34 CEST 2014 Bare-metal isn't that hard. Use use binaries from [1] together with some multiarch i386 suport:. sudo apt-get install libc6:i386 libc6-i686:i386 libgcc1:i386 What I'm interested in though is to cross-compile for Debian on beaglebone black, beagleboard xM, and raspberry pi. For OpenWRT it seems straightforward since it already comes with a toolchain and build system. I'd like to also sort out how to build multiple rust compilers, one for each architecture. [1] https://launchpad.net/gcc-arm-embedded/+download Entry: arm-linux-gnueabi-*-4.7 Date: Fri Sep 12 22:09:25 CEST 2014 Packages from emdebian all have a -4.7 version postfix which isn't always supported in build systems looking for cross tools, e.g. rust. Use this to create symlinks: cd /usr/bin for i in arm*4.7; do ln -s $i $(basename $i -4.7); done Entry: Cortex M4F float vs fixed Date: Sun Sep 21 13:51:05 CEST 2014 Float in M4F is VFP with missing features like double FP. FPv4-SP extension VFP float ops happen in S registers. VLDR/VSTR loads into / stores from S registers. Entry: Assembly remarks Date: Thu Sep 25 16:44:24 CEST 2014 pc-relative addressing in arm is quite strange.. 0xa (10) -> 40 0xb (11) -> 44 but why is this not 40,42,44,46 ? looks like PC only increments every 2 instructions in thumb mode. 10002: 4b0a ldr r3, [pc, #40] ; (1002c ) 10004: 4a0a ldr r2, [pc, #40] ; (10030 ) 10006: 4e0b ldr r6, [pc, #44] ; (10034 ) 10008: 4d0b ldr r5, [pc, #44] ; (10038 ) what is the point of __memset_veneer trampoline? what is the ip register? -> r12, scratch register / new-sb in inter-link-unit calls 00010520 <__memset_veneer>: 10520: b401 push {r0} 10522: 4802 ldr r0, [pc, #8] ; (1052c <__memset_veneer+0xc>) 10524: 4684 mov ip, r0 10526: bc01 pop {r0} 10528: 4760 bx ip 1052a: bf00 nop 1052c: 08014471 .word 0x08014471 what's the difference between push {rx, ...} and stmdb sp!, {rx, ...} -> push/pop are aliases what are the d registers? 1007a: ed2d 8b0c vpush {d8-d13} -> floating point extension registers. i'm guessing this is just the s registers aliased as d (double) registers so the above is the same as: vpush {s16-s26} apparently, 2-word instructions do not need to be 2-word aligned. why is "ite ne" followed by movne? 100ce: 2b00 cmp r3, #0 100d0: bf14 ite ne 100d2: 4663 movne r3, ip 100d4: 463b moveq r3, r7 again for "it mi", "submi" 10104: bf48 it mi 10106: 3a01 submi r2, #1 -> conditional instructions must be inside an it block -> suffix condition or inverse -> up to 4 following instr conditional it seems gcc does insert vfma instructions (fused mul acc) Entry: measure optimality Date: Thu Sep 25 17:19:01 CEST 2014 by computing the ratio of moves to math instructions Entry: neon vs. vfp Date: Fri Sep 26 17:52:30 CEST 2014 Entry: Q or GE Date: Sat Sep 27 15:54:56 CEST 2014 Point of Q: perform a series of operations, then check if overflow occured at the end. CPSR has the following 32 bits.[43] M (bits 0–4) is the processor mode bits. T (bit 5) is the Thumb state bit. F (bit 6) is the FIQ disable bit. I (bit 7) is the IRQ disable bit. A (bit 8) is the imprecise data abort disable bit. E (bit 9) is the data endianness bit. IT (bits 10–15 and 25–26) is the if-then state bits. GE (bits 16–19) is the greater-than-or-equal-to bits. DNM (bits 20–23) is the do not modify bits. J (bit 24) is the Java state bit. Q (bit 27) is the sticky overflow bit. V (bit 28) is the overflow bit. C (bit 29) is the carry/borrow/extend bit. Z (bit 30) is the zero bit. N (bit 31) is the negative/less than bit. [1] http://en.wikipedia.org/wiki/ARM_architecture [2] http://stackoverflow.com/questions/19557338/importance-of-qsaturation-flag-in-arm Entry: STM32F103 board Date: Wed Oct 29 14:20:54 EDT 2014 Board info at [2]. [master] tom@zoo:~/armdev/stm32f103$ cat openocd.cfg set CHIPNAME stm32f103c8t6 source [find interface/arm-usb-ocd.cfg] source [find target/stm32f1x.cfg] [master] tom@zoo:~/armdev/stm32f103$ cat openocd #!/bin/bash cd $(dirname $0) exec openocd -f openocd.cfg "$@" [master] tom@zoo:~/armdev/stm32f103$ ./openocd Open On-Chip Debugger 0.8.0-dev-00173-gc98856b-dirty (2013-09-15-10:22) Licensed under GNU GPL v2 For bug reports, read http://openocd.sourceforge.net/doc/doxygen/bugs.html Info : only one transport option; autoselect 'jtag' adapter speed: 1000 kHz adapter_nsrst_delay: 100 jtag_ntrst_delay: 100 cortex_m reset_config sysresetreq Info : clock speed 1000 kHz Info : JTAG tap: stm32f103c8t6.cpu tap/device found: 0x3ba00477 (mfg: 0x23b, part: 0xba00, ver: 0x3) Info : JTAG tap: stm32f103c8t6.bs tap/device found: 0x16410041 (mfg: 0x020, part: 0x6410, ver: 0x1) Info : stm32f103c8t6.cpu: hardware has 6 breakpoints, 4 watchpoints Error: stm32f103c8t6.cpu -- clearing lockup after double fault Polling target stm32f103c8t6.cpu failed, GDB will be halted. Polling again in 100ms Polling target stm32f103c8t6.cpu succeeded again C-c C-c TODO: compile latest openocd. [1] http://electronics.stackexchange.com/questions/30688/clearing-lockup-after-double-fault [2] http://www.chinalctech.com/index.php?_m=mod_product&_a=view&p_id=1029 Entry: libopencm3 Date: Wed Oct 29 14:47:13 EDT 2014 git clone git://github.com/libopencm3/libopencm3.git cd libopencm3 make This will yield lib/*.a including: lib/libopencm3_stm32f1.a git clone https://github.com/libopencm3/libopencm3-examples.git cd examples/stm32/f1/other/usb_cdcacm make OPENCM3_DIR=/home/tom/git/libopencm3 [master] tom@zoo:~/git/libopencm3-examples/examples/stm32/f1/other/usb_cdcacm$ ~/armdev/stm32f103/gdb cdcacm.elf GNU gdb (GDB) 7.6.1 ... Reading symbols from /home/tom/pub/git/libopencm3-examples/examples/stm32/f1/other/usb_cdcacm/cdcacm.elf...done. 0xffffffff in ?? () (gdb) load Loading section .text, size 0x1528 lma 0x8000000 Loading section .data, size 0x14 lma 0x8001528 Start address 0x80011a0, load size 5436 Transfer rate: 9 KB/sec, 2718 bytes/write. Entry: Openocd 0.8.0 Date: Wed Oct 29 15:42:54 EDT 2014 Let's start with latest release wget http://superb-dca3.dl.sourceforge.net/project/openocd/openocd/0.8.0/openocd-0.8.0.tar.gz cd openocd-0.8.0/ ./configure \ --enable-maintainer-mode \ --enable-legacy-ft2232_libftdi \ --enable-ftdi \ --enable-ti-icdi \ --enable-jlink ft2232 for olimex ARM-USB-OCD Entry: ftdi driver to replace ft2232 driver for olimex ARM-USB-OCD Date: Wed Oct 29 15:55:21 EDT 2014 ft2232 driver is deprecated. Compiling it anyway doesn't work for the olimex-arm-usb-ocd.cfg that's in openocd 0.8.0 Ok, both configs are still present. Just prefix directory with 'ftdi' source [find interface/ftdi/olimex-arm-usb-ocd.cfg] Entry: Can't connect after flashing bad code + FIX Date: Wed Oct 29 17:16:31 EDT 2014 Now I get: [master] tom@zoo:~/armdev/stm32f103$ ./openocd Open On-Chip Debugger 0.8.0 (2014-10-29-15:46) Licensed under GNU GPL v2 For bug reports, read http://openocd.sourceforge.net/doc/doxygen/bugs.html Info : only one transport option; autoselect 'jtag' adapter speed: 1000 kHz adapter_nsrst_delay: 100 jtag_ntrst_delay: 100 cortex_m reset_config sysresetreq Info : clock speed 1000 kHz Error: JTAG scan chain interrogation failed: all ones Error: Check JTAG interface, timings, target power, etc. Error: Trying to use configured scan chain anyway... Error: stm32f103c8t6.cpu: IR capture error; saw 0x0f not 0x01 Warn : Bypassing JTAG setup events due to errors Warn : Invalid ACK 0x7 in JTAG-DP transaction When holding reset it does come up properly. [master] tom@zoo:~/pub/git/armdev/stm32f103$ ./openocd Open On-Chip Debugger 0.5.0 (2011-08-09-08:45) Licensed under GNU GPL v2 For bug reports, read http://openocd.berlios.de/doc/doxygen/bugs.html Info : only one transport option; autoselect 'jtag' 1000 kHz adapter_nsrst_delay: 100 jtag_ntrst_delay: 100 cortex_m3 reset_config sysresetreq 100 kHz Info : clock speed 100 kHz Info : JTAG tap: stm32f103c8t6.cpu tap/device found: 0x3ba00477 (mfg: 0x23b, part: 0xba00, ver: 0x3) Info : JTAG tap: stm32f103c8t6.bs tap/device found: 0x16410041 (mfg: 0x020, part: 0x6410, ver: 0x1) Info : stm32f103c8t6.cpu: hardware has 6 breakpoints, 4 watchpoints When releasing reset: Warn : Invalid ACK 0x7 in JTAG-DP transaction Polling target stm32f103c8t6.cpu failed, GDB will be halted. Polling again in 100ms When pressing reset: Polling target stm32f103c8t6.cpu succeeded again This started happening after uploading something. Keeping the reset button pressed: (gdb) connect Polling target stm32f103c8t6.cpu succeeded again Info : accepting 'gdb' connection from 3333 Info : device id = 0x20036410 Warn : STM32 flash size failed, probe inaccurate - assuming 128k flash Info : flash size = 128kbytes undefined debug reason 7 - target needs reset (gdb) mon reset Info : JTAG tap: stm32f103c8t6.cpu tap/device found: 0x3ba00477 (mfg: 0x23b, part: 0xba00, ver: 0x3) Info : JTAG tap: stm32f103c8t6.bs tap/device found: 0x16410041 (mfg: 0x020, part: 0x6410, ver: 0x1) So this worked: - physically hold target in reset - start openocd - start gdb (possibly with .elf) - issue "mon halt" then release physical reset => target is halted and can be programmed. I just erased the flash[1] and now it connects properly. (gdb) mon flash erase_address 0x08000000 0x00020000 erased address 0x08000000 (length 131072) in 0.026083s (4907.411 KiB/s) Tried again - didn't work. With BOOT0=1 and BOOT1=1 (gdb) mon flash banks #0 : stm32f103c8t6.flash (stm32f1x) at 0x08000000, size 0x00010000, buswidth 0, chipwidth 0 (gdb) mon flash erase_address 0x08000000 0x00010000 erased address 0x08000000 (length 65536) in 0.024643s (2597.086 KiB/s) [1] http://openocd.sourceforge.net/doc/html/Flash-Commands.html Entry: ACM demo Date: Wed Oct 29 17:37:58 EDT 2014 Looks like it actually ran ok: Oct 29 16:46:54 zoo kernel: [86274.953817] usb 1-1.1.1.4.4: new full-speed USB device number 90 using xhci_hcd Oct 29 16:46:54 zoo kernel: [86275.044193] usb 1-1.1.1.4.4: New USB device found, idVendor=0483, idProduct=5740 Oct 29 16:46:54 zoo kernel: [86275.044196] usb 1-1.1.1.4.4: New USB device strings: Mfr=1, Product=2, SerialNumber=3 Oct 29 16:46:54 zoo kernel: [86275.044197] usb 1-1.1.1.4.4: Product: CDC-ACM Demo Oct 29 16:46:54 zoo kernel: [86275.044198] usb 1-1.1.1.4.4: Manufacturer: Black Sphere Technologies Oct 29 16:46:54 zoo kernel: [86275.044199] usb 1-1.1.1.4.4: SerialNumber: DEMO Oct 29 16:46:54 zoo kernel: [86275.044352] usb 1-1.1.1.4.4: ep 0x83 - rounding interval to 1024 microframes, ep desc says 2040 microframes Oct 29 16:46:54 zoo kernel: [86275.045072] cdc_acm 1-1.1.1.4.4:1.0: ttyACM0: USB ACM device Oct 29 16:46:54 zoo mtp-probe: checking bus 1, device 90: "/sys/devices/pci0000:00/0000:00:14.0/usb1/1-1/1-1.1/1-1.1.1/1-1.1.1.4/1-1.1.1.4.4" Oct 29 16:46:54 zoo mtp-probe: bus: 1, device: 90 was not an MTP device Entry: BOOT0 BOOT1 Date: Wed Oct 29 17:57:57 EDT 2014 There are two jumpers on the board: BOOT0, BOOT1. Boot jumpers are originally closest to the large pin header. (assuming that's 0) Trying different 0x20000000 RAM 0x08000000 Flash (mapped to 0) [1] http://stackoverflow.com/questions/22351703/stm32f030-and-boot0-pin Entry: libopencm3 build Date: Thu Oct 30 18:31:12 EDT 2014 [master] tom@zoo:~/pub/git/libopencm3-examples/examples/stm32/f1/other/usb_cdcacm$ OPENCM3_DIR=/home/tom/git/libopencm3 make V=1 Using /home/tom/git/libopencm3 path to library arm-none-eabi-gcc -Os -g -Wextra -Wshadow -Wimplicit-function-declaration -Wredundant-decls -Wmissing-prototypes -Wstrict-prototypes -fno-common -ffunction-sections -fdata-sections -MD -Wall -Wundef -I/home/tom/git/libopencm3/include -DSTM32F1 -mthumb -mcpu=cortex-m3 -msoft-float -mfix-cortex-m3-ldrd -o cdcacm.o -c cdcacm.c arm-none-eabi-gcc --static -nostartfiles -L/home/tom/git/libopencm3/lib -Tcdcacm.ld -Wl,-Map=cdcacm.map -Wl,--gc-sections -mthumb -mcpu=cortex-m3 -msoft-float -mfix-cortex-m3-ldrd cdcacm.o -lopencm3_stm32f1 -Wl,--start-group -lc -lgcc -lnosys -Wl,--end-group -o cdcacm.elf One option per line: CFLAGS: -Os -g -Wextra -Wshadow -Wimplicit-function-declaration -Wredundant-decls -Wmissing-prototypes -Wstrict-prototypes -fno-common -ffunction-sections -fdata-sections -MD -Wall -Wundef -I/home/tom/git/libopencm3/include -DSTM32F1 -mthumb -mcpu=cortex-m3 -msoft-float -mfix-cortex-m3-ldrd LDFLAGS --static -nostartfiles -L/home/tom/git/libopencm3/lib -Tcdcacm.ld -Wl,-Map=cdcacm.map -Wl,--gc-sections -mthumb -mcpu=cortex-m3 -msoft-float -mfix-cortex-m3-ldrd -lopencm3_stm32f1 -Wl,--start-group -lc -lgcc -lnosys -Wl,--end-group EDIT: The -m flags were missing on the linker line. Entry: stm32f usb libopencm3 Date: Thu Oct 30 18:50:33 EDT 2014 libopencm3/lib/usb/usb_f107.c stm32fx07_ep_write_packet stm32fx07_poll Running the cdc example code: libopencm3-examples/examples/stm32/f1/other/usb_cdcacm Why is it using otg_hs.h and not usb.h ? Entry: SW turned off Date: Thu Oct 30 19:13:06 EDT 2014 this might be the culprit ;) AFIO_MAPR |= AFIO_MAPR_SWJ_CFG_JTAG_OFF_SW_ON; Entry: Stepping on the f103 Date: Thu Oct 30 19:23:45 EDT 2014 So I'm able to step through the code. (gdb) p/x *0x8000000 $4 = 0x20005000 (gdb) p/x *0x8000004 $5 = 0x8001299 But setting $pc doesn't work. This does seem to reset properly: (gdb) mon reset halt JTAG tap: stm32f103c8t6.cpu tap/device found: 0x3ba00477 (mfg: 0x23b, part: 0xba00, ver: 0x3) JTAG tap: stm32f103c8t6.bs tap/device found: 0x16410041 (mfg: 0x020, part: 0x6410, ver: 0x1) target state: halted target halted due to debug-request, current mode: Thread xPSR: 0x01000000 pc: 0x08001298 msp: 0x20005000 Registers are out of sync. How to reload? stepi seems to solve that.. sometimes.. not much consistent behaviour. still buggy as hell this stuff... let's upgrade gdb as well.. it also complains about no hw breakpoint resources available. restarting openocd helped. anyways, seems to be "mostly ok". gud is working as well with gdb-7.8.1 Entry: cdcacm example Date: Thu Oct 30 19:58:05 EDT 2014 the elf built from libopencm3-examples works mine doesn't Entry: jitter Date: Fri Oct 31 08:46:46 EDT 2014 http://www.keil.com/forum/20318/how-to-reduce-interrupt-jitter/ Entry: arm linux rootfs qemu Date: Sun Nov 2 22:41:22 EST 2014 # tar xf rootfs.tar.gz # cp /usr/bin/qemu-arm-static usr/bin # chroot . /usr/bin/qemu-arm-static /bin/sh Entry: boot process vybrid Date: Sun Nov 2 23:01:11 EST 2014 [1] https://linuxlink.timesys.com/docs/gsg/twr_vf600 Entry: Interactive C Date: Wed Nov 5 13:52:29 EST 2014 Modify linker script to load into ram? This is just a vagues idea.. Let's stick to uploading images as it seems to be quite fast on the STM32F103. I'd like to figure out though why the reset isn't always working. Entry: gud emacs Date: Wed Nov 5 15:54:31 EST 2014 On zoo it works fine: source window comes up. On tx for some reason it doesn't.. Reading symbols from /home/tom/armdev/stm32f103/cdcacm.elf...done. stm32f103_poll (dev=0x20000014 ) at ../../usb/usb_f103.c:299 299 ../../usb/usb_f103.c: No such file or directory. Ah it doesn't find the file. How to add absolute paths to libopencm3? I recompiled it from ~/armdev/libopencm3 and now it works Entry: Debugging USB Date: Thu Nov 6 12:22:28 EST 2014 Halting the CPU causes USB timeouts. Currently I've only managed to run the CDCACM application by completely disconnecting the debugger. I see two ways to deal with this: - Give up on debugging USB in gdb - Run a GDB stub over USB while running in the background The question is really, what do I expect from a debugger tied to a running real-time system? Essentially I want to inspect memory and possibly execute some small code routines. Maybe best to just use the GDB serial protocol. This would provide a "console" through GDB, would avoid having to define an ad-hoc protocol, and allows extension of any other kind of RPC that might be useful. I wonder if a micro like STM32F103 can set its own breakpoints / watchpoints? EDIT: One thing I didn't think about is that the protocol is absolutely horrible :) I wonder if there's a translation layer that can be used. Entry: OpenOCD on/off Date: Thu Nov 6 15:31:46 EST 2014 Let's first focus on reliably restarting with debugger attached. I have a USB hub with power switches. If I flip the switch, I want openocd to stop. If I power on the JTAG interface, I want openocd to start. EDIT: see armdev/bin: -rwxr-xr-x 1 tom tom 301 Nov 6 14:50 openocd-dispatch -rwxr-xr-x 1 tom tom 1704 Nov 6 15:23 udev-arm-usb-ocd.sh Entry: Cortex M3 gdb stub Date: Thu Nov 6 15:44:37 EST 2014 Need to find something to start from. What I want is async debugging[4]. [1] https://code.google.com/p/nativeclient/issues/detail?id=2911 [2] https://gitorious.org/pmp-firmware-s-rockbox/ondabox/source/a42a56d8b00a92379399a648a2b4f25d9f069c72:gdb/arm-stub.c [3] http://www.embecosm.com/appnotes/ean4/embecosm-howto-rsp-server-ean4-issue-2.html [4] http://www.embecosm.com/appnotes/ean4/embecosm-howto-rsp-server-ean4-issue-2.html#sec_extended_async [5] https://www.youtube.com/channel/UCVPF4xiSILwfgo-VfjVohzQ Entry: libopencm3 USB IN >64 bytes Date: Thu Nov 6 23:22:51 EST 2014 To make a large transfer, a callback is necessary. The cdcacm example doesn't have one: usbd_ep_setup(usbd_dev, 0x01, USB_ENDPOINT_ATTR_BULK, 64, cdcacm_data_rx_cb); usbd_ep_setup(usbd_dev, 0x82, USB_ENDPOINT_ATTR_BULK, 64, NULL); usbd_ep_setup(usbd_dev, 0x83, USB_ENDPOINT_ATTR_INTERRUPT, 16, NULL); For IN enpoints this gets called after transfer is complete. Suspending output is a bit more painful than suspending input. So the solution is to either throw memory at the problem: generate output in memory and have a simple state machine export it, possibly doing some postprocessing (like RSP escapes). Alternatively, use a task that can be suspended. Some alternatives: - RTOS tasks - main program + interrupt state machines - cooperative multitasking [1] [1] http://hsl.wz.cz/tasks.htm Entry: gdb "console" Date: Fri Nov 7 18:39:50 EST 2014 Using gdb as a console to a real-time application. RSP protocol is polled from the main real-time loop. GDB sees consistent view in between updates of other state machines. Allow: - memory get/set - image loading - monitor commands - execution of expressions, e.g. "print toggle_pin(1)" However, there is no "current thread" in the sense of a halted target. $Pe=c9210008#b9 +$#00 +$G000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637c92100083c3d3e3f#f6 +$#00 +$G000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323330353637c92100083c3d3e3f#f2 +$#00 +$G000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323330353637c921000874020008#29 +$#00 +$Z0,80021c8,2#aa +$#00 +$m80021c8,2#61 +$0001#c1 +$X80021c8,0:#84 +$#00 +$M80021c8,2:bebe#09 +$#00 +$vCont?#49 +$#00 +$Hc0#db +$#00 +$c#63 +$#00 + That was in response to: (gdb) p main() warning: Invalid remote reply: This contains commands: G Z m X M vCont? H c What I want is maybe non-stop mode? Maybe it doesn't matter. There is no access to other threads anyway since there is no active contect while prodding at the console. Only state. So what is the current thread? Just a fake loop? The real main loop that polls the USB OUT endpoint? Entry: Look in gdb source for stubs Date: Fri Nov 7 21:24:19 EST 2014 Seems old.. No ARM stub? The one from RockBox might actually be functional. I have some idea now how it works, so maybe keep that one intact? Entry: continue Date: Sat Nov 8 13:26:29 EST 2014 So the basic structure of the stub seems to be working. Most of what's left is low-level fiddling: continue. GDB also complains: (gdb) p main() Program received signal SIGTRAP, Trace/breakpoint trap. 0xbc020008 in ?? () The program being debugged was signaled while in a function called from GDB. GDB remains in the frame where the signal was received. To change this behavior use "set unwindonsignal on". Evaluation of the expression containing the function (main) will be abandoned. When the function is done executing, GDB will silently stop. Assuming this is because the stack pointer is not at the expected position. How to find out what it actually expects? The simplest way seems to just reuse working code from the RockBox stub. Entry: usbmon Date: Sun Nov 9 12:21:09 EST 2014 zoo:/home/tom# mount -t debugfs none_debugs /sys/kernel/debug zoo:/home/tom# modprobe usbmon zoo:/home/tom# ls /sys/kernel/debug/usb/usbmon 0s 0u 1s 1t 1u 2s 2t 2u 3s 3t 3u 4s 4t 4u cat /sys/kernel/debug/usb/usbmon/0u |grep :1:026 Note that [1] says: The length of collected data is limited and can be less than the data length reported in the Data Length word. I've seen this for packet lengths of 128 where only 8 words (32 bytes) are presented. [1] https://www.kernel.org/doc/Documentation/usb/usbmon.txt Entry: debugging USB on f103 Date: Sun Nov 9 13:22:15 EST 2014 So it seems that the low-level libopencm3 part is running fine. RSP stub is mostly working as well. There is no real need for debugging at the packet level. Something I noticed though is that the max packet size seems to be 32 instead of 64. Strange.. So, what I want to do is to make a pass-through for the RSP data that will log it. The simplest way to do this is to bridge /dev/ttyACM0 to a tcp port and use a tcp sniffer. socat /dev/ttyACM0 TCP-LISTEN:12345,reuseaddr tcpflow -i lo -C -e port 12345 Entry: p main() hangs gdbstub Date: Sun Nov 9 13:37:15 EST 2014 Reason: $X800211c,2:..#fb $X800211c,2:..#fb $X800211c,2:..#fb $X800211c,2:..#fb Might be because writing to flash causes an exception. EDIT: Sending Exx at least prevents the crash. It would be better to not use software breakpoints. I.e. let the stub provide a more abstract interface. Entry: fixing p main() Date: Sun Nov 9 14:18:19 EST 2014 It tries to set a breakpoint: $m8002150,2#2b +$0023#c5 + $X8002150,2:..#cc +$Efd#0f + Here 0x8002150 is the reset handler. Why does it pick that particular address? It doesn't seem to depend on the original $pc. The 'Z' packet is used for breakpoints. It tries this first: $Z0,8002154,2#78 +$#00 So let's implement it. Ok, done. No more writing software breakpoints. So why reset vector? Maybe it is totally arbitrary? Need to look at what it sets: $Pe=cd210008#e4 +$OK#9a + $Pd=f8ffffff#f3 +$OK#9a + $Pf=f0110008#b3 +$OK#9a + $P19=00000001#78 +$OK#9a + $Z0,80021cc,2#d5 +$OK#9a + This corresponds to: lr 0x080021cd 134226381 sp 0xfffffff8 0xfffffff8 pc 0x080011f0 0x80011f0
cpsr 0x01000000 16777216 bp+1 == lr (lsb is thumb mode) It seems that the BP location really doesn't matter. It reserves 2 words on the current stack frame. Original sp = 0; What about cpsr? [1] https://sourceware.org/gdb/onlinedocs/gdb/Calling.html Entry: STM32F103C8T6 Date: Sun Nov 9 20:11:08 EST 2014 The board I'm using has an STM32F103C8T6: 20kB RAM 0x5000 64kB Flash $3.18 at future electronics[1]. For debugging it might be good to have an STM32F1 chip with a little more RAM. Which one? Package names[2]: STM32F103 C|R|V|Z F|G Package: C = LQFP 48 R = LQFP 64 V = LQFP 100 Z = LFBGA 144 Flash / RAM kb: 6 = 32 / 10 8 = 64 / 20 B = 128 / 20 C = 256 / 48 D = 384 / 64 E = 512 / 64 F = 758 / 96 G = 1024 / 96 What are the last 2 characters from the pin numbering? (T6) [1] http://www.futureelectronics.com/en/technologies/semiconductors/microcontrollers/32-bit/Pages/5227137-STM32F103C8T6.aspx?IM=0 [2] http://www.st.com/web/catalog/mmc/FM141/SC1169/SS1031/LN1565 Entry: gdbstub flash Date: Sun Nov 9 21:18:34 EST 2014 GDB needs a memory map to handle flashing properly. However it might work with ordinary M packets as well. It attempts to write 192 bytes at a time: $X8000000,c0:... Refman 3.3.3: - The Flash memory can be programmed 16 bits (half words) at a time. - The Flash memory erase operation can be performed at page level Page size is - 1kB for medium density devices (< 128kb) - 2kB for high density So when making the erase explicit this can be supported using ordinary memory access. Anyways.. its probably not too hard to support it: - qSupported[2] - qXfer:memory-map:read::offset,length - vFlashErase:addr,length - vFlashWrite:addr:XX - vFlashDone [1] https://sourceware.org/gdb/onlinedocs/gdb/Memory-Map-Format.html#Memory-Map-Format [2] https://sourceware.org/gdb/onlinedocs/gdb/General-Query-Packets.html#qSupported Entry: stm32f103 and jtag Date: Mon Nov 10 01:56:26 EST 2014 Can't get the USB to work while the JTAG is plugged in. Wondering what this is.. Maybe clock issue? Pins don't seem to conflict. Let's try with a SWD interface. Thing is though that this probably supports DFU. Together with serial monitor this might not need a separate JTAG adapter. Entry: Other arguments Date: Mon Nov 10 02:17:25 EST 2014 (gdb) p $sp $9 = (void *) 0x20001000 (gdb) p test_call(1,2,3,4,0x40,0x41,0x42,0x43) $X20000ff4,4:C...#27 $X20000ff0,4:B...#22 $X20000fec,4:A...#53 $X20000fe8,4:@...#27 It calls the code with sp 20000fe8 $Pd=e80f0020#e6 Entry: What are these other registers? Date: Mon Nov 10 02:22:40 EST 2014 $P13=00000000f050510200000000#b4 $P19=00000000#77 Entry: 48kB image? Date: Tue Nov 11 12:35:35 EST 2014 Image for gdbstub seems large. These are the hogs: 000002ee,__hexnan 000003ec,_realloc_r 00000530,_malloc_r 00000588,__gethex 00000eac,_strtod_r 000011b8,__ssvfscanf_r 000011f8,_dtoa_r 00001ada,_svfprintf_r I'm not sure why printf is in there, but scanf can probably be avoided as it's only parsing hex numbers. Entry: Weird stuff.. Date: Tue Nov 11 21:29:10 EST 2014 set *(uint32_t*)0x200000AC = ((uint32_t)counter_tick)|1 Entry: freenode #stm32 Date: Wed Nov 12 00:44:40 EST 2014 Look for the following in the irc log [1]. 00:42 < doelie> hi. anyone know if it's possible to set breakpoint registers from inside the machine as opposed to jtag/sw? i'm writing a special purpose gdb stub and was wondering if this even makes sense. 00:43 < doelie> particular machine is stm32f103c8 dongs' replies lead to: Debug inspection and monitor control register DEMCR[2]. FPB (flash patch breakpoint) programmer model[3]. Flash Patch Remap Register[4]. FP_CTRL 0xE0002000 See Flash Patch Control Register FP_REMAP 0xE0002004 See Flash Patch Remap Register FP_COMP0 0xE0002008 See Flash Patch Comparator Registers FP_COMP1 0xE000200C FP_COMP2 0xE0002010 FP_COMP3 0xE0002014 FP_COMP4 0xE0002018 FP_COMP5 0xE000201C FP_COMP6 0xE0002020 FP_COMP7 0xE0002024 The STM32F103 reference manual doesn't mention it except for a brief blurb at 31.12 [1] http://xob.kapsi.fi/~jpa/stm32/2014-11.log [2] http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0337e/CEGHJDCF.html [3] http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0337e/ch11s04s01.html [4] http://infocenter.arm.com/help/topic/com.arm.doc.ddi0337e/ch11s04s01.html#BABGGDHH Entry: GDB Stub Developer’s Guide Date: Thu Nov 13 12:54:51 EST 2014 http://www.kpitgnutools.com/developersguide.htm Entry: smstub vectors Date: Thu Nov 13 13:11:04 EST 2014 How should vectors be handled? Should the stub stay out of the way here? Check VTOR register[1][2] 0xE000ED08 In libopencm3.h all vectors are declared weak in libopencm3/stm32/f1/nvic.h [1] http://infocenter.arm.com/help/topic/com.arm.doc.dui0552a/Ciheijba.html [2] http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0552a/CIHFDJCA.html Entry: Stub mainloop Date: Thu Nov 13 13:37:34 EST 2014 Leave it up to the application. Poll GDB from its main loop? No that would complicate things. Entry: stm32f peripheral info using libopencm3 Date: Sat Nov 15 11:23:39 EST 2014 Starting from example [1]. rcc_peripheral_enable_clock timer_reset timer_set_mode Current timer value can be read out at: TIM1_CNT [1] https://gitorious.org/mdr32f9-libopencm3/mdr32f9-libopencm3-examples/source/f5b0aa5638b9903c7b76d14786d8090926cf7bb9:examples/stm32/f1/stm32-h103/timer/timer.c Entry: stm32f startup Date: Sat Nov 15 12:41:01 EST 2014 So reading out the TMR6 registers at 0x40001000 gives all 0. Something isn't starting up properly. Entry: Debug remote protocol Date: Sat Nov 15 12:53:58 EST 2014 It can be enabled in gdb as well: (gdb) set debug remote 1 Entry: Larger stm32f103 board works Date: Sat Nov 15 12:58:29 EST 2014 Clock issue: - rcc_clock_setup_in_hsi_out_48mhz(); // internal + rcc_clock_setup_in_hse_8mhz_out_72mhz(); Entry: I need a flat register map Date: Sat Nov 15 13:01:39 EST 2014 How to generate from libopenocd defs? Tried to mine the header files, but that was a half-working mess of ad-hoc shell scripts. Now using structs with instances defined in special secions + linker script. Can probably be automated further. (gdb) p/x M40.RCC.APB1ENR 0x800000 That's just USB. TIM6 is not running It just refuses to set that bit: (gdb) set M40.RCC.APB1ENR = 0x800010 (gdb) p/x M40.RCC.APB1ENR $78 = 0x800000 Setting TIM2 does work. (gdb) set M40.RCC.APB1ENR = 0x800001 (gdb) p/x M40.RCC.APB1ENR $81 = 0x800001 Maybe the device just doesn't have a TIM5,TIM6? Yes, that's why it doesn't work! The 103x8 devices only have 4 timers 1,2,3,4 I have 103C8 and 103R8 Entry: de-jitter Date: Sat Nov 15 23:57:26 EST 2014 Seems that interrupt latency is 12 cycles. Check this again[1] to see the special cases. If there are exceptions due to bus operation, de-jittering can be done based on timer values followed by a jump into a nop sequence. It's a bit harder to understand than on a PIC :) [1] http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka16366.html Entry: TIM2 Date: Sun Nov 16 00:07:47 EST 2014 So can pull one of the several interrupt flags in DEV.TIM2.SR Figure out how this gets routed to the ISR. Entry: Stub and vectors Date: Tue Nov 25 09:22:57 EST 2014 Move vector table. (gdb) p/x (int)&vector_table $2 = 0x8002800 Check VTOR register[1][2] 0xE000ED08 OK works #include /* Set Vector Table Offset to our memory based vector table */ SCB_VTOR = (uint32_t)&vector_table; Entry: registers and linker Date: Tue Nov 25 09:50:15 EST 2014 Problem with using linker for register structs is that it will not optimize the indirection. I.e. base of struct is patched. DEV.TIM2.SR This loads &DEV as 0x40000000, then adds offset of TIM2.SR Maybe linker can't patch addresses as offsets, i.e. patching a word by adding to it? Entry: F1 USART receive Date: Thu Dec 18 13:55:49 EST 2014 CR1[RE] = 1 It seems that SR needs to be read for DR to be updated. Entry: Setting bits Date: Sat Feb 7 11:43:48 EST 2015 What is the fastest way to set a bit in a register on CM3? Compiler generates: ldr r3, [pc, #32] ; r3 <- 0x40000010 TIM2.SR ldr r2, [r3, #0] bic.w r2, r2, #1 str r2, [r3, #0] The equivalent in gas is: .thumb .syntax unified tim2_isr: ldr r3, tim2_reg ldr r2, [r3, #0] bic r2, r2, #1 bx lr .align tim2_reg: .word 0x40000010 Unified syntax[1]. .syntax [unified | divided] This directive sets the Instruction Set Syntax as described in the ARM-Instruction-Set section. W suffix forces a 32-bit instruction encoding. The .N suffix forces a 16-bit instruction encoding. [1] https://sourceware.org/binutils/docs-2.23/as/ARM_002dInstruction_002dSet.html#ARM_002dInstruction_002dSet Entry: Bit-banded accesses versus read-modify-write accesses Date: Sat Feb 7 13:17:24 EST 2015 The bit-band operation to achieve the same result requires only a single instruction and one or two processor clock cycles. These operations are available in a fixed range of addresses, with each bit in the address range 0x20000000 to 0x200fffff being aliased at a word (4-byte) aligned address in the range 0x22000000 to 0x23fffffc in the SRAM space. The same mechanism applies to the corresponding address ranges in the region 0x40000000 to 0x43fffffc in the Peripheral space. This setting TIM2.SR.UIF = 0 on STM32F103 8002e52: 4b08 ldr r3, [pc, #32] ; (8002e74 ) 8002e54: 2200 movs r2, #0 8002e56: 601a str r2, [r3, #0] ... 8002e74: 42000400 .word 0x42000400 [1] http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka16401.html [2] http://spin.atomicobject.com/2013/02/08/bit-banding/ Entry: rust Date: Mon Feb 16 02:05:31 EST 2015 Compile from recent git. See bin/rustc* and rust/Makefile Qemu works with transparent user mode emulation if qemu-user is installed (probably needs armel arch?). Entry: STM32F level triggered interrupts Date: Sat May 9 02:00:30 CEST 2015 EXTI is all edge triggered. This is bad for some applications when it is possible to miss an edge during setup. The basic problem is that it is possible that an event arrives right before a clear pending operation. It seems possible to work around this by performing some extra reads.. [1] https://electronics.stackexchange.com/questions/158749/how-to-use-level-triggered-interrupts-with-stm32f1xx?rq=1 Entry: Qemu binfmt Date: Sat Jun 27 12:18:50 EDT 2015 The "binfmt" how did it work again? qemu-user-binfmt Entry: multiarch cross-compile Date: Sat Jun 27 12:58:36 EDT 2015 On zoo there is a dev32 lxc. Start there. Entry: semaphores Date: Sat Jul 18 03:48:42 EDT 2015 http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dht0008a/ch01s03s03.html Entry: fakeroot + qemu-arm-static Date: Mon Aug 31 14:18:08 CEST 2015 [1] https://lists.debian.org/debian-embedded/2011/04/msg00001.html Entry: rust bare metal arm Date: Sun Sep 20 07:08:42 EDT 2015 http://antoinealb.net/programming/2015/05/01/rust-on-arm-microcontroller.html Entry: qemu-arm-static Date: Fri Mar 25 18:39:49 EDT 2016 Hard to understand how it actually works, but with binfmt-support, it seems to be sufficient to place the target ld, ld-linux and libc in /etc/qemu-binfmt/arm/lib root@zoe:/etc/qemu-binfmt/arm/lib# ls -l total 1344 -rwxr-xr-x 1 root root 134328 Feb 27 00:48 ld-2.18.so lrwxrwxrwx 1 root root 10 Feb 22 23:03 ld-linux.so.3 -> ld-2.18.so -rwxr-xr-x 1 root root 1239048 Feb 27 00:48 libc-2.18.so lrwxrwxrwx 1 root root 12 Feb 22 23:02 libc.so.6 -> libc-2.18.so https://lists.debian.org/debian-embedded/2011/04/msg00001.html https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=604268;msg=70 https://wiki.debian.org/QemuUserEmulation So the way to go seems to be to get binfmt-support to work properly. That is then linked to run qemu-arm-static (or any other program). qemu-arm-static uses /etc/qemu-binfmt/arm/lib (hardcoded default). So i have it working up to the point that it works manually: cd $ROOT/bin ; qemu-arm-static ls but not automatically Installing qemu-user-binfmt made it work on zoo, which uses qemu-arm from qemu-user package. Also works on zoe, but I need to keep /etc/qemu-binfmt/arm/lib directory. I still find it odd that I can't chroot.. Ha, on zoo I had trouble before it looks like: tom@zoo:/lib$ ls -al ld-linux.so.3 lrwxrwxrwx 1 root root 28 Feb 17 17:26 ld-linux.so.3 -> arm-linux-gnueabi/ld-2.21.so It's part of libc6:armel Final word: dpkg --add-architecture armel apt-get update apt-get install libc6:armel qemu-user-binfmt or apt-get install libc6:armel qemu-user-static Both work. Now why doesn't the timesys chroot work? Wow this is tricky... This worked: chroot mnt qemu-arm-static -L / bin/sh This runs qemu-arm-static inside chroot, which is then told to look for libraries at / instead of its default location. Entry: openocd stlink Date: Tue Mar 28 11:19:21 EDT 2017 really... fucking dev tools. can't figure out how to halt the processor. it comes up fine but won't go into halt. Open On-Chip Debugger 0.9.0 (2015-05-28-17:08) Licensed under GNU GPL v2 For bug reports, read http://openocd.org/doc/doxygen/bugs.html Info : auto-selecting first available session transport "hla_swd". To override use 'transport select '. Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD adapter speed: 1000 kHz adapter_nsrst_delay: 100 none separate Info : Unable to match requested speed 1000 kHz, using 950 kHz Info : Unable to match requested speed 1000 kHz, using 950 kHz Info : clock speed 950 kHz Info : STLINK v2 JTAG v17 API v2 SWIM v4 VID 0x0483 PID 0x3748 Info : using stlink api v2 Info : Target voltage: 3.177706 Info : stm32f103c8t6.cpu: hardware has 6 breakpoints, 4 watchpoints Info : accepting 'gdb' connection on tcp/3333 Info : device id = 0x20036410 Warn : STM32 flash size failed, probe inaccurate - assuming 128k flash Info : flash size = 128kbytes undefined debug reason 7 - target needs reset Tried on HY-MiniSTM32V, separately powered. Now "mon halt" worked: 1. power up board. 2. power up programmer 3. target remote 4. monitor halt Then 5. reset board 6. monitor halt target state: halted target halted due to debug-request, current mode: Thread xPSR: 0x61000000 pc: 0x08000288 msp: 0x20001ff0 Now trying fresh small strip board, stlink-powered. That worked. Looks like my board is bad. Taking it out of the breadboard. Entry: git-private/armdev Date: Thu Apr 20 10:13:07 EDT 2017 Does it need to be private? IIRC that was just a lazy thing because at some point it contained some NDA stuff. It might be enough to just kill the history? It contains build tools setup and minimal libc for a host of arm and other targets, including qemu. Also has rust for arm setup. It seems simplest to leave it as is, and move relevant code to git/uc_tools The arm.txt file doesn't seem to contain NDA stuff so moved it to papers/arm.txt where you're reading it now. Entry: uc_tools bootloader + rust code? Date: Sat Sep 15 10:18:42 EDT 2018 What is needed to load a piece of rust code onto the STM32 boot loader? Say I want to write the serial port handler. So it needs to be able to: - go at a phsical address and find a structure there - set the function points to point into rust code The first is simple, the rest I don't know how to do. How can C code call a Rust function? https://users.rust-lang.org/t/how-to-call-rust-library-in-c/11436 #[no_mangle] extern "C" fn foo() { // stuff } http://greyblake.com/blog/2017/08/10/exposing-rust-library-to-c/ Maybe the simplest way is to create a static library. https://doc.rust-lang.org/cargo/reference/manifest.html#building-dynamic-or-static-libraries Practically, start with git/armboot, and produce an .a library exposing read and write functions. Then write a small C wrapper to glue it together. It's not git/armboot. This is old code. Entry: system level emulation Date: Tue May 28 10:41:20 EDT 2019 Using binfmt it is possible to have qemu run at the linux system call interface, i.e. only the application binary is emulated. How to use a debugger with that? E.g.: tom@panda:~/exo/axbc_overlay/mk/build$ qemu-arm-static ./test.pi.elf Entry: fractional multiplication in C Date: Sun May 17 19:13:30 EDT 2020 Probably best to do it in assembler: 32x32 -> 64 and keep only high word.