EDIT: If you are interested in making your own OS, I strongly suggest using AsmOS as a starting point, which includes everything discussed in this tutorial.

Hello!
Several people may want to write their own OSes, but I know from experience that it is very hard finding out where to start. I have put together a small tutorial and a basic kernel so that anyone who wants to can get started building their own OSes.

If anyone wants to skip the struggle of simply getting something to boot, I have attached KnightKernelBasic, which is what I gave to Eeems to build Rouge on. It requires ZDS, and I recommend using TI Developer with it as well.

Every OS needs these, just to boot:
*Page 00
*A valid OS header

But if you want it to actually do anything useful, it needs to:
*Initialize the LCD
*Set up memory
*Initialize the stack

You should have some other stuff, but that's all you really *need.* In order to boot and display something pretty, you really just need to have page 00, the stack, LCD, and a header. A basic OS header looks like this:


Code:
   jr Boot
     db 0,0,0,0,0,0
   db 0, 0 ; rst 08h
   db 0,0,0,0,0
   db 0, 0   ; rst 10h
   db 0,0,0,0,0
   db 0,0   ; rst 18h
    db 0,0,0,0,0
   db 0, 0 ; rst 20h
   db 0,0,0,0,0
   db 0,0   ; rst 28h
   db 0,0,0,0,0
   db 0,0   ; rst 30h
   db 0,0,0,0,0,0,0
   db 0, 0 ; rst 38h / System Interrupt
    db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
   db 0,0,0,0,0,0,0,0,0
   jp Boot
   dw 0A55Ah
Boot:
        ; This executes at boot


You could copy this into a document and start coding at Boot: and have an OS. This is also valid and signable, and may be sent to a calculator. It is worth noting that you need to have an interrupt or risk crashing the calculator. Add it at rst 38h:


Code:
; System Interrupt Routines
SysInterrupt:
   exx
   ex af, af'
   in a, (04h)
   bit 0, a
   jr nz, HandleON
   bit 1, a
   jr nz, HandleTimer1
   bit 2, a
   jr nz, HandleTimer2
   bit 4, a
   jr nz, HandleLink
   jr InterruptDone
HandleON:
   in a, (03h)
   res 0, a
   out (03h), a
   set 0, a
   out (03h), a
   ; ON interrupt
   jr InterruptDone
HandleTimer1:
   in a, (03h)
   res 1, a
   out (03h), a
   set 1, a
   out (03h), a
   ; Timer one interrupt (might be best to merge with timer 2)
   jr InterruptDone
HandleTimer2:
   in a, (03h)
   res 2, a
   out (03h), a
   set 2, a
   out (03h), a
   ; Timer two interrupt
   jr InterruptDone
HandleLink:
   in a, (03h)
   res 4, a
   out (03h), a
   set 4, a
   out (03h), a
   ; Link interrupt
InterruptDone:
   ex af, af'
   exx
   ei
   ret


This is a basic interrupt with blank spots to put your code. In order to actually compile and test your OS, you need to sign it. It may also be useful to convert it to a ROM for testing. TI Developer will do this for you automatically, but if you don't want to use ZDS or TI Developer, you can use os2tools.

Simple code to set up the LCD so you can draw on it:

Code:
   ld a, 40h
   out (10h), a
   ld a, 05h
   call LCDDelay
   out (10h), a
   ld a, 01h
   call LCDDelay
   out (10h), a
   ld a, 3
   call LCDDelay
   out (10h), a
   ld a, 0F6h
   call LCDDelay
   out (10h), a


And to set up memory (ROM 00\ROM 01\RAM 01\RAM 00):

Code:
    ld a, 1    ; Set flash page 1 in bank 1.
    out (6), a
    in a, (2)    ;get calc version
    rlca ;Roll bit 7 into carry.
    ld a, 41h ; Set ram page 1 in bank 2.
    jr nc, LowerModel
HigherModel:
    out (5),a
    ld a,81h
    out (7),a
    jr Done
LowerModel:
    out (6), a
    out (7),a
Done:


Now go build some OSes!
Useful information indeed. Smile

I note that your ISR clobbers the shadow registers. Do you intend to provide an easy way to avoid this problem? Personally, I prefer to use the stack at the expense of a few clock cycles.

Edit: Don't forget that if you're using a fixed interrupt handler at $38 (a Z80-specific addition) you will need to switch to interrupt mode 1 with im 1 first. The Z80 defaults to the interrupt mode 0 on reset for compatibility with the 8080, which expects the interrupting device to put a single-byte instruction on the data bus (this is the main reason rst exists).
Tutorials are always good Smile
However, I recommend you use .org, unless ZDS doesn't support that.
In the end you will need to compile it. Here's my current OS build script (not that is has anything to build right now Razz)

Code:
tools\brass "src\Page $00.z80"
tools\bin2hex "Page $00.bin" 20 0000 > "Page $00.hex"
tools\brass "src\Page $1D.z80"
tools\bin2hex "Page $1D.bin" 20 4000 > "Page $1D.hex"
tools\ostools-0.1\multihex 00 "Page $00.hex" 1D "Page $1D.hex" > os.hex
tools\ostools-0.1\packxxu os.hex -o os84.8xu -t 83p -q 0A -v 0.01 -h 255
tools\ostools-0.1\packxxu os.hex -o os83.8xu -t 83p -q 04 -v 0.01 -h 255
tools\rabbitsign\rabbitsign -t 8xu -k tools\keys\0A.key -K 0A -g -p -r os84.8xu
tools\rabbitsign\rabbitsign -t 8xu -k tools\keys\04.key -K 04 -g -p -r os83.8xu
del os83.8xu os84.8xu
copy src\PartesOS.h + *.inc PartesOS.h
del *.bin*
del *.hex
del PartesOS*.8xu
ren os83-signed.8xu "PartesOS 83+.8xu"
ren os84-signed.8xu "PartesOS 84+.8xu"

Note that you need OS Tools and RabbitSign (Windows version here). You'll also need the OS signing keys.
You can customize this to fit your needs (right now it's set to how my folders are set up, along with the OS name). Note that you need to set your assembler of choice to produce hex output. (Brass for some reason doesn't handle it properly, so I wrote my own bin2hex program. TASM doesn't have this problem)
The -v argument of packxxu can be changed to reflect OS version, though the other arguments should be left as is. Note that this script builds OS's for both the 83+(SE) and 84+(SE).

And yes, go build some OS's! Very Happy
SirCmpwn, a most excellent review and tutorial. I must second Ben's note about the z80 defaulting to im 0. Thanks for filling in a hole in the set of existing tutorials; I think this topic deserves a sticky.
Thanks Ben, for the IM 1 reminder, and thanks, KermM!
SirCmpwn wrote:
Thanks Ben, for the IM 1 reminder, and thanks, KermM!
Sure thing; I also moved it the z80 Assembly topic. Do you have any plans to write subsequent sections of this, for example how to take this framework and expand on it with a more complex memory manager and a scheduler?
I'd be interested to see discussion of a file system too, if you have one in mind. Smile
benryves wrote:
I'd be interested to see discussion of a file system too, if you have one in mind. Smile
Same here, especially since the design goals for a Flash-based filesystem are significantly different than a RAM- or disk-based one.
SirCmpwn, you do know that TIOS uses one of those timers to check for battery removal? One of those timer interrupts needs to check the battery status and turn off the calculator quickly if there are no batteries. See this IRC log.
DrDnar, thanks! I didn't know that, it seems quite useful to know.
KermM and BenRyves, I will discuss these more in depth when I release KnightKernel, as all of the above are implemented therein.
DrDnar wrote:
SirCmpwn, you do know that TIOS uses one of those timers to check for battery removal? One of those timer interrupts needs to check the battery status and turn off the calculator quickly if there are no batteries. See this IRC log.
DrDnar, an excellent point. There's actually a thread somewhere around here about how that works based on Brandon's research.
Note: I made a mistake in the first post, with an extra zero where it shouldn't be in the first code block. Make sure you change this if you are already using my code.
Good catch. Here's the topic I was referencing, btw:

http://www.cemetech.net/forum/viewtopic.php?p=99121
So is this a complete valid header?


Code:
.org $0000

OSHeader:
  jr Boot
  .db 0,0,0,0,0,0
  .db 0,0      ; rst 08h
  .db 0,0,0,0,0
  .db 0,0      ; rst 10h
  .db 0,0,0,0,0
  .db 0,0      ; rst 18h
  .db 0,0,0,0,0
  .db 0,0      ; rst 20h
  .db 0,0,0,0,0
  .db 0,0      ; rst 28h
  .db 0,0,0,0,0
  .db 0,0      ; rst 30h
  .db 0,0,0,0,0,0,0
  .dw SysInterrupt   ; rst 38h / System Interrupt
  .db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  .db 0,0,0,0,0,0,0,0,0
  jp Boot
  .dw 0A55Ah
Boot:
  jr Start_Of_OS
SysInterrupt:
  exx
  ex af, af'
  in a, (04h)
  bit 0, a
  jr nz, HandleON
  bit 1, a
  jr nz, HandleTimer1
  bit 2, a
  jr nz, HandleTimer2
  bit 4, a
  jr nz, HandleLink
  jr InterruptDone
HandleON:
  in a, (03h)
  res 0, a
  out (03h), a
  set 0, a
  out (03h), a
  ; ON interrupt
  jr InterruptDone
HandleTimer1:
  in a, (03h)
  res 1, a
  out (03h), a
  set 1, a
  out (03h), a
  ; Timer one interrupt (might be best to merge with timer 2)
  jr InterruptDone
HandleTimer2:
  in a, (03h)
  res 2, a
  out (03h), a
  set 2, a
  out (03h), a
  ; Timer two interrupt
  jr InterruptDone
HandleLink:
  in a, (03h)
  res 4, a
  out (03h), a
  set 4, a
  out (03h), a
  ; Link interrupt
InterruptDone:
  ex af, af'
  exx
  ei
  ret
Start_Of_OS:
;program code here
Yes, that is completely valid.
2 more things

Quote:
1) where the ;Timer1 and ;Timer2 interrupt are at, do I call the subroutines for the LCD and whatnot

2) is there still a stack?
1) Timer1 and Timer2 are the two different interrupts. Add what you like.
2) You need to make it yourself. ld SP, ADDRESS
1) I was refering to whether or not to directly copy and paste the code where those remarks are, to call a subroutine, or do nothing

2) ok, i have an old routine i wrote to create a stack and modify specific things in it as well.
1) I don't fully understand, my apologies.
2) Creating a stack is easy. Just ld sp, FFFFh
Timer1 and Timer2 both fire to the same addresses. It's up to the code that handle that interrupts to read port (3) and see what triggered this particular interrupt. Options are timer 1, timer 2, the link port, and the ON key. Therefore, if you want to have different things that happen on each of those, just check and mask port (3)'s value, and then jump appropriately.
  
Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

» Go to Registration page
» Goto page 1, 2, 3, 4, 5  Next
» View previous topic :: View next topic  
Page 1 of 5
» All times are UTC - 5 Hours
 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

 

Advertisement