Figure: Quickly assembled AT91SAM7S development system.

This Article Become Obsolete!

Please visit http://geektalks.cn to read the latest English version.

Project Origin

A couple of weeks ago, I bought a chip of AT91SAM7S32 from OURAVR — a local net shop and also a community for AVR/ARM related electronic design — just a chip, because I could afford neither a evaluation board nor a JTAG adapter with USB interface. (Unfortunately my laptop only have USB ports for I/O, I am unable to use a relatively cheaper Wiggler-like JTAG device.)

So, after searching in my tool box, I found the following things:

OK, that enough. I could make a mini development board by myself. And Benedikt Sauter provided us a wonderful tool — USBprog, I once tried it as a good AVRISP MK2 Clone. It can also be programmed as a OpenOCD adapter for programming and debugging ARM microcontrollers.

If you are acquainted with AVR microcontroller, also have a USBprog or just a USBN9604 chip on hand, this article will give you a method to play with ATMEL ARM with the following advantages:

But there are also disadvantages:

Make a AT91SAM7S32 Development Board

Instead of making a PCB, we can solder AT91SAM7S32 on a QFP to DIP board, add other components on that PCB or on a bread board attached to it. Female pin headers can be soldered for those GPIO ports.

Figure: schematics of the AT91SAM7S32 mini development board.

Make a USBprog as OpenOCD Adapter

You can build a new USBprog just like me, or add a level shifter and a JTAG header on your exist USBprog. Before or after the electronic task, firmware for OpenOCD should be downloaded to ATMEGA32.

Figure: schematics of USBprog as a OpenOCD adapter.
Important
If USBprog cannot be recognized by Linux or OpenOCD software
  1. decoupling capacitor between VCC and GND is absolutely necessary for this high frequency circuit.

  2. substitute the 24MHz crystal by a 24MHz external oscillator.

  3. if use a 24MHz crystal for USBN9604 other than a oscillator, 1M Ohm resistor between XIN and XOUT is necessary.

Install GNU Tool Chain For ARM

We have a evaluation board and a JTAG now, next you would like to install a free cross compile and debug environment on your computer. Installation procedure is almost as same as AVR's, first fetch binutils-2.16, gcc-4.0.2, newlib-1.14.0, and gdb-6.6 source. Of course it's recommended to use the latest versions of these tools. Then uncompress these packages.

$mkdir [binutils-build] #In this way, we can keep the source code tree clean.
$cd [binutils-build]
$[binutils-source]/configure --target=arm-elf --prefix=[toolchain-prefix] \
 --enable-interwork --enable-multilib
$make
$su -c 'make install'
$export PATH="$PATH:[toolchain-prefix]/bin"
$mkdir [gcc-build] #In this way, we can keep the source code tree clean.
$cd [gcc-build]
$su # you should become to root to execute the next configure script.
#[gcc-source]/configure --target=arm-elf --prefix=[toolchain-prefix] \
 --enable-interwork --enable-multilib \
 --enable-languages="c,c++" --with-newlib \
 --with-headers=[newlib-source]/newlib/libc/include
$make
$su -c 'make install'
$mkdir [newlib-build] #In this way, we can keep the source code tree clean.
$cd [newlib-build]
$[newlib-source]/configure --target=arm-elf --prefix=[toolchain-prefix] \
 --enable-interwork --enable-multilib
$make
$su -c 'make install'
$mkdir [gdb-build] #In this way, we can keep the source code tree clean.
$cd [gdb-build]
$[gdb-source]/configure --target=arm-elf --prefix=[toolchain-prefix]
 --enable-interwork --enable-multilib
$make
$su -c 'make install'

Install OpenOCD

First fetch the source archive from SVN Repository, then compiles as following.

$cd trunk
$./configure --enable-usbprog
$make
$su -c 'make install'

An example project

As an example project, download and unpack at91sam7s_getting_started_1.0.zip from ATMEL. Edit Makefile, We should change two variables to the following values:

ERASE_FCT=rm -f
TARGET=AT91SAM7S32

I would like to add some lines for further use.

GDBINITFILE=gdbinit-$(OUTFILE_FLASH)
$(GDBINITFILE): $(OUTFILE_FLASH).elf
        @echo "file $(OUTFILE_FLASH).elf"     > $(GDBINITFILE)
        @echo "target remote localhost:3333"    >> $(GDBINITFILE)
        @echo "monitor arm7_9 force_hw_bkpts enable"    >> $(GDBINITFILE)
        @echo
        @echo "Use 'arm-elf-gdb -x $(GDBINITFILE)'"

Because we use a 16MHz crystal for main oscillator to generate 48MHz main clock, not a 18.432MHz one which was used by ATMEL's evaulation board, we should also edit lowlevel.c, change AT91C_BASE_PMC->PMC_PLLR to a different value:

AT91C_BASE_PMC->PMC_PLLR = AT91C_CKGR_USBDIV_1           |
                           AT91C_CKGR_OUT_0              |
                           (16 << 8)                     |
                           (AT91C_CKGR_MUL & (95 << 16)) |
                           (AT91C_CKGR_DIV & 16);

also edit include/AT91SAM7S-EK.h:

/*
#define AT91B_MAIN_OSC        18432000               // Main Oscillator MAINCK
#define AT91B_MCK             ((18432000*73/14)/2)   // Output PLL Clock (48 MHz)
*/
#define AT91B_MAIN_OSC        16000000               // Main Oscillator MAINCK
#define AT91B_MCK             ((16000000*96/16)/2)   // Output PLL Clock (48 MHz)
#define AT91B_MASTER_CLOCK     AT91B_MCK

#endif /* AT91SAM7S-EK_H */

run

$make

to compile the example source.

Use OpenOCD

We need two configuration files and one script file for OpenOCD to program and debug the target. They are not really necessary, but will automate our work. Here is my example.

openocd.cfg:

#daemon configuration
telnet_port 4444
gdb_port 3333
daemon_startup reset

#interface
interface usbprog
jtag_speed 0

#use combined on interfaces or targets that can't set TRST/SRST separately
#reset_config trst_and_srst srst_pulls_trst
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> <startup mode>
#target arm7tdmi <reset mode> <chainpos> <endianness> <variant>
target arm7tdmi little run_and_init 0
run_and_halt_time 0 30

#flash configuration
#working_area 0 0x00200000 0x4000 nobackup
flash bank at91sam7 0 0 0 0 0

openocd_flash.cfg:

#daemon configuration
telnet_port 4444
gdb_port 3333
daemon_startup reset

#interface
interface usbprog
jtag_speed 0

#use combined on interfaces or targets that can't set TRST/SRST separately
#reset_config trst_and_srst srst_pulls_trst
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> <startup mode>
#target arm7tdmi <reset mode> <chainpos> <endianness> <variant>
target arm7tdmi little run_and_init 0
run_and_halt_time 0 30

#flash configuration
#working_area 0 0x00200000 0x4000 nobackup
flash bank at91sam7 0 0 0 0 0
target_script 0 reset openocd_at91sam7s_flash.script

The only difference between openocd.cfg and openocd_flash.cfg is the last line.

openocd_at91sam7s_flash.script:

#
# The following command wills 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(18.432MHz)
mww 0xfffffc20 0x00000601       # CKGR_MOR : enable the main oscillator(16.000MHz)
sleep 10
#mww 0xfffffc2c 0x00481c0e      # CKGR_PLLR: 96.1097 MHz(18.432MHz/14*(72+1))
mww 0xfffffc2c 0x005f1c10       # CKGR_PLLR: 96MHz(16.000MHz/16*(95+1))
sleep 10
#mww 0xfffffc30 0x00000007      # PMC_MCKR : MCK = PLL / 2 ~= 48 MHz
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 at91sam7s_getting_started_flash.bin 0x0
reset run
sleep 10
shutdown

Copy these three files to the directory of example project, connect USBprog to target board, run

$openocd -f openocd_flash.cfg

at91sam7s_getting_started_flash.bin will be programed to target's flash ROM and the program will start to run. If connect a LED to the PA0 port of our mini AT91SAM7S32 board, the LED will flash regularly.

For debug mode, run

$openocd

OpenOCD will open two TCP port, we can telnet to port 4444 to access command line interface.

$telnet localhost 4444

Or we can run gdb to debug the target.

$make gdbinit
$arm-elf-gdb -x gdbinit-at91sam7s_getting_started_flash

We can find more details of OpenOCD at its web page or AT91SAM7S mit OpenOCD programmieren.

Not The End

Congratulations, we have spent a meaningful weekend with pleasure, and you are deserved to take a shower and have a good dream.

But wait… Although ARM is no longer mysterious to us, on the other hand, we just start a new trip to the unknown world.

Adventure is going on.

If You Meet Troubles

This article is obsolete now, maybe it will cause you trouble, please visit http://geektalks.cn to get the latest message.