⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 uart.asm

📁 DSP 5402 声音压缩 Demo板测试程序
💻 ASM
📖 第 1 页 / 共 4 页
字号:
	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 + -