?? driv_internal_uart_asm.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 + -