而且强行导入内存会死机`^~~` 网上有可用的6502用的多任务源代码,原理是利用时钟中断让控制权交回系统,让系统保存当前任务的CPU状态,再恢复下一任务的CPU状态,再切换到下一任务。 我机子上居然有这资料,帖出来让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
stamtalock ; reset multitasking lock
lda#$40 ; setup timer for free running
staacr
lda#$c0 ; enable timer interrupts
staier
ldy#0
lda#0
stinit:sta$100,y ; reset stack to x'00'
iny
bnestinit
lda#$00 ; set actual task # to 0
stamtatask
ldy#maxtask-1 ; get max. number of tasks
initloop:
ldamtasini,y ; get initial stackpointer value
stamtastab,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
asla ; multiply with 2
tax ; and move result to reg x
stxmtatemp ; save reg x
ldaent_tab,x ; get pcl-value
ldxmtastab,y ; get stack pointer value
sta$0105,x ; save pcl register on stack
ldxmtatemp ; get reg x
ldaent_tab+1,x ; get pch-value
ldxmtastab,y ; get stack pointer value
sta$0106,x ; save pch register on stack
dey
bplinitloop ; ==> loop for all tasks
ldx#$3f ; set stack for task 0
txs
lda#0 ; initial load timer
stat1lsl
lda#40 ; about 1/100 sec timer value
stat1csh
cli ; enable interrupts
jmpent_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
bnemtaent01 ; because of jsr command
inc$106,x
mtaent01:
lda#$00 ; reset task lock
stamtalock
jmpmtaswitch ; and process task switch
;*------------------------------------------------------------------*
;* interrupt service routine *
;*------------------------------------------------------------------*
irq:
pha ; save registers on current stack
txa
pha
tya
pha
ldat1csl ; enable interrupt
lda#$c0 ; reset flag
staifr
ldamtalock ; is task locked ?
beqmtaswitch ; ==> no, then process task change
incmtalock ; indicate task switch requested
jmpirq_ret ; ==> and skip task change
mtaswitch: ; task switcher
ldymtatask ; get actual task number
tsx ; get actual stack pointer
stxmtastab,y ; and save it in table
iny ; calculate next task number
cpy#maxtask ; valid task number ?
bccmtanumok ; ==> yes
ldy#0 ; else start with task 0
mtanumok:
stymtatask ; save new task number
ldxmtastab,y ; get new stack pointer
txs ; and load it insp-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
实现不太可能,毕竟是8位低端CPU么 2楼的天书。。。 谢谢各位了,不过不知道在V5100上可不可能,听说它的的CPU是多任务结构的,那样就不必用这个不入流的方法了 方法是大同小异,即使硬件实现,还是要有类似的程序控制 貌似内存会不足``
唉,WQX已经很不错了`` 抢占式多线程最主要的是可以设置堆栈段,数据段,程序段,6502 根本没有这种硬件能力,所以3楼的程序强行将堆栈分为4部分,可以支持4个线程,不过这4个线程还是统一连接才保证运行正常,没有扩展的余地. 引用第2楼点虫虫于2006-08-17 15:41发表的“”:
网上有可用的6502用的多任务源代码,原理是利用时钟中断让控制权交回系统,让系统保存当前任务的CPU状态,再恢复下一任务的CPU状态,再切换到下一任务。
这个只能算模拟多线程吧,后台任务不会被执行的 多线程要把程序都编成'块'一样的东西,然后在总线循环中依条件而调用,似乎6502的内存和速度都跟不上~~~
[请教]关于在WQX上仿多线程操作
**** Hidden Message *****
页:
[1]