OS_CPU_A.ASM
上传用户:tzjinxin1
上传日期:2022-08-08
资源大小:272k
文件大小:8k
开发平台:

Visual C++

  1. ;/*
  2. ;*********************************************************************************************************
  3. ;*                                               uC/OS-II
  4. ;*                                               实时内核
  5. ;*
  6. ;*                        (c) Copyright 1992-1998, Jean J. Labrosse, Plantation, FL
  7. ;*                                               版权所有
  8. ;*
  9. ;*                                            MCU-51 专用代码
  10. ;*                                           KEIL C51大模式编译
  11. ;*
  12. ;* 文件名 : OS_CPU_A.ASM
  13. ;* 作者   : Jean J. Labrosse
  14. ;* 改编   : 杨屹 gdtyy@ri.gdt.com.cn 巨龙公司系统集成开发部 2002.09.27
  15. ;*********************************************************************************************************
  16. ;*/
  17. ;伪指令详细用法请查A51.PDF文件
  18. ;程序结构详见《uC/OS-II》193-198页
  19. ;不用此语句!!! $CASE    ;标号和变量名区分大小写
  20. $NOMOD51
  21. EA BIT 0A8H.7
  22. SP DATA 081H
  23. B DATA 0F0H
  24. ACC DATA 0E0H
  25. DPH DATA 083H
  26. DPL DATA 082H
  27. PSW DATA 0D0H
  28. TR0 BIT 088H.4
  29. TH0 DATA 08CH
  30. TL0 DATA 08AH
  31.         NAME OS_CPU_A    ;模块名
  32.         
  33. ;定义重定位段
  34. ?PR?OSStartHighRdy?OS_CPU_A    SEGMENT CODE
  35. ?PR?OSCtxSw?OS_CPU_A           SEGMENT CODE
  36. ?PR?OSIntCtxSw?OS_CPU_A        SEGMENT CODE
  37. ;?PR?OSTickISR?OS_CPU_A         SEGMENT CODE
  38. ;?PR?_?serial?OS_CPU_A          SEGMENT CODE
  39.         
  40. ;声明引用全局变量和外部子程序
  41.         EXTRN DATA  (?C_XBP)     ;仿真堆栈指针用于重入局部变量保存,为V2.51能被C使用定义在本模块中
  42.         EXTRN IDATA (OSTCBCur)
  43.         EXTRN IDATA (OSTCBHighRdy)
  44.         EXTRN IDATA (OSRunning)
  45.         EXTRN IDATA (OSPrioCur)
  46.         EXTRN IDATA (OSPrioHighRdy)
  47.     
  48.         EXTRN CODE  (_?OSTaskSwHook)
  49.         EXTRN CODE  (_?OSIntEnter)
  50.         EXTRN CODE  (_?OSIntExit)
  51.         EXTRN CODE  (_?OSTimeTick)        
  52. ;        EXTRN CODE  (_?serial)
  53.             
  54. ;对外声明4个不可重入函数
  55.         PUBLIC OSStartHighRdy
  56.         PUBLIC OSCtxSw
  57.         PUBLIC OSIntCtxSw
  58. ;        PUBLIC OSTickISR
  59. ;        PUBLIC SerialISR        
  60. ;分配堆栈空间。只关心大小,堆栈起点由keil决定,通过标号可以获得keil分配的SP起点。
  61. ?STACK SEGMENT IDATA
  62.         RSEG ?STACK
  63. OSStack:
  64.         DS 40H
  65. OSStkStart IDATA OSStack-1
  66. ;定义压栈出栈宏
  67. PUSHALL    MACRO
  68.         PUSH ACC
  69.         PUSH B
  70.         PUSH DPH
  71.         PUSH DPL
  72.         PUSH PSW
  73.         MOV  A,R0   ;R0-R7入栈
  74.         PUSH ACC
  75.         MOV  A,R1
  76.         PUSH ACC
  77.         MOV  A,R2
  78.         PUSH ACC
  79.         MOV  A,R3
  80.         PUSH ACC
  81.         MOV  A,R4
  82.         PUSH ACC
  83.         MOV  A,R5
  84.         PUSH ACC
  85.         MOV  A,R6
  86.         PUSH ACC
  87.         MOV  A,R7
  88.         PUSH ACC
  89.         ;PUSH SP    ;不必保存SP,任务切换时由相应程序调整
  90.         ENDM
  91.     
  92. POPALL    MACRO
  93.         ;POP  ACC   ;不必保存SP,任务切换时由相应程序调整
  94.         POP  ACC    ;R0-R7出栈
  95.         MOV  R7,A
  96.         POP  ACC
  97.         MOV  R6,A
  98.         POP  ACC
  99.         MOV  R5,A
  100.         POP  ACC
  101.         MOV  R4,A
  102.         POP  ACC
  103.         MOV  R3,A
  104.         POP  ACC
  105.         MOV  R2,A
  106.         POP  ACC
  107.         MOV  R1,A
  108.         POP  ACC
  109.         MOV  R0,A
  110.         POP  PSW
  111.         POP  DPL
  112.         POP  DPH
  113.         POP  B
  114.         POP  ACC
  115.         ENDM
  116.     
  117. ;子程序
  118. ;-------------------------------------------------------------------------
  119.         RSEG ?PR?OSStartHighRdy?OS_CPU_A
  120. OSStartHighRdy:
  121.         USING 0    ;上电后51自动关中断,此处不必用CLR EA指令,因为到此处还未开中断,本程序退出后,开中断。
  122.         LCALL _?OSTaskSwHook
  123. OSCtxSw_in:
  124.     
  125.         ;OSTCBCur ===> DPTR  获得当前TCB指针,详见C51.PDF第178页
  126.         MOV  R0,#LOW (OSTCBCur) ;获得OSTCBCur指针低地址,指针占3字节。+0类型+1高8位数据+2低8位数据
  127.         INC  R0
  128.         MOV  DPH,@R0    ;全局变量OSTCBCur在IDATA中
  129.         INC  R0
  130.         MOV  DPL,@R0
  131.     
  132.         ;OSTCBCur->OSTCBStkPtr ===> DPTR  获得用户堆栈指针
  133.         INC  DPTR        ;指针占3字节。+0类型+1高8位数据+2低8位数据
  134.         MOVX A,@DPTR     ;.OSTCBStkPtr是void指针
  135.         MOV  R0,A
  136.         INC  DPTR
  137.         MOVX A,@DPTR
  138.         MOV  R1,A
  139.         MOV  DPH,R0
  140.         MOV  DPL,R1
  141.     
  142.         ;*UserStkPtr ===> R5  用户堆栈起始地址内容(即用户堆栈长度放在此处)  详见文档说明  指针用法详见C51.PDF第178页    
  143.         MOVX A,@DPTR     ;用户堆栈中是unsigned char类型数据
  144.         MOV  R5,A        ;R5=用户堆栈长度
  145.     
  146.         ;恢复现场堆栈内容
  147.         MOV  R0,#OSStkStart
  148.         
  149. restore_stack:
  150.     
  151.         INC  DPTR
  152.         INC  R0
  153.         MOVX A,@DPTR
  154.         MOV  @R0,A
  155.         DJNZ R5,restore_stack
  156.     
  157.         ;恢复堆栈指针SP
  158.         MOV  SP,R0
  159.     
  160.         ;恢复仿真堆栈指针?C_XBP        
  161.         INC  DPTR
  162.         MOVX A,@DPTR
  163.         MOV  ?C_XBP,A    ;?C_XBP 仿真堆栈指针高8位
  164.         INC  DPTR
  165.         MOVX A,@DPTR
  166.         MOV  ?C_XBP+1,A  ;?C_XBP 仿真堆栈指针低8位
  167.     
  168.         ;OSRunning=TRUE
  169.         MOV  R0,#LOW (OSRunning)
  170.         MOV  @R0,#01
  171.     
  172.         POPALL
  173.         SETB EA    ;开中断
  174.         RETI
  175. ;-------------------------------------------------------------------------
  176.         RSEG ?PR?OSCtxSw?OS_CPU_A
  177. OSCtxSw:    
  178.         PUSHALL
  179.     
  180. OSIntCtxSw_in:
  181.     
  182.         ;获得堆栈长度和起址
  183.         MOV  A,SP
  184.         CLR  C
  185.         SUBB A,#OSStkStart
  186.         MOV  R5,A     ;获得堆栈长度        
  187.     
  188.         ;OSTCBCur ===> DPTR  获得当前TCB指针,详见C51.PDF第178页
  189.         MOV  R0,#LOW (OSTCBCur) ;获得OSTCBCur指针低地址,指针占3字节。+0类型+1高8位数据+2低8位数据
  190.         INC  R0
  191.         MOV  DPH,@R0    ;全局变量OSTCBCur在IDATA中
  192.         INC  R0
  193.         MOV  DPL,@R0
  194.     
  195.         ;OSTCBCur->OSTCBStkPtr ===> DPTR  获得用户堆栈指针
  196.         INC  DPTR        ;指针占3字节。+0类型+1高8位数据+2低8位数据
  197.         MOVX A,@DPTR     ;.OSTCBStkPtr是void指针
  198.         MOV  R0,A
  199.         INC  DPTR
  200.         MOVX A,@DPTR
  201.         MOV  R1,A
  202.         MOV  DPH,R0
  203.         MOV  DPL,R1
  204.         
  205.         ;保存堆栈长度
  206.         MOV  A,R5
  207.         MOVX @DPTR,A
  208.     
  209.         MOV  R0,#OSStkStart  ;获得堆栈起址
  210. save_stack:
  211.     
  212.         INC  DPTR
  213.         INC  R0
  214.         MOV  A,@R0
  215.         MOVX @DPTR,A
  216.         DJNZ R5,save_stack
  217.         
  218.         ;保存仿真堆栈指针?C_XBP
  219.         INC  DPTR
  220.         MOV  A,?C_XBP    ;?C_XBP 仿真堆栈指针高8位
  221.         MOVX @DPTR,A
  222.         INC  DPTR
  223.         MOV  A,?C_XBP+1  ;?C_XBP 仿真堆栈指针低8位
  224.         MOVX @DPTR,A        
  225.     
  226.         ;调用用户程序
  227.         LCALL _?OSTaskSwHook
  228.         
  229.         ;OSTCBCur = OSTCBHighRdy
  230.         MOV  R0,#OSTCBCur
  231. MOV  R1,#OSTCBHighRdy
  232. MOV  A,@R1
  233.         MOV  @R0,A
  234.         INC  R0
  235. INC  R1
  236. MOV  A,@R1
  237.         MOV  @R0,A
  238.         INC  R0
  239. INC  R1
  240. MOV  A,@R1
  241.         MOV  @R0,A
  242.                 
  243.         ;OSPrioCur = OSPrioHighRdy  使用这两个变量主要目的是为了使指针比较变为字节比较,以便节省时间。
  244.         MOV  R0,#OSPrioCur
  245. MOV  R1,#OSPrioHighRdy
  246. MOV  A,@R1
  247.         MOV  @R0,A
  248.         
  249.         LJMP OSCtxSw_in
  250. ;-------------------------------------------------------------------------
  251.         RSEG ?PR?OSIntCtxSw?OS_CPU_A
  252.         
  253. OSIntCtxSw:
  254.         ;调整SP指针去掉在调用OSIntExit(),OSIntCtxSw()过程中压入堆栈的多余内容
  255.         ;SP=SP-4
  256.         MOV  A,SP
  257.         CLR  C
  258.         SUBB A,#4
  259.         MOV  SP,A
  260.         
  261.         LJMP OSIntCtxSw_in
  262. ;以下的中断处理函数移到C程序中,并按2.51格式改动
  263. ;-------------------------------------------------------------------------
  264. ;        CSEG AT 000BH    ;OSTickISR
  265. ;        LJMP OSTickISR   ;使用定时器0
  266. ;        RSEG ?PR?OSTickISR?OS_CPU_A
  267. ;
  268. ;OSTickISR:        
  269. ;        
  270. ;        USING 0        
  271. ;        PUSHALL
  272. ;在此实现用户时钟中断功能        
  273. ;        CLR  TR0
  274. ;        MOV  TH0,#70H    ;定义Tick=50次/秒(即0.02秒/次)
  275. ;        MOV  TL0,#00H    ;OS_CPU_C.C  和  OS_TICKS_PER_SEC
  276. ;        SETB TR0
  277. ;以下是必须的        
  278. ;        LCALL _?OSIntEnter
  279. ;        LCALL _?OSTimeTick
  280. ;        LCALL _?OSIntExit
  281. ;        POPALL        
  282. ;        RETI
  283. ;-------------------------------------------------------------------------
  284. ;        CSEG AT 0023H    ;串口中断
  285. ;        LJMP SerialISR   ;工作于系统态,无任务切换。
  286. ;        RSEG ?PR?_?serial?OS_CPU_A
  287. ;        
  288. ;SerialISR:
  289. ;        
  290. ;        USING 0        
  291. ;        PUSHALL
  292. ;        CLR  EA
  293. ;        LCALL _?serial        
  294. ;        SETB EA
  295. ;        POPALL        
  296. ;        RETI
  297. ;-------------------------------------------------------------------------
  298.         END
  299. ;-------------------------------------------------------------------------