NMI on small Z80 computer, and where is RAM?

Discussion about other targets
Post Reply
hareti
New member
Posts: 7
Joined: Sat Jan 30, 2021 6:30 pm

NMI on small Z80 computer, and where is RAM?

Post by hareti »

Hi, I've built a small Z80 computer and I want to try programming it in C instead of the assembly that I have been using. I've got the z88dk compiler installed and working but I have two questions to get me started :

1) How do I tell the compiler where ROM and RAM are ? I see there is a command line option -zorg, but is there a way to set the start of ROM and RAM in the code ?

This leads on to my next question.

2) I need to implement an NMI handler. The wiki says "the best way to accommodate this mode is to include the NMI interrupt routine in the C startup code". There is nothing in the link that this points to. Is this C start up code part of the standard library ? I guess I could write my own startup code, but I need to be able to tell the compiler to put the NMI handler at 0x0066.

Any help is greatly appreciated.
User avatar
dom
Well known member
Posts: 2072
Joined: Sun Jul 15, 2007 10:01 pm

Re: NMI on small Z80 computer, and where is RAM?

Post by dom »

I've done a bit of digging and I think I know the documentation you are referring to. Lets rewind and go back to the start!

Unfortunately there are two different methods for adding support for a new machine in z88dk, the "classic" way and the "newlib" way. I suppose the key difference between them (from a user perspective) is that newlib provides the C standard library and any extra functionality is machine specific API, whereas classic provides the same C standard library and any extra functionality will preferentially sit behind a cross platform API rather than a machine specific API.

Personally, I find adding a target via newlib trickier than classic, however alvin wrote a guide in this thread here: https://z88dk.org/forum/viewtopic.php?f=3&t=10055

For me, classic is much easier - the Krokha I announced earlier today was just a handful of files. Unfortunately I've not written a guide on how to do it, well I have several times but they're not up-to-date, so it'll be a case of learning from examples.

For a (classic) ROM compilation, this might be a good crt file to look at: https://github.com/z88dk/z88dk/blob/mas ... d_crt0.asm

in that file you can see how all the rsts and interrupt entry points are handled. The code origin (CRT_ORG_CODE) defaults to 0x0000 and the RAM address can be shifted by changing CRT_ORG_BSS.

The equivalent of that in newlib is the +z80 target, it's documented here: https://github.com/z88dk/z88dk/wiki/New ... --Embedded - and has a few more features but they are broadly analogous.

I realise I may not have answered the questions in the way you asked them, if you let me know your machine details: memory addresses, ports, any firmware entry points, attached chips (graphics, PSG etc) I can setup a skeleton in a branch for you.
hareti
New member
Posts: 7
Joined: Sat Jan 30, 2021 6:30 pm

Re: NMI on small Z80 computer, and where is RAM?

Post by hareti »

Thanks for your detailed response.

Last night I did stumble upon the NewLib Platform Embedded document that you mentioned above. I managed to get it working but passing the -pragma-define:CTR_ORG_CODE= command line parameter has no effect on the code generated. This is the full command I am using :

zcc +z80 -vn -SO3 -startup=1 -clib=sdcc_iy test.c -o test -create-app

I think it's the ROM model that I need so I'm using startup=1.

I'll go through alvin's guide later today and see how I get on.

My system is super simple, it's the first one I've built so just wanted to see if I could get something working. For simplicity sake I split the address space down the middle so it has 32k of ROM and 32k RAM. It also has one input port and one output port at 0x00 and 0x01, and a parallel RTC at 0x02. The output port drives some LEDs and a serial display and the input port has some buttons on it.

I've got it reading from the RTC and showing the time on the display with the ability to set the time with the buttons, all done in assembly. I want to see if I can get this compiler working now.
hareti
New member
Posts: 7
Joined: Sat Jan 30, 2021 6:30 pm

Re: NMI on small Z80 computer, and where is RAM?

Post by hareti »

Hi again,

I managed to get the compiler working and it runs on my board.

I'm stuck on getting the NMI to work. I see in the interrupt documentation that there is no direct support for the NMI in z88dk and it must be included manually in the c startup code : https://www.z88dk.org/wiki/doku.php?id= ... rrupts#nmi

I've had a look through the z80_crt_0.asm.m4 startup file in libsrc->_DEVELOPMENT->target->z80 and I can see where the various sections are included. I can't figure out where in all this my NMI code should be included. I see there is a STARTUP section in the z80_crt_0 file, but the NMI code has to be placed at 0x0066. I can put code in this STARTUP section, but it appears at address 0x0000. Adding .org 0x0066 just results in compile errors.

Am I looking in the right place ?
User avatar
dom
Well known member
Posts: 2072
Joined: Sun Jul 15, 2007 10:01 pm

Re: NMI on small Z80 computer, and where is RAM?

Post by dom »

hareti wrote: Tue Feb 02, 2021 5:02 pm Hi again,

I managed to get the compiler working and it runs on my board.

I'm stuck on getting the NMI to work. I see in the interrupt documentation that there is no direct support for the NMI in z88dk and it must be included manually in the c startup code : https://www.z88dk.org/wiki/doku.php?id= ... rrupts#nmi

I've had a look through the z80_crt_0.asm.m4 startup file in libsrc->_DEVELOPMENT->target->z80 and I can see where the various sections are included. I can't figure out where in all this my NMI code should be included. I see there is a STARTUP section in the z80_crt_0 file, but the NMI code has to be placed at 0x0066. I can put code in this STARTUP section, but it appears at address 0x0000. Adding .org 0x0066 just results in compile errors.

Am I looking in the right place ?
If you define CRT_ENABLE_NMI=2 then I think you just need to implement a function named _z80_nmi() - the only thing placed at 0x0066 is a jp _z80_nmi(). So you could place it in the code_user section for example in assembler file within your project - no need to mess around with the crt files.
hareti
New member
Posts: 7
Joined: Sat Jan 30, 2021 6:30 pm

Re: NMI on small Z80 computer, and where is RAM?

Post by hareti »

OK, I've defined a function in my code called _z80_nmi() and set defc TAR__crt_enable_nmi = 1 in crt_config.inc

Now when I compile I get the error symbol '_z80_nmi' not defined from file crt_page_zero_z80.inc

Where do I define the interrupt function so that that the compiler or linker can find it ?
User avatar
dom
Well known member
Posts: 2072
Joined: Sun Jul 15, 2007 10:01 pm

Re: NMI on small Z80 computer, and where is RAM?

Post by dom »

As a quick example (no changes to CRT files at all):

Code: Select all

// main.c
int main() {
    return 0;
}

Code: Select all

; nmi.asm
        SECTION code_user

        PUBLIC  _z80_nmi

_z80_nmi:
        push    hl
        pop     hl
        retn
Compile with:

Code: Select all

zcc +z80 nmi.asm main.c -pragma-define:CRT_ENABLE_NMI=1 -m
Disassemble:

Code: Select all

z88dk-dis -x a.map a_CODE.bin

...
                    jp      _z80_nmi                        ;[0066] c3 73 01
...
_z80_nmi:
                    push    hl                              ;[0173] e5
                    pop     hl                              ;[0174] e1
                    retn                                    ;[0175] ed 45
hareti
New member
Posts: 7
Joined: Sat Jan 30, 2021 6:30 pm

Re: NMI on small Z80 computer, and where is RAM?

Post by hareti »

That works, thanks very much for your help.
hareti
New member
Posts: 7
Joined: Sat Jan 30, 2021 6:30 pm

Re: NMI on small Z80 computer, and where is RAM?

Post by hareti »

So I don't know whether I am losing my mind, but I've run into another problem.

I made a copy the folder with the working interrupt code and started adding in the rest of my code to this, but now the nmi interrupt doesn't work. Looking at the disassembled code, 0x0066 now jumps to a function called l_retn. The _z80_nmi label and code is still there in the disassembly, but it looks like nothing points to it now.

Code: Select all

                    jp      l_retn                          ;[0066] c3 fa 00

 ...
 
 l_retn:
                    retn                                    ;[00fa] ed 45

...

_z80_nmi:
                    push    af                              ;[0139] f5
I copied the folder again so its contents is identical to the original working test, but I still get the same result even though they are identical apart from the c file name, and are complied with exactly same options. One works, the other doesn't.

Code: Select all

zcc +z80 -startup=1 nmi.asm nmi_test.c -pragma-define:CRT_ENABLE_NMI=1 -m -create_app
What on earth have I done ?
User avatar
dom
Well known member
Posts: 2072
Joined: Sun Jul 15, 2007 10:01 pm

Re: NMI on small Z80 computer, and where is RAM?

Post by dom »

hareti wrote: Thu Feb 04, 2021 5:30 pmWhat on earth have I done ?
I'm wondering if you're using a z88dk from before June last year. Do you have a zcc_opt.def file in the broken directory? If so delete it.
hareti
New member
Posts: 7
Joined: Sat Jan 30, 2021 6:30 pm

Re: NMI on small Z80 computer, and where is RAM?

Post by hareti »

Not sure which version I was using. I've downloaded the latest nightly build and it's working fine now. Thanks again.
Post Reply