原创文章,如有转载,请注明出处:/desertsz/article/details/6877873
三、iop主程序
iop.asm是iop的主程序,在该文件中需要注意的是.section伪指令对应的label,以及.page0,.data,.code等,这些标志与iop.lnk文件相关,结合起来看就会明白lnk文件指定的6502的地址是怎么划分的。6502是8位MCU,虽然跟51或PIC不一样,但也是大同小异,运行的方式也是:上电复位→跳到中断向量表的复位中断处→调用复位服务程序→初始化(清RAM,设置I/O口,中断,定时器,外围等)→跳到主程序入口地址→然后在一个死循环中顺序调用其它子功能程序,周而复始。下面对iop中的各个步骤分别进行说明:
1. 复位服务程序
1.1 清RAM
.codevReset:seildx #FFHtxsldx #RAM_TOPlClearAllRAM:stz 0,Xinxcpx #RAM_BOTTOMbne lClearAllRAM
1.2 #595 设置红外遥控接收脚为输入
rmb IR_IN_bit, IR_PORT_CFG
1.3 #766~787 设置游戏手柄数据接收脚为输入
rmb GPAD_D0, GPAD_PORT_D0rmb GPAD_D1, GPAD_PORT_D1
1.4 #811~841 如果IOP_DATA7_H不为0,则根据IOP_DATA6的值初始化TimerB定时器,设置定时器的定时时长。(16位模式,因为只需要设置一次,所以可能是自动装载,时长为112us)
lda IOP_DATA7_Hcmp #0bne lUseOuterIRjmp lEndIRTimerlUserOuterIR:lda IOP_DATA6_L;设置TimberB的定时时长sta TimerB_Lolda IOP_DATA6_Hsta TimerB_Hilda #0sta IOP_DATA6_Lsta IOP_DATA6_HlEndIRTimer:lda #INT_TIMER_B;使能TimerB中断sta IntMask
1.5 #850 设置rVfdPollingTm,112*100=11200us,约每11ms(主要用于处理lRunOthersFun间隔时间)
1.6 #1045 打开总中断,跳到主循环执行
clijmp lToMainLoop;跳到主循环执
2. 主循环
2.1 延时调用lRunOthersFun
.org (($+31)/32)*32;.code+32位对齐后的地址lToMainLoop:lda rVfdPollingTmbne lRunOthersFun;间隔11.2ms跳转lda #100sta rVfdPollingTm;设置下一次的间隔时间:11.2ms
2.2 lRunOthersFun,检测交换变量IOP_DATA0_H,根据RISC发过来的命令执行相应的功能
lRunOthersFun:lda IOP_DATA0_Hand #FUN_MASK;%11110000beq lToMainLoop;请求标志一般是高4位,为1时表示有请求;;bit7~6:主功能; bit5~4:子功能;主功能优先级比子功能高;如果没有请求,则跳到主循环等待下次执行taxand #FUN_MAIN_MASK;%11000000bne lChkMainFun01;如果有主功能请求,则跳到主功能程序;由于子功能VFD驱动的宏没打开不起作用,所以就略过不做说明
2.3 lChkMainFun01,根据主功能请求,调用对应的子程序
lChkMainFun01:txacmp #FUN_GPAD_READ;%1001=read game padbne lCheckNext01;如果主功能请求不是“读取游戏手柄按键”,则跳到lCheckNext01,由于jsr fReadGamePad;调用手柄按键检测子程序jmp lFunComplete;跳到功能请求结束部分lCheckNext01:;%0110=uartjmp lFunCompletelCheckNext02:;%0111=i2c_writejmp lFunCompletelCheckNext03:;%1000=i2c_readjmp lFunCompletelCheckNext04:;%1010=uart/%1101=16316_writejmp lFunCompletelCheckNext05:;%1110=16316_readjmp lFunComplete
2.4lFunComplete,清请求标志
lFunComplete:;清除请求标志,跳到主循环部分lda IOP_DATA0_Hand #!FUN_MASKsta IOP_DATA0_Hjmp lToMainLoop