[ECOS] RE: how to run the program

k e ndgipper@yahoo.com
Thu Aug 31 19:12:00 GMT 2000

Apologies for the lame format of my previous post.

here it is again

Hopefully, these comments will help you get your application running
without GDB.  I use Linux.  If you're using Windows you'll have
to figure out the translation.

I routinely run applications on the ARM AEB-1 without using GDB
and without even knowing how to use the flash rom.  (Maybe someday
I'll learn that, too)

The following steps will detail how I get the following program to run
on the AEB-1 without using GDB.

// Sample program: sample.c
//  AEB-1 specific code
// This program will blink LED1 as a heartbeat.
// Print hello 3 times.
// Ask the user to type a floating point number
// then tell the user what number was entered.
// The hello thread then endlessly reports the
// eCos system time.
// The heartbeat continues as the only active thread.

#include <stdio.h>                      /* printf ,etc.*/
#include <cyg/kernel/kapi.h>            /* All the kernel specific stuff */

cyg_thread thread_s[2];         /* space for two thread objects */
char stack[2][4096];            /* space for two 4K stacks  - which is probably huge */
cyg_handle_t simple_threadA, simple_threadB;  // make room for thread handles
cyg_thread_entry_t simple_program, blinker_led4; // declare the thread functions
cyg_mutex_t cliblock;          // a mutex object for our I/O calls

void cyg_user_start(void)
  cyg_mutex_init(&cliblock); // initialize the mutex storage area
  // create the thread for the hello dialogue
  cyg_thread_create(4, simple_program, (cyg_addrword_t) 0,
                    "Thread A", (void *) stack[0], 4096,
                    &simple_threadA, &thread_s[0]);
  // create the thread for the heartbeat
  cyg_thread_create(4, blinker_led4, (cyg_addrword_t) 0,
                    "Blinker4", (void *) stack[1], 256,
                    &simple_threadB, &thread_s[1]);
  // start both threads


// this is the LED heartbeat thread
void blinker_led4(cyg_addrword_t data)
  char *PC=(char*)0xFFFF1C00;   // The base address of the PPI
                                // notice I'm using an 8 bit data size
                                // since that is the size of the I/O port
  PC=PC+0x08;  // the offset to I/O PORT C whose high nibble is the LED bank
  while (1)  // infinite loop
    *PC=*PC|0x80; // activeate it:   | 0b1000000
    cyg_thread_delay(100); // wait a little bit
    *PC=*PC&0x70; // de-activeate it:  & 0b0111000
    cyg_thread_delay(100); // wait a little bit

// this is the dialogue thread
void simple_program(cyg_addrword_t data)
  char *PC=(char*)0xFFFF1C00; // can use the PPI here too
  int i; // a counter
  float test_float; // storage for a number
  cyg_tick_count_t time;

  PC=PC+0x08;  // the LED channel

  *PC=*PC|0x10; // turn on LED4 (green) all's fine

  // let's say hello three times 
    { // this block is mutexed  .... more to understand about this, later
      printf("Hello, World! %d of 2\r\n",i);  // still have to say \r\n for some reason
  cyg_thread_delay(100);  // wait a little...
  *PC=*PC&0xE0; // turn off LED4 (green) signal hello done
  *PC=*PC|0x20; // turn on LED3 (yellow) signal we want some input
      printf("Type a number  ->"); // request
      scanf("%f",&test_float);    // wait for an answer (note that heartbeat continues)
      printf("\n\rYou said ->%f<-\n\r",test_float); // duh
  *PC=*PC&0xD0; // turn off LED3 (yellow)
  *PC=*PC|0x40; // turn on LED2 (red)  dialogue thread complete
// now print the time occasionally
        printf("Time->%lld\n\r",time); // request
    cyg_thread_delay(100); // wait a little bit


Step 1: Configure an image of eCos that supports regular serial
        I/O rather than GDB encoded I/O.

The following eCos image build should be done in a separate
experimental directory.  I've done this in a directory that
is called ecos-work.  Which I'll refer to in Step 2.

I've configured an image of eCos that turns off the diagnostic I/O
garbly gook that encodes the I/O for GDB.  This was necessary for
using a "terminal" program to talk to the AEB.
Hopefully, you're familiar with configuring and building eCos for
the AEB-1.  I've included the following fine grained configuration
changes to the default ecosconfig for the AEB-1

Fine grained alterations:
edit the ecos.ecc file with the following changes

   purpose: Set the TTY console to the device /dev/tty1 (which we'll setup below)
    change: # user_value "\"/dev/ttydiag\""
        to:  user_value "\"/dev/tty1\""

   purpose: Turn off the TTYDIAG junk - which I think is to support gdb
    change: # user_value 1
        to:  user_value 0

   purpose: Turn on the AEB specific UART1 and call it /dev/tty1
                can't say why I chose tty1
    change: # user_value 0
        to:  user_value 1

    change: # user_value 0
        to:  user_value 1

    change: # user_value "\"/dev/ser1\""
        to:  user_value "\"/dev/tty1\""

   Do this if you have the AEB-1C board 
   purpose: Change memory model to AEB-1C board (256K) rather than AEB-1B board (128K)
    change: # user_value B
        to:  user_value C

   purpose: This is still a mystery, but it made scanf behave better.
            Without this, the buffer had to be filled before scanf returned.
    change: # user_value 1
        to:  user_value 0
       also turned off _EXIT_FFLUSH to resolve conflict

   purpose: Change the libc default console to our device defined above
            (this is for printf, etc)
    change: # user_value "\"/dev/ttydiag\""
        to:  user_value "\"/dev/tty1\""

That does it for the fine grained configuration.....

Now, the actual library and header files must be made:
  ecosconfig check
     ensure no conflicts.  If there are, then you'll have to track them from there.
  ecosconfig tree
     which builds the configuration tree
     which actually builds the libraries based on the configuration established in the ecos.ecc
  make tests
     which builds the test programs  -  not really necessary and not used in this example

That's it for Step 1.  The eCos configuration is ready for running on the AEB-1 without GDB.

Step 2: Build your application

Rather than include a Makefile (which novices often get hung up on) here's
a script that I'll call mybuild :

## beginning of script called mybuild
##  USAGE:  mybuild file
##      where file is prefix of source code file.c
##   example: mybuild sample
rm $1.o
rm $1
rm $1tmp
rm $1tmp2
rm $1arm
arm-elf-gcc -mcpu=arm7di -c -o $1.o  -Wall -I$HOME/ecos-work/install/include -ffunction-sections
-fdata-sections $1.c
arm-elf-gcc -mcpu=arm7di  -L$HOME/ecos-work/install/lib -Wl,--gc-sections -o $1 $1.o -Ttarget.ld
arm-elf-objcopy --strip-debug $1 $1tmp
arm-elf-objcopy -O binary $1tmp $1tmp2
uuencode $1tmp2 $1tmp2 | tr '`' ' ' > $1arm
## end of script

It's not elegant, but gets the point across.  Here's what's going on.
The first 5 lines are cleanup.  (A Makefile would be more elegant)
The first arm-elf-gcc compiles the source for your application 
     -mcpu=arm7di   picks the cpu for the AEB-1
     -c             compile only, no linking
     -o $1.o        the object file name    (sample.o)
     -Wall          report all warnings
                    directory for the include files in the application source code:
                #include <stdio.h>                      /* printf ,etc.*/
                #include <cyg/kernel/kapi.h>            /* All the kernel specific stuff */
                    removes unused functions from object file.  Keeps size of executable down.
                    removes unused data from object file.  Keeps size of executable down.
     $1.c           the source file
The next arm-elf-gcc links the source to the eCos library that was built in step1
     -mcpu=arm7di   picks the cpu for the AEB-1 (maybe redundant, I don't know)
                    where to go for the library
                    tells the linker to actually do the -ffunction-sections and -fdata-sections
                    stuff, above.  (I think.  Anyone have any more info on how this works?)
     -o $1          the output file name  (sample)
     $1.o           the object file to be linked
     -Ttarget.ld    the linker script that the eCos build creates  (full of lots of intricate
                    that I haven't completely figured out yet)
     -nostdlib      leave out the gcc libraries thus only using the eCos library (which nicely
                    include a C-API, etc.)
The first arm-elf-objcopy strips the debug stuff (if any) from the linked code.
     $1             the linked file (sample)
     $1tmp          the output of this first objcopy
The next arm-elf-objcopy "relocates" the code and turns it into executable code for the AEB.
     $1tmp          the input
     $1tmp2         the output
The uuencode translates the AEB executable to an ASCII form that the AEB downloader will
receive and translate back to binary and load into ram.
     $1tmp2         the name of the file to read
     $1tmp2         the name to put into the ASCII file
     tr '`' ' '     translates ` to blanks (which is what the AEB loader wants)
     $1arm          the final ASCII file that the AEB boot loader will receive

That's it for step 2..... You're ready to run the samplearm file on the AEB

Step 3: Download and run the application

The "terminal" program that I use is minicom.  It should be easy
to convert the following for your terminal program.

Start up minicom.  Use ALT-P to set to comm parameters to 38400 8N1
Power up the AEB board and minicom will print out the AEB greeting.
Hit return within two seconds to keep the AEB boot program running.
You'll have a prompt Boot:
Now it's time to download the program to the board.
The AEB download command will put the AEB into a mode for receiving
the uuencoded executable:
   download c000
            this means store the downloaded binary starting at memory
            address c000
The AEB will reply with a note indicating that it is ready to receive.
I haven't had luck (haven't tried to hard) using minicom to actually
upload the file.  So, in another window I type
       cat samplearm >> /dev/modem
If you can figure out the minicom upload I'd be interested.
Anyway, the red LED will flicker for each line that is received
from the serial port.  The above command will include the EOF
character so when it's done I get the Boot: prompt back.
Now it's loaded and you're ready to run it.
The command
    go c040
will run the program.  At this time, I don't remember the details
behind the address c000 in the download command and the
execution at c040
I suspect it's in the target.ld file during linking.  But not sure.

Any way the program should be running....

The sample program at one point will ask for the user to type in
a number.  I haven't figured out the echo yet, though.  

Final comments:
I discovered all of this by scrounging thru web pages and
some trial and error.  Hopefully, the sample will work and
then you can start learning from here.  I'd be interested in
knowing if it did work for you.
And if you can answer any of my uncertainties about some of the
details that I mention above, that would be appreciated.

Do You Yahoo!?
Yahoo! Mail - Free email you can access from anywhere!

More information about the Ecos-discuss mailing list