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

📄 bf53xsccb_interface.asm

📁 ADI BLACKFIN BF533 的IIC驱动程序
💻 ASM
📖 第 1 页 / 共 2 页
字号:
/******************************************************************************/
//
// Name: BF533 EZ-KIT video GP receive mode (8bit) for the Omnivision chip OV6630
//
/*****************************************************************************************************************


/*****************************************************************************************

(C) Copyright 2003 - Analog Devices, Inc.  All rights reserved.

File Name:				Main.asm

Date Modified:			01/08/07		TL		Rev 2.0

Software:       		VisualDSP++4.5, Assembler 1.1.0.2, Linker 3.8.0.2

Hardware:				BF533 EZ-KIT Board (rev 1.2), Blackfin EZ-Extender (rev 1.2)

Chip:					ADSP-BF533 REV 0.2

Special Connections:  None

Purpose:		To configure the ADV video devices 
				
				
Program Parameters:

************************************************************************************************/

/*************** SCCB Start Settings**************************************/
/*Before Calling the SCCB_Interface the inputs to the SCCB_Taskmanager 	 */
/*must be done. 														 */
/* Write to the "SCCB_Control" a "1" for reading from the Device or 	 */
/* a "2" for writing to the Device.										 */
/*																		 */
/* Leave the number of bytes totaly in "SCCB_Wordcount". Device Addresses*/
/* and Word Addresses included.											 */
/*																		 */
/* Write all data to the "SCCB_DataIn". 								 */
/* e.g.Writing to the device:											 */
/*																		 */
/*			SCCB_DataIn 			Device Address	(LSB must be Zero)	 */
/*									Word Address						 */
/*									Data 1								 */
/*									  .									 */
/*									  .									 */
/*************************************************************************/
/* (e.g.Reading from the device:										 */
/*			SCCB_DataIn 			Device Address	(LSB must be zero)   */
/*									Word Address						 */
/*									Device Address	(LSB must be one)	 */
/*									Data can be read via SCCB_DataOut	 */
/*************************************************************************/


#include <defBF533.h>

/*************** SCCB Constants  ************************************/
#define ISR_SCCB_Timer 0xFFE0202C	//Address of the interrupt register (EVT11 in this case)
#define System_MMR_High_Address 0xFFC00000	//The high address word is handled like pages
#define Core_MMR_High_Address 0xFFE00000	//The high address word is handled like pages
#define SCL_PERIOD 0x200                  // scl_period >= 133MHz/(3 x 0.4MHz)
#define SCL_HIGH SCL_PERIOD >> 1
#define SCL 0x1            // serial clock is PF0
#define SDA 0x2            // serial data is PF1
#define scl_bit 0          // scl = PF0
#define sda_bit 1          // sda = PF1
/*************** SCCB Variables  ************************************/
.section L1_data_a;
.var		SCCB_Variable_High_Address;
.var		SCCB_Control;
.var		SCCB_Bit_Count;
.var		SCCB_Word_Count;
.var		SCCB_Write_Read_Register;
.var		SCCB_Data_Pointer;
.var		SCCB_DataIn[60];				
.var		SCCB_DataOut[60];				
.var		SCCB_Point_of_State;
.var		SCCB_Read_Count;
.var        SCCB_In_Progress = 0;
.var		SCCB_Read_Start_Cond0_Task_Val;
/*************** SCCB Macros ****************************************/
//These macros are used in all routine to push/pop all registers 
//and to reset the timer interrupt again
#define SCCB_Start_Macro\
		[--SP] = ASTAT;\
		[-- SP] = (R7:0, P5:0)

#define SCCB_End_Macro\
		p0.h = hi(TIMER_STATUS);\
		p0.l = lo(TIMER_STATUS);\
		R0 = 0x0011 (z);\
		w[p0] = R0;\
		\
		(R7:0, P5:0) = [SP++];\
		ASTAT = [SP++];\
		SSYNC

/**********************************************************************/

/*************** SCCB Global Settings *********************************/
.section L1_code;
.global		SCCB_Interface;
.global		SCCB_Control;
.global		SCCB_Word_Count;
.global		SCCB_DataIn;				
.global		SCCB_DataOut;
.global		SCCB_Read_Count;
.global     SCCB_In_Progress;
/**********************************************************************/

	

/*************** SCCB Main Init ***************************************/
///////////////////////////////////////////////////////////////////////////
//No register must be kept for this Interface because all contents are	 //
//stored in the variables above. As you can see before entering the   	 //
//SCCB_Interface Subroutine all registers will be pushed onto the stack. //
//For each access to the SCCB device this subroutine will just be executed/
//one time. After execution the pushed registers are poped back again.   //
//The Timer interrupt initialized in this "asm" file will link to the    //
//subroutines required for this interface each time it comes up          //
//The data sent to the device will be eight bits wide for configuration  //
//purposes to video devices only.										 //
///////////////////////////////////////////////////////////////////////////
SCCB_Interface:
			[--SP] = ASTAT;
			[-- SP] = (R7:0, P5:0) ;

/*************** SCCB Timer Interrupt Vector Init ***********************/
//In case the timer will be used for several applications the Interrupt 
//vetctor for this Interface is set here. The address of the routine to be 
//executed at first is filled in the interrupt register here.

P0.H = hi(ISR_SCCB_Timer);
P0.L = lo(ISR_SCCB_Timer);	//Base address of the interrupt vector
r0.h =  SCCB_Start_Cond1;
r0.l =  SCCB_Start_Cond1;
[p0] = R0;				//ISR Start Address will be written in the EVT register

/*************** SCCB GPIO init as SDA and SCL ****************************/
	p0.h = hi(System_MMR_High_Address);		//High address of all the system registers

	// disable PF inputs    
    p0.l = lo(FIO_INEN);
    r0 = w[p0](z);
    bitclr(r0, scl_bit);
    bitclr(r0, sda_bit);
    w[p0] = r0;

	//The Flag PF1(SDA) and PF0(SCL) shall be high 
	p0.l = lo(FIO_FLAG_S);		
	r0 = w[p0](z);
	bitset(r0, scl_bit);
	bitset(r0, sda_bit);
	w[p0] = r0;

	
    //Set bit PF1(SDA) & PF0(SCL) as outputs
	p0.l = lo(FIO_DIR);
	r0 = w[p0](z);
	bitset(r0, scl_bit);
	bitset(r0, sda_bit);
	w[p0] = r0;

	
/*************************************************************************/

/***************** SCCB Timer0 Init ***************************************/
	p0.h = hi(System_MMR_High_Address);		//High address of all the system registers

	p0.l = lo(TIMER_STATUS);	
	r0.l = 0x0011;	w[p0] = r0;			//Clear Timer Interrupt and Overflow bit 

	p0.l = lo(TIMER_DISABLE);			//disable timer
	r1 = 0x0001(z);	
	w[p0] = r0;
	
	/* Setup Timer0:  PWM_OUT mode, pulse hi, count to end of */
	/* period, interrupt, sample TMR0 pin, enable pad,     */
	/* Bit configuration:  0x001D = 0000 0000 0001 1101		  */
	
	P0.L = lo(TIMER0_CONFIG);
	P0.H = hi(TIMER0_CONFIG);
	R0.L = 0x001D;
	W[P0] = R0.L;

	// The period is set to provide a 3:1 ratio of SCL to TMR0
	
	P0.L = lo(TIMER0_PERIOD);
	P0.H = hi(TIMER0_PERIOD);
	R0 = SCL_PERIOD (z);
	[P0] = R0;

	// Width of provides 50% duty cycle: scl_high = 1/2 of scl_period
	
	P0.L = lo(TIMER0_WIDTH);
	P0.H = hi(TIMER0_WIDTH);
	R0 = SCL_PERIOD >> 1 (z);
	[P0] = R0;

/*************************************************************************/

/*************** SCCB Timer0 Interrupt ************************************/
	p0.h = hi(System_MMR_High_Address);		//High address of all the system registers

	
	p0.l = lo(SIC_IMASK);		//Timer0 has been enabled
	r0 = [p0];
	bitset(r0,16);				
	[p0] = r0;


	p0.h = hi(IMASK);
	p0.l = lo(IMASK);
	r0 = [p0];
	bitset(r0,11);
	[p0] = r0;							//Enable the "IVEC11" interrupt

	p0.h = hi(System_MMR_High_Address);		//High address of all the system registers
	p0.l = lo(TIMER_ENABLE);				//enable timer
	r1 = 0x0001(z);	
	w[p0] = r0;

/*************************************************************************/

/*************** SCCB Start Setup ****************************************/
/*																		 */
/*************************************************************************/
//prepares the variables used in this Interface

	p1.h = SCCB_Variable_High_Address;	//works as a page for all Variables
	p2.h = SCCB_Variable_High_Address;

	p1.l = SCCB_Bit_Count;
	r0 = 0x8;
	[p1] = r0;	

	p1.l = SCCB_Read_Count;
	r0 = 0x2;               // dev wr addr + word addr to start
	[p1] = r0;
	
	
	p1.l = SCCB_Read_Start_Cond0_Task_Val;
	r0 = 0;               // due to an extra start condition at reading from device
	[p1] = r0;			  // this variable is reqired
	
	
	
	p1.l = SCCB_DataIn;
	p2.l = SCCB_Data_Pointer;
	[p2] = p1;
	p2.l = SCCB_Write_Read_Register;
	r0 = [p1];
	[p2] = r0;
/*************************************************************************/

		(R7:0, P5:0) = [SP++];
		ASTAT = [SP++];

SCCB_Interface.END:		
RTS;

//This is the end of the Init program. All other subroutine will be called
//by the Timer Interrupt separately.
/*************** SCCB End of Init ****************************************/




/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
//Each timer interrupt will just call one of the following subroutines.
//That restults to a SCCB speed depending of the Timer speed. The time 
//between the timer interrupts can be used for processing of user data
//there are no loops that would cause a decrease of processor speed

/*************** SCCB Start Cond1 ****************************************/
SCCB_Start_Cond1:
	SCCB_Start_Macro;

	p0.h = hi(System_MMR_High_Address);		//High address of all the system registers

	p0.l = lo(FIO_FLAG_C);		//The Flag PF1 (SDA) will be cleared at first (Start Condition!)	
	r0.l = SDA;
	w[p0] = r0;


	P0.H = hi(ISR_SCCB_Timer); P0.L = lo(ISR_SCCB_Timer);	//Base address of the interrupt vector
	r0.h =  SCCB_Start_Cond2; r0.l =  SCCB_Start_Cond2;
	[p0] = R0;				//ISR Start Address will be written in the EVT register


	SCCB_End_Macro;
RTI;
/*************** SCCB Start Cond2 ****************************************/
SCCB_Start_Cond2:

	SCCB_Start_Macro;

	p0.h = hi(System_MMR_High_Address);		//High address of all the system registers

	p0.l = lo(FIO_FLAG_C);		//The Flag PF0 (SCL) will be cleared at second (Start Condition!)
	r0.l = SCL;
	w[p0] = r0;

	P0.H = hi(ISR_SCCB_Timer); P0.L = lo(ISR_SCCB_Timer);	//Base address of the interrupt vector
	r0.h =  SCCB_Send_Data; r0.l =  SCCB_Send_Data;
	[p0] = R0;				//ISR Start Address will be written in the EVT register


	SCCB_End_Macro;
RTI;
/*************** SCCB Send Data to the Device*******************************/
//"SCCB_Send_Data" will send all the addresses and data required for communication
//to the device. The data must be shifted through the GPIO Pin PF1 (SDA)
SCCB_Send_Data:

	SCCB_Start_Macro;

	p0.h = hi(System_MMR_High_Address);	//High address of all the system registers
	p1.h = SCCB_Variable_High_Address;	//works as a page for all Variables

	p1.l = SCCB_Write_Read_Register;
	r0 = [p1];

	CC = BITTST(r0, 7);
	IF CC JUMP SCCB_Send_DATA_SET_SDA;	//Check the data bit in order to clear or 
	p0.l = lo(FIO_FLAG_C);				//The contents of the bit check was zero
	r5.l = SDA;
	w[p0] = r5;			//so the GPIO pin must been cleared
JUMP	SCCB_Bit_Sent_End;
	
SCCB_Send_DATA_SET_SDA:	
	p0.l = lo(FIO_FLAG_S);				//So, the GPIO pin must been set
	r5.l = SDA;
	w[p0] = r5;	

SCCB_Bit_Sent_End:					
	r0 = r0 << 1;						//shift the byte to get the next bit
	p1.l = SCCB_Write_Read_Register;	//save the shifted byte for the run
	[p1] = r0;

	p1.l = SCCB_Bit_Count;				//load the bit counter to count the 
	r1 = [p1];
	r1 += -1;							//decrement the bit counter. 
	[p1] = r1;							//So, that last bit can be detected

	P0.H = hi(ISR_SCCB_Timer); P0.L = lo(ISR_SCCB_Timer);	//Base address of the interrupt vector
	r0.h =  SCCB_Write_Clock; r0.l =  SCCB_Write_Clock;
	[p0] = R0;				//ISR Start Address will be written in the EVT register

	SCCB_End_Macro;
RTI;

SCCB_Send_DATA_Word_Sent:	//byte has been sent
	// enable PF inputs    
    p0.l = lo(FIO_INEN);
    r0 = w[p0](z);
    bitset(r0, sda_bit);
    w[p0] = r0;

	p0.l = lo(FIO_DIR);		
	r0.l = w[p0];
	bitclr(r0, sda_bit);    //configure SDA bit as an input to accept slave acknowledge
	w[p0] = r0;			

	P0.H = hi(ISR_SCCB_Timer); P0.L = lo(ISR_SCCB_Timer);	//Base address of the interrupt vector
	r0.h =  SCCB_ACK_TST; r0.l =  SCCB_ACK_TST;
	[p0] = R0;				//ISR Start Address will be written in the EVT register

	SCCB_End_Macro;
RTI;
/*************** SCCB Send Data to the Device finish *******************************/

/*************** SCCB SCCB Clock routine********************************************/
SCCB_Write_Clock:

	SCCB_Start_Macro;

	p0.h = hi(System_MMR_High_Address);		//High address of all the system registers
	p1.h = SCCB_Variable_High_Address;	//works as a page for all Variables

	p0.l = lo(FIO_FLAG_S);
	r0.l = W[p0];
	CC = BITTST (r0, scl_bit);
	IF CC JUMP SCCB_Set_Write_Clock_Low; // if scl high, then set it low
	r0 = SCL(z);                         // if scl low, then set it high
	w[p0] = r0;		

	SCCB_End_Macro;
RTI;     // remain in this state upon the next interrupt

SCCB_Set_Write_Clock_Low:

	p0.l = lo(FIO_FLAG_C);
	r0 = SCL(z);
	w[p0] = r0;

	p1.l = SCCB_Bit_Count;				//load the bit counter to count the 
	r1 = [p1];
	CC = r1 == 0;
	IF CC JUMP SCCB_Send_DATA_Word_Sent;//If eight bits are sent get the next byte

	P0.H = hi(ISR_SCCB_Timer); P0.L = lo(ISR_SCCB_Timer);	//Base address of the interrupt vector
	r0.h =  SCCB_Send_Data; r0.l =  SCCB_Send_Data;
	[p0] = R0;				//ISR Start Address will be written in the EVT register

	SCCB_End_Macro;
RTI;

/**************************************************************/
/*************** SCCB SCCB Acknowledge routines****************/

SCCB_ACK_Wait:   // After receiving a word an extra delay is insterted

	SCCB_Start_Macro;

	p0.h = hi(System_MMR_High_Address); //High address of all the system registers
	p1.h = SCCB_Variable_High_Address;	//works as a page for all Variables
	
	p1.l = SCCB_Word_Count;
	r1 = [p1];
	CC = r1 == 1;
	IF CC JUMP No_Acknowledge_By_Master;  

	// disable PF inputs    
    p0.l = lo(FIO_INEN);
    r0 = w[p0](z);
    bitclr(r0, sda_bit);
    w[p0] = r0;

	//Acknowledge by master
	p0.l = lo(FIO_DIR);		
	r0.l = w[p0];			//Clear SDA to drive the master acknowledge
	bitset(r0, sda_bit);    //configure SDA bit as an output
	w[p0] = r0;			
	
	p0.l = lo(FIO_FLAG_C);             // drive SDA low 			
	r0 = SDA(z);
	w[p0] = r0;

	
	P0.H = hi(ISR_SCCB_Timer);
	P0.L = lo(ISR_SCCB_Timer);	// Int Vector Base Addr
	r0.h =  SCCB_ACK_TST;
	r0.l =  SCCB_ACK_TST;       // next state: test for ACK
	[p0] = R0;
	
	SCCB_End_Macro;
RTI;




No_Acknowledge_By_Master:	

	p0.l = lo(FIO_FLAG_S);             // drive SCL high			
	r0 = SCL(z);
	w[p0] = r0;

	P0.H = hi(ISR_SCCB_Timer);
	P0.L = lo(ISR_SCCB_Timer);	// Int Vector Base Addr
	r0.h =  SCCB_ACK_MNGR;
	r0.l =  SCCB_ACK_MNGR;       // next state: test for ACK
	[p0] = R0;

⌨️ 快捷键说明

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