This is the mail archive of the
ecos-discuss@sources.redhat.com
mailing list for the eCos project.
RE: how to run the program
- To: ecos-discuss at sourceware dot cygnus dot com
- Subject: [ECOS] RE: how to run the program
- From: k e <ndgipper at yahoo dot com>
- Date: Thu, 31 Aug 2000 19:02:31 -0700 (PDT)
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.
/* INCLUDES */
#include <stdio.h> /* printf
,etc.*/
#include <cyg/kernel/kapi.h> /* All the
kernel specific stuff */
// GLOBAL VARIABLES
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
// MAIN PROGRAM
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
cyg_thread_resume(simple_threadA);
cyg_thread_resume(simple_threadB);
}
// 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
for(i=0;i<3;i++)
{
cyg_mutex_lock(&cliblock);
{ // 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_mutex_unlock(&cliblock);
}
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
cyg_mutex_lock(&cliblock);
{
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
cyg_mutex_unlock(&cliblock);
}
*PC=*PC&0xD0; // turn off LED3 (yellow)
*PC=*PC|0x40; // turn on LED2 (red) dialogue thread
complete
// now print the time occasionally
while(1)
{
time=cyg_current_time();
cyg_mutex_lock(&cliblock);
{
printf("Time->%lld\n\r",time); // request
cyg_mutex_unlock(&cliblock);
}
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)
at: CYGPKG_IO_SERIAL_TTY_CONSOLE
change: # user_value "\"/dev/ttydiag\""
to: user_value "\"/dev/tty1\""
purpose: Turn off the TTYDIAG junk - which I think
is to support gdb
at: CYGPKG_IO_SERIAL_TTY_TTYDIAG
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
at: CYGPKG_IO_SERIAL_ARM_AEB
change: # user_value 0
to: user_value 1
at: CYGPKG_IO_SERIAL_ARM_AEB_SERIAL1
change: # user_value 0
to: user_value 1
at: CYGDAT_IO_SERIAL_ARM_AEB_SERIAL1_NAME
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)
at: CYGHWR_HAL_ARM_AEB_REVISION
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.
at: CYGSEM_LIBC_STDIO_WANT_BUFFERED_IO
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)
at: CYGDAT_LIBC_STDIO_DEFAULT_CONSOLE
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
make
which actually builds the libraries based on the
configuration established in the ecos.ecc file
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 -nostdlib
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
-I$HOME/ecos-work/install/include
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 */
-ffunction-sections
removes unused functions from
object file. Keeps size of executable down.
-fdata-sections
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)
-L$HOME/ecos-work/install/lib
where to go for the library
-Wl,--gc-sections
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 stuff
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.
Have fun.
keith
__________________________________________________
Do You Yahoo!?
Yahoo! Mail - Free email you can access from anywhere!
http://mail.yahoo.com/