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

📄 spi驱动.txt

📁 MPC850的SPI接口的驱动
💻 TXT
📖 第 1 页 / 共 2 页
字号:
/* sysSpiNvRam.c - SPI interface to serial EEPROM library */

/* Copyright 1984-1996 Wind River Systems, Inc. */
#include "copyright_wrs.h"

/*
modification history
--------------------
*/

/*
DESCRIPTION
This library contains routines to manipulate non-volatile RAM (NV-RAM)
which is accessed as a Serial Peripheral Interface (SPI). Read and write
routines are included.

The macro NV_RAM_SIZE must be defined to provide parameter checking
for sysNvRamSet() and sysNvRamGet(). The macro NV_BOOT_OFFSET must be
defined and point to an offset that allows enough room for 256 bytes.

This library provides processor specific routines.

SEE ALSO:
.pG "Configuration" */


/* includes */

#include "vxWorks.h"
#include "vme.h"
#include "memLib.h"
#include "cacheLib.h"
#include "sysLib.h"
#include "config.h"
#include "string.h"
#include "intLib.h"
#include "logLib.h"
#include "stdio.h"
#include "taskLib.h"
#include "vxLib.h"
#include "arch/ppc/vxPpcLib.h"
#include "drv/sio/ppc860Sio.h"
#include "drv/multi/ppc860Siu.h"
#include "yourBsp.h" /* e.g. ads860.h */

/* Definitions for SPI. */
#define SPI_RX_BD_BASE 0x480
#define SPI_TX_BD_BASE 0x488

#define SPI_TX_BUF_SZ 0x100
#define SPI_RX_BUF_SZ 0x100
#define SPI_TRANS_RX_BD_LAST 0x0800 /* last in frame */
#define SPI_TRANS_RX_BD_WRAP 0x2000 /* wrap back to first BD */
#define SPI_TRANS_RX_BD_EMPTY 0x8000 /* buffer is empty */
#define SPI_TRANS_TX_BD_LAST 0x0800 /* last in frame */
#define SPI_TRANS_TX_BD_WRAP 0x2000 /* wrap back to first BD */
#define SPI_TRANS_TX_BD_READY 0x8000 /* ready for Tx */

#define SPI_INTERFACE_PINS 0x0000E
#define EnSPI 0x0F77
#define DisSPI 0x0E77
#define SPI_STR 0x80

#define SPI_SERIAL_EEPROM_SZ NV_RAM_SIZE /* bytes */
#define SPI_SERIAL_CMD_SEQ_SZ 3

LOCAL UCHAR eep_wt_scratch[(SPI_SERIAL_EEPROM_SZ + SPI_SERIAL_CMD_SEQ_SZ)];
LOCAL UCHAR* eep_wt_ptr;

LOCAL UCHAR spiTxBuf[SPI_TX_BUF_SZ];
LOCAL UCHAR spiRxBuf[SPI_RX_BUF_SZ];

typedef struct /* SPI_BUF */
{
VUINT16 statusMode; /* status and control */
VUINT16 dataLength; /* length of data buffer in bytes */
u_char * dataPointer; /* points to data buffer */
} SPI_BD;

typedef struct /* SPI_PARAM */
{
VUINT16 rbase; /* Rx buffer descriptor base address */
VUINT16 tbase; /* Tx buffer descriptor base address */
VUINT8 rfcr; /* Rx function code */
VUINT8 tfcr; /* Tx function code */
VUINT16 mrblr; /* maximum receive buffer length */
VUINT32 rstate; /* Rx internal state */
VUINT32 res1; /* reserved/internal */
VUINT16 rbptr; /* Rx buffer descriptor pointer */
VUINT16 res2; /* reserved/internal */
VUINT32 res3; /* reserved/internal */
VUINT32 tstate; /* Tx internal state */
VUINT32 res4; /* reserved/internal */
VUINT16 tbptr; /* Tx buffer descriptor pointer */
VUINT16 res5; /* reserved/internal */
VUINT32 res6; /* reserved/internal */
VUINT32 res7; /* reserved/internal */
VUINT16 rpbase; /* relocatable parameter ram base */
VUINT16 res8; /* reserved/internal */
} SPI_PARAM;
typedef SPI_PARAM *pSPI_PARAM;
typedef SPI_BD * pSPI_BD ;

typedef struct spi_dev
{
BOOL init;
BOOL open;
pSPI_PARAM pPram;
pSPI_BD pTxBdBase;
UINT16 txBdBaseOffset;
int txBdNext;
pSPI_BD pRxBdBase;
UINT16 rxBdBaseOffset;
int rxBdNext;
VUINT32 xmitState;
VUINT32 rcvState;
VUINT32 regBase; /* register/DPR base address */
VUINT32 dualpRam; /* dual port ram base address */
VUINT16 pram_base_offset;
INT32 loopbackType; /* type of loopback to use */
} SPI_DEV;

LOCAL SPI_DEV spiDev =
{
FALSE, FALSE, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL
};


/* Forward declarations for NV-RAM (serial EEPROM). */
LOCAL STATUS sysNvRamGetStatus(
void);
LOCAL void sysNvRamWriteEnable(
void);
LOCAL void sysNvRamWriteByte(
UCHAR data,
USHORT eep_addr);


/******************************************************************************
*
* sysHwSpiInit - initializes NV-RAM
*
* This routine initializes NV-RAM to prepare for subsequent reads from or
* writes to NV-RAM.
*
* RETURNS: none
*/

void sysHwSpiInit(
void)
{
SPI_DEV* pSpi;


pSpi = &spiDev;

/* SPI initialization cannot occur more than once. */
if (pSpi->init == TRUE)
{
return;
}

/* Get IMMR register base. */
pSpi->regBase = vxImmrGet();

/* Get pointer to dual-ported RAM. */
pSpi->dualpRam = (INT32) DPRAM(pSpi->regBase);

/* Set pointer to SPI parameter RAM. */
pSpi->pPram = (pSPI_PARAM) (PPC860_DPR_SPI(pSpi->dualpRam));

/* Clear parameter RAM values. */
pSpi->pPram->rbase = 0;
pSpi->pPram->tbase = 0;
pSpi->pPram->rfcr = 0;
pSpi->pPram->tfcr = 0;
pSpi->pPram->mrblr = 0;
pSpi->pPram->rstate = 0;
pSpi->pPram->res1 = 0;
pSpi->pPram->rbptr = 0;
pSpi->pPram->res2 = 0;
pSpi->pPram->res3 = 0;
pSpi->pPram->tstate = 0;
pSpi->pPram->res4 = 0;
pSpi->pPram->tbptr = 0;
pSpi->pPram->res5 = 0;
pSpi->pPram->res6 = 0;
pSpi->pPram->rpbase = 0;
pSpi->pPram->res8 = 0;

/* Set up SCC dual-ported RAM. */
#ifdef INCLUDE_CPM
{
UINT32 tempeRx = (UINT32) allocDpramFromPool(8);
UINT32 tempeTx = (UINT32) allocDpramFromPool(8);
pSpi->rxBdBaseOffset = (UINT16) (tempeRx & 0x0000FFFF);
pSpi->txBdBaseOffset = (UINT16) (tempeTx & 0x0000FFFF);

/* Adjust dual port RAM addresses, which are offsets from IMMR. */
pSpi->rxBdBaseOffset -= 0x2000;
pSpi->txBdBaseOffset -= 0x2000;
}
#else
pSpi->rxBdBaseOffset = (UINT16) SPI_RX_BD_BASE;
pSpi->txBdBaseOffset = (UINT16) SPI_TX_BD_BASE;
#endif
pSpi->pRxBdBase = (pSPI_BD) (pSpi->dualpRam + pSpi->rxBdBaseOffset);
pSpi->pTxBdBase = (pSPI_BD) (pSpi->dualpRam + pSpi->txBdBaseOffset);

/*
** Configure port B pins to enable SPIMOSI, SPIMISO and SPICLK pins.
** PBPAR and PBDIR bits 30, 29, 28 ones;
** PBODR bits 30, 29, 28 zeros.
** (SPI_INTERFACE_PINS is 0xE.)
*/
*PBPAR(pSpi->regBase) |= SPI_INTERFACE_PINS;
*PBDIR(pSpi->regBase) |= SPI_INTERFACE_PINS;

/* Set up the Port B pins. */
*PBPAR(pSpi->regBase) &= ~0x00001; /* make CS a GP I/O pin */
*PBDIR(pSpi->regBase) |= 0x00001;
*PBDAT(pSpi->regBase) |= 0x00001; /* de-assert for now */

/*
** Write RBASE and TBASE in the SPI parameter RAM to point to
** Rx BD and Tx BD in dual port RAM.
*/
pSpi->pPram->rbase = (UINT16) ((UINT32) pSpi->rxBdBaseOffset & 0x0000ffff);
pSpi->pPram->tbase = (UINT16) ((UINT32) pSpi->txBdBaseOffset & 0x0000ffff);

/* Initialize Rx and Tx parameters for SPI. */
*MPC860_CPCR(pSpi->regBase) = 0x0051;

/* Wait for initialization to complete. */
while (*MPC860_CPCR(pSpi->regBase) & 1)
{
/* Busy-wait. */
;
}

/* Initialize the SDMA register. */
*MPC860_SDCR(pSpi->regBase) |= 0x0001;

/* Write MRBLR with the maximum # of bytes per receive. */
/* SPI_RX_BUF_SZ is 0x100. */
pSpi->pPram->mrblr = 1;

/* Write RFCR and TFCR for normal operation. */
/* MPC860_RFCR_MOT_BE is 0x18. */
pSpi->pPram->rfcr = MPC860_RFCR_MOT_BE;
pSpi->pPram->tfcr = MPC860_RFCR_MOT_BE;

/* Set up buffer pointers. */
eep_wt_ptr = &eep_wt_scratch[0];

/* Initialize buffer descriptors. */
pSpi->pTxBdBase->statusMode =
(SPI_TRANS_TX_BD_LAST | SPI_TRANS_TX_BD_WRAP);
pSpi->pTxBdBase->dataLength = 0;
pSpi->pTxBdBase->dataPointer = spiTxBuf;

pSpi->pRxBdBase->statusMode =
(SPI_TRANS_RX_BD_EMPTY | SPI_TRANS_RX_BD_LAST | SPI_TRANS_RX_BD_WRAP);
pSpi->pRxBdBase->dataLength = 0;
pSpi->pRxBdBase->dataPointer = spiRxBuf;

/* Clear events. */
*MPC860_SPIE(pSpi->regBase) = 0xFF;

pSpi->init = TRUE;

*MPC860_SPMODE(pSpi->regBase) = DisSPI;

return;
} /* end of sysHwSpiInit */


/******************************************************************************
*
* sysNvRamGet - get the contents of non-volatile RAM
*
* This routine copies the contents of non-volatile memory into a specified
* string. The string is terminated with an EOS.
*
* RETURNS: OK, or ERROR if access is outside the non-volatile RAM range.
*
* SEE ALSO: sysNvRamSet(), sysHwSpiInit()
*/

STATUS sysNvRamGet(
char* string,
int strLen,
int offset)
{
UCHAR eeprom_data[(SPI_SERIAL_EEPROM_SZ + SPI_SERIAL_CMD_SEQ_SZ)];
SPI_DEV* pSpi;

pSpi = &spiDev;

if (pSpi->init != TRUE)
return(ERROR);

offset += NV_BOOT_OFFSET; /* boot line begins at = 0 */

if ((offset < 0)
|| (strLen < 0)
|| ((offset + strLen) > SPI_SERIAL_EEPROM_SZ))
return (ERROR);

/* Wait for EEPROM to become ready. */
while (sysNvRamGetStatus() == ERROR)
{
/* Busy-wait. */
;
}

/* Assert EEPROM chip select (CS). */
*PBDAT(pSpi->regBase) &= 0x3FFFE;

/* Disable SPI (serial port interface). */
*MPC860_SPMODE(pSpi->regBase) = DisSPI;

/* Set SPI read value. */
pSpi->pPram->mrblr = strLen + SPI_SERIAL_CMD_SEQ_SZ;

/* Set up buffer descriptors. */
pSpi->pRxBdBase->dataPointer = &eeprom_data[0];
pSpi->pRxBdBase->dataLength = 0;
pSpi->pRxBdBase->statusMode = (SPI_TRANS_RX_BD_EMPTY | SPI_TRANS_RX_BD_WRAP);
pSpi->pTxBdBase->dataPointer = eep_wt_ptr;
pSpi->pTxBdBase->statusMode = 0x0000;

/* Enable SPI. */
*MPC860_SPMODE(pSpi->regBase) = EnSPI;

/* Set up for "read data from memory array beginning at selected addr". */
*eep_wt_ptr = 3;

/* Start address of EEPROM block to be read. */
*(USHORT*) (eep_wt_ptr + 1) = (USHORT)offset;

/* Buffer length to read. */
pSpi->pTxBdBase->dataLength = strLen + SPI_SERIAL_CMD_SEQ_SZ;

pSpi->pTxBdBase->statusMode = ( SPI_TRANS_TX_BD_READY |
SPI_TRANS_TX_BD_WRAP |
SPI_TRANS_TX_BD_LAST );

/* Start transfer. */
*MPC860_SPCOM(pSpi->regBase) = SPI_STR;

/* Wait for reading to finish. */

⌨️ 快捷键说明

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