This page explains the GDB dealing with the 68332, linker scripts, the crt0.S operation and a library called libmrm.a containing the basic functions needed by m68k-elf-gcc. The examples given here describes the situation on how to download programs to the mrm without cpu32bug dependencies. As the 68332 with m68k-bdm-elf-gdb gets reset and is being stopped right here, we have a situation where we are completely independent from any code from cpu32dbg. Which allows to write and debug a 68332 from a reset state. Since the gcc is dependent on some routines to I/O a new library libmrm.a has been written that does the same as libbcc.a but with no TRAP 15 to cpu32bug. The library support is undoubly incomplete: the source is included :-) The example programs should work.
The gdb will look for the .text segment in the result object file and download the code through the bdm to the 68332.
where the downloadBaseAddress is the start point of the code to be downloaded from the BDM. When the downloadBaseAddress is set to 0x0, it basically does the same as a 68332 reset sequence. The linker script described below does exactly this.
Therefore in order to make things to work, I slightly rewrote the Linker Script for the MRM. See the GNU LD Man pages for more information on the commands. Again, to use it change and experiment from my example, for deeper understanding follow the reference.
I'll explain the most important lines of the MRM Linker Script. The links point to the relevant sections of the GNU LD manual. The linker script is passed to the gcc compiler with the -T <filename> command line option.
STARTUP(crt0.o) OUTPUT_ARCH(m68k) /* Uncomment this if you want srecords. This is needed for a.out * if you plan to use GDB. OUTPUT_FORMAT(srec) */ SEARCH_DIR(.) SEARCH_DIR(../libmrm) GROUP(-lmrm -lc -lgcc) __DYNAMIC = 0;
The SEARCH_DIR tells the linker to add search directories for libraries, same as the -L option for the gcc. One search dir added is for libmrm.a. which (probably) resides in a different directory than the compiled program. The GROUP command does the same as the -l command of gcc.
The memory definitions are done with the MEMORY command as seen below. This is for an MRM with 512KB of memory.
/*
* Setup the memory map of the Mini RoboMind.
* stack grows down from high memory.
*
* The memory map look like this:
* +--------------------+ <- low memory
* | .text |
* | _etext |
* | ctor list | the ctor and dtor lists are for
* | dtor list | C++ support
* +--------------------+
* | .data | initialized data goes here
* | _edata |
* +--------------------+
* | .bss |
* | __bss_start | start of bss, cleared by crt0
* | _end | start of heap, used by sbrk()
* +--------------------+
* . .
* . .
* . .
* | __stack | top of stack
* +--------------------+
*/
MEMORY
{
ram (rwx) : ORIGIN = 0x0000, LENGTH = 0x80000
}
The following piece defines some symbols like __ram_start and __prog_start. __progstart is placed 1024 (0x400) bytes after the vector table. The stack is placed at the end of the RAM. The PROVIDE command exports the symbol so that the linker can use it in resolving or using it's address.
/* * allocate the stack to be at the top of memory, since the stack * grows down */ __ram_start = 0x0000; /* start of vector table */ __prog_start = __ram_start + 0x400; /* start of code after vectors */ __stack = 0x80000-4; PROVIDE (__stack = 0x80000-4);
See crt0.S stuff where they are executed. They must be initialized in case we don't provide them. The names speak for themselves.
/* * Initalize some symbols to be zero so we can reference them in the * crt0 without core dumping. These functions are all optional, but * we do this so we can have our crt0 always use them if they exist. * This is so BSPs work better when using the crt0 installed with gcc. * We have to initalize them twice, so we cover a.out (which prepends * an underscore) and coff object file formats. */ PROVIDE (hardware_init_hook = 0); PROVIDE (_hardware_init_hook = 0); PROVIDE (software_init_hook = 0); PROVIDE (_software_init_hook = 0);
The SECTIONS command tells the linker how to map the input sections into output sections, ... follow the link for the rest of the explanation. Here is my SECTIONS adapted for the MRM:
/*
* stick everything in ram (of course)
*/
SECTIONS
{
.text :
{
LONG(__stack); /* initial stack pointer at address 0x0 */
/* note: gdb uses this to init vbr */
LONG(__prog_start); /* initial PC counter */
. = . +(0x400-8); /* reserve space for vectors */
*(.text) /* default ENTRY point! */
Program code is stored from this point on.
Next follow a list for the C++ global constructors and destructors. The __INIT_SECTION__ and __FINI_SECTION__ are used by crt0.S to call the global constructors and desctructors
. = ALIGN(0x4);
__CTOR_LIST__ = .;
___CTOR_LIST__ = .;
LONG((__CTOR_END__ - __CTOR_LIST__) / 4 - 2)
*(.ctors)
LONG(0) /* end of list */
__CTOR_END__ = .;
__DTOR_LIST__ = .;
___DTOR_LIST__ = .;
LONG((__DTOR_END__ - __DTOR_LIST__) / 4 - 2)
*(.dtors)
LONG(0) /* end of list */
__DTOR_END__ = .;
*(.rodata)
*(.gcc_except_table)
. = ALIGN(0x4);
__INIT_SECTION__ = . ;
LONG (0x4e560000) /* linkw %fp,#0 */
*(.init)
SHORT (0x4e5e) /* unlk %fp */
SHORT (0x4e75) /* rts */
__FINI_SECTION__ = . ;
LONG (0x4e560000) /* linkw %fp,#0 */
*(.fini)
SHORT (0x4e5e) /* unlk %fp */
SHORT (0x4e75) /* rts */
_etext = .;
PROVIDE(etext = .);
*(.lit)
} > ram
.data :
{
copy_start = .;
PROVIDE(copy_start = .);
*(.shdata)
*(.data)
_edata = .;
copy_end = .;
PROVIDE(copy_end = .);
} > ram
.bss :
{
. = ALIGN(0x4);
__bss_start = . ;
*(.shbss)
*(.bss)
*(COMMON)
_end = ALIGN (0x8);
__end = _end;
} > ram
.stab 0 (NOLOAD) :
{
*(.stab)
}
.stabstr 0 (NOLOAD) :
{
*(.stabstr)
}
}
CRT stands for C Run Time. It contains the startup code and provide initialization for the C and C++ runtime. Before it calls main(),
There is a default, precompiled crt0.S in
/gcc-m68k/lib/gcc-lib/m68k-elf/3.3.1/../../../../m68k-elf/lib/mcpu32/crt0.o but it can be overridden by placing an own crt0.o file in the same directory. Adapting the crt0.S might be needed if one wants to initializes the 68332 in a very early stage. An example would be to disable the hardware watch dog. Note that currently the run332.gdb scripts disables the hardware watch dog. The best place to do so is around the start symbol (see crt0.S code snippet)
/*
* crt0.S -- startup file for m68k-coff
*
* Copyright (c) 1995, 1996, 1998 Cygnus Support
*
* The authors hereby grant permission to use, copy, modify, distribute,
* and license this software and its documentation for any purpose, provided
* that existing copyright notices are retained in all copies and that this
* notice is included verbatim in any distributions. No written agreement,
* license, or royalty fee is required for any of the authorized uses.
* Modifications to this software may be copyrighted by their authors
* and need not follow the licensing terms described here, provided that
* the new terms are clearly indicated on the first page of each file where
* they apply.
*/
#include "asm.h"
.title "crt0.S for m68k-coff"
#define STACKSIZE 0x4000
/*
* Define an empty environment.
*/
.data
.align 2
SYM (environ):
.long 0
.align 2
.text
/*
* These symbols are defined in C code, so they need to always be
* named with SYM because of the difference between object file formats.
*/
/* These are defined in C code. */
.extern SYM (main)
.extern SYM (exit)
.extern SYM (hardware_init_hook)
.extern SYM (software_init_hook)
.extern SYM (atexit)
.extern SYM(__do_global_dtors)
/*
* These values are set in the linker script, so they must be
* explicitly named here without SYM.
*/
.extern __stack
.extern __bss_start
.extern _end
/*
* set things up so the application will run. This *must* be called start.
*/
.global SYM (start)
SYM (start):
/*
* put any hardware init code here
*/
/* See if user supplied their own stack (__stack != 0). If not, then
* default to using the value of %sp as set by the ROM monitor.
*/
movel IMM(__stack), a0
cmpl IMM(0), a0
jbeq 1f
movel a0, sp
1:
/* set up initial stack frame */
link a6, IMM(-8)
/*
* zero out the bss section.
*/
movel IMM(__bss_start), d1
movel IMM(_end), d0
cmpl d0, d1
jbeq 3f
movl d1, a0
subl d1, d0
subql IMM(1), d0
2:
clrb (a0)+
#ifndef __mcf5200__
dbra d0, 2b
clrw d0
subql IMM(1), d0
jbcc 2b
#else
subql IMM(1), d0
jbpl 2b
#endif
3:
/*
* initialize target specific stuff. Only execute these
* functions it they exist.
*/
lea SYM (hardware_init_hook), a0
cmpl IMM(0),a0
jbeq 4f
jsr (a0)
4:
lea SYM (software_init_hook), a0
cmpl IMM(0),a0
jbeq 5f
jsr (a0)
5:
/*
* call the main routine from the application to get it going.
* main (argc, argv, environ)
* we pass argv as a pointer to NULL.
*/
#ifdef ADD_DTORS
/* put __do_global_dtors in the atexit list so the destructors get run */
movel IMM (SYM(__do_global_dtors)),(sp)
jsr SYM (atexit)
#endif
movel IMM (__FINI_SECTION__),(sp)
jsr SYM (atexit)
jsr __INIT_SECTION__
pea 0
pea SYM (environ)
pea sp@(4)
pea 0
jsr SYM (main)
movel d0, sp@-
/*
* drop down into exit incase the user doesn't. This should drop
* control back to the ROM monitor, if there is one. This calls the
* exit() from the C library so the C++ tables get cleaned up right.
*/
jsr SYM (exit)
The libmrm.a replaces the libbcc.a library found in the newlib package. I did so because the libbcc.a assumes that cpu32bug is already initialized. I didn't like that. This library defines a few functions which are needed by the libc and assume some kind of operating system. Since we use a maiden 68332 with no OS, most of then are empty and return 0 or return an error. Note that the Makefile used is a stripped version of a Makefile generated in newlib and must probably adapted if one installs a new compiler. The libmrm.tar.gz contains the *.c *.h *.S and libmrm.a.
The minimum stubs are found in the following files:
The files compile to a library named libmrm.a.
Note that you need yourself to supply the functions for outbyte() and inbyte() yourself.
Example can be found in the mrmtest-new.tar.gz