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

📄 bf53xsccb_interface.asm

📁 ADI BLACKFIN BF533 的IIC驱动程序
💻 ASM
📖 第 1 页 / 共 2 页
字号:
	SCCB_End_Macro;
RTI;



SCCB_ACK_TST:

	SCCB_Start_Macro;

	p0.h = hi(System_MMR_High_Address); //High address of all the system registers
	
	p0.l = lo(FIO_FLAG_S);             // drive SCL high			
	r0 = SCL(z);
	w[p0] = r0;
	
	r0.l = W[p0];
	CC = BITTST (r0,sda_bit);		//Check SDA input. It should be low

	IF CC JUMP SCCB_ACK_Error;	    //If not, something is wrong

	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; // task manager state
	[p0] = R0;
	
	SCCB_End_Macro;
RTI;
	
SCCB_ACK_MNGR:

	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_C);
	r0 = SCL (z);
	w[p0] = r0;      // toggle SCL to low
	
	
	[--SP] = RETS;			// enable nesting;  save return address to the stack
	CALL SCCB_Taskmanger;
	RETS = [sp++];

	SCCB_End_Macro;
RTI;


SCCB_ACK_Error:
NOP;	// An error occured due to a miss of a slave Acknowledge!
JUMP	SCCB_ACK_Error;

	SCCB_End_Macro;
RTI;
/*****************************************************************************************/

/*************** SCCB SCCB Taskmanger routine********************************************/
//The Taskmanager handles the different use of the interface. It can be written to the 
//device or read from the device. Up to sixty bytes can be written to 
//or read from the device. Finishing the data transfer links to the stop condition.

SCCB_Taskmanger:

	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
	p2.h = SCCB_Variable_High_Address;

	p1.l = SCCB_Bit_Count; 		//The bit counter must be loaded again after sending each byte
	r0 = 0x8;
	[p1] = r0;	

	p1.l = SCCB_Control;
	r0 = [p1];
	CC = r0 == 2;				//"1" means read from the device. "2" means write to the device
	IF CC JUMP SCCB_Write_Task;

	p1.l = SCCB_Read_Count;		//If read has been chosen care must been taken of the write read 
	r1 = [p1];					//interaction
	CC = r1 == 0;
	IF CC JUMP SCCB_Read1_Task;  // jump after first 3 bytes got sent

	p2.l = SCCB_Read_Start_Cond0_Task_Val;	
	r2 = [p2];								// in read mode after device addr and sub addr has 
	r2 = r1 | r2;							// been sent an extra start condition must be inserted	
	CC = r2 == 1;							// before the second device addr can be sent
	IF CC JUMP SCCB_Read_Start_Cond0_Task;	
	 
	CC = r1 == 3;
	IF CC JUMP SCCB_Read2_Task;	//"3" means start reading the device
	r1 += -1;                   // otherwise, decrement the count and keep writing
	[p1] = r1;

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

	p0.l = lo(FIO_DIR);		
	r0.l = w[p0];
	bitset(r0, sda_bit);		//configure SDA as output
	w[p0] = r0;

	p1.l = SCCB_Word_Count;
	r1 = [p1];
	r1 += -1;
	[p1] = r1;	
	CC = r1 == 0;		//check the number of bytes already sent 
	IF CC JUMP SCCB_Stop_Cond_Task;	//invoke the stop condition when all bytes are sent
	
	p1.l = SCCB_Data_Pointer;
	p2 = [p1];
	NOP;
	NOP;
	NOP;
	p3 = [p2++];		//Increment the pointer to the data array
	[p1] = p2;

	p1.l = SCCB_Write_Read_Register;
	r1 = [p2];
	[p1] = r1;
	
	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

RTS;

SCCB_Read_Start_Cond0_Task:
//insert a delay to place the read start condition
	P0.H = hi(ISR_SCCB_Timer); P0.L = lo(ISR_SCCB_Timer);	//Base address of the interrupt vector
	r0.h =  SCCB_Read_Start_Cond1_Task; r0.l =  SCCB_Read_Start_Cond1_Task;
	[p0] = R0;				//ISR Start Address will be written in the EVT register

RTS;

SCCB_Read_Start_Cond1_Task:
	SCCB_Start_Macro;
//in order to generate the read start condition SDA & SCL must be set to high

	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

	// disable PF inputs    
    p0.l = lo(FIO_INEN);
    r0 = w[p0](z);
    bitclr(r0, sda_bit);
    w[p0] = r0;
	
	p0.l = lo(FIO_DIR);		
	r0.l = w[p0];
	bitset(r0, sda_bit);	//configure SDA as output
	w[p0] = r0;

	p0.l = lo(FIO_FLAG_S);
	r0 = SCL | SDA(z);
	w[p0] = r0;	   // set SDA & SCL

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

	SCCB_End_Macro;
RTI;	

SCCB_Read_Start_Cond2_Task:
	SCCB_Start_Macro;
//clear SDA at first to begin the start condition
	
	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_C);
	r0 = SDA(z);
	w[p0] = r0;	   //SDA to low
	
	p1.l = SCCB_Read_Start_Cond0_Task_Val;	//after the read start condition has been executed 
	r0 = 0x8 (z);						//it must never apear again
	[p1] = r0;
	
	P0.H = hi(ISR_SCCB_Timer); P0.L = lo(ISR_SCCB_Timer);	//Base address of the interrupt vector
	r0.h =  SCCB_ACK_MNGR; r0.l =  SCCB_ACK_MNGR;
	[p0] = R0;				//ISR Start Address will be written in the EVT register

	SCCB_End_Macro;
RTI;	
	
SCCB_Stop_Cond_Task:
//start the stop condition procedure after all bytes has been sent
	
	P0.H = hi(ISR_SCCB_Timer); P0.L = lo(ISR_SCCB_Timer);	//Base address of the interrupt vector
	r0.h =  SCCB_Stop_Cond0; r0.l =  SCCB_Stop_Cond0;
	[p0] = R0;				//ISR Start Address will be written in the EVT register

RTS;

SCCB_Read1_Task:
	p1.l = SCCB_Read_Count;
	r0 = 3;
	[p1] = r0;

	p1.l = SCCB_Write_Read_Register;	//Get the data to send
	r0 = 0;
	[p1] = r0;

	p1.l = SCCB_DataOut;
	p2.l = SCCB_Data_Pointer;
	[p2] = p1;

SCCB_Read2_Task:

	p1.l = SCCB_Word_Count;
	r1 = [p1];
	r1 += -1;
	[p1] = r1;	

	CC = r1 == 0;
	IF CC JUMP SCCB_Stop_Cond_Task;	// Link to the Stop condition after all bytes has been received
	
	// make sure SDA is configured as input
	// 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 = w[p0](z);
	bitclr(r0, sda_bit);
	w[p0] = r0;
	
	P0.H = hi(ISR_SCCB_Timer); P0.L = lo(ISR_SCCB_Timer);	//Base address of the interrupt vector
	r0.h =  SCCB_Rcv_Clk_Test; r0.l =  SCCB_Rcv_Clk_Test;
	[p0] = R0;				//ISR Start Address will be written in the EVT register

RTS;


/*************** SCCB Receive Data***************************************/
SCCB_Receive_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
	p2.h = SCCB_Variable_High_Address;

	p1.l = SCCB_Write_Read_Register;	//Get the current rcv byte
	r0 = [p1];
	r0 = r0 << 1;						//shift the byte to get the next bit

	p1.l = SCCB_Word_Count;
	r1 = [p1];
	CC = r1 == 0;		//check the number of bytes already received 
	IF CC JUMP SCCB_Stop_Receive_Data;	

	p0.l = lo(FIO_FLAG_S);
	r5.l = w[p0];
	CC = BITTST (r5,sda_bit);		//Check the SDA bit.
	IF CC JUMP SCCB_Receive_High_detected;	
	
	BITCLR (r0,0);
JUMP	SCCB_End_of_Receive_Bit;

SCCB_Receive_High_detected:
	BITSET (r0,0);

SCCB_End_of_Receive_Bit:

	p0.l = lo(FIO_FLAG_C);
	r5.l = SCL;                      // drive SCL low
	w[p0] = r5;

	p1.l = SCCB_Write_Read_Register; //save the shifted byte for the run
	[p1] = r0;

	p1.l = SCCB_Bit_Count;           // update the bit count
	r1 = [p1];
	r1 += -1;
	[p1] = r1;	
	CC = r1 == 0;                   // check if it was the last bit
	IF CC JUMP SCCB_Receive_Data_Word_Sent; // jump when last bit

	P0.H = hi(ISR_SCCB_Timer);
	P0.L = lo(ISR_SCCB_Timer);	//Base address of the interrupt vector
	r0.h =  SCCB_Rcv_Clk_Test;
	r0.l =  SCCB_Rcv_Clk_Test;   // next state
	[p0] = R0;

	SCCB_End_Macro;
RTI;

SCCB_Receive_Data_Word_Sent:

	p1.l = SCCB_Data_Pointer;
	p2 = [p1];
	p3.l = SCCB_Write_Read_Register;	//save the shifted byte for the run
	p3.h = SCCB_Write_Read_Register;	
	r0 = [p3];
	[p2] = r0;
	r0 = 0;
	[p3] = r0;			//clear the content of "SCCB_Write_Read_Register" for next byte
	NOP;				//3 cycles will be required for read an write action
	NOP;
	NOP;
	p3 = [p2++];		//Increment the pointer to the data array
	[p1] = p2;

	P0.H = hi(ISR_SCCB_Timer);
	P0.L = lo(ISR_SCCB_Timer); //Base address of the interrupt vector
	r0.h =  SCCB_ACK_Wait; 
	r0.l =  SCCB_ACK_Wait;    //go to this state to wait one int period 
	[p0] = R0;

	SCCB_End_Macro;
RTI;

SCCB_Stop_Receive_Data:
	// disable PF inputs    
    p0.l = lo(FIO_INEN);
    r0 = w[p0](z);
    bitclr(r0, sda_bit);
    w[p0] = r0;
	
	p0.l = lo(FIO_DIR);		
	r0.l = w[p0];
	bitset(r0, sda_bit); // configure SDA as output 
	w[p0] = r0;

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

	SCCB_End_Macro;
RTI;
/*************** SCCB Receive Clock Test routine********************************************/

SCCB_Rcv_Clk_Test:

	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_Rcv_Clk_Lo;    // if scl high, jump to clear it
	
	// if scl low, then set it high in the next state
	P0.H = hi(ISR_SCCB_Timer);
	P0.L = lo(ISR_SCCB_Timer);  //interrupt vector base addr
	r0.h =  SCCB_Rcv_Clk_Hi;
	r0.l =  SCCB_Rcv_Clk_Hi;    // next state
	[p0] = R0;
	
	SCCB_End_Macro;
RTI;

SCCB_Set_Rcv_Clk_Lo:

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

	SCCB_End_Macro;
RTI;      // stay in this state until the next interrupt

/*****************************************************************/
/*************** SCCB Receive Clock Hi routine********************/

SCCB_Rcv_Clk_Hi:

	SCCB_Start_Macro;

	p0.h = hi(System_MMR_High_Address);		//High address of all the system registers
	p0.l = lo(FIO_FLAG_S);
	r0 = SCL (z);
	w[p0] = r0;                             // set SCL high
	
	P0.H = hi(ISR_SCCB_Timer);
	P0.L = lo(ISR_SCCB_Timer);  //interrupt vector base addr
	r0.h =  SCCB_Receive_Data;
	r0.l =  SCCB_Receive_Data;  // next state
	[p0] = R0;
	
	SCCB_End_Macro;
RTI;


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

/*************** SCCB Stop Cond0,1 ****************************/
//Invoke stop condition if the transmission is complete
SCCB_Stop_Cond0:  // do nothing (just a delay)

	SCCB_Start_Macro;

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

	SCCB_End_Macro;
RTI;

SCCB_Stop_Cond1:

	SCCB_Start_Macro;

	p0.h = hi(System_MMR_High_Address);		//High address of all the system registers
	p0.l = lo(FIO_FLAG_S);	
	r0 = SCL(z);
	w[p0] = r0;

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

	SCCB_End_Macro;
RTI;
/*************** SCCB Stop Cond2 ****************************************/
SCCB_Stop_Cond2:

	SCCB_Start_Macro;

	p0.h = hi(System_MMR_High_Address);		//High address of all the system registers
	p0.l = lo(FIO_FLAG_S);		            //set SDA high to stop
	r0 = SDA (z);
	w[p0] = r0;

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

	SCCB_End_Macro;
RTI;
/*************** SCCB Stop Cond2 ****************************************/
//The transmission ends and all the timer settings must be diabled
//This would be a good place to set a bit to replay the transfer is done
SCCB_End_of_Transmission:

	SCCB_Start_Macro;

	p0.l = lo(TIMER_DISABLE);			//disable timer
	r1 = 0x0001(z);	
	w[p0] = r0;

	p0.h = hi(System_MMR_High_Address);		//High address of all the system registers
	p0.l = lo(TIMER_STATUS);	
	r0 = 0x1011(z);
	w[p0] = r0;	//disable the timer clear interrupt bit and overflow bit

   	p0.l = lo(SIC_IMASK);				//disable mask the Timer0 again
	r0 = [p0];
	bitclr(r0,16);
	[p0] = r0;
	
	p0.h = SCCB_In_Progress;       //keeps the core away from calling the SCCB twice
	p0.l = SCCB_In_Progress;
	r0 = 0;
	[p0] = r0;
	
	SCCB_End_Macro;

RTI;
/*****************************************************************************************/

⌨️ 快捷键说明

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