Showing posts with label gnucross. Show all posts
Showing posts with label gnucross. Show all posts

2010-11-21

making gdb-stub work from rom

Well after some long break I'm back on the m68k... I had time to draw some of the schematics of the circuit, only the CPU and most of the support circuitry. The rest of the circuit is straight forward, I connected my EPROM emulator and a massive 512K bytes SRAM to the bus and finally a MC68901 Multi Function Peripheral (MFP) handling the serial port and SD card interface. The CPU clock is at the moment 4MHz, so I can share it with the MFP, later I intend to clock the CPU at 8MHz.
Since my previous post, I've done/settled on a couple of things:
  1. I'll use gcc and gdb to do get the system up and running. Currently I managed to compile gcc-3.4.6 for target m68k-elf and gdb-6.8;
  2. I've created basic linker scripts for running from ROM and running from RAM. Both have been proven to work with C source (C++ probably won't work). I've also created two CRT0.S for each of these linker scripts;
  3. Compiling the gdb-stub and link it to ROM proved a big challenge, but I managed in the end. The source m68k-stub.c that comes with gdb suffers from severe bit rot, most of the assembly source doesn't compile either because the syntax is no longer supported or because "handling multi line strings has changed in 2001";
  4. Still doesn't work perfect, the first time I load, break main and continue, remote-gdb ends up "somewhere", on the second time I load and continue (no need to break main, this is handled by the server) it works OK and I can even step lines of code. This probably has to do with my "trick" to make gdb-stub work from ROM without referencing any program at all (the frame information is not correct... I think...). On the second run (after the initial crash), this frame is correctly initialized.
  5. I'll add a 3V power supply and a SD Card interface for "disk drive", based on some previous work I did with the Arduino, I don't expect big difficulty.
  6. Placing the vectors in memory was actually quite easy, I needed to learn some m68k assembly and now I do it in CRT0.S. Due to a requirement of the gdb-stub to identify the generated exception, I had to build a two step exception processing. First the vectors 0 to 256 are initialized to unique locations starting at 0x400 in steps of 8. On each of these, 8 bytes there's a NOP and a Jump to Sub Routine long to the exception_handler, this pushes a unique address per exception on to the stack, the exception_handler pops this address and identifies the exception that was generated.
I had a old monitor that I "pop" from storage, to test dual head with openSUSE 11.2 and it works great. I really think it's a great advantage to work with two monitors, one for programming other for debugging or one for drawing the circuit and the other to check the PCB, Bill of Materials, Stocks, vendors, spreadsheet, etc.
Another thing I noticed is that I still can't get away from printouts of the code.. and I wish I had an old matrix printer with form paper... those were the days...

2010-03-22

mini68k adding libraries and serial port

I admit I haven't been very focused at my hobbies, but that's life. I've been working here and there: getting the Arduino and the SHT11 working together (see here for library), converting a metal-gear servo to continuous rotation (I followed this how-to), trying to design a photodiode amplifier (I'm following this, this and what is available from this), debugging the SolarLight project and working on the schematics of the mini68k and finally getting some code running on it.
I've been feeling a bit more confident with gcc-m68k and I've been increasing the complexity of the programs. I managed to link in the gcc library (libgcc), I tried out the -msoftfloat option (compile, I didn't check the results of a floating operation yet) and I created my own putc and getc functions using the USART of the MC68901 (MFP) in pooled mode.
I want to change my CRT0.S to include some hardware support functions before main() is run. Initialize the interrupt vectors (pointing to a "interrupt error" routine), printing some console message during initialization and doing some hardware test (RAM, MFP).
I'm still unsure of a few things:

  • An interrupt level 7 is basically a NMI, my system switches from ROM to RAM at the 8th clock, at the 9th clock if a NMI is pending the CPU will jump to an uninitialized vector! I must read the specs again but I think this could be a problem. Or not, if the system is int7 incapable (IPL2/0 or IPL1 permanently to 1) or has a gate enabling interrupts;
  • the MFP interrupt is physically enabled (i.e. connected to the CPU or gated by self for example)? (see point above), how does gcc link to interrupts (newer gcc versions work well ex. AVR-gcc), how do I place the vectors in memory?;
  • I want to build a gdb-stub/rom monitor, will it handle the vector allocation/writing? If so, my operating system (loading from somewhere ROM or disk) will also be in supervisor mode? (and also handle these?);
  • Can/Should I implement some sort of memory protection (writes to first 1K-vectors and last 1K-SupervisorStack of RAM must be made in supervisor mode)?;
  • For the end project of a CP/M 68k what type of media do I use? Going back to floppies would be definitely cool but I'm sure I would need some sort of DMA as I don't think the 68000 is fast enough (and surely not at the current speed of 4MHz). With SD I'd use only a few I/O pins (from the MFP?) but some SD cards are only 3.3V and my system runs at 5V. Or I could use a Compact Flash card, most can work at 5V, and it is easy to get some old CF cards (64/128MB) or even a IBM microdrive I've found once here; I would need to build two 8bit ports (A output to control the drive, B for bidirectional data) and this is breadboard space...
  • I would also like to "upgrade" the logic circuits to one of the M4A5-32/32 I've build an adaptor for and change the DTACK circuit to actually drive the line when releasing the bus (until AS goes high).
Well for now that is a still a lot of work in progress, I doubt Spring and/or Summer will allow me more time but I'm trying to keep you posted.

2010-02-27

Das Blinklicht with gcc-elf-m68k

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".

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.

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.

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

2010-02-10

Next Project Minimal CP/M 68k

The Solarlight project has been taking more than normal, but the truth is I haven't had much time lately...so I decided to announce my next project, revive a minimal CP/M-68k system and document the process. The main components are a MC68008 CPU, a MC68901 MPU, 512K of SRAM, 32k EPROM, and a IDE/ATA connector. The MPU (multi-peripheral unit) will serve as UART and probably as basic memory manager, the IDE interface will probably be based in GIDE or something similar. While I'm still working on the schematics, I've already built the base circuit from my hand written schematics... here's a picture.

The sources and documentation of the code are available in Gaby's site. This site used the sources to build a VAX version, so the sources appear not to have suffered from too much of "bit rot".
For cross compiling and debugging I'll try to use binutils/gcc/gdb in remote mode. I'll try to build the cross tools (elf format, coff has been since long time killed) and a remote gdb-stub to download and debug some initial code... we'll see how it goes..
Here I've already built the cross-compiler toolchain for m68k-elf (binutils-2.20, gcc-core-3.4.6, gdb-6.8 and newlib 1.18.0), I didn't use a more recent one because from searching gcc-3.x.x is easier to cross compile with the newlib, and I wanted to use a smaller libraries than libc.
Download the sources from the gnu ftp site (except for newlib that is here), I followed this guide because not only it appeared simpler (no "bootstrap compiler" step) but also it is dedicated to embedded systems. Don't forget to move newlib and libgloss inside the gcc directory and after the binutils compile put them in the path. I also used gnu gdb instead of insight but no other than that.
Finally set the path in your .profile for your convenience, see here for details on OpenSuse.
My first objective after building the system on a breadboard is to download a small m68k assembly program to the EPROM EMULATOR and see it run, then a small C program and finally a gdb-stub. Then I'll have to repeat the process since from that point on there must be a change in the linker file as programs stop being linked to ROM but linked to RAM.
I've successfully assembled a "loop:nop,nop,bra.s loop" but a few problems or "unknowns" remain...
I've created my simple assembly file called test.S

/*
* test.S -- test file for assembler output
*/

#include "asm.h"
.title "test.S - test file for assembler output m68k-elf-as"
#define STACKSIZE 0x4000

.data

.text

.extern __stack

.global SYM (_start)
SYM (_start):
nop
nop
bra.s _start

I assemble it with "m68k-elf-gcc -c test.S -o test.o" then link it still with gcc "m68k-elf-gcc test.o -o test.x -nostartfiles -nostdlib -v -fpic -WL,Ttest.ld"
I had to include the -nostartfiles and -nostdlib to remove the standard crt0 and the global constructors for C++.
My current linker file is very simple and probably some things are missing for a full C program compilation but for now things appear to be ok.

/* ld file for rom programs */
/* for 8 cycles rom is at 0x00000 (fetch SP and PC), from then on 0x80000
/* STARTUP(crt0.o) - no startup file*/
OUTPUT_ARCH(m68k)
OUTPUT_FORMAT(srec)
SEARCH_DIR(.)
/*
*Setup the memory map of mini68k, stack grows down from high memory.
*/
MEMORY {
ram (rwx) : ORIGIN = 0x01000, LENGTH = 0x80000-0x01000
rom : ORIGIN = 0x80000, LENGTH = 64K }
/*
* allocate the stack to be at the top of memory, since the stack
* grows down, also PUSH => -(SP) = xx, i.e. predecrement therefore
* first stack address never gets written
*/

PROVIDE (__stack = 0x80000);

SECTIONS
{
.text :
{
_stext = .;
*(.text .text.*)
. = ALIGN(0x4);
_etext = .;
} > rom

.data :
{
*(.data .data.*)
_edata = .;
} > ram

.bss :
{
. = ALIGN(0x4);
__bss_start = . ;
*(.bss .bss.*)
_end = ALIGN (0x8);
__end = _end;
} > ram
} /* missing in the initial file - causes an error ld does not complain! - beware */

Then I can also successfully convert the object file test.x to a SRECORD file with the command "m68k-elf-objcopy -O srec test.x test.S19" and then revert the intermediate object file test.x to assembler with "m68k-lef-objdump -d -X test.x > test.dis"
After successfully removing all the initialization code gcc attaches to your code (with -nostartfiles -nostdlib(p.s. you only need the first one since you don't add any library function)) I was left with one question, why is my code placed at absolute address 0x80000054?? when I told in the linker file to put it at 0x80000 (less a few zeros in the middle) Here is the disassembly:

test.x: file format elf32-m68k

Disassembly of section .text:

80000054 <_start>:
80000054: 4e71 nop
80000056: 4e71 nop
80000058: 60fa bras 80000054 <_start>

Ok, this was a bug. I forgot a } in the memory definitions of the linker file *.ld... After adding it the code was located at the correct place 0x80000.
Well there are still some hurdles to overcome, namely:
- placing the start SP and start address in vectors 0 and 1;
- place the other vector in ram
- place the code in proper ROM addresses (and the initial SP,PC)
- download the code and see it run...
... the path through cross-gcc appears to be hard ...