📄 isr.s03
字号:
; SERIAL PORT COMMUNICATIONS |
; |
; void Serial(void) |
; |
; This module is the serial port Interrupt Service Routine. It follows the standard uC/OS|
; procedure of interrupt handling: |
; |
; - machine registers saving |
; - OS entry notification (OSIntEnter) |
; - interrupt handling (application specific) |
; - OS exit notification (may result in a context switch) |
; - machine registers restoration. |
; |
; In this application, receive and transmit interrupts are handled as follows: |
; |
; - Receive interrupt: We test for a flag bit that denotes whether or not we are in a |
; code transfer. If so, we call procedure "Load_Code". If not in a |
; code transfer, we check if character received is a 'CR' (Carriage |
; Return), which would signal the end of a data block. In this case |
; we call the OS procedure to signal the communications semaphore |
; ("OSSemPost()"). This in turn will awaken the "Communications Ma- |
; nager" task, which is pending on this semaphore. This task will |
; look at the communications receive buffer, and will act on. |
; |
; If character is not a 'CR', it is simply stored in the buffer, and|
; the buffer pointer is incremented accordingly. |
; |
; - Transmit interrupt: We test a flag bit that signals whether this was the last byte |
; in a block to be transmitted. If it is, (flag cleared) the block |
; has been sent, and this is the indication. We simply reset the |
; block pointers. If it is not (flag set), we get the next byte in |
; the block, and send it. |
;----------------------------------------------------------------------------------------+
MODULE SERIAL ;Module name
RSEG CODE ;Relocatable segment
;<---[ Symbols available for other modules: ]-------------------------------------------->
PUBLIC Serial ;Handles microcontroller serial port
;<---[ Symbols referenced, in other modules: ]------------------------------------------->
EXTERN OSSemPost ;Module: Function to signal a semaphore
EXTERN OSIntEnter ;Module: Notify OS that interrupt is being serviced
EXTERN OSIntExit ;Module: Notify OS that interrupt is being exited
EXTERN Comm_Sem ;Address of the serial port semaphore handle
;<--------------------------------------------------------------------------------------->
Serial: ;Module entry point
push PSW ;Save PSW
push ACC ;Save accumulator
push b ;Save B register
push Bk0_r0 ;Save Bank #0 R0
push Bk0_r1 ;Save Bank #0 R1
push Bk0_r2 ;Save Bank #0 R2
push Bk0_r3 ;Save Bank #0 R3
push Bk0_r4 ;Save Bank #0 R4
push Bk0_r5 ;Save Bank #0 R5
push Bk0_r6 ;Save Bank #0 R6
push Bk0_r7 ;Save Bank #0 R7
push DPH ;Save Pointer high
push DPL ;Save Pointer low
push XSP ;Save xstack base pointer high
push XSP+1 ;Save xstack base pointer low
lcall OSIntEnter ;Read-modify-write increment of OSIntNesting
jbc TI, xmt_on ;Skip if transmit interrupt
clr RI ;It's a receive interrupt: clear bit
mov a, SBUF ;Get character
jnb COD_FLAG, ser_01 ;If we're not in the middle of a code download, get out
; call Load_Code ;We are: Load Code (call procedure...)
sjmp ser_00 ;..and return to caller
xmt_on: jnb XMT_FLAG, ser_00 ;If there is no transmission, we're done
mov a, Bk2_r0 ;Get pointer high to next byte to send
cjne a, Bk2_r2, not_yet ;Compare with top of block (h)
mov a, Bk2_r1 ;Get pointer low to next byte to send
cjne a, Bk2_r3, not_yet ;Compare with top of block (l)
clr XMT_FLAG ;Block transmitted: we're done
sjmp ser_00 ;..and get out
not_yet: mov DPH, Bk2_r0 ;Point to next byte (h)
mov DPL, Bk2_r1 ;..idem (l)
movx a, @dptr ;Get next byte to send
inc dptr ;Increment pointer
mov Bk2_r0, DPH ;Save data pointer in the registers
mov Bk2_r1, DPL ;..of bank #2
mov SBUF, a ;And transmit the data byte
sjmp ser_00 ;Return to code
ser_01: cjne a, #CR, ser_02 ;If not a "Carriage Return", go on
mov DPH, Bk3_r0 ;Load pointer to reception buffer (high)
mov DPL, Bk3_r1 ;Load pointer to reception buffer (low)
clr a ;Clear accumulator
movx @dptr, a ;Store block delimiter in reception buffer
mov Bk3_r0, #HIGH RCV_BUFF ;Set the pointer to the reception buffer..
mov Bk3_r1, #LOW RCV_BUFF ;..pointing to the buffer base
mov R7, #01 ;Parameter: pointer type (IAR specific)
mov dptr, #Comm_Sem + 1 ;Point to the semaphore handle (high)
movx a, @dptr ;Read pOS_EVENT high
mov R6, a ;Parameter: pointer high
inc dptr ;Increment pointer
movx a, @dptr ;Read pOS_EVENT low
mov R5, a ;Parameter: pointer low
call OSSemPost ;Call procedure to signal semaphore
sjmp ser_00 ;Return to code
ser_02: mov b, a ;Save byte received in register B
mov a, Bk3_r0 ;Load pointer to buffer (high)
cjne a, #HIGH XMT_BUFF, ser_03 ;Verify we do not overflow buffer
mov Bk3_r0, #HIGH RCV_BUFF ;Error: Reset pointers to the communication buffer..
mov Bk3_r1, #LOW RCV_BUFF ;..to the base of buffer
; mov ERR_BUFF, #OVERFLOW ;Log the error
sjmp ser_00 ;And return to code
ser_03: mov DPH, a ;Load pointer to reception buffer (high)
mov DPL, Bk3_r1 ;Load pointer to reception buffer (low)
mov a, b ;Retrieve character received
movx @dptr, a ;Pass byte to buffer
inc dptr ;Point to next location in buffer
mov Bk3_r0, DPH ;Save new pointer high
mov Bk3_r1, DPL ;Save new pointer low
mov SBUF, a ;Echo character to host
ser_00: lcall OSIntExit ;Decrement OSIntNesting
pop XSP+1 ;Restore xstack base pointer low
pop XSP ;Restore xstack base pointer high
pop DPL ;Restore pointer low
pop DPH ;Restore pointer high
pop Bk0_r7 ;Restore Bank #0 R7
pop Bk0_r6 ;Restore Bank #0 R6
pop Bk0_r5 ;Restore Bank #0 R5
pop Bk0_r4 ;Restore Bank #0 R4
pop Bk0_r3 ;Restore Bank #0 R3
pop Bk0_r2 ;Restore Bank #0 R2
pop Bk0_r1 ;Restore Bank #0 R1
pop Bk0_r0 ;Restore Bank #0 R0
pop b ;Restore register B
pop ACC ;Restore accumulator
pop PSW ;Restore PSW
reti ;Jump to execute scheduled task
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -