?? sysspinvram.c
字號:
/* 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 <offset> = 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 + -