From mboxrd@z Thu Jan 1 00:00:00 1970 From: k e To: ecos-discuss@sourceware.cygnus.com Subject: [ECOS] RE: how to run the program Date: Thu, 31 Aug 2000 19:02:00 -0000 Message-id: <20000901020231.19116.qmail@web1102.mail.yahoo.com> X-SW-Source: 2000-08/msg00397.html 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 /* printf ,etc.*/ #include /* 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 /* printf ,etc.*/ #include /* 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/