Let's make an OS together! [KERNEL ALREADY DONE!]
- BitWise
- In Memoriam
- Posts: 996
- Joined: 02 Mar 2004
- Location: Berkshire, UK
- Contact:
Re: Let's make an OS together! [KERNEL ALREADY DONE!]
The 6502's stack is 256 bytes maximum. Divided by 8 makes 32 bytes per task which it a bit small but is just about workable (after all some PICs have just 8 levels of call or 16 bytes). Personally I'd say that 4 task stacks of 64 bytes is more useful.
Keep the tasks A, X and Y registers and return address on the task's stack. Don't waste time copying them to/from zero page. The address and flags are pushed by the interrupt so just push A,Y & Y then save the stack pointer so you can restored them when the task is reactivated.
The only things you need to keep in memory are the current task number and the array of stack pointers for inactive tasks.
Instead of having lots of routines (task0r, task1r, etc) that are virtually identical use some data tables and an index register.
You should study Joachim's code (http://6502.org/source/kernels/minikernel.txt) more closely.
Keep the tasks A, X and Y registers and return address on the task's stack. Don't waste time copying them to/from zero page. The address and flags are pushed by the interrupt so just push A,Y & Y then save the stack pointer so you can restored them when the task is reactivated.
The only things you need to keep in memory are the current task number and the array of stack pointers for inactive tasks.
Instead of having lots of routines (task0r, task1r, etc) that are virtually identical use some data tables and an index register.
You should study Joachim's code (http://6502.org/source/kernels/minikernel.txt) more closely.
Andrew Jacobs
6502 & PIC Stuff - http://www.obelisk.me.uk/
Cross-Platform 6502/65C02/65816 Macro Assembler - http://www.obelisk.me.uk/dev65/
Open Source Projects - https://github.com/andrew-jacobs
6502 & PIC Stuff - http://www.obelisk.me.uk/
Cross-Platform 6502/65C02/65816 Macro Assembler - http://www.obelisk.me.uk/dev65/
Open Source Projects - https://github.com/andrew-jacobs
-
Gradius2000
- Posts: 32
- Joined: 31 Aug 2017
Re: Let's make an OS together! [KERNEL ALREADY DONE!]
BitWise wrote:
The 6502's stack is 256 bytes maximum. Divided by 8 makes 32 bytes per task which it a bit small but is just about workable (after all some PICs have just 8 levels of call or 16 bytes). Personally I'd say that 4 task stacks of 64 bytes is more useful.
Keep the tasks A, X and Y registers and return address on the task's stack. Don't waste time copying them to/from zero page. The address and flags are pushed by the interrupt so just push A,Y & Y then save the stack pointer so you can restored them when the task is reactivated.
The only things you need to keep in memory are the current task number and the array of stack pointers for inactive tasks.
Instead of having lots of routines (task0r, task1r, etc) that are virtually identical use some data tables and an index register.
You should study Joachim's code (http://6502.org/source/kernels/minikernel.txt) more closely.
Keep the tasks A, X and Y registers and return address on the task's stack. Don't waste time copying them to/from zero page. The address and flags are pushed by the interrupt so just push A,Y & Y then save the stack pointer so you can restored them when the task is reactivated.
The only things you need to keep in memory are the current task number and the array of stack pointers for inactive tasks.
Instead of having lots of routines (task0r, task1r, etc) that are virtually identical use some data tables and an index register.
You should study Joachim's code (http://6502.org/source/kernels/minikernel.txt) more closely.
Otherwise, I am implementing the double stack size update now, so you can have 8 tasks of 32 bytes.
Edit: The update's done! It should work fine, too!
-
Gradius2000
- Posts: 32
- Joined: 31 Aug 2017
Re: Let's make an OS together! [KERNEL ALREADY DONE!]
The next update is here; 0.4.0 Alpha! It is SUPER small now because I turned all 8 jump routines into 1! Thank you everyone for your help so far!
- BitWise
- In Memoriam
- Posts: 996
- Joined: 02 Mar 2004
- Location: Berkshire, UK
- Contact:
Re: Let's make an OS together! [KERNEL ALREADY DONE!]
Here is my quick hack at eight tasks
You can force a yield from task with a BRK as it would drops into the IRQ. (But remember that BRK is really a two byte instruction so you'd have to put an extra byte in your code unless the assembler does it for you)
You could add an array of control flags (one byte per task indexed by TASKNO) if you wanted to disable tasks and check them in the interrupt handler. If no tasks are runnable then you could do a CLI followed by a WAI as on a real system to wait for a hardware interrupt which may make a task runnable.
Code: Select all
.opt Proc65c02,CaseSensitive
;===============================================================================
; Constants
;-------------------------------------------------------------------------------
STACK = $0100
;===============================================================================
; Memory Areas
;-------------------------------------------------------------------------------
.org $00
TASKNO .ds 1 ; The current task 0-7
TASKSP .ds 8 ; Inactive task stack pointer values
;===============================================================================
; Power On Reset
;-------------------------------------------------------------------------------
.org $f000
.start *
RESET:
sei ; Reset flags (in case of JMP ($FFFC))
cld
ldy #7 ; Initialise task stacks
.Init ldx INITSP,Y
tya ; Save task number
pha
asl ; Convert to index for PC
tay
stz STACK+1,x ; Clear initial Y
stz STACK+2,x ; Clear initial X
stz STACK+3,x ; Clear initial A
stz STACK+4,x ; Clear initial P
lda INITPC+0,y ; Set initial task PC
sta STACK+5,x
lda INITPC+1,y
sta STACK+6,x
ply ; Recover task number
stx TASKSP,Y ; Save the stack pointer
dey ; Repeat for all tasks
bpl .Init
txs ; Set the initial stack
stz TASKNO ; .. and task number
ply ; Start the first task
plx
pla
rti
;===============================================================================
; Interrupt Handler
;-------------------------------------------------------------------------------
IRQ: pha ; Save tasks A,X & Y
phx
phy
ldy TASKNO ; Save the tasks stack
tsx
stx TASKSP,y
iny ; Find the next task
cpy #8
bcc .Skip
ldy #0
.Skip sty TASKNO
ldx TASKSP,y ; Load new tasks stack
txs
ply ; Restore its registers
plx
pla
NMI: rti ; And continue
; Initial stack pointer values for each task
INITSP: .byte $ff-6,$df-6,$bf-6,$9f-6
.byte $7f-6,$5f-6,$3f-6,$1f-6
; Initial task entry points
INITPC: .word Task0,Task1,Task2,Task3
.word Task4,Task5,Task6,Task7
;===============================================================================
; Dummy Tasks
;-------------------------------------------------------------------------------
; Simple tasks that print thier task number until interrupted
Task0: lda #'0'
jsr OutCh
bra Task0
Task1: lda #'1'
jsr OutCh
bra Task1
Task2: lda #'2'
jsr OutCh
bra Task2
Task3: lda #'3'
jsr OutCh
bra Task3
Task4: lda #'4'
jsr OutCh
bra Task4
Task5: lda #'5'
jsr OutCh
bra Task5
Task6: lda #'6'
jsr OutCh
bra Task6
Task7: lda #'7'
jsr OutCh
bra Task7
;===============================================================================
; Simulator Output Routines
;-------------------------------------------------------------------------------
IO_AREA = $e000
IO_CLS = IO_AREA+0
IO_PUTC = IO_AREA+1
IO_PUTR = IO_AREA+2
IO_PUTH = IO_AREA+3
IO_GETC = IO_AREA+4
OutCh: sta IO_PUTR
rts
;===============================================================================
; Vectors
;-------------------------------------------------------------------------------
.org $fffa
.word NMI
.word RESET
.word IRQ
.end
You could add an array of control flags (one byte per task indexed by TASKNO) if you wanted to disable tasks and check them in the interrupt handler. If no tasks are runnable then you could do a CLI followed by a WAI as on a real system to wait for a hardware interrupt which may make a task runnable.
- Attachments
-
- tasks.asm
- (3.32 KiB) Downloaded 62 times
Andrew Jacobs
6502 & PIC Stuff - http://www.obelisk.me.uk/
Cross-Platform 6502/65C02/65816 Macro Assembler - http://www.obelisk.me.uk/dev65/
Open Source Projects - https://github.com/andrew-jacobs
6502 & PIC Stuff - http://www.obelisk.me.uk/
Cross-Platform 6502/65C02/65816 Macro Assembler - http://www.obelisk.me.uk/dev65/
Open Source Projects - https://github.com/andrew-jacobs
- BitWise
- In Memoriam
- Posts: 996
- Joined: 02 Mar 2004
- Location: Berkshire, UK
- Contact:
Re: Let's make an OS together! [KERNEL ALREADY DONE!]
Using the stack while setting up the the stack so I've removed the PHA/PLY in the initialisation with a spot of recoding. I'll post again it a bit. Just adding a few more features.
Andrew Jacobs
6502 & PIC Stuff - http://www.obelisk.me.uk/
Cross-Platform 6502/65C02/65816 Macro Assembler - http://www.obelisk.me.uk/dev65/
Open Source Projects - https://github.com/andrew-jacobs
6502 & PIC Stuff - http://www.obelisk.me.uk/
Cross-Platform 6502/65C02/65816 Macro Assembler - http://www.obelisk.me.uk/dev65/
Open Source Projects - https://github.com/andrew-jacobs
- BitWise
- In Memoriam
- Posts: 996
- Joined: 02 Mar 2004
- Location: Berkshire, UK
- Contact:
Re: Let's make an OS together! [KERNEL ALREADY DONE!]
Heres an improved version. Not none of the variables need to be on page zero -- it just makes the code a bit smaller.
Code: Select all
.opt Proc65c02,CaseSensitive
;===============================================================================
; Constants
;-------------------------------------------------------------------------------
STACK = $0100
;===============================================================================
; Memory Areas
;-------------------------------------------------------------------------------
.org $00
TASKNO .ds 1 ; The current task 0-7
TASKLK .ds 1 ; Bit map of stopped tasks
TASKSP .ds 8 ; Inactive task stack pointer values
;===============================================================================
; Power On Reset
;-------------------------------------------------------------------------------
.org $f000
.start *
RESET: sei ; Reset flags (in case of JMP ($FFFC))
cld
ldy #7 ; Initialise task stacks
.Init ldx INITSP,Y
stx TASKSP,Y
tya ; Convert task number
asl ; .. to index for PC
tay
stz STACK+1,x ; Clear initial Y
stz STACK+2,x ; Clear initial X
stz STACK+3,x ; Clear initial A
stz STACK+4,x ; Clear initial P
lda INITPC+0,y ; Set initial task PC
sta STACK+5,x
lda INITPC+1,y
sta STACK+6,x
tya ; Recover task number
lsr
tay
dey ; Repeat for all tasks
bpl .Init
txs ; Set the initial stack
stz TASKNO ; .. and task number
stz TASKLK ; All tasks runnable
ply ; Start the first task
plx
pla
rti
;-------------------------------------------------------------------------------
; Switch to another task
TaskYield: brk ; Cause an interrup to switch task
nop
rts ; Continue the original task
; Make the task indicated by A runnable
TaskStart: and #7 ; Ensure task number in range
pha
tax ; Convert to bit mask
lda MASKS,x
trb TASKLK ; And mark as runnable
pla
rts
; Cause this task to be stopped
TaskStopSelf: lda TASKNO ; Stop the calling task
; Make the task indicated by A un-runnable
TaskStop: and #7 ; Ensure task number in range
pha
tax ; Convert to bit mask
lda MASKS,x
tsb TASKLK ; And mark as stopped
pla
cmp TASKNO ; Stopped the running task?
beq TaskYield ; Yes, switch to another
rts ; Continue
;-------------------------------------------------------------------------------
; Initial stack pointer values for each task
INITSP: .byte $ff-6,$df-6,$bf-6,$9f-6
.byte $7f-6,$5f-6,$3f-6,$1f-6
; Initial task entry points
INITPC: .word Task0,Task1,Task2,Task3
.word Task4,Task5,Task6,Task7
; Bit masks
MASKS: .byte 1,2,4,8,16,32,64,128
;===============================================================================
; Interrupt Handler
;-------------------------------------------------------------------------------
IRQ: pha ; Save tasks A,X & Y
phx
phy
.Handle ; Handle hardware interrupts here. Exit to .Done if not
; switching task due to timer or BRK
ldy TASKNO ; Save the tasks stack
tsx
stx TASKSP,y
.Loop iny ; Find the next task
cpy #8
bcc .Skip
ldy #0
.Skip
cpy TASKNO ; Back at original Task?
bne .Test
; If no tasks are runnable then wait until a hardware
; interrupt occurs and hope that it will make a task
; runnable.
; wai ; Not supported in the simulator
bra .Handle
.Test tya ; No, is the task runnable?
tax
lda MASKS,y
and TASKLK
bne .Loop ; No
sty TASKNO ; Found a new task
ldx TASKSP,y ; Load its stack pointer
txs
.Done ply ; Restore its registers
plx
pla
NMI: rti ; And continue
;===============================================================================
; Dummy Tasks
;-------------------------------------------------------------------------------
; Simple tasks that print thier task number until interrupted
Task0: lda #'0'
jsr OutCh
bra Task0
Task1: lda #'1'
jsr OutCh
bra Task1
Task2: lda #'2'
jsr OutCh
bra Task2
Task3: lda #'3'
jsr OutCh
bra Task3
Task4: lda #'4'
jsr OutCh
bra Task4
Task5: lda #'5'
jsr OutCh
bra Task5
Task6: lda #'6'
jsr OutCh
bra Task6
; Task 7 will give up control after a printing 16 characters
Task7: lda #'7'
ldx #16
.Loop jsr OutCh
dex
bne .Loop
jsr TaskYield
bra Task7
;===============================================================================
; Simulator Output Routines
;-------------------------------------------------------------------------------
IO_AREA = $e000
IO_CLS = IO_AREA+0
IO_PUTC = IO_AREA+1
IO_PUTR = IO_AREA+2
IO_PUTH = IO_AREA+3
IO_GETC = IO_AREA+4
OutCh: sta IO_PUTR
rts
;===============================================================================
; Vectors
;-------------------------------------------------------------------------------
.org $fffa
.word NMI
.word RESET
.word IRQ
.end
- Attachments
-
- tasks.asm
- (4.91 KiB) Downloaded 56 times
Andrew Jacobs
6502 & PIC Stuff - http://www.obelisk.me.uk/
Cross-Platform 6502/65C02/65816 Macro Assembler - http://www.obelisk.me.uk/dev65/
Open Source Projects - https://github.com/andrew-jacobs
6502 & PIC Stuff - http://www.obelisk.me.uk/
Cross-Platform 6502/65C02/65816 Macro Assembler - http://www.obelisk.me.uk/dev65/
Open Source Projects - https://github.com/andrew-jacobs
-
Gradius2000
- Posts: 32
- Joined: 31 Aug 2017
Re: Let's make an OS together! [KERNEL ALREADY DONE!]
BitWise wrote:
Heres an improved version. Not none of the variables need to be on page zero -- it just makes the code a bit smaller.
Code: Select all
.opt Proc65c02,CaseSensitive
;===============================================================================
; Constants
;-------------------------------------------------------------------------------
STACK = $0100
;===============================================================================
; Memory Areas
;-------------------------------------------------------------------------------
.org $00
TASKNO .ds 1 ; The current task 0-7
TASKLK .ds 1 ; Bit map of stopped tasks
TASKSP .ds 8 ; Inactive task stack pointer values
;===============================================================================
; Power On Reset
;-------------------------------------------------------------------------------
.org $f000
.start *
RESET: sei ; Reset flags (in case of JMP ($FFFC))
cld
ldy #7 ; Initialise task stacks
.Init ldx INITSP,Y
stx TASKSP,Y
tya ; Convert task number
asl ; .. to index for PC
tay
stz STACK+1,x ; Clear initial Y
stz STACK+2,x ; Clear initial X
stz STACK+3,x ; Clear initial A
stz STACK+4,x ; Clear initial P
lda INITPC+0,y ; Set initial task PC
sta STACK+5,x
lda INITPC+1,y
sta STACK+6,x
tya ; Recover task number
lsr
tay
dey ; Repeat for all tasks
bpl .Init
txs ; Set the initial stack
stz TASKNO ; .. and task number
stz TASKLK ; All tasks runnable
ply ; Start the first task
plx
pla
rti
;-------------------------------------------------------------------------------
; Switch to another task
TaskYield: brk ; Cause an interrup to switch task
nop
rts ; Continue the original task
; Make the task indicated by A runnable
TaskStart: and #7 ; Ensure task number in range
pha
tax ; Convert to bit mask
lda MASKS,x
trb TASKLK ; And mark as runnable
pla
rts
; Cause this task to be stopped
TaskStopSelf: lda TASKNO ; Stop the calling task
; Make the task indicated by A un-runnable
TaskStop: and #7 ; Ensure task number in range
pha
tax ; Convert to bit mask
lda MASKS,x
tsb TASKLK ; And mark as stopped
pla
cmp TASKNO ; Stopped the running task?
beq TaskYield ; Yes, switch to another
rts ; Continue
;-------------------------------------------------------------------------------
; Initial stack pointer values for each task
INITSP: .byte $ff-6,$df-6,$bf-6,$9f-6
.byte $7f-6,$5f-6,$3f-6,$1f-6
; Initial task entry points
INITPC: .word Task0,Task1,Task2,Task3
.word Task4,Task5,Task6,Task7
; Bit masks
MASKS: .byte 1,2,4,8,16,32,64,128
;===============================================================================
; Interrupt Handler
;-------------------------------------------------------------------------------
IRQ: pha ; Save tasks A,X & Y
phx
phy
.Handle ; Handle hardware interrupts here. Exit to .Done if not
; switching task due to timer or BRK
ldy TASKNO ; Save the tasks stack
tsx
stx TASKSP,y
.Loop iny ; Find the next task
cpy #8
bcc .Skip
ldy #0
.Skip
cpy TASKNO ; Back at original Task?
bne .Test
; If no tasks are runnable then wait until a hardware
; interrupt occurs and hope that it will make a task
; runnable.
; wai ; Not supported in the simulator
bra .Handle
.Test tya ; No, is the task runnable?
tax
lda MASKS,y
and TASKLK
bne .Loop ; No
sty TASKNO ; Found a new task
ldx TASKSP,y ; Load its stack pointer
txs
.Done ply ; Restore its registers
plx
pla
NMI: rti ; And continue
;===============================================================================
; Dummy Tasks
;-------------------------------------------------------------------------------
; Simple tasks that print thier task number until interrupted
Task0: lda #'0'
jsr OutCh
bra Task0
Task1: lda #'1'
jsr OutCh
bra Task1
Task2: lda #'2'
jsr OutCh
bra Task2
Task3: lda #'3'
jsr OutCh
bra Task3
Task4: lda #'4'
jsr OutCh
bra Task4
Task5: lda #'5'
jsr OutCh
bra Task5
Task6: lda #'6'
jsr OutCh
bra Task6
; Task 7 will give up control after a printing 16 characters
Task7: lda #'7'
ldx #16
.Loop jsr OutCh
dex
bne .Loop
jsr TaskYield
bra Task7
;===============================================================================
; Simulator Output Routines
;-------------------------------------------------------------------------------
IO_AREA = $e000
IO_CLS = IO_AREA+0
IO_PUTC = IO_AREA+1
IO_PUTR = IO_AREA+2
IO_PUTH = IO_AREA+3
IO_GETC = IO_AREA+4
OutCh: sta IO_PUTR
rts
;===============================================================================
; Vectors
;-------------------------------------------------------------------------------
.org $fffa
.word NMI
.word RESET
.word IRQ
.end
I hope for the future of my operating system as i can't wait to program this kernel!
- BigDumbDinosaur
- Posts: 9428
- Joined: 28 May 2009
- Location: Midwestern USA (JB Pritzker’s dystopia)
- Contact:
Re: Let's make an OS together! [KERNEL ALREADY DONE!]
BitWise wrote:
Heres an improved version.
x86? We ain't got no x86. We don't NEED no stinking x86!
- BitWise
- In Memoriam
- Posts: 996
- Joined: 02 Mar 2004
- Location: Berkshire, UK
- Contact:
Re: Let's make an OS together! [KERNEL ALREADY DONE!]
BigDumbDinosaur wrote:
Just think how much more succinct that would be with the '816 in native mode. 
Overall I'd say less succinct for the '816
Andrew Jacobs
6502 & PIC Stuff - http://www.obelisk.me.uk/
Cross-Platform 6502/65C02/65816 Macro Assembler - http://www.obelisk.me.uk/dev65/
Open Source Projects - https://github.com/andrew-jacobs
6502 & PIC Stuff - http://www.obelisk.me.uk/
Cross-Platform 6502/65C02/65816 Macro Assembler - http://www.obelisk.me.uk/dev65/
Open Source Projects - https://github.com/andrew-jacobs
- jac_goudsmit
- Posts: 229
- Joined: 23 Jun 2011
- Location: Rancho Cucamonga, California
- Contact:
Re: Let's make an OS together! [KERNEL ALREADY DONE!]
Gradius2000 wrote:
Okay, everybody! The nanokernel still doesnt have I/O, but you can safely make a task that drives such at $F800. Anyway, the kernel now has 16 Byte x 8 Task Stacks! I hope you guys are glad, too!
===Jac
-
Gradius2000
- Posts: 32
- Joined: 31 Aug 2017
Re: Let's make an OS together! [KERNEL ALREADY DONE!]
jac_goudsmit wrote:
Gradius2000 wrote:
Okay, everybody! The nanokernel still doesnt have I/O, but you can safely make a task that drives such at $F800. Anyway, the kernel now has 16 Byte x 8 Task Stacks! I hope you guys are glad, too!
===Jac
Anyway, as I am testing the new kernel 1.0.3, it seems to be running fine.
WARNING: The 6502 simulator by Michal has a severe bug with bit testing in "run" mode, but not "animate" mode, as the message I am testing cannot be stopped with the current kernel
As I produce more and more hardware support, it seems to get harder and harder (as ALL assembly might do).
I will post the drivers on github with an include file. Won't sort the programs so far as there isn't that many yet.
-
Gradius2000
- Posts: 32
- Joined: 31 Aug 2017
Re: Let's make an OS together! [KERNEL ALREADY DONE!]
Well, I successfully turned the kernel into a [modular? I don't remember...] tree! Hopefully you guys can grab the source more nicely now! Finally it looks like a real github tree 
- BigDumbDinosaur
- Posts: 9428
- Joined: 28 May 2009
- Location: Midwestern USA (JB Pritzker’s dystopia)
- Contact:
Re: Let's make an OS together! [KERNEL ALREADY DONE!]
Gradius2000 wrote:
WARNING: The 6502 simulator by Michal has a severe bug with bit testing in "run" mode, but not "animate" mode, as the message I am testing cannot be stopped with the current kernel
x86? We ain't got no x86. We don't NEED no stinking x86!
Re: Let's make an OS together! [KERNEL ALREADY DONE!]
Years ago I tested the latest version of the 6502 simulator 1.2.12 with my functional test and did not find anything wrong with the BIT instructions. If there is a bug my test didn't catch I am interested in the details.
6502 sources on GitHub: https://github.com/Klaus2m5
-
Gradius2000
- Posts: 32
- Joined: 31 Aug 2017
Re: Let's make an OS together! [KERNEL ALREADY DONE!]
Version 1.2.11 was the only one I could find... Don't know if it just was my computer acting up. The program is very buggy on my machine sometimes. If the code is extended (which it is now) it doesn't have the same problem!
I guess Core i-3rd gen based Pentiums aren't good after all...
Edit: Is there a link to 1.2.12?
Edit: Is there a link to 1.2.12?