need AT91R40008 simple examples

I have one of the LED_SWING examples working that is written in C. I'm using cygwin and gnu tools.

I'm looking for some simple examples for further study, preferably written in C.

  1. A simple polling serial port example. I've tried this one modified from Atmel but it doesn't seem to work (any idea why?). It builds and I get a binary file that is 2440 bytes long. I load it with ebload on the at91eb40a evaluation board. According to the readme.txt it should transmit at 38400 baud on usart 0 which I've been assuming is "Serial A" on the board. Hyperterm shows nothing with settings 38400, n, 8, 1, no flow control.

#include "targets/eb40a/eb40a.h" #include "parts/r40008/reg_r40008.h"

int main ( void ) { unsigned int i; unsigned int c;

// Stop channel US0_CR = ( US_TXDIS | US_RXDIS | US_RSTTX | US_RSTRX ); for (i=1000; i>0; i--);

// Clear PDC counts (Rx and Tx)

US0_RCR = 0x00000000; US0_TCR = 0x00000000;

// Disable ITs


// Initialize the channel


// Start channel

US0_CR = ( US_RXEN | US_TXEN ); for (i=1000; i>0; i--);

c = 'A';

//for (c=0; ; c++) { while(1) { //c &= 0x00FF; for (; (US0_CSR & (1 0; i--) {} // delay

/* // Wait Rx ready for (; (US0_CSR & (1

Reply to
William Wuister
Loading thread data ...


I read Lewin Edwards excellent book (see my review at, and adapted his EB40 example code for the EB40A. Here is the source. I build and execute this code under Cygwin and WinXP. I hope it works for you and helps you get started with polled serial I/O on the EB40A.

Please notice that I use .gdbinit (below) to configure and download via gdb, and I execute ./ (below) to initiate a download. This runs gdb, loads my newly built EB40A program, and produces a gdb prompt. I enter 'cont' (or 'continue') at the gdb prompt and my EB40A application runs. I can interact with it from a terminal connected to the serial port.

If you get it working, and enter 'asdf' at the terminal, the program output should be:

startup ok [00000000] rx = 'a' [00000001] rx = 'd' [00000002] rx = 's' [00000003] rx = 'f'

Please note that I regard this as weekend experimental code. I would not base a commercial product on polled I/O, or this unproven sample code.

I have not taken the time to figure out how to do interrupt driven I/O on the EB40A, but I have a colleague who has this working. I'll ping him and see if he is interested in posting his code. I don't know if he has a minimal enough version, independent of his full product, to be useful to EB40A experimenters in the newsgroup.

Good luck.


------------------------------------------------------------------------ Makefile


# Makefile for load.elf

CFLAGS = -g -I. -mcpu=arm7tdmi ASFLAGS = -mcpu=arm7tdmi -gstabs LDFLAGS = -Teb40a-ram.ld -nostartfiles -Lgcc -L. OBJS = boot.o main.o EXE = load.elf

$(EXE): $(OBJS) arm-elf-gcc $(LDFLAGS) -o $(EXE) $(OBJS)

boot.o: boot.s arm-elf-as $(ASFLAGS) -o boot.o boot.s

main.o: main.c eb40a.h serial.h arm-elf-gcc -c $(CFLAGS) -o main.o main.c

clean: rm -f $(OBJS) rm -f $(EXE)

------------------------------------------------------------------------ eb40a-ram.ld


/* eb40a-ram.ld */

ENTRY(vectors) SEARCH_DIR(.)

MEMORY { sram : org = 0x00010000, len = 0x00040000 }

SECTIONS { .text : { *(.text); . = ALIGN(4); *(.rodata*); . = ALIGN(4); *(.glue_7t); . = ALIGN(4); *(.glue_7); . = ALIGN(4); etext = .; } > sram .data ADDR(.text) + SIZEOF(.text) : { __data_start__ = .; *(.data) . = ALIGN(4); __data_end__ = .; edata = .; _edata = .; } .bss ADDR(.data) + SIZEOF(.data) : { __bss_start__ = .; *(.bss); *(COMMON) __bss_end__ = .; _stack_bottom = .; . += 0x800; _stack_top = .; } end = .; _end = .; __end__ = .; .stab 0 (NOLOAD) : { [ .stab ] } .stabstr 0 (NOLOAD) : { [ .stabstr ] } }

------------------------------------------------------------------------ boot.s


@ boot.s -- init and call C main() on EB40A

.section .text .code 32 .globl vectors

vectors: b reset b . b . b . b . b . b . b . reset:

@clear .bss section ldr r1,bss_start ldr r2,bss_end ldr r3,=0 clear_bss: cmp r1,r2 strne r3,[r1],#+4 bne clear_bss

@init stack pointer ldr r13,stack_pointer

@call main bl main

@loop forever if main() exits b vectors

stack_pointer: .word _stack_top bss_start: .word __bss_start__ bss_end: .word __bss_end__

------------------------------------------------------------------------ eb40a.h


/* eb40a.h -- AT91EB40A / AT91R40008 */

/* register and field names based on AT91R40008 PDF */

#ifndef _EB40A_H #define _EB40A_H

#define EB40A_MCKI 66000000 // 66 MHz master clock

#define PS_BASE 0xffff4000 // power save base register #define PS_PCER 0x04 // peripheral clock enable reg #define PS_PCER_US1 0x00000008 // USART1 clock enable

#define PIO_BASE 0xffff0000 // PIO controller base register #define PIO_PDR 0x04 // PIO disable register #define PIO_SODR 0x30 // PIO set output data register #define PIO_CODR 0x34 // PIO clear output data register

#define PIO_TXD1 0x00200000 // USART1 transmit data signal #define PIO_RXD1 0x00400000 // USART1 receive data signal

#define LED_D1 0x00010000 // eb40a led 1 #define LED_D2 0x00020000 // eb40a led 2 #define LED_D3 0x00040000 // eb40a led 3 #define LED_D4 0x00080000 // eb40a led 4 #define LED_D5 0x00000008 // eb40a led 5 #define LED_D6 0x00000010 // eb40a led 6 #define LED_D7 0x00000020 // eb40a led 7 #define LED_D8 0x00000040 // eb40a led 8

#define LED_ALL 0x000f0078 // eb40a leds 1-8

#define WRITEREGW(addr,value) \ *((volatile unsigned int *) (addr)) = (value) #define WRITEREGH(addr,value) \ *((volatile unsigned short *) (addr)) = (value) #define WRITEREGB(addr,value) \ *((volatile unsigned char *) (addr)) = (value)

#define READREGW(addr) \ (*((volatile unsigned int *) (addr))) #define READREGH(addr) \ (*((volatile unsigned short *) (addr))) #define READREGB(addr) \ (*((volatile unsigned char *) (addr)))


// end.

------------------------------------------------------------------------ serial.h


/* serial.h -- AT91EB40A / AT91R40008 */

/* register and field names based on AT91R40008 PDF */

#ifndef _SERIAL_H #define _SERIAL_H

#define USART0_BASE 0xfffd0000 // USART0 base register #define USART1_BASE 0xfffcc000 // USART1 base register

#define US_CR 0x00 // control register #define US_MR 0x04 // mode register #define US_IER 0x08 // interrupt enable register #define US_IDR 0x0c // interrupt disable register #define US_IMR 0x10 // interrupt mask register #define US_CSR 0x14 // channel status register #define US_RHR 0x18 // receiver holding register #define US_THR 0x1c // transmitter holding register #define US_BRGR 0x20 // baud rate generator register #define US_RTOR 0x24 // receiver timeout register #define US_TTGR 0x28 // transmitter time guard register #define US_RES1 0x2c // reserved #define US_RPR 0x30 // receive pointer register #define US_RCR 0x34 // receive counter register #define US_TPR 0x38 // transmit pointer register #define US_TCR 0x3c // transmit counter register

#define US_RSTRX 0x00000004 // reset receiver #define US_RSTTX 0x00000008 // reset transmitter

#define US_CHRL_8 0x000000c0 // 8 bits #define US_PAR_NO 0x00000800 // parity none #define US_DBSTOP_1 0x00000000 // 1 stop bit

#define US_RXRDY 0x00000001 // enable RXRDY interrupt #define US_TXRDY 0x00000002 // enable TXRDY interrupt

#define US_RXEN 0x00000010 // receiver enable #define US_TXEN 0x00000040 // transmitter enable


/* end */

------------------------------------------------------------------------ main.c


// ----------------------------------------------- // // File: main.c // // Platform: Atmel AT91EB40A // // Processor: AT91R40008 ARM7TDMI // // Date: 8 Aug 2003 // // Desc: Demonstrate polled serial operation. // // ----------------------------------------------- //

#include #include

#include "eb40a.h" #include "serial.h"

static void ser_init(int); static void ser_putc(char); static int ser_getc(void); static void ser_puts(char *);

static void led_on(int); static void led_off(int);

int main(void) { int c; unsigned int counter = 0; char iobf[32];




ser_puts("startup ok\r\n");

for (;;) { if ((c = ser_getc()) != -1) { sprintf(iobf, "[%.8u] rx = '%c'\r\n", counter++, isprint(c) ? c : '.'); ser_puts(iobf); } } }

static void ser_init(int baudrate) { int base = USART1_BASE;

// enable clock input to baud rate gen (power saving) WRITEREGW(PS_BASE + PS_PCER, PS_PCER_US1);

// PIO disable (enable peripheral control) USART1 TX RX WRITEREGW(PIO_BASE + PIO_PDR, PIO_TXD1 | PIO_RXD1);

// reset transmitter and receiver WRITEREGW(base + US_CR, US_RSTTX | US_RSTRX);

// set serial mode to N/8/1 WRITEREGW(base + US_MR, US_PAR_NO | US_CHRL_8 | US_DBSTOP_1);

// set baud rate WRITEREGW(base + US_BRGR, EB40A_MCKI / (16 * baudrate));

// disable all interrupts for this serial port WRITEREGW(base + US_IDR, 0xFFFFFFFF);

// enable transmitter and receiver WRITEREGW(base + US_CR, US_TXEN | US_RXEN); }

static void ser_putc(char c) { // wait for transmit holding buffer empty while (!(READREGW(USART1_BASE + US_CSR) & US_TXRDY)) ;


static int ser_getc(void) { if (!(READREGW(USART1_BASE + US_CSR) & US_RXRDY)) return -1; return READREGW(USART1_BASE + US_RHR); }

static void ser_puts(char *s) { while (*s) ser_putc(*(s++)); }

static void led_on(int led) { WRITEREGW(PIO_BASE + PIO_CODR, led); }

static void led_off(int led) { WRITEREGW(PIO_BASE + PIO_SODR, led); }

// end.

------------------------------------------------------------------------ .gdbinit


# .gdbinit set remotebaud 115200 target rdi com1 load



#!/usr/bin/bash # arm-elf-gdb load.elf


Reply to


if follow the link bellow you should be able to download a package for the EB40A that besides implementing the Java VM using GNU tools also contains ported Atmel's library and the C code implementing the interrupt driven serial communication using the terminal library function calls.

formatting link


Reply to
Peter Gasparik


I tried your example but it still doesn't work. I did modify it to use USART0 instead of USART1, since I didn't have the correct serial cable handy. I used ebload to load the program at 0x100. Then I started hyperterm to look at com1 / usart0 at 38400 baud/N/8/1/no flow control, and hit sw2 on the eb40a. I should have then seen serial data, but didn't. Tomorrow I'll try usart1 when I can find the right cable.

You're able to get gdb to run, which I haven't. It just locks up when I type "target rdi com1". I also tried your .gdbinit and gdb locks up. What operating system are you running. I'm running win2k. I built arm-elf-gdb from the latest source in cygwin, and the cross-compiler too, which seems to work fine.

thanks, William

Reply to
William Wuister


Matching up the serial cable seems sensible. I don't have the EB40A hardware in front of me, but I recall something about one of the serial cables being straight-through so it would be important to chase that down and get it right.

I have not tried downloading this particular code using EBLoad, but I have had continued success using gdb under WinXP. I would think it would work for you as well under Win2K but can't claim to have tried that.

I located my notes from when I successfully installed and built the GNU toolchain based on the CD and directions in Lewin Edwards' book. I hope Lewin won't mind my passing this information along to you in the newsgroup. I would encourage everyone interested to purchase his excellent book for much more useful information on the subject.

I built the GNU toolchain twice. My first build was based on the tar files included on the CD that came with the book. I used that toolchain, including gdb, successfully for several days. I then decided to see if I would be successful repeating the procedure using newer GNU versions that I downloaded from the Internet. That build was also successful and is described further below.

For the first build, using the files from the CD, I installed Cygwin and determined the version as 1.3.16 using 'uname -r'. Please note that in the menu provided by Cygwin setup.exe, you must change Devel installation from Default to Install in order to install Cygwin targeted versions of gcc, ld, etc. I also make selections in the menu to install vim, less, more, clear, etc.

Once you are up and running in the Cygwin bash shell, perform the following steps to install and configure the GNU tool chain for arm-elf development:

cd /tmp

tar zxvf binutils-2.13.1.tar.gz tar zxvf gcc-3.2.tar.gz tar zxvf gdb-5.2.tar.gz tar zxvf newlib-1.10.0.tar.gz

cd /tmp/binutils-2.13.1 ./configure --target=arm-elf --prefix=/tools/arm-elf make all install


cd /tmp/gcc-3.2 ./configure --target=arm-elf --prefix=/tools/arm-elf --enable-languages=c,c++ --without-headers --with-newlib make all-gcc install-gcc

mkdir /tmp/newlib-build cd /tmp/newlib-build ../newlib-1.10.0/configure --target=arm-elf --prefix=/tools/arm-elf make all install

cd /tmp/gcc-3.2 ./configure --target=arm-elf --prefix=/tools/arm-elf --enable-languages=c,c++ --with-newlib make all-gcc install-gcc

cd /tmp/gdb-5.2 ./configure --target=arm-elf --prefix=/tools/arm-elf make all install

That's it. It should work. Note that gcc is built in two phases above, before and after the newlib build, first without headers and then with headers after newlib is bootstrap compiled. This is required. Note also that newlib is built in a separate newlib-build directory. Edwards states that this is required, or it won't work properly.

As mentioned, I used the toolchain built above successfully for several days. Then for my second toolchain build, I downloaded the current versions of Cygwin and the GNU tools from:

formatting link
formatting link
formatting link
formatting link
formatting link

This produced the following versions:

Cygwin 1.3.22-1 binutils-2.13.92.tar.bz2 gcc-3.3.1.tar.bz2 gdb-5.3.tar.bz2 newlib-1.11.0.tar.gz

I rebuilt the GNU toolchain from these versions using the same procedure documented above, and my sample code for the EB40A built and executed properly in this new environment. I continue to use this toolchain. I haven't checked lately, but I suspect that these versions are probably stale by now. Open source marches on.

One weekend I tried adding the Insight graphical front-end to gdb, but that turned out to be difficult due to Tcl/Tk compatibility issues with Cygwin that are documented at Red Hat (if I recall correctly, I did not keep notes on this). I tried applying the recommended patches but it got messy so I abandoned that and returned to command line gdb as documented above. Works great.

I hope this helps and you can get gdb running on your system.


Reply to


I rebuilt the arm gnu tools using your script and built 'load.elf' from your example files. Except that I used the following versions:

cygwin version: 1.5.5(0.94/3/2)

binutils-2.14.tar.gz gcc-3.3.1.tar.gz gdb-6.0.tar.gz newlib-1.11.0.tar.gz

this made a load.elf:

text data bss dec hex filename 32264 1796 2296 36356 8e04 load.elf

I then ran the, but gdb locks up like before.

I think that I followed your procedure exactly, except for the versions of cygwin and the packages. I guess that I'll give that a try and will let you know.

thanks, William

Reply to
William Wuister


I used the tar files and the cygwin version from the "shoestring" book and now gdb works. I guess that I had a bad build of something. I was using the latest source code as of a couple of weeks ago. I used the procedure found on a website about "building gnu tools", which was a little different. Anyway, it works now. I'm hoping that gdb will make it easier to get this board fully running. So, you still don't have any simple interrupt examples?

thanks, William

Reply to
William Wuister


When I replied to your post I tweaked the subject line and that surprised me by forking the thread. Please see my response under:

Re: need AT91R40008 simple examples (EB40A)



Reply to

FWIW, my newsreader did not fork the thread. That depends on what you're using to read news.



Change is inevitable, progress is not.
Reply to
Dave Hansen


Glad to hear you got it running. That's excellent.

No, I don't have any simple interrupt examples. However, I would recommend that you take a look at Peter's code available at:

formatting link

I have run this on my EB40A very successfully. Sure, I am using it for embedded Java on the EB40A, but Peter provides interrupt source for the I/O beneath his Java I/O classes. You might have to trim out a few things to get what you want, but from what I recall (I spent quite a bit of time with this package) the EB40A low level I/O is nicely segregated in platform specific source directories.

I have rebuilt the simpleRTJ Java VM (and EB40A support code) using exactly the same GNU toolchain we have been discussing. I can vouch for the simpleRTJ QuickStart document as being complete and all you need to get this running.

Please note that Peter intends you to use EBLoad to download his code to the EB40A, not gdb. I have used EBLoad with this code successfully. I don't know if gdb will download and execute this code, but EBLoad is convenient in this case.

If you write some simple interrupt driven code, I would be keenly interested in taking it for a test drive if you care to post it. (That would be a 'first available weekend' project for me, so no hurry.)



Reply to

I'm working on it. I'll probably figure it out in a few days. It's a part time project. My real job is win32 C++. Atmel has some examples on their Septemer, 2003 "Getting Started" CD, but I was looking for something smaller, I guess. I may look more at that this weekend. If I get something working, I'll post it.


Reply to
William Wuister

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.