AT91SAM7S mit OpenOCD programmieren

Wechseln zu: Navigation, Suche

von Benutzer:Andreas

Einführung

Dieser Artikel soll zeigen wie man einen AT91SAM7S über JTAG mit Hilfe von OpenOCD programmiert.

OpenOCD bietet zwei Kommunikationsschnittstellen: eine per Telnet benutzbare (Port 4444) und eine für GDB (Port 3333). Für die ersten Schritte oder einfache Aufgaben ist es am Besten erst mal das Telnet-Interface zu verwenden.

Konfiguration von OpenOCD + Wiggler

at91sam7_wiggler.cfg:

telnet_port 4444
gdb_port 3333

#interface
interface parport
parport_port 0x378
parport_cable wiggler
jtag_speed 0
reset_config srst_only

jtag_device 4 0x1 0xf 0xe

target arm7tdmi little reset_halt 0 arm7tdmi
daemon_startup reset

flash bank at91sam7 0 0 0 0 0

Grundfunktionen

ICE Modus wählen

Falls es einen JTAGSEL Eingang gibt (z. B. AT91SAM7S, AT91SAM7X), darf der JTAGSEL Jumper nicht gesetzt sein! JTAGSEL wählt zwischen dem JTAG Modus (z. B. um JTAG IDs zu lesen), wenn JTAGSEL=1 (Jumper gesetzt), und dem EmbeddedICE Modus (Jumper offen).

Programmausführung anhalten

> halt
requesting target halt...
> Target 0 halted
target halted in Thumb state due to debug request, current mode: User
cpsr: 0x40000010 pc: 0x0010031e

Programmausführung fortsetzen/starten

> resume
Target 0 resumed
> poll
target state: running

Reset auslösen

> reset
> Target 0 halted
target halted in ARM state due to debug request, current mode: Supervisor
cpsr: 0x600000d3 pc: 0x00000000

Flash-Programmierung mit OpenOCD

Ggf. NVM-bit 2 setzen mit SAM-BA (nur bei AT91SAM7X)

Vorsicht: Wenn der ERASE-Pin des SAM7X gebraucht wurde, muss man erst das NVM-Bit 2 setzen, ggf. mit SAM-BA. Ansonsten startet der SAM7X immer im Bootloadermodus und nie aus dem FLASH. OpenOCD unterstützen das Verändern der NVM-Bits ab SVN-Version~90 (August 31st, 2006, Befehl at91sam7 gpnvm.

Ggf. Programmausführung anhalten

siehe oben

Lock-Bits entfernen

Im Flash hat sich SAM-BA eingenistet und seine Lockbits gesetzt:

> flash info 0
#1: at91sam7 at 0x00100000, size 0x00010000, buswidth 4, chipwidth 0

at91sam7 information:
cidr: 0x27090540, arch: 0x0070, eproc: ARM7TDMI, version:0x000,  flashsize: 0x00010000
main clock(estimated): 18614kHz 
pagesize: 128, lockbits: 16 0x0003, pages in lock region: 32 
securitybit: 0, nvmbits: 0x0

> flash protect 0 0 15 off
> flash info 0
#1: at91sam7 at 0x00100000, size 0x00010000, buswidth 4, chipwidth 0

at91sam7 information:
cidr: 0x27090540, arch: 0x0070, eproc: ARM7TDMI, version:0x000,  flashsize: 0x00010000
main clock(estimated): 18614kHz 
pagesize: 128, lockbits: 16 0x0000, pages in lock region: 32 
securitybit: 0, nvmbits: 0x0


Beim AT91SAM7S256 muss man flash protect 0 0 7 off benutzen

Löschen

Der Flash kann nur in einem Stück gelöscht werden (Blöcke 0-15), ansonsten kommt eine Fehlermeldung:

> flash erase 0 0 15

Programmieren

Die hochzuladende Datei muss ins Binärformat gebracht werden, z. B. mit

arm-elf-objcopy -O binary test.elf test.bin

Anschließend kann die Datei mit folgendem Befehl in den Flash geschrieben werden:

> flash write 0 test.bin 0

Resetten

> reset
> resume
Target 0 resumed
> poll
target state: running

Jetzt sollte das Programm loslaufen.

Verwendung von GDB

Start und Herstellen der Verbindung

arm-elf-gdb test.elf

(gdb) target remote 192.168.0.33:3333
Remote debugging using 192.168.0.33:3333
0x00000000 in ?? ()

Ausführen von OpenOCD-Befehlen

Alle OpenOCD-Befehle lassen sich auch von GDB aus ausführen:

(gdb) monitor <befehl>

Beim Debuggen von Programmen im Flash: Hardware-Breakpoints erzwingen

monitor arm7_9 force_hw_bkpts enable

Integration in Makefile

Wenn man auf eine IDE verzichten möchte und deshalb nur einen Texteditor (z. B. VIM) verwendet, bietet es sich an, häufig ausgeführten Aktionen einen Abschnitt im Makefile zu spendieren.

OpenOCD Konfiguration

Die nachfolgende Konfiguration von OpenOCD ist derjenigen weiter oben sehr ähnlich. Der direkte Zugriff auf die Hardware erfordert zwingend superuser Rechte, was für eine Automatisierte Ausführung natürlich hinderlich ist. Daher kommt die Schnittstelle zu ppdev zum Einsatz.

  • Dazu das ppdev Kernelmodul laden:
    modprobe ppdev
  • Und/Oder in /etc/modules einfügen.
  • Rechte für Zugriff auf parport0: Benutzernamen in /etc/group eintragen, idR bei lp

/etc/openocd.cfg: (bei mir sucht openocd zuerst nach /etc/openocd.cfg, falls keine Datei angegeben wurde)

#daemon configuration
telnet_port 4444
gdb_port 3333
daemon_startup attach

#interface
interface parport
parport_port /dev/parport0
parport_cable wiggler
jtag_speed 0
#reset_config trst_and_srst|trst_only|srst_only srst_pulls_trst|trst_pulls_srst|combined
reset_config srst_only

#jtag scan chain
#format L IRC IRCM IDCODE (Length, IR Capture, IR Capture Mask, IDCODE)
jtag_device 4 0x1 0xf 0xe

#target configuration
#target <type> <endianness> <startup mode> <chainpos> <variant>
target arm7tdmi little reset_halt 0 
daemon_startup reset

#working_area 0 0x208000 0x4000 nobackup
flash bank at91sam7 0 0 0 0 0

/etc/openocd_flash.cfg:

#daemon configuration
telnet_port 4444
gdb_port 3333
daemon_startup reset

#interface
interface parport
parport_port /dev/parport0
parport_cable wiggler
jtag_speed 0
#reset_config trst_and_srst|trst_only|srst_only srst_pulls_trst|trst_pulls_srst|combined
reset_config srst_only

#jtag scan chain
#format L IRC IRCM IDCODE (Length, IR Capture, IR Capture Mask, IDCODE)
jtag_device 4 0x1 0xf 0xe

#target configuration
#target <type> <endianness> <startup mode> <chainpos> <variant>
target arm7tdmi little run_and_init 0 
run_and_halt_time 0 30

#working_area 0 0x208000 0x4000 nobackup
flash bank at91sam7 0 0 0 0 0
target_script 0 reset /etc/openocd_at91sam7_flash.script

/etc/openocd_at91sam7_flash.script:

# 
# The following commands will be executed on
# reset (because of run_and_init in the config-file)
# - halt target
# - init ecr
# - flash content of file main.bin into target-memory
# - shutdown openocd
#
# created by Martin Thomas 
# http://www.siwawi.arubi.uni-kl.de/avr_projects/arm_projects
# based on information from Dominic Rath 
#

halt
sleep 10

# Init - taken form the script openocd_at91sam7_ecr.script 
mww 0xfffffd44 0x00008000	# disable watchdog
mww 0xfffffd08 0xa5000001	# enable user reset
mww 0xfffffc20 0x00000601	# CKGR_MOR : enable the main oscillator
sleep 10
mww 0xfffffc2c 0x00481c0e 	# CKGR_PLLR: 96.1097 MHz
sleep 10
mww 0xfffffc30 0x00000007	# PMC_MCKR : MCK = PLL / 2 ~= 48 MHz
sleep 10
mww 0xffffff60 0x003c0100	# MC_FMR: flash mode (FWS=1,FMCN=60)
# arm7_9 force_hw_bkpts enable	# program resides in flash

# AT91SAM7 flash command-"batch"
# adapted by Martin Thomas based on information from Dominic Rath - Thanks
arm7_9 dcc_downloads enable
sleep 10
poll
flash probe 0
flash write 0 main.bin 0x0
reset run
sleep 10
shutdown

Wie unschwer zu erkennen ist, habe ich mich bei der großartigen Arbeit von Martin Thomas bedient. Das ändert sich auch beim Makefile nicht.

Integration in das Makefile

An geeigneter Stelle (wo man es zur Not auch wieder findet) ist folgendes in das Makefile von WinARM einzufügen:

# OpenOCD Flags
OPENOCDFLAGS = -f /etc/openocd_flash.cfg

INSIGHT = arm-elf-insight
OPENOCD = openocd
KILLALL = killall

# Program the device.
program: $(TARGET).bin
ifeq ($(RUN_MODE),ROM_RUN)
	 $(OPENOCD) $(OPENOCDFLAGS)
endif

debug: begin insight end

insight:
ifeq ($(RUN_MODE),RAM_RUN)
	$(OPENOCD) & $(INSIGHT) $(TARGET).elf -ex "target remote localhost:3333" -ex "monitor arm7_9 sw_bkpts enable" -ex "load"
	$(KILLALL) $(OPENOCD)
else
	$(OPENOCD) & $(INSIGHT) $(TARGET).elf -ex "target remote localhost:3333" -ex "monitor arm7_9 force_hw_bkpts enable"
	$(KILLALL) $(OPENOCD)
endif

Damit schreibt ein simples

make program

die Datei main.bin ins Flash und ein

make debug

startet OpenOCD und Insight, verbindet sich und lädt bei Bedarf das Programm ins Ram. Funktioniert hervorragend vom VI aus ;)

Anmerkungen:

  • Ich weiß nicht mehr, welcher Teufel mich geritten hat, aber ich habe OpenOCD dazu gebracht, zuerst nach /etc/openocd.cfg zu suchen, wenn keine Datei angegeben wird. Das müsste man sonst im Makefile berücksichtigen, wenn im aktuellen Pfad keine openocd.cfg existiert.
  • Einrückungen im Makefile müssen ein TAB-Zeichen sein. Eine äquivalente Anzahl Leerzeichen funktioniert nicht!

Weblinks