need AT91R40008 simple examples

Do you have a question? Post it now! No Registration Necessary

Translate This Thread From English to

Threaded View

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 (i10%00; i>0; i--);

    // Clear PDC counts (Rx and Tx)

    US0_RCR  = 0x00000000;
    US0_TCR  = 0x00000000;

    // Disable ITs

    US0_IDR = 0xFFFFFFFF;

    // Initialize the channel

    PIO_PDR = ( PIOTXD0 | PIORXD0 );
    //US0_MR = ( US_ASYNC_MODE | US_CHMODE_LOCAL_LOOPBACK );
    US0_MR = US_ASYNC_MODE;
    US0_BRGR = 53;

    // Start channel

    US0_CR = ( US_RXEN | US_TXEN );
    for (i10%00; i>0; i--);

    c = 'A';

    //for (c=0; ; c++)  {
    while(1)  {
        //c &= 0x00FF;
        for (; (US0_CSR & (1 << 1)) == 0; );    // Wait Tx
ready

        US0_THR = c;
// send byte

        for(i=0x00200000; i>0; i--) {}            //
delay

        /*
        // Wait Rx ready
        for (; (US0_CSR & (1 << 0)) == 0; );

        // Receive and check byte
        if (US0_RHR != c)  {
        }
        */

    }

    return(0);
}

2. a simple interrupt-driven serial test program (hopefully in C).

3. a simple interrupt example.

thanks,
William



Re: need AT91R40008 simple examples
William,

I read Lewin Edwards excellent book (see my review at amazon.com), 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 ./load.sh (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.

Jim

------------------------------------------------------------------------
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)))

#endif

// 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

#endif

/* end */

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

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

#include <stdio.h>
#include <stdlib.h>

#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];

  led_off(LED_ALL);

  ser_init(38400);

  led_on(LED_D1);

  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))
    ;

  WRITEREGW(USART1_BASE + US_THR, (int) c);
}

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

------------------------------------------------------------------------
load.sh
------------------------------------------------------------------------

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

------------------------------------------------------------------------

Re: need AT91R40008 simple examples
Jim,

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



Re: need AT91R40008 simple examples (EB40A)
William,

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

PATH=/tools/arm-elf/bin:$PATH

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:

  www.cygwin.com
  http://sources.redhat.com/binutils /
  http://gcc.gnu.org /
  http://sources.redhat.com/gdb /
  http://sources.redhat.com/newlib /

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.

Jim

Re: need AT91R40008 simple examples (EB40A)
Jim,

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 load.sh, 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


Re: need AT91R40008 simple examples (EB40A)
Jim,

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


Re: need AT91R40008 simple examples (EB40A)
William,

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:

  http://rtjcom.com/download/download.html#eb40a

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.)

Regards,

Jim

Re: need AT91R40008 simple examples (EB40A)
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.

William



On 12 Nov 2003 14:45:27 -0800, snipped-for-privacy@aol.com (Jim) wrote:

Quoted text here. Click to load it


Re: need AT91R40008 simple examples
William,

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)

Thanks.

Jim

Re: need AT91R40008 simple examples

Quoted text here. Click to load it

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

Regards,

                               -=Dave
--
Change is inevitable, progress is not.

Re: need AT91R40008 simple examples
William,

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.

http://rtjcom.com/download/download.html#eb40a

Peter



Site Timeline