09 May 2017, 07:14 | #1 |
Registered User
Join Date: Dec 2016
Location: USA
Posts: 101
|
Amiga 'Jumpstart' example?
I found an old Stackoverflow post about writing a 68K operating system as an educational exercise. Someone suggested using the Amiga hardware as a base since it's pretty easy to work with and well-documented since everyone twiddles the hardware directly to do anything cool anyway. It seems like a fun little project.
It can be easily done by writing a replacement ROM and loading it into WinUAE as the boot ROM. Unfortunately the example code in the link on that page (which blinks the power LED and plays with the screen colors) seems to have disappeared. Long shot, but did anyone here save a copy of it? |
09 May 2017, 18:45 | #2 |
Registered User
Join Date: Feb 2017
Location: Denmark
Posts: 1,099
|
I don't have the original code, but the following should do the same:
Code:
; Assemble with vasm -phxass -x -Fbin -o rom.bin rom.s ; Supply rom.bin to Winuae with e.g. -s kickstart_rom_file="%CD%\rom.bin" org $fc0000 ; System ROM image location custom=$dff000 bplcon0=$100 color00=$180 ciaa=$bfe001 pra=$000 ddra=$200 ; The ROM is mapped at $000000 on startup shadowing RAM rom_start: dc.l 0 ; Initial SP dc.l rom_code ; Initial PC rom_code: move.l #custom, a0 ; a0 = custom move.l #ciaa, a1 ; a1 = ciaa move.b #3, ddra(a1) ; Set port A direction to output for /LED and OVL move.b #0, pra(a1) ; Disable OVL (Memory from $0 onwards available) move.w #1<<9, bplcon0(a0) ; BPU=0, COLOR=1 .l: bchg.b #1, pra(a1) ; Blink LED move.w d0, color00(a0) ; Change background color addq.w #1, d0 moveq #-1, d1 .delay: dbf d1, .delay bra.s .l Code:
; init.s XREF _kmain section init,code ciaa=$bfe001 pra=$000 ddra=$200 ; The ROM is located at $fc0000 but is mapped at $000000 afer reset shadowing RAM rom_start: dc.l $10000 ; Initial SP dc.l rom_code ; Initial PC rom_code: move.b #3, ciaa+ddra ; Set port A direction to output for /LED and OVL move.b #0, ciaa+pra ; Disable OVL (Memory from $0 onwards available) jmp _kmain Code:
/* boot.c */ typedef unsigned char UBYTE; typedef unsigned short UWORD; typedef unsigned long ULONG; #define COLORS ((volatile UWORD*)0xdff180) #define VPOS ((*((volatile ULONG*)0xdff004) >> 8) & 0x1ff) #define CIAAPRA *((volatile UBYTE*)0xbfe001) void kmain(void) { for (unsigned short c=0;;++c) { // Blink LED every 16th frame if ((c&15)==0) CIAAPRA ^= 2; // Change background color COLORS[0] = c; // Wait for VBLANK while (VPOS != 10) ; while (VPOS == 10) ; } } Code:
/* rom.ld */ SECTIONS { . = 0xfc0000; /* System ROM image location */ .everything: { *(init) *(CODE) *(DATA) *(BSS) } } Code:
vbccm68k.exe -c99 -warn=-1 -dontwarn=168 -dontwarn=81 -maxerrors=0 -speed -O=1023 -o=boot.s boot.c vasmm68k_mot_win32.exe -phxass -x -Fhunk -o init.o init.s vasmm68k_mot_win32.exe -phxass -x -Fhunk -o boot.o boot.s vlink.exe -Trom.ld -brawbin1 -o rom.bin init.o boot.o Last edited by paraj; 09 May 2017 at 21:20. |
09 May 2017, 21:35 | #3 |
Registered User
Join Date: May 2017
Location: Sao Paulo
Posts: 17
|
Hi guys. Additionally, if you plan to use interrupt routines, make sure that the binary image is exact 256K or 512K and the last 7 words in "ROM" are "0019 001a 001b 001c 001d 001e 001f":
At offsets $3fff0 - $3ffff for a 256K ROM. At offsets $7fff0 - $7ffff for a 512K ROM. Otherwise exception handling will not work as expected. Not sure how to define that in the linker script. |
10 May 2017, 00:54 | #4 | |
Defendit numerus
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
|
Quote:
For the casual reader: the last 7 words in 68k mem address space was an indices in exception table, counting from $0. Normallly vector number $19->location $64 was Autovector Interrupt Level 1, $1A Autovector Interrupt Level 2 and so on to Level 7 (NMI IRQ, $1F). So explained the 'strange' value in ROM. (I'm not sure about Spurious Interrupt Vector ($18), some kickstarts seems to set it, but i don't think Amiga can generate spurious interrupt..) You can potentially change this values, but all you know about Amiga [interrupts management] does not work anymore Bye, ross Last edited by ross; 10 May 2017 at 01:22. Reason: [] |
|
12 May 2017, 23:31 | #5 | ||
Natteravn
Join Date: Nov 2009
Location: Herford / Germany
Posts: 2,496
|
Just add this:
Code:
. = 0xfffff0; .vecs: { *(vectors) } For "vectors" just take something like this: Code:
section vectors,data dc.w $18,$19,$1a,$1b,$1c,$1d,$1e,$1f Quote:
Quote:
A more sophisticated approach is to define memory regions. Put the data and BSS into RAM and the code and constants into ROM. Like this: Code:
MEMORY { RAM: org=0, len=0x80000 ROM: org=0xfc0000, len=0x3fff0 VEC: org=0xfffff0, len=16 } SECTIONS { .rom: { *(CODE) } >ROM .data: { *(DATA) } >RAM AT>ROM .vecs: { *(vectors) } >VEC .bss (NOLOAD): { *(BSS) } >RAM } That's quite interesting. I know about these vectors in the Amiga ROM, but I never really understood how they are used. There is no code in the ROM which uses them, AFAIK. Anybody knows more? |
||
12 May 2017, 23:47 | #6 | ||
Defendit numerus
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
|
Quote:
Quote:
Cheers, ross |
||
13 May 2017, 00:23 | #7 |
Defendit numerus
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
|
Interesting!
Spurious Interrupt. During the interrupt acknowledge cycle, if no device responds by asserting DTACK or AVEC, VPA, BERR should be asserted to terminate the vector acquisition. The processor separates the processing of this error from bus error by forming a short format exception stack and fetching the spurious interrupt vector instead of the bus error vector. The processor then proceeds with the usual exception processing. So in a really compromised machine (with no device that acknowledge interrupts) a spurious can be generated! Maybe usefull for some DiagROM code |
13 May 2017, 02:44 | #8 |
Defendit numerus
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
|
Ok, a compendium for the sequence of events during an interrupt (some info from Exec_Interrupts, some from Motorola Manual, some from my deduction).
Long post. When a hardware device decides to cause an interrupt sends a signal to the interrupt control portions of the 4703 (Paula) custom chip. The 4703 interrupt control logic notices this new signal and performs two primary operations. First, it records that the interrupt has been requested by setting a flag bit in the INTREQ register. Second, it examines the INTENA register to determine whether the corresponding interrupt and the interrupt master are enabled. If both are enabled, the 4703 generates an interrupt request by placing the priority level of the request onto the three 68000 interrupt control input lines (IPL0, IPL1, IPL2). These three signals correspond to seven interrupt priority levels in the 68000. If the priority of the new interrupt is greater than the current processor priority the processor acknowledges the interrupt and initiates processing. Interrupt level 7 is edge-triggered. On the other hand, the interrupt levels 1 to 6 are level sensitive. But as soon as the status register (SR) is saved the processor updats its interrupt mask to the same level. Value in SR disables all interrupts below or equal to I2/1/0. Once the 68000 has decided to ACK an interrup request, it pushes PC and SR to stack, enter supervisor mode, inhibit tracing, updates the priority mask bits and also the address lines A3-A1 with the interrupt level. Then assert AS to inform the external device that A3-A1 has the IRQ level and sets FC2/1/0 to 111 to run an IACK cycle for 8bit vector number acquisition. The 68000 multiplies the 8bit vector by 4 to determine the pointer to locations containing the starting address of the service routine. External logic can respond to interrupt acknowledge in one of the following ways: by requesting automatic vectoring or by placing a vector number on the data bus (nonautovector) or by indicating that no device is responding (spurious interrupt). [If the hardware asserts VPA to terminate the IACK bus cycle, the 68000 directs itself automatically to the proper interrupt vector corrisponding to the current interrupt level.] In nonautovector situation, the interrupting device uses external hardware to place a vector number on data lines D0-D7, and then performs a DTACK handshake to terminate the IACK bus cycle. The user vector number allowed are $40 to $FF, but Motorola has not implemented a protection on the first entries so that user-interrupt vectors may overlap at the discretion of the system designer. In Amiga seems that (clever!) designers used A3-A1 (with others Ax lines tied to 1) to address [FFFFF(16)]A3A2A1[1(2)] (so the odd address) in ROM and select in data line D7-D0 the vector number. So Amiga is a nonautovector machine using autovector indices making possible all the 4703 IRQ subpriority. Exec must now further decode the interrupt by examining the INTREQ and INTENA 4703 chip registers. Once the active interrupt has been determined, Exec indexes into an ExecBase array to fetch the interrupt's handler entry point and handler data pointer addresses. Exec now turns control over to the interrupt handler by calling it as if it were a subroutine. This handler may deal with the interrupt directly or may propagate control further by invoking interrupt server chain processing. Some hardware expert can confirm? Cheers, ross |
13 May 2017, 12:19 | #9 |
WinUAE developer
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 49
Posts: 26,505
|
Yes, thats correct, Amiga uses non-autovector mode. ("In nonautovector situation" part)
|
13 May 2017, 15:25 | #10 |
Defendit numerus
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
|
Thanks Toni.
So You can fill $FFFFF0with: Code:
dc.w $4118,$5219,$4F1A,$531B,$201C,$361D,$381E,$6B1F A R O S 6 8 k |
13 May 2017, 16:16 | #11 |
WinUAE developer
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 49
Posts: 26,505
|
Yeah, even bytes are unused
|
13 May 2017, 16:37 | #12 |
Defendit numerus
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
|
mmh, about all this ROM indices, there is something missing in AROS code:
AROS/arch/m68k-amiga/boot/romcheck.c near line 152: Code:
p = (uint8_t*)rom + len - 16; for (i = 0; i < 7; i++) { p[i * 2 + 1] = i + 0x18; p[i * 2 + 0] = 0; } Code:
for (i = 0; i <= 7; i++) { Bye! ross |
13 May 2017, 18:10 | #13 | |
Natteravn
Join Date: Nov 2009
Location: Herford / Germany
Posts: 2,496
|
Quote:
I always wondered why the Amiga didn't just use autovector-mode, as it doesn't use any interrupt vectors outside the autovector range (in contrast to the Atari ST, for example). |
|
13 May 2017, 18:37 | #14 |
Registered User
Join Date: May 2017
Location: Sao Paulo
Posts: 17
|
I just read the chapters about "interrupt acknowledge cycles" in all M680x0 User´s Manuals and it seems that only the 68000, 68010, 68020 and 68030 set the interrupt level in A1-A3 and drive A0, A4-A31 address lines high. The 68040 and 68060 drive all address lines high.
I wonder how an 040 or 060 equipped Amiga can still work. It would always read the vector number $1f from $ffffffff. Maybe turbo cards make use of autovector mode. Does anyone know some details? |
13 May 2017, 20:52 | #15 | |
Defendit numerus
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
|
Quote:
|
|
13 May 2017, 21:13 | #16 |
WinUAE developer
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 49
Posts: 26,505
|
It is also very cheap, no extra hardware needed
|
13 May 2017, 21:37 | #17 | |||
Defendit numerus
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
|
Quote:
In AROS source even only 68000 and 68010 are marked for ROM 'indices' use. But something interesting in 060 manual: Transfer Cycle Modifier (TM2–TM0). These three-state outputs provide supplemental information for each transfer cycle type. For interrupt acknowledge transfers, the TMx signals carry the interrupt level being acknowledged. So a 1:1 map of A3-A1.. Quote:
Quote:
Last edited by ross; 13 May 2017 at 21:51. Reason: better quoting... |
|||
13 May 2017, 22:21 | #18 |
WinUAE developer
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 49
Posts: 26,505
|
I haven't really examined what 68020+ do but I have always assumed it is 68000/010 only feature.
I just did quick test with ACA500plus and 68060, 68030 and 68020 A1200 accelerators + custom flashed KS 3.1 ROM image with last 16 bytes erased. It still worked fine. (Except in 68000 mode) |
14 May 2017, 20:28 | #19 |
Registered User
Join Date: Jan 2017
Location: Den Haag / Netherlands
Posts: 193
|
Is there someone who has a full working copy of this and willing to share (through github)? I find this quite interesting (especially the version with c in it).
|
14 May 2017, 21:00 | #20 |
Registered User
Join Date: Feb 2017
Location: Denmark
Posts: 1,099
|
I can clean up my quick-and-dirty code and include the suggestions from the interesting discussion upthread if you want. What compiler/assembler/etc. are you using?
|
Currently Active Users Viewing This Thread: 1 (0 members and 1 guests) | |
Thread Tools | |
|
|