Question

I've started writing a boot loader for my z80 system. So far the program can accept hex via serial and load it to a location in the memory.

The problem I have though is the boot loader is at the start of memory and uses the interrupts, How can I load a new program with out overwriting the boot loader?

(Also a loaded program might want to use the interrupts as well)

Was it helpful?

Solution

The best and most widely used approach is to split your app into a stable boot loader that is never updated, and the application that you can replace from time to time.

AFAIK, in Z80 there are just interrupt vectors and there no support for replacing them in the CPU itself. You need to have something in your hardware that will replace your memory blocks.

Othewise you need to have feature that bootloaders is not using anything in the app part during the download and block any interrupts that can call anything in the app.

OTHER TIPS

W.r.t. locations, you may place the bootloader at the top of the address space and load a program at the beginning of the address space.

You can also include the location and size of the program in the protocol so the bootloader would be able to check whether the pair of values is compatible with the bootloader location and size (IOW, whether or not the program would overwrite the bootloader if loaded).

Another option is to include relocation information in the program and a simple relocator in the bootloader. That way you'd be able to load the program at any location if there's enough free memory. This is what many OSes do when they load programs.

As for the interrupts, I don't see a problem. Who or what is there not to allow the program to use interrupts? Or do you want the bootloader to say resident and either continue to do something in the background or be able to return to it from the program? If you don't need any of these, just let the program use the interrupts (you probably don't even need to do anything to allow that).

If, OTOH, you do want the bootloader to remain functional you can introduce an extra layer of indirection by maintaining an additional interrupt vector table. The primary ISRs would extract the secondary ISRs from this interrupt vector table and jump there. Your bootloader and program would then need to do this in order to add a new or override an existing ISR:

  1. disable interrupts
  2. get the old ISR address from the additional interrupt vector table
  3. put the new ISR address into the table
  4. enable interrupts

Removing an ISR is obvious and similar to the above.

The new ISR can then:

  1. before doing its work call the old ISR (the address is preserved at step 2 above)
  2. after doing its work call the old ISR
  3. just do its work without calling the old ISR

You need to require that the programs and bootloader use this table and restore it when they no longer need to have their own ISRs in it.

I don't know what issues you may need to solve if you chain ISRs by executing the old ones before/after the new ones. But in some systems that's a possible design. Many x86 PC programs and drivers did that in MSDOS.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top