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

📄 patchi2c.c

📁 MPC860的配置I2C示例代码
💻 C
字号:
/*
 *
 * File:  patchi2c.c
 * Description:  Simple I2C driver	using patch to relocate I2C parameters
 *
 *	Target device:  Any MPC8xx processor with a CPM-driven I2C
 *
 * This driver uses the RAM microcode patch which relocates the I2C and
 * SPI parameters to locations other than their default.
 *
 * The driver first loads and enables and enables the microcode.
 *
 * Then the driver sets up the I2C in master mode to transmit a message
 * to itself (i.e. loopback).  It performs an I2C write transmission to its
 * own station address.  [Note that loopback operation is not possible for
 * I2C read transmissions.]
 *
 * After sending the message, the driver 'terminates' in an infinite loop.
 *
 * NOTES <<<IMPORTANT:  PLEASE READ>>>:
 *    1) A pullup resistor is required on the I2C data and clock lines (PB27
 *       and PB26 of the MPC860)
 *    2) DISABLE Data Cache for pages containing Rx/Tx buffers.
 *
 *
 * 7/18/97    sgj         Initial version.
 * 10/14/97   sgj         Fixed bug -- initialize RSTATE and TSTATE params
 *
 */

#include <string.h>

#include "mpc860.h"
#include "patchi2c.h"

/* Internal Routines */
void startup(void);
void UcodeInit();
void RLI2CInit();	
void I2CStart();
void Main(void);

/* Set of I2C Receive Buffers and Transmit Buffer */
LB rtxbuf[NUM_RXBDS+1];

/* Stack Frame Stuff for mpc8bug */
int stack[100];
int stackTop;

/* Arrays containing I2C/SPI-parameter-relocating microcode patch */
unsigned long ucodeArray1[0x74] = 
{ 0x7fffefd9, 0x3ffd0000, 0x7ffb49f7, 0x7ff90000, 
  0x5fefadf7, 0x5f89adf7, 0x5fefaff7, 0x5f89aff7, 
  0x3a9cfbc8, 0xe7c0edf0, 0x77c1e1bb, 0xf4dc7f1d, 
  0xabad932f, 0x4e08fdcf, 0x6e0faff8, 0x7ccf76cf, 
  0xfd1ff9cf, 0xabf88dc6, 0xab5679f7, 0xb0937383, 
  0xdfce79f7, 0xb091e6bb, 0xe5bbe74f, 0xb3fa6f0f, 
  0x6ffb76ce, 0xee0df9cf, 0x2bfbefef, 0xcfeef9cf, 
  0x76cead24, 0x90b2df9a, 0x7fddd0bf, 0x4bf847fd, 
  0x7ccf76ce, 0xcfef7e1f, 0x7f1d7dfd, 0xf0b6ef71, 
  0x7fc177c1, 0xfbc86079, 0xe722fbc8, 0x5fffdfff, 
  0x5fb2fffb, 0xfbc8f3c8, 0x94a67f01, 0x7f1d5f39, 
  0xafe85f5e, 0xffdfdf96, 0xcb9faf7d, 0x5fc1afed, 
  0x8c1c5fc1, 0xafdd5fc3, 0xdf9a7efd, 0xb0b25fb2, 
  0xfffeabad, 0x5fb2fffe, 0x5fce600b, 0xe6bb600b, 
  0x5fcedfc6, 0x27fbefdf, 0x5fc8cfde, 0x3a9ce7c0, 
  0xedf0f3c8, 0x7f0154cd, 0x7f1d2d3d, 0x363a7570, 
  0x7e0af1ce, 0x37ef2e68, 0x7fee10ec, 0xadf8efde, 
  0xcfeae52f, 0x7d0fe12b, 0xf1ce5f65, 0x7e0a4df8, 
  0xcfea5f72, 0x7d0befee, 0xcfea5f74, 0xe522efde,  
  0x5f74cfda, 0x0b627385, 0xdf627e0a, 0x30d8145b, 
  0xbffff3c8, 0x5fffdfff, 0xa7f85f5e, 0xbffe7f7d, 
  0x10d31450, 0x5f36bfff, 0xaf785f5e, 0xbffda7f8, 
  0x5f36bffe, 0x77fd30c0, 0x4e08fdcf, 0xe5ff6e0f, 
  0xaff87e1f, 0x7e0ffd1f, 0xf1cf5f1b, 0xabf80d5e, 
  0x5f5effef, 0x79f730a2, 0xafdd5f34, 0x47f85f34, 
  0xafed7fdd, 0x50b24978, 0x47fd7f1d, 0x7dfd70ad, 
  0xef717ec1, 0x6ba47f01, 0x2d267efd, 0x30de5f5e, 
  0xfffd5f5e, 0xffef5f5e, 0xffdf0ca0, 0xafed0a9e, 
  0xafdd0c3a, 0x5f3aafbd, 0x7fbdb082, 0x5f8247f8
  };

unsigned long ucodeArray2[0x1d] = 
{ 0x3e303430, 0x34343737, 0xabf7bf9b, 0x994b4fbd,  
  0xbd599493, 0x349fff37, 0xfb9b177d, 0xd9936956,  
  0xbbfdd697, 0xbdd2fd11, 0x31db9bb3, 0x63139637,  
  0x93733693, 0x193137f7, 0x331737af, 0x7bb9b999,  
  0xbb197957, 0x7fdfd3d5, 0x73b773f7, 0x37933b99,  
  0x1d115316, 0x99315315, 0x31694bf4, 0xfbdbd359,  
  0x31497353, 0x76956d69, 0x7b9d9693, 0x13131979,  
  0x79376935
  };

/* startup -- Initial program entry point */
void  startup(void)
{

/* Stack Frame / Entrypoint Stuff for mpc8bug */
#ifdef MetaWare
	_ASM("_start:	.global	_start ");
	_ASM("		addis   %r1,%r0,stackTop@ha");
	_ASM("		ori     %r1,%r1,stackTop@l");
#else
#ifdef Diab
	 asm("_start:	.gbl	_start ");
	 asm("		addis   r1,r0,stackTop@ha");
	 asm("		ori     r1,r1,stackTop@l");
#endif
#endif

    Main();

    while(1);    /* loop here for a while */
}

void Main()
{
	 int breakonme = 0;

	 /* Initialize Microcode */
	 UcodeInit();
    /* Initialize I2C (using relocated parameters) */
    RLI2CInit();
	 /* Start I2C in loopback */
	 I2CStart();

	 breakonme++;  		 /* This is just a convenient place to break using
	                        a source-level debugger.  No significance. */

	 while(1);
}

/**************************************************************
  *
  * Microcode Initialization Routine  
  *
  * Function UcodeInit -- Copies two blocks of microcode (the
  *                       first to the lowest block of DPRAM,
  *                       the second to the microcode extension
  *                       block in DPRAM).  Then enables the
  *                       microcode
  *
  * Input Parameters:  none
  *
  *************************************************************/

void UcodeInit()
{
	EPPC *immr = (EPPC *) (GetIMMR() & 0xffff0000);
	unsigned long *targetptr;
	unsigned int i;

	immr->cp_rccr = 0;    /* Unlock microcode program area */

	/* Copy first block of microcode to lowest block of DPRAM */
	targetptr = (unsigned long *) & (immr->udata_bd_ucode);
	for(i=0; i<(0x74); i++) *(targetptr++) = ucodeArray1[i];

	/* Copy second block of microcode to microcode extension block of DPRAM */	
	targetptr = (unsigned long *) & (immr->ucode_ext);
	for(i=0; i<(0x1d); i++) *(targetptr++) = ucodeArray2[i];
	
	/* Activate the microcode per the instructions in the microcode manual*/ 
	immr->cp_rccr = 0;

	immr->cp_rctr3 = 0x802e;   /*  We're only relocating the I2C parameters */
	immr->cp_rctr4 = 0x802c;
	immr->cp_rccr = 1;
							   
}	


/**************************************************************
  *
  * I2C Initialization Routine	using relocated I2C parameters
  *
  * Function: I2CInit -- Initializes I2C registers, parameters,
  *                      and buffer descriptors
  *
  *  Sets pointer to relocated I2C parameters, then
  *  sets up I2C for write transmission to its own station
  *   address.  Interrupts are not enabled.
  *
  * Input Parameters:  none 
  *
  *************************************************************/

void RLI2CInit()
{
    EPPC *immr = (EPPC *) (GetIMMR() & 0xffff0000);    /* MPC8xx internal register map */
	 RTXBD *rtx = (RTXBD *) immr->udata_bd_ucode2;      /* Pointer to BD area of DPRAM */
	 char *txbuf;     
	 unsigned short *rpbase;             /* Pointer to relocated I2C parameters */
	 struct i2c_pram *rli2cparams;		/* Relocated I2C parameters */
	 unsigned long templong;		 /* Temporary unsigned long for pointer arithmetic */


  /* Point to RPBASE in old I2C param area */
	 templong = (unsigned long) (& (immr->pram[PAGE1_PRAM].scc.pothers.i2c_idma.i2c) );    
	 templong = templong + 0x0000002c;
	 rpbase = (unsigned short *) templong;

  /* Put I2C parameters in DSP2 area */
    rli2cparams = (struct i2c_pram *) (& (immr->pram[PAGE4_PRAM].scc.pothers.smc_modem.modem_param) );
 
 	 /* Relocate the I2C parameters */

	 *rpbase = 0x1fc0;  /* Locate parameters in DSP2 area (Offset from DPRAM base) */

    /* Configure Port B pins to enable I2CSDA and I2CSCL */

	 immr->pip_pbodr |= (0x0030);				  /* Set I2CSDA and I2CSCL to open-drain */

    immr->pip_pbpar |= (0x00000030);			  /* Enable I2CSDA and I2CSCL as outputs */
    immr->pip_pbdir |= (0x00000030);
    
    /* I2C Parameter RAM */
    rli2cparams->rfcr = 0x10;
    rli2cparams->tfcr = 0x10;
    rli2cparams->mrblr = BUFF_MAX_LEN;

    /* You have to manually initialize rstate and tstate if using the microcode patch.
	    [You don't normally have to for I2C */ 
    rli2cparams->rstate = 0;
	rli2cparams->tstate = 0;


	 /* I2C Registers */

	 immr->i2c_i2mod = 0x00;	   /* Disable I2C before initializing it */
	 immr->i2c_i2add = 0x80;	   /* Station address = 0x80 */
	 immr->i2c_i2brg = 0x20;	   /* Arbitrary choice of baud rate: BRGCLK/32 */
	 immr->i2c_i2cer = 0x17;	   /* Clear out I2C events */
	 immr->i2c_i2cmr = 0x00;	   /* Disable interrupts from I2C */
	 immr->i2c_i2mod = 0x01;
	 /* Note:  Original version of MPC860 manual states that the REVD=1 in the I2CMOD
	           register sends MSB first (I2C normal operation).  This was an ERRATUM.
			   REVD must be set to zero for normal I2C operation.

	 /* I2C Buffers */

	 /* point RBASE to first RX BD */
    rli2cparams->rbase = (unsigned short) & rtx->rxbd[0];
    /* point TBASE to TX BD */ 
	 rli2cparams->tbase = (unsigned short) & rtx->txbd; 

	 /* You have to manually initialize rbptr and tbptr if using the microcode patch.
	    [You don't normally have to for I2C */ 

	 rli2cparams->rbptr = rli2cparams->rbase;
	 rli2cparams->tbptr = rli2cparams->tbase;


	 rtx->rxbd[0].bd_length = 0;                   /* reset */
	 rtx->rxbd[0].bd_addr = (char *) & rtxbuf[0];  /* point RX BD to first RX buffer address */
	 rtx->rxbd[0].bd_cstatus = 0xa000;			   /* ready and wrap */

	 rtx->txbd.bd_length = 0x0019;
	 rtx->txbd.bd_addr = (char *) & rtxbuf[TXBD_INDX];

	 /* Put address and message in TX buffer */
	 txbuf = (char *) rtx->txbd.bd_addr;
	 txbuf[0] = 0x80;	    /* TX address and write command, sending to our own address 0x80 */
    strcpy((txbuf+1), "In-a-gadda-da-vida, baby");	    

	 rtx->txbd.bd_cstatus = 0xac00;				   /* ready, wrap, last, and start */

	 /*
	  * Init RX & TX Parameters Command not supported by the microcode patch,
	  * so do it in two separate commands.
	  */

	 /*
     * Issue Init RX Parameters Command for I2C.
     */

    while( immr->cp_cr & (0x0001) );    /* SPIN UNTIL READY TO ISSUE COMMAND */
    immr->cp_cr = (0x0111);    /* ISSUE COMMAND */
    while( immr->cp_cr & (0x0001) );    /* SPIN UNTIL COMMAND PROCESSED */

	 /*
     * Issue Init TX Parameters Command for I2C.
     */

    while( immr->cp_cr & (0x0001) );    /* SPIN UNTIL READY TO ISSUE COMMAND */
    immr->cp_cr = (0x0211);    /* ISSUE COMMAND */
    while( immr->cp_cr & (0x0001) );    /* SPIN UNTIL COMMAND PROCESSED */



}


/*
 * I2C Start routine
 *
 * Function: I2CStart -- sets master mode and starts the transmitter
 *
 */

void I2CStart()
{
    EPPC *immr = (EPPC *) (GetIMMR() & 0xffff0000);    /* MPC8xx internal register map */

	 immr->i2c_i2com = 0x81;		/*  Set master mode and issue start command */
}


/*
 * GetIMMR() returns the current value in IMMR register.
 */
GetIMMR()
{
#ifdef MetaWare
    _ASM(" mfspr  %r3,638 ");    /* IMMR is spr #638 */
#else
#ifdef Diab
    asm(" mfspr  r3,638 ");        /* IMMR is spr #638 */
#endif
#endif
}

⌨️ 快捷键说明

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