[ << ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
(C) 2001 - Tom Walsh - tom@openhardware.net - all rights reserved.
Building absolute, ROM-able, code is an advanced topic and you can easily make mistakes. Probably the best way to build such code is to "breakpoint" the code, either with a debugger (ICE), or by printing critical address values out a serial port to a console. On my DragonBall design, I will print a signaling character out the serial port during the boot process, then place the processor in a forever loop (die: bra die). Once I get the indication that I have encountered my "breakpoint", I then invoke the BDM mode on the board and examine the memory contents using a kermit script. I am available to give instruction on the topic of embedded programming, please contact me for details.
First of all, my system memory map is this:
|----------|- 0xffffffff | | | UNUSED | | | |----------|- 0x10007fff | | | 32K | | EPROM | | | |----------|- 0x10000000 | | | UNUSED | | | |----------|- 0x0203ffff | | | COMPACT | | FLASH | | | |----------|- 0x0201ffff | | | ETHERNET | | | |----------|- 0x02000000 | | | UNUSED | | | | | | UNUSED | | | |----------|- 0x007fffff | | | 8M DRAM | | | |----------|- 0x00000000 |
Looking at the loader code, let’s examine the criteria for allowing the boot code to run: 1) .text section must be located (linked) at a physical address, that is within the PROM, so that we can make calls to functions that we have written and the code we "land" on is the expected code. 2) .data section must be located within volatile storage (RAM) so that we can operate upon it, and we have to initialize the contents of that RAM so stuff like: ’char it[] = "here I am";’ will work. 3) .bss section must also be located within volatile RAM so it can be modified, but unlike the .data section, we must ZERO the contents of the .bss section (this is expected of us). bss variables are those which have no initialization: ’char it [80];’. 4) .const section (IF ANY) we don’t need to worry about as it should be placed within the .text section by default, if we don’t explicitly mention it in the .ld file.
move.l #0x2000000, %d0 ; Point to the Ethernet chip. move.l %d0, %a0 wiggle: move.b (%a0), %d0 ; Access CSB0 (pin 55). bra wiggle ; DO NOT JUMP! Keep it relative! |
BTW. If you haven't written your own `crt0.S' file (my case: boot.S), then you will be in big trouble attempting to construct a bootloader! Boot code has a radically different startup sequence than that of the stock `crt0.o' files you write applications against. The boot.S file can simply be something like:
#define ASSEMBLY .text bra main exit: bra exit |
I would only advise expert C coders to build their initialization code in C!!! To ensure that any instructions that gcc emits are relative branches, prior to the initialization of the chip selects, you would have to dump the gcc output into an assembly source file, then read the source and look for gotcha’s like an absolute jump instruction. A word about initializing chip selects, always initialize your ROM (Flash, EPROM, etc) that contains your boot code first, that way you don’t activate, say DRAM, and collide with CSA0 that is still configured to activate everywhere!
For example, my bootstrap.ld:
MEMORY { ram : ORIGIN = 0x00200000, LENGTH = 0x0001FFFF flash : ORIGIN = 0x10000000, LENGTH = 0x007FFFFF dram : ORIGIN = 0x0021FFFF, LENGTH = 0x000E0000 eram : ORIGIN = 0x007FFFF0, LENGTH = 1 } SECTIONS { .text : { _stext = . ; *(.text) _etext = . ; __data_rom_start = ALIGN(4); } > flash .data : { _sdata = . ; *(.data) _edata = . ; } > ram .bss : { _sbss = . ; *(.bss) *(COMMON) _ebss = . ; } > ram .eram : { _ramend = .; } > eram } |
1. The first 1 Megabyte of data (linux kernel) is pulled out of the Compact Flash and loaded into DRAM starting with address 0x0.
2. Then the kernel is jumped to at location 0x400, the code at location 0x400 in the kernel is the beginning of my crt0_cf.S file from arch/m68knommu/platform/68EZ328/ez328lcd/. Knowing that the first 1+ Meg of DRAM is going to be used to hold the data loaded from the CF drive, I start my boot.S RAM usage for the .data + .bss sections at 0x200000. This should give me plenty of room to let future kernels "grow". The .text section contains any .const data + bootloader code, so that can stay in ROM at location 0x1000000 (this is where the CSA0 was finally set for).
These two key sections of the linker .ld file, MEMORY + SECTIONS, are exactly what they infer: The MEMORY dictates a memory mapping of regions of the machine and give symbolic names. The SECTIONS area dictates where the sections (.text, .const, .data & .bss) are to be placed, and in what order within each SECTION. FLASH: .text section is all sections (named by gcc) to have *(.text) , or anything.text in its section name, to be placed within the MEMORY location I arbitrarily named this area flash. The flash SECTION is MEMORY mapped into 0x1000000..0x1007fff. NOTE that I also have placed some symbols, _stext + _etext, within the flash SECTION? Those symbols can also be resolved by the linker and I can (and do) refer to some of those symbols in my boot.S code.
RAM: is the next two SECTIONS, the same situation as explained in the CODE above. NOTE that the ram MEMORY area is first filled with the variables from the .data section then it is "filled" with the .bss section.
ERAM: this is to set the symbol _ramend so that I can refer to it in boot.S to set the processor stack to the top of DRAM.
boot.bin: bootstrap.coff $(OBJCOPY) -O binary --remove-section=.data --remove-section=.bss \ bootstrap.coff boot.text $(OBJCOPY) -O binary --remove-section=.text --remove-section=.bss \ bootstrap.coff boot.data cat boot.text boot.data > boot.bin |
m68k-coff-objcopy -O binary bootstrap.coff boot.bin |
moveal #_sbss, %a0 moveal #_ebss, %a1 /* Fill .bss with ZEROs until %a0 == %a1 */ L1: movel #0, %a0@+ cmpal %a0, %a1 bhi L1 /* Copy data segment from ROM to RAM */ moveal #__data_rom_start, %a0 moveal #_sdata, %a1 moveal #_edata, %a2 /* Copy %a0 to %a1 until %a1 == %a2 */ L2: movel %a0@+, %d0 movel %d0, %a1@+ cmpal %a1, %a2 bhi L2 lp: |
[ << ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |