The first program you write when you learn a language is the "hello world" classic, in a embedded system where you don't have a serial port (or you don't know if it is working) you have to use "das blinklicht" example. Er... it's just a blinking LED.
After setting up the cross compiler tool chain you'll need to set up the linker script and the crt0.s files.
The linker script defines where (in physical addresses) is the RAM and ROM of your system, which sections of code go into where and in my case the reset vector and initial stack pointer. There are still some things missing (namely libraries, floating point and multiplication/aritmetic), but I'm a step closer. I must admit that I found these (crt0.s and ldscript) on the net but I don't remember where or who did them. I've just change them a little.
Although the ROM is mapped on reset during the first 8 clocks at 0x00000, after the 8th clock ROM gets mapped at 0x80000. When you are programming a real eprom (or using my "linux-updated" rom emulator) you must move the code to the bottom of the ROM. This is accomplished with the command "AT".
OUTPUT_FORMAT(srec)
OUTPUT_ARCH(m68k)
OUTPUT(rom.srec) /* The default filename, if -o is missing */
SEARCH_DIR(.) /* include CRT0.S */
/* removed libraries path pointing nowhere, might need to correct this... - JS */
/* Define where RAM and EPROM areas reside.
* This gives the linker a rough possibility to detect errors while linking,
* for example a .text-section growing bigger than 64k.
* Don't rely too heavy on this, it can detect only very crude errors.
*/
/* moved before sections -JS */
MEMORY {
rom : ORIGIN = 0x00080000, LENGTH = 64K
ram : ORIGIN = 0x00000400, LENGTH = 511k /* after the 1k byte of vectors */
}
SECTIONS
{
/* Text section at start of ROM
* The next line tells the linker that the EPROM on my board starts
* at 0x00080000. The command AT (0) places the code on address 0 in
* the S-Record output file, ready for burning in an EPROM.
*/
.text 0x00080000 : AT (0)
{
LONG (0x00080000) /* RESET SSP - JS */
LONG (___main) /* RESET PC - JS */
__s_text = . ; /* Define a symbol */
* (.text)
CONSTRUCTORS
__e_text = . ; /* Those symbols are used by crt0.S */
} > rom
/* Data section; initialisation data is stored immediately
* after the text section in the ROM, but is loaded for
* use in RAM
* Again, the first address (0x00000400) tells the linker where
* the RAM is mapped, while AT (SIZEOF(.text)) puts the initial data
* into the output file right after the end of the .text section,
* from where it can be copied into RAM on startup.
*/
.data 0x00000400 : AT (SIZEOF(.text))
{
__s_data = . ; /* Symbols, to know where to */
*(.data)
__e_data = . ; /* copy the data. */
} > ram
/* BSS section:
* 0x00000400 + SIZEOF(.data) places the .bss-section into the RAM
* right after the .data-section. The defined symbols enable the
* startup code to clear this RAM area.
*/
.bss 0x00000400 + SIZEOF(.data) :
{
__s_bss = . ; /* We should be able */
*(.bss)
*(COMMON)
__e_bss = . ; /* to clear the bss. */
} > ram
}
GCC creates a section of code for "initialized data" called .data, this section is put into ROM and at the start it is copied into RAM (at CRT0.S), with the blinklicht program I don't use any .data or .bss or even stack, so for now I will not test if this works.
/*
* Sample crt0.S startup file.
*
* IMPORTANT: THIS FILE NEEDS A LINKER SCRIPT WHICH DEFINES THE NEEDED
* SYMBOLS __s_bss, __e_bss, __s_data, __e_data, __e_text
*/
.text
/*
* This is the reset code.
* It copies the startup data into the RAM (.data section)
* and clears the bss.
*/
.globl ___main
startup:
___main: lea.l __s_bss,%a0 /* Clear bss */
move.l #__e_bss,%d0
1: cmp.l %d0,%a0
beq.s 2f
clr.b (%a0)+
bra.s 1b
2:
lea.l __e_text,%a0 /* Move data to ram */
lea.l __s_data,%a1
move.l #__e_data,%d0
1: cmp.l %a1,%d0
beq.s 2f
move.b (%a0)+,(%a1)+
bra.s 1b
2:
clr.l -(%sp) /* **envp is null */
clr.l -(%sp) /* **argv is null */
clr.l -(%sp) /* argc is zero, too */
jsr _main /* Call the C-program */
lea 12(%sp),%sp /* Clean up the stack 3*4 */
/*
* main usually should not return. If it does anyway, halt the system.
*/
halt: bra halt
Without using optimizations -O2 your software loops will not be cleared by the optimizer, and it is pretty easy calculate the time taken for the software loops.
test.o: file format elf32-m68k
Disassembly of section .text:
00000000 <_main>:
0: 514f subqw #8,%sp
2: 42af 0004 clrl %sp@(4)
6: 13fc ffff 000c moveb #-1,c0002 <_main+0xc0002>
c: 0002
e: 202f 0004 movel %sp@(4),%d0
12: 13c0 000c 0000 moveb %d0,c0000 <_main+0xc0000>
18: 52af 0004 addql #1,%sp@(4)
1c: 60f0 bras e <_main+0xe>
1e: 4e71 nop
I had calculated an access to the MFP m68901 every 15us with a 4MHz clock and what I had was 30us.. I found the "problem" the next day, the instruction timing sheets are for the m68000 with its 16bit data bus, a 68008 takes two memory cycles for each of m68000, therefore twice as long.
The simple makefile is here
#
#
#
#
#
#
#
CC = m68k-elf-gcc
AS = m68k-elf-as
AR = m68k-elf-ar
LD = m68k-elf-ld
OBJDUMP = m68k-elf-objdump
OBJCOPY = m68k-elf-objcopy
all : test.S19 test.dis
crt0.o : crt0.S Makefile
m68k-elf-gcc -c -o crt0.o -m68000 crt0.S
test.o : test.c Makefile
$(CC) test.c -o test.o -c -m68000 -fomit-frame-pointer
test.x : test.o crt0.o ldscript.ld Makefile
$(LD) -Map test.map crt0.o test.o -Tldscript.ld -v -nostartfiles -o test.x
test.S19 : test.x Makefile
$(OBJCOPY) -O srec test.x test.S19
test.dis : test.x Makefile
$(OBJDUMP) -d test.o > test.dis
crt0.dis : crt0.o Makefile
$(OBJDUMP) -d crt0.o > crt0.dis
download: test.S19
/media/disk/Projects/microrom/sw/microrom test.S19 -s -e512 -rl
clean :
rm *.o
rm *.x
rm *.dis
rm *.map
2 comments:
Thanks for this post.
This helped me starting with the software for my 68008 project. ;-)
Thanks for this post!
It helped me much with starting the software for my 68008 project! :-)
Post a Comment
Links to this post
Create a Link