?? uart.asm
字號:
bc SkipDisableTx,tc ; if another pkt is in buffer for Tx, don't disable DMA
andm #~TxDMACh,*(DMPREC) ; disable DMA channel for Tx
SkipDisableTx:
.if INTERRUPT_BASED
call _UARTTBEint ; call routine to handle transmitter reg empty
.endif
popm st0
rete ; return and enable global interrupts
*****************************************************************
* Function: _UARTTxChar *
* Purpose: Adds parity, start, and stop bits to *
* character to transmit. Puts coded character *
* into raw Tx buffer and resets the Transmit *
* Holding Register Empty flag. Only call when *
* THRE=1. *
* Inputs: al = character to transmit *
* Outputs: none *
* Modified: a,ar2,st0(tc,c),brc,rea,rsa *
*****************************************************************
_UARTTxChar:
pshm imr ; save the IMR state to restore Tx DMA int at end
andm #~TxDMAInt,*(imr) ; disable the DMA Tx interrupt (so DMA ISR doesn't change state here)
.if DMA_ABU_FIX; 5402 workaround (can't start DMA ABU in 2nd half of buffer)
bitf *(txbufhalf),#1 ; check if in 2nd half of buffer (txbufhalf=1)
bc NoAdjust,ntc ; if not, nothing to worry about, so skip out
cmpm *(numTxPkts),#0 ; check if DMA is disabled (no packets to transmit)
bc NoAdjust,ntc ; if DMA still on, nothing to worry about, so skip out
xorm #1,*(txbufhalf) ; set txbufhalf to 0 to point to 1st half
stm #TxDMAptr,DMSA ; set subaddress to Tx DMA Source register.
stm #Tx1stStart,DMSDN ; Set Tx DMA pointer to start of 1st half
NoAdjust:
.endif ; end 5402 workaround
bitf *(txbufhalf),#1 ; check if in 2nd half of buffer
xorm #1,*(txbufhalf) ; toggle the buffer half which is available
stm #Tx2ndStart,ar2 ; assume in 2nd half of buffer (point to start of this half)
xc 2,ntc ; if not,
stm #Tx1stStart,ar2 ; point ar2 to the start of first half of buffer
.if (PARITY==EVEN)|(PARITY==ODD) ;
call ParityCalc ; returns parity in TC: (0=even, 1=odd) and char in AL
.if PARITY==EVEN ;
xc 2,tc ; if need to add one to make even parity
or #1,DATABITS,a ; add in the parity bit
.endif
.if PARITY==ODD
xc 2,ntc ; if need to add one to make odd parity
or #1,DATABITS,a ; add in the parity bit
.endif ;
.elseif PARITY==MARK
or #1,DATABITS,a ; MARK parity always adds in the parity bit
.endif
stm #DATABITS+PARITYBITS-1,brc ; now translate the data and parity bits in the character
rptbd CodeLoop-1 ;
st #00000h,*ar2fwd ; write the start bit first
ror a ; rotate LSb out of A into C (carry bit)
st #00000h,*ar2 ; assume it is a zero and write code for 0 into buffer
xc 2,c ; if it was a 1 instead,
st #0ffffh,*ar2 ; write code for 1 into buffer
mar *ar2fwd ; increment buffer pointer
CodeLoop: ;
rpt #TxHSTOPBITS-1 ;
st #000ffh,*ar2fwd ; write the stop bits into the buffer
startTx:
addm #1,*(numTxPkts) ; increment number of pkts in Tx buffer
cmpm *(numTxPkts),#2 ; check if another pkt was already in buffer (now have 2)
andm #~THRE,*(_UARTLSR) ; signal that no space is available in Tx buffer (assume it now has 2 words)
bcd SkipDMARestart,tc ; if another pkt in buffer, skip the restart routine
stm #SPSA,ar2 ; point to McBSP subaddress register
st #SPCR2,*ar2+ ; write the SPCR2 subregister offset and point to access register
waitReady:
bitf *ar2,#XRDY ; check if XRDY==1
bc waitReady,ntc ; wait until serial port has clocked out any bits in XSR
stm #TxDMAptr,DMSA ; set subaddress to Tx DMA Source register
mvmd DMSDN,ar2 ; get source address w/o autoincrement and put in ar2
mvdk *ar2fwd,DXR1reg ; write first "bit" to DXR
mvdm ar2,DMSDN ; write decremented address to DMA
orm #TxDMACh,*(DMPREC) ; enable DMA channel for Tx data.
orm #THRE,*(_UARTLSR) ; signal that one space is still available in Tx buffer
SkipDMARestart:
popm imr ; restore state of IMR (turn Tx DMA int back on)
ret
*****************************************************************
* Function: _UARTRxChar *
* Purpose: Returns last character read by UART and *
* resets the Data Ready (DR) flag. *
* Inputs: none *
* Outputs: al = received character *
* intm = 0 *
* Modified: a *
*****************************************************************
_UARTRxChar:
pshm imr ; save the IMR state to restore Rx DMA int at end
andm #~RxDMAInt,*(imr) ; disable the DMA Rx interrupt
andm #~DR,*(_UARTLSR) ; once read, reset the flag
ld *(rxchar),a ; return the character in al
popm imr ; restore state of IMR (turn Rx DMA int back on)
ret
*****************************************************************
* Function: _UARTInit *
* Purpose: Initializes variables as well as the *
* McBSP and DMA registers. When this function *
* returns, the DMA and McBSP are initialized *
* but are not enabled. *
* Inputs: none *
* Outputs: none *
* Modified: ar2,a,brc,rea,rsa *
*****************************************************************
_UARTInit:
st #MASK1011b,*(mask1011b) ; init mask values
st #MASK0100b,*(mask0100b)
st #DECODER_MASK,*(decodeMask)
st #1,*(one) ; init 1
st #0,*(_UARTLSR) ; clear the status register
stm #SPCR1,SPSA ; write the SPCR1 sub-address
andm #~RRST,*(McBSPDataReg) ; write the SPCR1 register value to put rx in reset
stm #SPCR2,SPSA ; write the SPCR2 sub-address
andm #~(FRST|GRST|XRST),*(McBSPDataReg) ; write the SPCR2 register value to put tx in reset
stm #SPSA,ar2 ; point ar2 to McBSP subaddress register
ldx #McBSPInitTable,16,a ; get the program address of the McBSP init table
or #McBSPInitTable,a ; both high and low words
stm #(EndMcBSPInitTable-McBSPInitTable)/2-1,brc
rptb McBSPloop-1 ;
reada *ar2+ ; set the subaddress
add #1,a ; increment the table pointer
reada *ar2- ; write the value
add #1,a ; increment the table pointer
McBSPloop: ;
rpt #RESET_LATENCY-1
nop ; wait for McBSP to sync internally
andm #~(TxDMACh|RxDMACh),*(DMPREC) ; disable DMA channels for Tx and Rx data.
orm #(INTOSEL<<6),*(DMPREC) ; set multiplexed interrupt choices
andm #~(TxDMACh<<8|RxDMACh<<8),*(DMPREC); set DMA channel Priorities low (=0)
ldx #DMAInitTable,16,a ; get the program address of the DMA init table
or #DMAInitTable,a ; both high and low words
stm #DMSA,ar2 ; point ar2 to the DMA Rx channel subaddress register
reada *ar2+ ; store the first subaddress
add #1,a ; increment the table pointer
rpt #(EndDMARxInitTable-DMARxInitTable)-1
reada *ar2 ; write the values, autoincrementing
add #5,a ; update the table address
stm #DMSA,ar2 ; point ar2 to the DMA Tx channel subaddress register
reada *ar2+ ; store the first subaddress
add #1,a ; increment the table pointer
rpt #(EndDMATxInitTable-DMATxInitTable)-1
reada *ar2 ; write the values, autoincrementing
ret
*****************************************************************
* Function: _UARTStart *
* Purpose: Enables UART for reception by enabling the *
* Rx and TX DMA channels and taking the *
* receiver of McBSP out of reset. The *
* DMA is reinitialized in this routine to *
* ensure correct alignment of DMA pointers *
* in case DMA halted in mid-word last time. *
* Note that this routine will globally enable *
* all unmasked interrupts. *
* Inputs: a: -1 = start Rx only *
* 0 = start Rx and Tx *
* 1 = start Tx only *
* Outputs: none *
* Modified: imr,ifr,intm(st1),SPCR1,SPCR2,DMPREC *
*****************************************************************
_UARTStart:
stm #SPCR2,SPSA ; write the SPCR2 sub-address
orm #GRST,*(McBSPDataReg) ; enable clk generator (if not already enabled)
rpt #RESET_LATENCY-1
nop ; wait for 2 bit clocks
bc TxStartUp,agt ; if input denotes Tx only startup, branch
RxStartUp:
andm #~(BI|FE|PE|OE|DR),*(_UARTLSR) ; init the status reg bits for Rx to 0
st #0,*(rxbufhalf) ; initialize the half of Rx buffer to get bits from
stm #(RxDMAptr+1),DMSA ; set subaddress to Rx DMA Destination register.
stm #Rx1stStart,DMSDN ; DMDST: Destination is Receive raw data buffer
stm #RxDMAInt,ifr ; clear all pending Rx interrupts
orm #RxDMAInt,*(imr) ; enable the DMA Rx interrupt
orm #RxDMACh,*(DMPREC) ; enable DMA channel for Rx data.
stm #SPCR1,SPSA ; write the SPCR1 sub-address
orm #RRST,*(McBSPDataReg) ; write the SPCR1 register value to enable rx
bc SkipTxStartUp,alt ; if input denotes Rx only startup, branch
TxStartUp:
st #0,*(txbufhalf) ; initialize the half of Tx buffer to put bits in
orm #THRE,*(_UARTLSR) ; init the status reg bits for Tx (available for tx)
st #0,*(numTxPkts) ; init number of pkts in tx buffer to 0
stm #TxDMAptr,DMSA ; set subaddress to Tx DMA Source register.
stm #Tx1stStart,DMSDN ; DMSRC: Source is Transmit raw data buffer
stm #TxDMAInt,ifr ; clear all pending Tx interrupts
orm #TxDMAInt,*(imr) ; enable the DMA Tx interrupt
stm #SPCR2,SPSA ; write the SPCR2 sub-address
orm #XRST,*(McBSPDataReg) ; write the SPCR2 register value to enable tx
SkipTxStartUp:
rpt #RESET_LATENCY-1
nop ; wait for McBSP to come out of reset
rsbx intm ; enable maskable interrupts
ret
*****************************************************************
* Function: _UARTStop *
* Purpose: Disables UART for reception by disabling the *
* Rx and TX DMA channels and putting the *
* receiver and transmitter on McBSP in reset. *
* Waits until all data from Tx buffer *
* has been transmitted before it halts Tx UART. *
* Inputs: a: -1 = stop Rx only *
* 0 = stop Rx and Tx *
* 1 = stop Tx only *
* Outputs: none *
* Modified: ar2,imr,st0(tc),SPCR1,SPCR2,DMPREC *
*****************************************************************
_UARTStop:
bcd ShutDownTx,agt ; if input denotes Tx only shutdown, branch
stm #SPSA,ar2 ; point to McBSP subaddress register
ShutDownRx:
andm #~RxDMAInt,*(imr) ; disable the DMA Rx interrupt
andm #~RxDMACh,*(DMPREC) ; disable DMA channel for Rx data.
st #SPCR1,*ar2+ ; write the SPCR1 sub-address and point to access register
andm #~RRST,*ar2- ; write the SPCR1 register value to disable rx and move pointer back
andm #~DR,*(_UARTLSR) ; clear data ready flag so no more data received
bc SkipShutDownTx,alt ; if input denotes Rx only shutdown, branch
st #SPCR2,*ar2+ ; write the SPCR2 sub-address and point to access register
andm #~GRST,*ar2- ; disable clk generator when both rx and tx shutdown
ShutDownTx:
cmpm *(numTxPkts),#0 ;
bc ShutDownTx,ntc ; wait until all pkts have been sent
st #SPCR2,*ar2+ ; write the SPCR2 subregister offset and point to access register
waitDone:
bitf *ar2,#XRDY ; check if XRDY==1
bc waitDone,ntc ; wait until serial port has clocked out any bits in XSR
mar *ar2- ; point to subaddress register
andm #~TxDMAInt,*(imr) ; disable the DMA Tx interrupt
andm #~TxDMACh,*(DMPREC) ; disable DMA channel for Tx data.
st #SPCR2,*ar2+ ; write the SPCR2 sub-address and point to access register
andm #~XRST,*ar2- ; write the SPCR2 register value to disable tx and move pointer back
andm #~THRE,*(_UARTLSR) ; clear THRE flag so no more data sent
SkipShutDownTx:
rpt #RESET_LATENCY-1
nop ; wait for McBSP to go into reset
ret
*****************************************************************
* Function: _UARTSetBaudRate *
* Purpose: Sets new baud rate for UART. The UART MUST *
* be stopped before calling this routine. Use *
* _UARTStop to halt the UART (both tx and rx). *
* Inputs: a = new baud divisor *
* Outputs: none *
* Modified: a, SRGR1 *
*****************************************************************
_UARTSetBaudRate:
sub #1,a ; reduce divisor by 1 for correct storage to McBSP register
stm #SRGR1,SPSA ; write the SRGR1 sub-address to address register
stlm a,McBSPDataReg ; write the register value to data register
ret
*****************************************************************
* Function: _UARTSetBreak *
* Purpose: Sends a packet of all 0, including what *
* would normally be the stop & parity bits. *
* Must call with input of 0 to end the *
* break before can transmit another char. *
* Only call when THRE=1. *
* Inputs: a != 0 - send break *
* a = 0 - end break *
* Outputs: none *
* Modified: a,ar2,st0(tc) *
*****************************************************************
_UARTSetBreak:
pshm imr ; save the IMR state to restore Tx DMA int at end
andm #~TxDMAInt,*(imr) ; disable the DMA Tx interrupt (so DMA ISR doesn't change state here)
.if DMA_ABU_FIX; 5402 workaround (can't start DMA ABU in 2nd half of buffer)
bitf *(txbufhalf),#1 ; check if in 2nd half of buffer (txbufhalf=1)
bc NoAdjust2,ntc ; if not, nothing to worry about, so skip out
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -