- 注册时间
- 2004-8-27
- 最后登录
- 1970-1-1
|
发表于 2006-8-17 18:21:52
|
显示全部楼层
我机子上居然有这资料,帖出来让LZ看看:
;*------------------------------------------------------------------*
;* *
;* Mini Multitasking Kernel *
;* for 6502 Systems *
;* *
;* by Joachim Deboy *
;* *
;* This mini kernel uses IRQ interrupts from a free running *
;* 6522-timer for task switching. It currently supports 4 *
;* concurrent tasks. The tasks receive control for fixed time *
;* slices in a round robin method. It should be easily possible *
;* to implement a priority driven task selector in the inter- *
;* rupt service routine. *
;* *
;* For performance reasons, the stack page will not be copied *
;* for every task switch, but is divided into 4 parts, one for *
;* each task. Because of that only the stack pointer and the *
;* other processor registers must be saved and loaded, when *
;* performing a task switch. A disadvantage is the 'home made' *
;* further limitation of the already short stack area. *
;* *
;* Two macros are implemented to allow a simple kind of seria- *
;* lization between concurrent tasks. A call of the enq-macro *
;* locks task switching until the deq-macro is used. This also *
;* prevents a discuption of a time critical process. *
;* *
;* This software is part of a heater control software, which *
;* runs at my home for several years now. *
;* It may be freely used and modified to suit other possible *
;* applications, but i can't guarantee for the usablity *
;* in any way. Use it at for own risk. *
;* *
;* If you have any comments, questions, further ideas or if you *
;* find any bugs, please contact me under joachim@deboy.de *
;* *
;*------------------------------------------------------------------*
;* page 0 addresses *
;*------------------------------------------------------------------*
mtarlow =$00 ; multitasking kernel, ret-addr., low
mtarhig =$01 ; multitasking kernel, ret-addr.,high
mtatemp =$02 ; multitasking kernel, temp. work
mtatask =$03 ; multitasking kernel, actual task
mtastab =$04 ; multitasking kernel, stack pointers
mtastbe =$07 ; multitasking kernel, end of st-ptrs
reserved =$08 ; reserved
mtalock =$09 ; multitasking lock x'00' = free
;*------------------------------------------------------------------*
;* 6522 ports *
;*------------------------------------------------------------------*
orb =$c310 ; output-register a
ora =$c311 ; output-register b
ddrb =$c312 ; data direction register b
ddra =$c313 ; data direction register a
t1csl =$c314 ; read: counter, low
; ; write: preset, low
t1csh =$c315 ; read & write: counter, high
t1lsl =$c316 ; read & write preset low, low
t1lsh =$c317 ; read & write preset, high
acr =$c31b ; acr-helpregister
pcr =$c31c ; pcr-register
ifr =$c31d ; interrupt-flag-register
ier =$c31e ; interrupt-enable-register
orahlp =$c31f ; output-register a w/o handshaking
;*------------------------------------------------------------------*
;* define macros *
;*------------------------------------------------------------------*
#define enq() inc mtalock
#define deq() dec mtalock \ beq $+8 \ jsr mtaentry \ inc $100
;*------------------------------------------------------------------*
;* initialization routine *
;*------------------------------------------------------------------*
.org $f000
init:
lda #$00 ; init output ports of pia 2
sta mtalock ; reset multitasking lock
lda #$40 ; setup timer for free running
sta acr
lda #$c0 ; enable timer interrupts
sta ier
ldy #0
lda #0
stinit: sta $100,y ; reset stack to x'00'
iny
bne stinit
lda #$00 ; set actual task # to 0
sta mtatask
ldy #maxtask-1 ; get max. number of tasks
initloop:
lda mtasini,y ; get initial stackpointer value
sta mtastab,y ; and save value in page 0 table
tax ; move stack pointer value to reg x
lda #$b0 ; set initial flag register contents
sta $0104,x ; save flag register on stack
tya ; get actual task number
asl a ; multiply with 2
tax ; and move result to reg x
stx mtatemp ; save reg x
lda ent_tab,x ; get pcl-value
ldx mtastab,y ; get stack pointer value
sta $0105,x ; save pcl register on stack
ldx mtatemp ; get reg x
lda ent_tab+1,x ; get pch-value
ldx mtastab,y ; get stack pointer value
sta $0106,x ; save pch register on stack
dey
bpl initloop ; ==> loop for all tasks
ldx #$3f ; set stack for task 0
txs
lda #0 ; initial load timer
sta t1lsl
lda #40 ; about 1/100 sec timer value
sta t1csh
cli ; enable interrupts
jmp ent_task0 ; enter task 0
;*------------------------------------------------------------------*
;* table of task entry addresses *
;*------------------------------------------------------------------*
ent_tab:
.word ent_task0
.word ent_task1
.word ent_task2
.word ent_task3
;*------------------------------------------------------------------*
;* program call entry to interrupt service routine *
;*------------------------------------------------------------------*
mtaentry:
php ; save processor status on stack
; ; for interrupt simulation
pha ; save registers on current stack
txa
pha
tya
pha
tsx
inc $105,x ; add 1 to return address
bne mtaent01 ; because of jsr command
inc $106,x
mtaent01:
lda #$00 ; reset task lock
sta mtalock
jmp mtaswitch ; and process task switch
;*------------------------------------------------------------------*
;* interrupt service routine *
;*------------------------------------------------------------------*
irq:
pha ; save registers on current stack
txa
pha
tya
pha
lda t1csl ; enable interrupt
lda #$c0 ; reset flag
sta ifr
lda mtalock ; is task locked ?
beq mtaswitch ; ==> no, then process task change
inc mtalock ; indicate task switch requested
jmp irq_ret ; ==> and skip task change
mtaswitch: ; task switcher
ldy mtatask ; get actual task number
tsx ; get actual stack pointer
stx mtastab,y ; and save it in table
iny ; calculate next task number
cpy #maxtask ; valid task number ?
bcc mtanumok ; ==> yes
ldy #0 ; else start with task 0
mtanumok:
sty mtatask ; save new task number
ldx mtastab,y ; get new stack pointer
txs ; and load it in sp-register
irq_ret:
pla ; load registers from current stack
tay
pla
tax
pla
rti ; ==> go and process task
mtasini .byte $39,$79,$b9,$f9 ; initial stackpointer values
maxtask =$-mtasini
.org $fffa
nmivector .word init ; nmi vector
resvector .word init ; reset vector
irqvector .word irq ; irq vector
.end
|
|