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

📄 driv_internal_uart_asm.s

📁 UCOS-II2.76在ADI-BF533上的移植.在UCOS-II网站提供的源码基础上修改了几处汇编代码.采用2.76版系统内核移植,在DSP++4.0上调试成功
💻 S
字号:
/*
*********************************************************************************************************
*                                                uC/OS-II
*                                          The Real-Time Kernel
*
*										  Driver functions for
*										  ADSP-BF533 Internal Uart
*
* File : Driv_Internal_UART_Asm.s
* By   : Ron Territo   ron@territocomputerservices.com
*********************************************************************************************************

Copyright...

This code is placed in the public domain, and can be distributed freely with no restrictions provided that the heading
of each source module file is not modified to remove the credit to the original author.
  
Disclaimer...

This program code is provided "as is". There is no warranty, either expressed or implied as to its fitness for use in
any application. It is provided only as an example of porting the MicroC/OS operating system to the Blackfin processor.
Its use is strictly at the risk of the user. The author will not be liable for any damages direct or consequential related
to the use of this software including, but not limited to loss of profit.

*/



#include <cdefBF533.h>
#include "uCOS-II_V2.70\os_cfg.h";

.import "uCOS-II_V2.70\source\ucos_ii.h";


#define TX_BUFFER_SIZE 1024
#define RX_BUFFER_SIZE 1024


/*
*****************************************************************************
*
*	External functions &  variables
*
*****************************************************************************
*/

.extern _CpuRegisterEventHandler;
.extern _CpuIrqOff;
.extern _CpuIrqOn;
.extern _CpuEnableEvent;
.extern _CpuEnableInterrupt;
.extern _CpuSaveContext;
.extern _CpuRestoreContext;

.extern struct OS_TCB _OSTCBCur;
.extern _OSIntExit;
.extern _OSIntNesting;
.extern _OSRunning;
.extern _OSFlagCreate;
.extern _OSFlagPost;


/*
*********************************************************************************************************
*
*	Global Data
*
*********************************************************************************************************
*/


.section data1;

.global _EvUARTFlags;
.var _EvUARTFlags;

.var __OSErr;

.global _RxIntBufferEptr;
.var _RxIntBufferEptr;
.global _RxIntBufferFptr;
.var _RxIntBufferFptr;
.global _RxIntBufferTptr;
.var _RxIntBufferTptr;
.global _RxIntBuffer;
.byte _RxIntBuffer[RX_BUFFER_SIZE];

.global _TxIntBufferEptr;
.var _TxIntBufferEptr;
.global _TxIntBufferFptr;
.var _TxIntBufferFptr;
.global _TxIntBufferTptr;
.var _TxIntBufferTptr;
.global _TxIntBuffer;
.byte _TxIntBuffer[TX_BUFFER_SIZE];

.section program;


/*
*********************************************************************************************************
*
*               Internal UART Initialization
*
* Description: 	This function is called to initialize the Internal UART 
*
*
* Arguments  : 	Baud Rate,,,,  R0
*				Config'n.....  R1 
*
*				see defines for Baud and config in "Internal_UART.h"
*
*********************************************************************************************************
*/

.global _InternalUARTInit;

_InternalUARTInit:

	link 12;
	[ --sp ] = rets;					// save return address
	

	/* Load the Line Control Register */

	p1.H = ( UART_LCR >>16) & 0xFFFF;
	p1.L = ( UART_LCR & 0xFFFF );
	r2 = 0x80;							// set DL access in LCR	
	W [ p1 ] = r2;

	/* Load the divisor Register */
		
	p1.H = ( UART_DLL >>16) & 0xFFFF;	// set DL  high and low bytes
	p1.L = ( UART_DLL & 0xFFFF );
	r3 = 0xFF;
	r2 = r0 & r3;
	W [ p1 ] = r2;
	p1.H = ( UART_DLH >>16) & 0xFFFF;
	p1.L = ( UART_DLH & 0xFFFF );
	r0 >>= 8;
	r2 = r0 & r3;
	W [ p1 ] = r2;
	
	/* Enable the UART Clock */
	
	p1.H = ( UART_GCTL >>16) & 0xFFFF;	
	p1.L = ( UART_GCTL & 0xFFFF );
	r2 = 0x01;							// Enable clock ( no IrDA )
	W [ p1 ] = r2;

		
	/* Load the Line Control Register */

	p1.H = ( UART_LCR >>16) & 0xFFFF;
	p1.L = ( UART_LCR & 0xFFFF );
	r3 = 0x7F;
	r2 = r1 & r3;						// set config and not DL access	
	W [ p1 ] = r2;
	
	/* Load UART Interrupt Enable Register */
	
	p1.H = ( UART_IER >>16) & 0xFFFF;
	p1.L = ( UART_IER & 0xFFFF );
	r2 = 0x1;							// enable Rx only int
	W [ p1 ] = r2;

	
	/* Set exception vector */
			
	r0 = 10;							// Interrupt Event 10 = UART Rx Tx
	r1.H = _InternalUARTInt;
	r1.L = _InternalUARTInt;
	call _CpuRegisterEventHandler;
	
	/* Create a uC/OS Event Falg group for UART */
	
	r0 = 0; 							// Initial Flag value
	r1.H = __OSErr;						// address of error variable
	r1.L = __OSErr;
	call _OSFlagCreate;					// Call OS to create flag
	p1.H = _EvUARTFlags;
	p1.L = _EvUARTFlags;
	[ p1 ] = r0;						// store return value ( is FlagGroup address )
	p1.H = __OSErr;						// address of error
	p1.L = __OSErr;
	r0 = B [ p1 ] (Z);					// get error value
	cc = r0 == 0;
	if !cc jump _InternalUARTInitx;		// error

	/* Setup buffer pointers */
	
	r0.H = _RxIntBuffer;
	r0.L = _RxIntBuffer;
	p1.H = _RxIntBufferFptr;
	p1.L = _RxIntBufferFptr;
	[ p1 ] = r0;
	p1.H = _RxIntBufferEptr;
	p1.L = _RxIntBufferEptr;
	[ p1 ] = r0;
	r1 = RX_BUFFER_SIZE-1;
	r0 = r0 + r1;
	p1.H = _RxIntBufferTptr;
	p1.L = _RxIntBufferTptr;
	[ p1 ] = r0;

	r0.H = _TxIntBuffer;
	r0.L = _TxIntBuffer;
	p1.H = _TxIntBufferFptr;
	p1.L = _TxIntBufferFptr;
	[ p1 ] = r0;
	p1.H = _TxIntBufferEptr;
	p1.L = _TxIntBufferEptr;
	[ p1 ] = r0;
	r1 = TX_BUFFER_SIZE-1;
	r0 = r0 + r1;
	p1.H = _TxIntBufferTptr;
	p1.L = _TxIntBufferTptr;
	[ p1 ] = r0;
	
	
	/* Enable exception event */
	
	r0 = 0x400;							// Interrupt Mask 0x400 = UART Rx & Tx
	call _CpuEnableEvent;
	
	/* Enable peripheral interrupt */
	
	r0 = 0x3;							// Peripheral Interrupt mask for UART Rx & Tx
	r0 <<=14;
	call _CpuEnableInterrupt;

	r0 = 0;								// no error
	
_InternalUARTInitx:
	rets = [ sp++ ];					// Restore return address & exit	
	unlink;	
	rts;		
_InternalUARTInit.end:


/*
****************************************
*
*	Internal UART Interrupt Handler
* 		for uC/OS-II
*
****************************************
*/	

_InternalUARTInt:

/////////////////
// ISR Preamble
////////////////

	[ --sp ] = r0;
	[ --sp ] = r1;
	[ --sp ] = p1;
	cli r0;								// stop all ints & save mask
	[ --sp ] = r0;
		
	[ --sp ] = reti;					// save sys regs				
	[ --sp ] = astat;
					
		
//////////////////
// ISR Processing
//////////////////

__InternalUARTIntL:
//	p1.H = ( UART_IIR >>16) & 0xFFFF;
//	p1.L = ( UART_IIR & 0xFFFF );
//	r0 = W [ p1 ] (Z);					// read the Interrupt Identification Reg
	
//	cc = r0 < 0x02 (IU);				// no int				
//	if cc jump __InternalUARTIntE;

//	cc = r0 < 0x04 (IU);				// test Tx empty				
//	if cc jump __InternalUARTIntTx;
	
//	cc = r0 < 0x06 (IU);				// test Rx avail				
//	if cc jump __InternalUARTIntRx;
	
//	jump __InternalUARTIntErr;			// must be Err


	p1.H = ( UART_LSR >>16) & 0xFFFF;
	p1.L = ( UART_LSR & 0xFFFF );
	r0 = W [ p1 ] (Z);
	
	cc = bittst( r0,0 );
	if cc jump __InternalUARTIntRx;

	cc = bittst( r0,5 );
	if !cc 	jump __InternalUARTIntE;
	
	p1.H = ( UART_IER >>16 ) & 0xFFFF;
	p1.L = ( UART_IER & 0xFFFF );
	r0 = W [ p1 ] (Z);
	cc = bittst( r0,1 );
	if cc jump __InternalUARTIntTx;
	
	jump __InternalUARTIntE;
	
//----------------------------	
// Receive Character Available
//----------------------------
	
__InternalUARTIntRx:
	[ --sp ] = fp;						// save more sys registers
	[ --sp ] = rets;
	
	call _CpuSaveContext;				// save all register context

	p1.H = _RxIntBufferFptr;			// get "fill" pointer for Rx Buffer
	p1.L = _RxIntBufferFptr;
	p0 = [ p1 ];
	
	p2.H = ( UART_RBR >>16) & 0xFFFF;	// get the next character from UART
	p2.L = ( UART_RBR & 0xFFFF );
	r3 = W [ p2 ] (Z);

	r1 = 1;								// flag = Char Received
	
	r0 = p0;							// Rx Buffer "fill" pointer
	p2.H = _RxIntBufferTptr;			// Rx Buffer "top" pointer
	p2.L = _RxIntBufferTptr;
	r2 = [ p2 ];

	cc = r2 < r0;						// did we overflow RxBuffer ?
	if !cc jump __InternalUARTIntRx1;
	
	r2 = 0x02;
	r1 = r1 | r2;						// set Rx Overflow event flag
	
//	p1.H = ( UART_IER >>16) & 0xFFFF;	// stop any more ints
//	p1.L = ( UART_IER & 0xFFFF );
//	r0 =  W [ p1 ] (Z);
//	r2 = ~0x1;
//	r0 = r0 & r2;
//	W [ p1 ] = r0;

	jump	__InternalUARTIntRx2;

__InternalUARTIntRx1:

	B [ p0 ] = r3;						// store char in Rx Buffer
	r0 += 1;							// bump fill pointer
	[ p1 ] = r0;
	
	
__InternalUARTIntRx2:
	p1.H = _OSIntNesting;				// bump OS Int Nesting level
	p1.L = _OSIntNesting;
	r0 = [ p1 ];
	r0 += 1;				
	[ p1 ] = r0;
	
	link 0;
	p1.H = _EvUARTFlags;				// signal EvUARTFlag that Rx data is avail
	p1.L = _EvUARTFlags;
	r0 = [ p1 ];
	r2 = 1;								// option = OS_FLAG_SET
	r3.H = __OSErr;						// address of error var
	r3.L = __OSErr;
	[ --sp ] = r3;						// save args on stack
	[ --sp ] = r2;
	[ --sp ] = r1;						
	[ --sp ] = r0;						
	call _OSFlagPost;					// OSFlagPost();
	unlink;

	p1.H = _OSIntNesting;				// grind OS Int Nesting level
	p1.L = _OSIntNesting;
	r0 = [ p1 ];
	r0 += -1;				
	[ p1 ] = r0;

	call _CpuRestoreContext;			// restore register context
	rets = [ sp++ ];					// restore sys regs
	fp = [ sp++ ];
	
//	jump __InternalUARTIntE;
	jump __InternalUARTIntL;

	
//----------------------------	
// Transmit Buffer Empty
//----------------------------
	
__InternalUARTIntTx:
	[ --sp ] = fp;						// save more sys registers
	[ --sp ] = rets;
	
	call _CpuSaveContext;				// save all register context

	p0.H = _TxIntBufferFptr;			// get filling & emptying pointers
	p0.L = _TxIntBufferFptr;
	r0 = [ p0 ];
	p1.H = _TxIntBufferEptr;
	p1.L = _TxIntBufferEptr;
	r1 = [ p1 ];
	
	cc = r0 == r1;						// are we drained ?
	if !cc jump __InternalUARTIntTx1;	// no... go send next char
	 
	r0.H = _TxIntBuffer;				// reset pointers to buffer head
	r0.L = _TxIntBuffer;
	[ p0 ] = r0;
	[ p1 ] = r0;
	
	p0.H = ( UART_IER >>16) & 0xFFFF;	// stop any more tx ints
	p0.L = ( UART_IER & 0xFFFF );
	r0 =  W [ p0 ] (Z);
	bitclr ( r0, 1);
	W [ p0 ] = r0;

	r1 = 4;								// ev flag = TX Empty
	jump __InternalUARTIntTxX;
	
	
__InternalUARTIntTx1:
	p0 = r1;							// emptying pointer
	r1 += 1;							// bump emptying pointer
	[ p1 ] = r1;
	r0 = B [ p0 ] (Z);					// get char there			
	p0.H = ( UART_THR >>16) & 0xFFFF;
	p0.L = ( UART_THR & 0xFFFF );
	W [ p0 ] = r0;						// put char in UART transmiter
	r1 = 8;								// evflag = TX Ready

__InternalUARTIntTxX:
	p1.H = _OSIntNesting;				// bump OS Int Nesting level
	p1.L = _OSIntNesting;
	r0 = [ p1 ];
	r0 += 1;				
	[ p1 ] = r0;
	
	link 0;
	p1.H = _EvUARTFlags;				// signal EvUARTFlag that Tx data is sent
	p1.L = _EvUARTFlags;
	r0 = [ p1 ];
	r2 = 1;								// option = OS_FLAG_SET
	r3.H = __OSErr;						// address of error var
	r3.L = __OSErr;
	[ --sp ] = r3;						// save args on stack
	[ --sp ] = r2;
	[ --sp ] = r1;						
	[ --sp ] = r0;						
	call _OSFlagPost;					// OSFlagPost();
	unlink;

	p1.H = _OSIntNesting;				// grind OS Int Nesting level
	p1.L = _OSIntNesting;
	r0 = [ p1 ];
	r0 += -1;				
	[ p1 ] = r0;


	call _CpuRestoreContext;			// restore register context
	rets = [ sp++ ];					// restore sys regs
	fp = [ sp++ ];

//	jump __InternalUARTIntE;
	jump __InternalUARTIntL;

	
	
//----------------------------	
// Receive Error
//----------------------------
	
__InternalUARTIntErr:
	p1.H = ( UART_LSR >>16) & 0xFFFF;
	p1.L = ( UART_LSR & 0xFFFF );
	r0 = W [ p1 ] (Z);
//	jump __InternalUARTIntE;
	jump __InternalUARTIntL;
		

//////////////////
// ISR Postamble
/////////////////
	
__InternalUARTIntE:

	astat = [ sp++ ];				// restore sys regs
	reti = [ sp++ ];
	
	r0 = [ sp++ ];
	sti r0;
	p1 = [ sp++ ];
	r1 = [ sp++ ];
	r0 = [ sp++ ];	

	rti;				
	
_InternalUARTInt.end:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -