Reply by mjames_doveridge March 20, 20082008-03-20
>
> I am already doing this. Using SSP as an SPI port is very easy as
> long as you are doing polling io:
>

Have you specific problem with interrupts on the SPI, or is it just
that it's more awkward/complex?

Rgds,
Martin

An Engineer's Guide to the LPC2100 Series

Reply by nader chinichian March 20, 20082008-03-20
Hi,
I attach my code for you I do exact you told me.but I always trap here:
//wait for ready flag
while(!(enc28j60_read_address(ENC28J60_REG_ESTAT) & 0x01));
I test my code with an atmega64 and it work fine.
The code work for MMC/SD!!!
could you please see my code.
In your enc28j60 code I use #include "spi.h", please send this,may be help.
thanks.

profdc9 wrote:
The code works both with ENC28J60 and MMC/SD. More code follows at
end of message...

--- In l..., "profdc9" wrote:
>
> --- In l..., "Nader" wrote:
> >
> > Hello,
> > I try to connect a enc28j60/ss to lpc2148 with SSP as SPI @ 15Mhz,
> > but it fail to read/write with enc28j60. the enc28j60 is a little hot!
> > I search only find code for SPI0 :(. So I'd like to know is anyone
> > here have any experiment to connect enc28j60 to SSP of lpc2000?
> >
> > Thanks.
> >
>
> I am already doing this. Using SSP as an SPI port is very easy as
> long as you are doing polling io:
>
> Code to initialize SPI port:
>
> void initSSP(void)
> {
> SCB_PCONP |= SCB_PCONP_PCSPI1;
>
> SSP_CR0 = SSP_CR0_DSS_8 | SSP_CR0_FRF_SPI;
> SSP_CR1 = 0x00;
> SSP_IMSC = 0x00;
>
> SSP_CPSR = SPI_MMC_SPEED;
>
> PCB_PINSEL1 = (PCB_PINSEL1 & ~(PCB_PINSEL1_P017_MASK |
> PCB_PINSEL1_P018_MASK | PCB_PINSEL1_P019_MASK));
> PCB_PINSEL1 = (PCB_PINSEL1 | (PCB_PINSEL1_P017_SCK1 |
> PCB_PINSEL1_P018_MISO1 | PCB_PINSEL1_P019_MOSI1));
> PCB_PINSEL1 = (PCB_PINSEL1 & ~(PCB_PINSEL1_P020_MASK |
> PCB_PINSEL1_P021_MASK | PCB_PINSEL1_P022_MASK));
> }
>
> Code to do SSP transfer:
>
> U8 spiTransfer (U8 c)
> {
> while (!(SSP_SR & SSP_SR_TNF));
> SSP_DR = c;
> while (!(SSP_SR & SSP_SR_RNE));
> return (U8) SSP_DR;
> }
>
> You will have to manually fiddle the chip select line yourself
> though.
>
> Dan
>
>
>
> Definitions from JC Wren's LPC2148 demo:
>
> #define PCB_PINSEL1 (*(pREG32 (0xe002c004)))
> #define PCB_PINSEL1_P016_GPIO ((unsigned int) 0x00000000)
> #define PCB_PINSEL1_P016_EINT0 ((unsigned int) 0x00000001)
> #define PCB_PINSEL1_P016_MAT02 ((unsigned int) 0x00000002)
> #define PCB_PINSEL1_P016_CAP02 ((unsigned int) 0x00000003)
> #define PCB_PINSEL1_P016_MASK ((unsigned int) 0x00000003)
>
> #define PCB_PINSEL1_P017_GPIO ((unsigned int) 0x00000000)
> #define PCB_PINSEL1_P017_CAP12 ((unsigned int) 0x00000004)
> #define PCB_PINSEL1_P017_SCK1 ((unsigned int) 0x00000008)
> #define PCB_PINSEL1_P017_MAT12 ((unsigned int) 0x0000000c)
> #define PCB_PINSEL1_P017_MASK ((unsigned int) 0x0000000c)
>
> #define PCB_PINSEL1_P018_GPIO ((unsigned int) 0x00000000)
> #define PCB_PINSEL1_P018_CAP13 ((unsigned int) 0x00000010)
> #define PCB_PINSEL1_P018_MISO1 ((unsigned int) 0x00000020)
> #define PCB_PINSEL1_P018_MAT13 ((unsigned int) 0x00000030)
> #define PCB_PINSEL1_P018_MASK ((unsigned int) 0x00000030)
>
> #define PCB_PINSEL1_P019_GPIO ((unsigned int) 0x00000000)
> #define PCB_PINSEL1_P019_MAT12 ((unsigned int) 0x00000040)
> #define PCB_PINSEL1_P019_MOSI1 ((unsigned int) 0x00000080)
> #define PCB_PINSEL1_P019_CAP12 ((unsigned int) 0x000000c0)
> #define PCB_PINSEL1_P019_MASK ((unsigned int) 0x000000c0)
>
> #define PCB_PINSEL1_P020_GPIO ((unsigned int) 0x00000000)
> #define PCB_PINSEL1_P020_MAT13 ((unsigned int) 0x00000100)
> #define PCB_PINSEL1_P020_SSEL1 ((unsigned int) 0x00000200)
> #define PCB_PINSEL1_P020_EINT3 ((unsigned int) 0x00000300)
> #define PCB_PINSEL1_P020_MASK ((unsigned int) 0x00000300)
>
> #define PCB_PINSEL1_P021_GPIO ((unsigned int) 0x00000000)
> #define PCB_PINSEL1_P021_PWM5 ((unsigned int) 0x00000400)
> #define PCB_PINSEL1_P021_AD16 ((unsigned int) 0x00000800)
> #define PCB_PINSEL1_P021_CAP13 ((unsigned int) 0x00000c00)
> #define PCB_PINSEL1_P021_MASK ((unsigned int) 0x00000c00)
>
> #define PCB_PINSEL1_P022_GPIO ((unsigned int) 0x00000000)
> #define PCB_PINSEL1_P022_AD17 ((unsigned int) 0x00001000)
> #define PCB_PINSEL1_P022_CAP00 ((unsigned int) 0x00002000)
> #define PCB_PINSEL1_P022_MAT00 ((unsigned int) 0x00003000)
> #define PCB_PINSEL1_P022_MASK ((unsigned int) 0x00003000)
>
> #define PCB_PINSEL1_P023_GPIO ((unsigned int) 0x00000000)
> #define PCB_PINSEL1_P023_VBUS ((unsigned int) 0x00004000)
> #define PCB_PINSEL1_P023_RSVD2 ((unsigned int) 0x00008000)
> #define PCB_PINSEL1_P023_RSVD3 ((unsigned int) 0x0000c000)
> #define PCB_PINSEL1_P023_MASK ((unsigned int) 0x0000c000)
>
> #define PCB_PINSEL1_P024_RSVD0 ((unsigned int) 0x00000000)
> #define PCB_PINSEL1_P024_RSVD1 ((unsigned int) 0x00010000)
> #define PCB_PINSEL1_P024_RSVD2 ((unsigned int) 0x00020000)
> #define PCB_PINSEL1_P024_RSVD3 ((unsigned int) 0x00030000)
> #define PCB_PINSEL1_P024_MASK ((unsigned int) 0x00030000)
>
> #define PCB_PINSEL1_P025_GPIO ((unsigned int) 0x00000000)
> #define PCB_PINSEL1_P025_AD04 ((unsigned int) 0x00040000)
> #define PCB_PINSEL1_P025_AOUT ((unsigned int) 0x00080000)
> #define PCB_PINSEL1_P025_RSVD3 ((unsigned int) 0x000c0000)
> #define PCB_PINSEL1_P025_MASK ((unsigned int) 0x000c0000)
>
> #define PCB_PINSEL1_P026_RSVD0 ((unsigned int) 0x00000000)
> #define PCB_PINSEL1_P026_RSVD1 ((unsigned int) 0x00100000)
> #define PCB_PINSEL1_P026_RSVD2 ((unsigned int) 0x00200000)
> #define PCB_PINSEL1_P026_RSVD3 ((unsigned int) 0x00300000)
> #define PCB_PINSEL1_P026_MASK ((unsigned int) 0x00300000)
>
> #define PCB_PINSEL1_P027_RSVD0 ((unsigned int) 0x00000000)
> #define PCB_PINSEL1_P027_RSVD1 ((unsigned int) 0x00400000)
> #define PCB_PINSEL1_P027_RSVD2 ((unsigned int) 0x00800000)
> #define PCB_PINSEL1_P027_RSVD3 ((unsigned int) 0x00c00000)
> #define PCB_PINSEL1_P027_MASK ((unsigned int) 0x00c00000)
>
> #define PCB_PINSEL1_P028_GPIO ((unsigned int) 0x00000000)
> #define PCB_PINSEL1_P028_AD01 ((unsigned int) 0x01000000)
> #define PCB_PINSEL1_P028_CAP02 ((unsigned int) 0x02000000)
> #define PCB_PINSEL1_P028_MAT02 ((unsigned int) 0x03000000)
> #define PCB_PINSEL1_P028_MASK ((unsigned int) 0x03000000)
>
> #define PCB_PINSEL1_P029_GPIO ((unsigned int) 0x00000000)
> #define PCB_PINSEL1_P029_AD02 ((unsigned int) 0x04000000)
> #define PCB_PINSEL1_P029_CAP03 ((unsigned int) 0x08000000)
> #define PCB_PINSEL1_P029_MAT03 ((unsigned int) 0x0c000000)
> #define PCB_PINSEL1_P029_MASK ((unsigned int) 0x0c000000)
>
> #define PCB_PINSEL1_P030_GPIO ((unsigned int) 0x00000000)
> #define PCB_PINSEL1_P030_AD03 ((unsigned int) 0x10000000)
> #define PCB_PINSEL1_P030_EINT3 ((unsigned int) 0x20000000)
> #define PCB_PINSEL1_P030_CAP00 ((unsigned int) 0x30000000)
> #define PCB_PINSEL1_P030_MASK ((unsigned int) 0x30000000)
>
> #define PCB_PINSEL1_P031_GPIO ((unsigned int) 0x00000000)
> #define PCB_PINSEL1_P031_UPLED ((unsigned int) 0x40000000)
> #define PCB_PINSEL1_P031_CONNECT ((unsigned int) 0x80000000)
> #define PCB_PINSEL1_P031_RSVD3 ((unsigned int) 0xc0000000)
> #define PCB_PINSEL1_P031_MASK ((unsigned int) 0xc0000000)
>
>
/*##############################################################################
> ## SSP - Synchronous Serial Port
>
##############################################################################*/
>
> #define SSP_CR0 (*(pREG32 (0xe0068000)))
> #define SSP_CR1 (*(pREG32 (0xe0068004)))
> #define SSP_DR (*(pREG32 (0xe0068008)))
> #define SSP_SR (*(pREG32 (0xe006800C)))
> #define SSP_CPSR (*(pREG32 (0xe0068010)))
> #define SSP_IMSC (*(pREG32 (0xe0068014)))
> #define SSP_RIS (*(pREG32 (0xe0068018)))
> #define SSP_MIS (*(pREG32 (0xe006801C)))
> #define SSP_ICR (*(pREG32 (0xe0068020)))
>
> #define SSP_FIFO_DEPTH (8)
>
> #define SSP_CR0_DSS_4 ((unsigned int) 0x00000003)
> #define SSP_CR0_DSS_5 ((unsigned int) 0x00000004)
> #define SSP_CR0_DSS_6 ((unsigned int) 0x00000005)
> #define SSP_CR0_DSS_7 ((unsigned int) 0x00000006)
> #define SSP_CR0_DSS_8 ((unsigned int) 0x00000007)
> #define SSP_CR0_DSS_9 ((unsigned int) 0x00000008)
> #define SSP_CR0_DSS 10 ((unsigned int) 0x00000009)
> #define SSP_CR0_DSS_11 ((unsigned int) 0x0000000a)
> #define SSP_CR0_DSS_12 ((unsigned int) 0x0000000b)
> #define SSP_CR0_DSS_13 ((unsigned int) 0x0000000c)
> #define SSP_CR0_DSS_14 ((unsigned int) 0x0000000d)
> #define SSP_CR0_DSS_15 ((unsigned int) 0x0000000e)
> #define SSP_CR0_DSS_16 ((unsigned int) 0x0000000f)
> #define SSP_CR0_FRF_SPI ((unsigned int) 0x00000000)
> #define SSP_CR0_FRF_SSI ((unsigned int) 0x00000010)
> #define SSP_CR0_FRF_MW ((unsigned int) 0x00000020)
> #define SSP_CR0_CPOL ((unsigned int) 0x00000040)
> #define SSP_CR0_CPHA ((unsigned int) 0x00000080)
> #define SSP_CR0_SCR ((unsigned int) 0x0000ff00)
>
> #define SSP_CR1_LBM ((unsigned int) 0x00000001)
> #define SSP_CR1_SSE ((unsigned int) 0x00000002)
> #define SSP_CR1_MS ((unsigned int) 0x00000004)
> #define SSP_CR1_SOD ((unsigned int) 0x00000008)
>
> #define SSP_SR_TFE ((unsigned int) 0x00000001)
> #define SSP_SR_TNF ((unsigned int) 0x00000002)
> #define SSP_SR_RNE ((unsigned int) 0x00000004)
> #define SSP_SR_RFF ((unsigned int) 0x00000008)
> #define SSP_SR_BSY ((unsigned int) 0x00000010)
>
> #define SSP_IMSC_RORIM ((unsigned int) 0x00000001)
> #define SSP_IMSC_RTIM ((unsigned int) 0x00000002)
> #define SSP_IMSC_RXIM ((unsigned int) 0x00000004)
> #define SSP_IMSC_TXIM ((unsigned int) 0x00000008)
>
> #define SSP_RIS_RORRIS ((unsigned int) 0x00000001)
> #define SSP_RIS_RTRIS ((unsigned int) 0x00000002)
> #define SSP_RIS_RXRIS ((unsigned int) 0x00000004)
> #define SSP_RIS_TXRIS ((unsigned int) 0x00000008)
>
> #define SSP_MIS_RORMIS ((unsigned int) 0x00000001)
> #define SSP_MIS_RTMIS ((unsigned int) 0x00000002)
> #define SSP_MIS_RXMIS ((unsigned int) 0x00000004)
> #define SSP_MIS_TXMIS ((unsigned int) 0x00000008)
>
> #define SSP_ICR_RORIC ((unsigned int) 0x00000001)
> #define SSP_ICR_RTIC ((unsigned int) 0x00000002)
>

Also, here is the PINSEL code:

void spiEthChipSelect(BOOL select)
{
if (select) {
SSP_CPSR = SPI_ETH_SPEED;
GPIO0_IOCLR = SPI_ETH_SEL;
}
else
{
GPIO0_IOSET = SPI_ETH_SEL;
}
}

Here is my ENC28J60 code from Iain Dunnington (uEthernet). I
made a few changes/fixed a bug or two from the original...

#include "lpc210x.h"
#include "enc28j60.h"
#include "spi.h"

/******************************************************************************/
/** \file enc28j60.c
* \brief Driver code for enc28j60.
* \author Iain Derrington (www.kandi-electronics.com)
* \date 0.1 20/06/07 First Draft \n
* 0.2 11/07/07 Removed CS check macros. Fixed bug in writePhy
* 0.3 12.07/07 Altered for uIP 1.0
*/
/*******************************************************************************/

// define private variables

/** MAC address. Should be set using a function.*/
u8_t bytMacAddress[6] = {0x00,0xa0,0xc9,0x14,0xc8,0x29};
TXSTATUS TxStatus;

// define private functions
static u8_t ReadETHReg(u8_t); // read a ETX reg
static u8_t ReadMacReg(u8_t); // read a MAC reg
static u16_t ReadPhyReg(u8_t); // read a PHY reg
static u16_t ReadMacBuffer(u8_t * ,u16_t); //read the mac buffer
(ptrBuffer, no. of bytes)
static u8_t WriteCtrReg(u8_t,u8_t); // write to control reg
static u8_t WritePhyReg(u8_t,u16_t); // write to a phy reg
static u16_t WriteMacBuffer(u8_t *,u16_t); // write to mac buffer
static void ResetMac(void);

static u8_t SetBitField(u8_t, u8_t);
static u8_t ClrBitField(u8_t, u8_t);
static void BankSel(u8_t);
static void spitest(void);

//define usefull macros

/** MACRO for selecting or deselecting chip select for the ENC28J60.
Some HW dependancy.*/
#define SEL_MAC(x) spiEthChipSelect((x))
/** MACRO for rev B5 fix.*/
#define ERRATAFIX SetBitField(ECON1, ECON1_TXRST);ClrBitField(ECON1,
ECON1_TXRST);ClrBitField(EIR, EIR_TXERIF | EIR_TXIF)

/***********************************************************************/
/** \brief Initialise the MAC.
*
* Description: \n
* a) Setup SPI device. Assume Reb B5 for sub 8MHz operation \n
* b) Setup buffer ptrs to devide memory in In and Out mem \n
* c) Setup receive filters (accept only unicast).\n
* d) Setup MACON registers (MAC control registers)\n
* e) Setup MAC address
* f) Setup Phy registers
* \author Iain Derrington
* \date 0.1 20/06/07 First draft
*/
/**********************************************************************/

void initMAC(void)
{
u16_t test;
spiInit(); // initialise the SPI
spiResetEthernet();

ResetMac(); // erm. Resets the MAC.

// setup memory by defining ERXST and ERXND
BankSel(0); // select bank 0
WriteCtrReg(ERXSTL,(u8_t)( RXSTART & 0x00ff));
WriteCtrReg(ERXSTH,(u8_t)((RXSTART & 0xff00)>> 8));
WriteCtrReg(ERXNDL,(u8_t)( RXEND & 0x00ff));
WriteCtrReg(ERXNDH,(u8_t)((RXEND & 0xff00)>>8));

// Make sure Rx Read ptr is at the start of Rx segment
WriteCtrReg(ERXRDPTL, (u8_t)( RXSTART & 0x00ff));
WriteCtrReg(ERXRDPTH, (u8_t)((RXSTART & 0xff00)>> 8));

BankSel(1); // select bank 1
WriteCtrReg(ERXFCON,( ERXFCON_UCEN + ERXFCON_CRCEN + ERXFCON_BCEN));

// Initialise the MAC registers
BankSel(2); // select bank 2
SetBitField(MACON1, MACON1_MARXEN); // Enable reception of frames
WriteCtrReg(MACLCON2, 63);
WriteCtrReg(MACON3, MACON3_FRMLNEN + // Type / len field will be
checked
MACON3_TXCRCEN + // MAC will append valid CRC
MACON3_PADCFG0); // All small packets will be
padded

SetBitField(MACON4, MACON4_DEFER);
WriteCtrReg(MAMXFLL, (u8_t)( MAXFRAMELEN & 0x00ff)); // set max
frame len
WriteCtrReg(MAMXFLH, (u8_t)((MAXFRAMELEN & 0xff00)>>8));
WriteCtrReg(MABBIPG, 0x12); // back to back interpacket
gap. set as per data sheet
WriteCtrReg(MAIPGL , 0x12); // non back to back
interpacket gap. set as per data sheet
WriteCtrReg(MAIPGH , 0x0C);

//Program our MAC address
BankSel(3);
WriteCtrReg(MAADR1,bytMacAddress[0]);
WriteCtrReg(MAADR2,bytMacAddress[1]);
WriteCtrReg(MAADR3,bytMacAddress[2]);
WriteCtrReg(MAADR4,bytMacAddress[3]);
WriteCtrReg(MAADR5,bytMacAddress[4]);
WriteCtrReg(MAADR6,bytMacAddress[5]);

// Initialise the PHY registes
WritePhyReg(PHCON1, 0x000);
test =ReadPhyReg(PHCON1);
WritePhyReg(PHCON2, PHCON2_HDLDIS);
WriteCtrReg(ECON1, ECON1_RXEN); //Enable the chip for reception
of packets
}

/***********************************************************************/
/** \brief Writes a packet to the ENC28J60.
*
* Description: Writes ui_len bytes of data from ptrBufffer into ENC28J60.
* puts the necessary padding around the packet to make
it a legit
MAC packet.\n \n
1) Program ETXST. \n
2) Write per packet control byte.\n
3) Program ETXND.\n
4) Set ECON1.TXRTS.\n
5) Check ESTAT.TXABRT. \n

* \author Iain Derrington
* \param ptrBuffer ptr to byte buffer.
* \param ui_Len Number of bytes to write from buffer.
* \return uint True or false.
*/
/**********************************************************************/
u16_t MACWrite()
{
volatile u16_t i;
volatile u16_t address = TXSTART;
u8_t bytControl;

bytControl = 0x00;

BankSel(0); // select bank 0

WriteCtrReg(EWRPTL,(u8_t)( TXSTART & 0x00ff)); // Set write
buffer to point to start of Tx Buffer
WriteCtrReg(EWRPTH,(u8_t)((TXSTART & 0xff00)>>8));

address += WriteMacBuffer(&bytControl,1); //
write per packet control byte

address+=WriteMacBuffer(&uip_buf[0], UIP_LLH_LEN);
if(uip_len <= UIP_LLH_LEN + UIP_TCPIP_HLEN)
{
address+=WriteMacBuffer(&uip_buf[UIP_LLH_LEN], uip_len - UIP_LLH_LEN);
}
else
{
address+=WriteMacBuffer(&uip_buf[UIP_LLH_LEN], UIP_TCPIP_HLEN);
address+=WriteMacBuffer(uip_appdata, uip_len - UIP_TCPIP_HLEN -
UIP_LLH_LEN);
}

WriteCtrReg(ETXSTL,(u8_t)( TXSTART & 0x00ff)); // write ptr
to start of Tx packet
WriteCtrReg(ETXSTH,(u8_t)((TXSTART & 0xff00)>>8));

WriteCtrReg(ETXNDL, (u8_t)( address & 0x00ff)); // Tell MAC
when the end of the packet is
WriteCtrReg(ETXNDH, (u8_t)((address & 0xff00)>>8));

ClrBitField(EIR,EIR_TXIF);
SetBitField(EIE, EIE_TXIE |EIE_INTIE);

ERRATAFIX;
SetBitField(ECON1, ECON1_TXRTS); // begin
transmitting;

#if 1
{
int count = 0;
do
{
count++;
}while ((!(ReadETHReg(EIR) & (EIR_TXIF))) && (count < 30000));
// kill some time. Note: Nice place to block?
}

ClrBitField(ECON1, ECON1_TXRTS);
#else
do
{
}while (!(ReadETHReg(EIR) & (EIR_TXIF))); // kill some
time. Note: Nice place to block?
ClrBitField(ECON1, ECON1_TXRTS);

BankSel(0); // read tx
status bytes
address++; // increment ptr
to address to start of status struc
WriteCtrReg(ERDPTL, (u8_t)( address & 0x00ff)); // Setup the
buffer read ptr to read status struc
WriteCtrReg(ERDPTH, (u8_t)((address & 0xff00)>>8));
ReadMacBuffer(&TxStatus.v[0],7);

if (ReadETHReg(ESTAT) & ESTAT_TXABRT) // did
transmission get interrupted?
{
if (TxStatus.bits.LateCollision)
{
ClrBitField(ECON1, ECON1_TXRTS);
SetBitField(ECON1, ECON1_TXRTS);

ClrBitField(ESTAT,ESTAT_TXABRT | ESTAT_LATECOL);
}
ClrBitField(EIR, EIR_TXERIF | EIR_TXIF);
ClrBitField(ESTAT,ESTAT_TXABRT);

return FALSE; // packet
transmit failed. Inform calling function
} // calling
function may inquire why packet failed by calling [TO DO] function
else
{
return TRUE; // all fan
dabby dozy
}
#endif
return TRUE;
}

/***********************************************************************/
/** \brief Tries to read a packet from the ENC28J60.
*
* Description: If a valid packet is available in the ENC28J60 this
function reads the packet into a
* buffer. The memory within the ENC28J60 will then be
released. This version of the
driver does not use interrupts so this function needs
to be polled.\n \n
*
* 1) Read packet count register. If >0 then continue else return. \n
* 2) Read the current ERXRDPTR value. \n
* 3) Write this value into ERDPT. \n
* 4) First two bytes contain the ptr to the start of next packet.
Read this value in. \n
* 5) Calculate length of packet. \n
* 6) Read in status byte into private variable. \n
* 7) Read in packet and place into buffer. \n
* 8) Free up memory in the ENC. \n
*
* \author Iain Derrington
* \param ptrBuffer ptr to buffer of bytes where the packet should be
read into.
* \return u16_t, the number of complete packets in the buffer -1.

*/
/**********************************************************************/
u16_t MACRead()
{
volatile u16_t u16_t_pckLen,test;
volatile u16_t u16_t_rdptr,u16_t_wrtptr;
static u16_t nextpckptr = RXSTART;
volatile RXSTATUS ptrRxStatus;
volatile u8_t bytPacket;

BankSel(1);

bytPacket = ReadETHReg(EPKTCNT); // How many packets have
been received

if(bytPacket == 0)
return bytPacket; // No full packets received

BankSel(0);

WriteCtrReg(ERDPTL,(u8_t)( nextpckptr & 0x00ff)); //write this
value to read buffer ptr
WriteCtrReg(ERDPTH,(u8_t)((nextpckptr & 0xff00)>>8));

ReadMacBuffer((u8_t*)&ptrRxStatus.v[0],6); // read next
packet ptr + 4 status bytes
nextpckptr = ptrRxStatus.bits.NextPacket;

uip_len=ptrRxStatus.bits.ByteCount;
if (uip_len > UIP_BUFSIZE) uip_len = UIP_BUFSIZE;
ReadMacBuffer(uip_buf,uip_len); // read packet into buffer

// ptrBuffer should now
contain a MAC packet
BankSel(0);
WriteCtrReg(ERXRDPTL,ptrRxStatus.v[0]); // free up ENC memory my
adjustng the Rx Read ptr
WriteCtrReg(ERXRDPTH,ptrRxStatus.v[1]);

// decrement packet counter
SetBitField(ECON2, ECON2_PKTDEC);

return uip_len;
}

/*------------------------Private Functions-----------------------------*/

/***********************************************************************/
/** \brief ReadETHReg.
*
* Description: Reads contents of the addressed ETH reg over SPI bus.
Assumes correct bank selected.
*
*
* \author Iain Derrington
* \param bytAddress Address of register to be read
* \return byte Value of register.
*/
/**********************************************************************/
static u8_t ReadETHReg(u8_t bytAddress)
{
u8_t bytData;

if (bytAddress > 0x1F)
return FALSE; // address invalid, [TO DO]

SEL_MAC(TRUE); // ENC CS low
SPIWrite(&bytAddress,1); // write opcode
SPIRead(&bytData, 1); // read value
SEL_MAC(FALSE);

return bytData;

}

/***********************************************************************/
/** \brief ReadMacReg.
*
* Description: Read contents of addressed MAC register over SPI bus.
Assumes correct bank selected.
*
* \author Iain Derrington
* \param bytAddress Address of register to read.
* \return byte Contens of register just read.
*/
/**********************************************************************/
static u8_t ReadMacReg(u8_t bytAddress)
{
u8_t bytData;

if (bytAddress > 0x1F)
return FALSE; // address invalid, [TO DO]

SEL_MAC(TRUE); // ENC CS low

SPIWrite(&bytAddress,1); // write opcode
SPIRead(&bytData, 1); // read dummy byte
SPIRead(&bytData, 1); // read value
SEL_MAC(FALSE);

return bytData;
}

/***********************************************************************/
/** \brief Write to phy Reg.
*
* Description: Writing to PHY registers is different to writing the
other regeisters in that
the registers can not be accessed directly. This
function wraps up the requirements
for writing to the PHY reg. \n \n

1) Write address of phy reg to MIREGADR. \n
2) Write lower 8 bits of data to MIWRL. \n
3) Write upper 8 bits of data to MIWRL. \n \n
*
*
* \author Iain Derrington
* \param address
* \param data
* \return byte
*/
/**********************************************************************/
static u8_t WritePhyReg(u8_t address, u16_t data)
{
if (address > 0x14)
return FALSE;

BankSel(2);

WriteCtrReg(MIREGADR,address); // Write address of Phy reg
WriteCtrReg(MIWRL,(u8_t)data); // lower phy data
WriteCtrReg(MIWRH,((u8_t)(data >>8))); // Upper phydata

return TRUE;
}

/***********************************************************************/
/** \brief Read from PHY reg.
*
* Description: No direct access allowed to phy registers so the
folling process must take place. \n \n
* 1) Write address of phy reg to read from into MIREGADR. \n
* 2) Set MICMD.MIIRD bit and wait 10.4uS. \n
* 3) Clear MICMD.MIIRD bit. \n
* 4) Read data from MIRDL and MIRDH reg. \n
* \author Iain Derrington
* \param address
* \return uint
*/
/**********************************************************************/
static u16_t ReadPhyReg(u8_t address)
{
volatile u16_t uiData;
volatile u8_t bytStat;

do {
int count=0;
BankSel(2);
WriteCtrReg(MIREGADR,address); // Write address of phy register to
read
SetBitField(MICMD, MICMD_MIIRD); // Set rd bit
do
{
bytStat = ReadMacReg(MISTAT);
}while ((bytStat & MISTAT_BUSY) && (count++ < 3000));
} while (bytStat & MISTAT_BUSY);

ClrBitField(MICMD,MICMD_MIIRD); // Clear rd bit
uiData = (u16_t)ReadMacReg(MIRDL); // Read low data byte
uiData |=((u16_t)ReadMacReg(MIRDH)<<8); // Read high data byte

return uiData;
}

/***********************************************************************/
/** \brief Write to a control reg .
*
* Description: Writes a byte to the address register. Assumes that
correct bank has
* all ready been selected
*
* \author Iain Derrington
* \param bytAddress Address of register to be written to.
* \param bytData Data to be written.
* \returns byte
*/
/**********************************************************************/
static u8_t WriteCtrReg(u8_t bytAddress,u8_t bytData)
{
if (bytAddress > 0x1f)
{
return FALSE;
}

bytAddress |= WCR_OP; // Set opcode
SEL_MAC(TRUE); // ENC CS low
SPIWrite(&bytAddress,1); // Tx opcode and address
SPIWrite(&bytData,1); // Tx data
SEL_MAC(FALSE);

return TRUE;
}

/***********************************************************************/
/** \brief Read bytes from MAC data buffer.
*
* Description: Reads a number of bytes from the ENC28J60 internal
memory. Assumes auto increment
* is on.
*
* \author Iain Derrington
* \param bytBuffer Buffer to place data in.
* \param byt_length Number of bytes to read.
* \return uint Number of bytes read.
*/
/**********************************************************************/
static u16_t ReadMacBuffer(u8_t * bytBuffer,u16_t byt_length)
{
u8_t bytOpcode;
volatile u16_t len;

bytOpcode = RBM_OP;
SEL_MAC(TRUE); // ENC CS low

SPIWrite(&bytOpcode,1); // Tx opcode
len = SPIRead(bytBuffer, byt_length); // read bytes into buffer
SEL_MAC(FALSE); // release CS

return len;

}
/***********************************************************************/
/** \brief Write bytes to MAC data buffer.
*
* Description: Reads a number of bytes from the ENC28J60 internal
memory. Assumes auto increment
* is on.
*
* \author Iain Derrington
* \param bytBuffer
* \param ui_len
* \return uint
* \date WIP
*/
/**********************************************************************/
static u16_t WriteMacBuffer(u8_t * bytBuffer,u16_t ui_len)
{
u8_t bytOpcode;
volatile u16_t len;

bytOpcode = WBM_OP;
SEL_MAC(TRUE); // ENC CS low

SPIWrite(&bytOpcode,1); // Tx opcode
len = SPIWrite(bytBuffer, ui_len); // read bytes into buffer
SEL_MAC(FALSE); // release CS

return len;

}

/***********************************************************************/
/** \brief Set bit field.
*
* Description: Sets the bit/s at the address register. Assumes
correct bank has been selected.
*
* \author Iain Derrington
* \param bytAddress Address of registed where bit is to be set
* \param bytData Sets all the bits high.
* \return byte True or false
*/
/**********************************************************************/
static u8_t SetBitField(u8_t bytAddress, u8_t bytData)
{
if (bytAddress > 0x1f)
{
return FALSE;
}

bytAddress |= BFS_OP; // Set opcode
SEL_MAC(TRUE); // ENC CS low

SPIWrite(&bytAddress,1); // Tx opcode and address
SPIWrite(&bytData,1); // Tx data
SEL_MAC(FALSE);

return TRUE;
}

/***********************************************************************/
/** \brief Clear bit field on ctr registers.
*
* Description: Sets the bit/s at the address register. Assumes
correct bank has been selected.
*
* \author Iain Derrington
* \param bytAddress Address of registed where bit is to be set
* \param bytData Sets all the bits high.
* \return byte True or false
*/
/**********************************************************************/
static u8_t ClrBitField(u8_t bytAddress, u8_t bytData)
{
if (bytAddress > 0x1f)
{
return FALSE;
}

bytAddress |= BFC_OP; // Set opcode
SEL_MAC(TRUE); // ENC CS low

SPIWrite(&bytAddress,1); // Tx opcode and address
SPIWrite(&bytData,1); // Tx data
SEL_MAC(FALSE);

return TRUE;
}

/***********************************************************************/
/** \brief Bank Select.
*
* Description: Select the required bank within the ENC28J60
*
*
* \author Iain Derrington
* \param bank Value between 0 and 3.
* \date 0.1 09/06/07 First draft
*/
/**********************************************************************/
static void BankSel(u8_t bank)
{
volatile u8_t temp;

if (bank >3)
return;

temp = ReadETHReg(ECON1); // Read ECON1 register
temp &= ~ECON1_BSEL; // mask off the BSEL bits
temp |= bank; // set BSEL bits
WriteCtrReg(ECON1, temp); // write new values back to ENC28J60
}
/***********************************************************************/
/** \brief ResetMac.
*
* Description: Sends command to reset the MAC.
*
*
* \author Iain Derrington
*/
/**********************************************************************/
static void ResetMac(void)
{
u8_t bytOpcode = RESET_OP;
SEL_MAC(TRUE); // ENC CS low

SPIWrite(&bytOpcode,1); // Tx opcode and address
SEL_MAC(FALSE);

}

---------------------------------
Looking for last minute shopping deals? Find them fast with Yahoo! Search.


=======================================================================Groups related to lpc2000
=======================================================================
msp430 (388 common members)
http://groups.yahoo.com/group/msp430?v=1&t=ipt&ch=email&pub=groups&slktr0&sec=recg
Computers & Internet/Hardware: Welcome to the MSP430 User's Group! The purpose of...

AVR-Chat (177 common members)
http://groups.yahoo.com/group/AVR-Chat?v=1&t=ipt&ch=email&pub=groups&slktr1&sec=recg
Microprocessors/Microcontrollers: A place for Atmel AVR Microcontroller users to sha...

LTspice (165 common members)
http://groups.yahoo.com/group/LTspice?v=1&t=ipt&ch=email&pub=groups&slktr2&sec=recg
Engineering/Electrical: Dedicated to the exchange of information about LTs...

Homebrew_PCBs (157 common members)
http://groups.yahoo.com/group/Homebrew_PCBs?v=1&t=ipt&ch=email&pub=groups&slktr3&sec=recg
Engineering/Electrical: Designing, making, etching, soldering, printed cir...

e-embedded (151 common members)
http://groups.yahoo.com/group/e-embedded?v=1&t=ipt&ch=email&pub=groups&slktr4&sec=recg
Internet/Internet Appliances: Open-membership mailing list for embedded system d...
Reply by profdc9 March 19, 20082008-03-19
The code works both with ENC28J60 and MMC/SD. More code follows at
end of message...

--- In l..., "profdc9" wrote:
>
> --- In l..., "Nader" wrote:
> >
> > Hello,
> > I try to connect a enc28j60/ss to lpc2148 with SSP as SPI @ 15Mhz,
> > but it fail to read/write with enc28j60. the enc28j60 is a little hot!
> > I search only find code for SPI0 :(. So I'd like to know is anyone
> > here have any experiment to connect enc28j60 to SSP of lpc2000?
> >
> > Thanks.
> > I am already doing this. Using SSP as an SPI port is very easy as
> long as you are doing polling io:
>
> Code to initialize SPI port:
>
> void initSSP(void)
> {
> SCB_PCONP |= SCB_PCONP_PCSPI1;
>
> SSP_CR0 = SSP_CR0_DSS_8 | SSP_CR0_FRF_SPI;
> SSP_CR1 = 0x00;
> SSP_IMSC = 0x00;
>
> SSP_CPSR = SPI_MMC_SPEED;
>
> PCB_PINSEL1 = (PCB_PINSEL1 & ~(PCB_PINSEL1_P017_MASK |
> PCB_PINSEL1_P018_MASK | PCB_PINSEL1_P019_MASK));
> PCB_PINSEL1 = (PCB_PINSEL1 | (PCB_PINSEL1_P017_SCK1 |
> PCB_PINSEL1_P018_MISO1 | PCB_PINSEL1_P019_MOSI1));
> PCB_PINSEL1 = (PCB_PINSEL1 & ~(PCB_PINSEL1_P020_MASK |
> PCB_PINSEL1_P021_MASK | PCB_PINSEL1_P022_MASK));
> }
>
> Code to do SSP transfer:
>
> U8 spiTransfer (U8 c)
> {
> while (!(SSP_SR & SSP_SR_TNF));
> SSP_DR = c;
> while (!(SSP_SR & SSP_SR_RNE));
> return (U8) SSP_DR;
> }
>
> You will have to manually fiddle the chip select line yourself
> though.
>
> Dan
>
> Definitions from JC Wren's LPC2148 demo:
>
> #define PCB_PINSEL1 (*(pREG32 (0xe002c004)))
> #define PCB_PINSEL1_P016_GPIO ((unsigned int) 0x00000000)
> #define PCB_PINSEL1_P016_EINT0 ((unsigned int) 0x00000001)
> #define PCB_PINSEL1_P016_MAT02 ((unsigned int) 0x00000002)
> #define PCB_PINSEL1_P016_CAP02 ((unsigned int) 0x00000003)
> #define PCB_PINSEL1_P016_MASK ((unsigned int) 0x00000003)
>
> #define PCB_PINSEL1_P017_GPIO ((unsigned int) 0x00000000)
> #define PCB_PINSEL1_P017_CAP12 ((unsigned int) 0x00000004)
> #define PCB_PINSEL1_P017_SCK1 ((unsigned int) 0x00000008)
> #define PCB_PINSEL1_P017_MAT12 ((unsigned int) 0x0000000c)
> #define PCB_PINSEL1_P017_MASK ((unsigned int) 0x0000000c)
>
> #define PCB_PINSEL1_P018_GPIO ((unsigned int) 0x00000000)
> #define PCB_PINSEL1_P018_CAP13 ((unsigned int) 0x00000010)
> #define PCB_PINSEL1_P018_MISO1 ((unsigned int) 0x00000020)
> #define PCB_PINSEL1_P018_MAT13 ((unsigned int) 0x00000030)
> #define PCB_PINSEL1_P018_MASK ((unsigned int) 0x00000030)
>
> #define PCB_PINSEL1_P019_GPIO ((unsigned int) 0x00000000)
> #define PCB_PINSEL1_P019_MAT12 ((unsigned int) 0x00000040)
> #define PCB_PINSEL1_P019_MOSI1 ((unsigned int) 0x00000080)
> #define PCB_PINSEL1_P019_CAP12 ((unsigned int) 0x000000c0)
> #define PCB_PINSEL1_P019_MASK ((unsigned int) 0x000000c0)
>
> #define PCB_PINSEL1_P020_GPIO ((unsigned int) 0x00000000)
> #define PCB_PINSEL1_P020_MAT13 ((unsigned int) 0x00000100)
> #define PCB_PINSEL1_P020_SSEL1 ((unsigned int) 0x00000200)
> #define PCB_PINSEL1_P020_EINT3 ((unsigned int) 0x00000300)
> #define PCB_PINSEL1_P020_MASK ((unsigned int) 0x00000300)
>
> #define PCB_PINSEL1_P021_GPIO ((unsigned int) 0x00000000)
> #define PCB_PINSEL1_P021_PWM5 ((unsigned int) 0x00000400)
> #define PCB_PINSEL1_P021_AD16 ((unsigned int) 0x00000800)
> #define PCB_PINSEL1_P021_CAP13 ((unsigned int) 0x00000c00)
> #define PCB_PINSEL1_P021_MASK ((unsigned int) 0x00000c00)
>
> #define PCB_PINSEL1_P022_GPIO ((unsigned int) 0x00000000)
> #define PCB_PINSEL1_P022_AD17 ((unsigned int) 0x00001000)
> #define PCB_PINSEL1_P022_CAP00 ((unsigned int) 0x00002000)
> #define PCB_PINSEL1_P022_MAT00 ((unsigned int) 0x00003000)
> #define PCB_PINSEL1_P022_MASK ((unsigned int) 0x00003000)
>
> #define PCB_PINSEL1_P023_GPIO ((unsigned int) 0x00000000)
> #define PCB_PINSEL1_P023_VBUS ((unsigned int) 0x00004000)
> #define PCB_PINSEL1_P023_RSVD2 ((unsigned int) 0x00008000)
> #define PCB_PINSEL1_P023_RSVD3 ((unsigned int) 0x0000c000)
> #define PCB_PINSEL1_P023_MASK ((unsigned int) 0x0000c000)
>
> #define PCB_PINSEL1_P024_RSVD0 ((unsigned int) 0x00000000)
> #define PCB_PINSEL1_P024_RSVD1 ((unsigned int) 0x00010000)
> #define PCB_PINSEL1_P024_RSVD2 ((unsigned int) 0x00020000)
> #define PCB_PINSEL1_P024_RSVD3 ((unsigned int) 0x00030000)
> #define PCB_PINSEL1_P024_MASK ((unsigned int) 0x00030000)
>
> #define PCB_PINSEL1_P025_GPIO ((unsigned int) 0x00000000)
> #define PCB_PINSEL1_P025_AD04 ((unsigned int) 0x00040000)
> #define PCB_PINSEL1_P025_AOUT ((unsigned int) 0x00080000)
> #define PCB_PINSEL1_P025_RSVD3 ((unsigned int) 0x000c0000)
> #define PCB_PINSEL1_P025_MASK ((unsigned int) 0x000c0000)
>
> #define PCB_PINSEL1_P026_RSVD0 ((unsigned int) 0x00000000)
> #define PCB_PINSEL1_P026_RSVD1 ((unsigned int) 0x00100000)
> #define PCB_PINSEL1_P026_RSVD2 ((unsigned int) 0x00200000)
> #define PCB_PINSEL1_P026_RSVD3 ((unsigned int) 0x00300000)
> #define PCB_PINSEL1_P026_MASK ((unsigned int) 0x00300000)
>
> #define PCB_PINSEL1_P027_RSVD0 ((unsigned int) 0x00000000)
> #define PCB_PINSEL1_P027_RSVD1 ((unsigned int) 0x00400000)
> #define PCB_PINSEL1_P027_RSVD2 ((unsigned int) 0x00800000)
> #define PCB_PINSEL1_P027_RSVD3 ((unsigned int) 0x00c00000)
> #define PCB_PINSEL1_P027_MASK ((unsigned int) 0x00c00000)
>
> #define PCB_PINSEL1_P028_GPIO ((unsigned int) 0x00000000)
> #define PCB_PINSEL1_P028_AD01 ((unsigned int) 0x01000000)
> #define PCB_PINSEL1_P028_CAP02 ((unsigned int) 0x02000000)
> #define PCB_PINSEL1_P028_MAT02 ((unsigned int) 0x03000000)
> #define PCB_PINSEL1_P028_MASK ((unsigned int) 0x03000000)
>
> #define PCB_PINSEL1_P029_GPIO ((unsigned int) 0x00000000)
> #define PCB_PINSEL1_P029_AD02 ((unsigned int) 0x04000000)
> #define PCB_PINSEL1_P029_CAP03 ((unsigned int) 0x08000000)
> #define PCB_PINSEL1_P029_MAT03 ((unsigned int) 0x0c000000)
> #define PCB_PINSEL1_P029_MASK ((unsigned int) 0x0c000000)
>
> #define PCB_PINSEL1_P030_GPIO ((unsigned int) 0x00000000)
> #define PCB_PINSEL1_P030_AD03 ((unsigned int) 0x10000000)
> #define PCB_PINSEL1_P030_EINT3 ((unsigned int) 0x20000000)
> #define PCB_PINSEL1_P030_CAP00 ((unsigned int) 0x30000000)
> #define PCB_PINSEL1_P030_MASK ((unsigned int) 0x30000000)
>
> #define PCB_PINSEL1_P031_GPIO ((unsigned int) 0x00000000)
> #define PCB_PINSEL1_P031_UPLED ((unsigned int) 0x40000000)
> #define PCB_PINSEL1_P031_CONNECT ((unsigned int) 0x80000000)
> #define PCB_PINSEL1_P031_RSVD3 ((unsigned int) 0xc0000000)
> #define PCB_PINSEL1_P031_MASK ((unsigned int) 0xc0000000)
/*##############################################################################
> ## SSP - Synchronous Serial Port
>
##############################################################################*/
>
> #define SSP_CR0 (*(pREG32 (0xe0068000)))
> #define SSP_CR1 (*(pREG32 (0xe0068004)))
> #define SSP_DR (*(pREG32 (0xe0068008)))
> #define SSP_SR (*(pREG32 (0xe006800C)))
> #define SSP_CPSR (*(pREG32 (0xe0068010)))
> #define SSP_IMSC (*(pREG32 (0xe0068014)))
> #define SSP_RIS (*(pREG32 (0xe0068018)))
> #define SSP_MIS (*(pREG32 (0xe006801C)))
> #define SSP_ICR (*(pREG32 (0xe0068020)))
>
> #define SSP_FIFO_DEPTH (8)
>
> #define SSP_CR0_DSS_4 ((unsigned int) 0x00000003)
> #define SSP_CR0_DSS_5 ((unsigned int) 0x00000004)
> #define SSP_CR0_DSS_6 ((unsigned int) 0x00000005)
> #define SSP_CR0_DSS_7 ((unsigned int) 0x00000006)
> #define SSP_CR0_DSS_8 ((unsigned int) 0x00000007)
> #define SSP_CR0_DSS_9 ((unsigned int) 0x00000008)
> #define SSP_CR0_DSS 10 ((unsigned int) 0x00000009)
> #define SSP_CR0_DSS_11 ((unsigned int) 0x0000000a)
> #define SSP_CR0_DSS_12 ((unsigned int) 0x0000000b)
> #define SSP_CR0_DSS_13 ((unsigned int) 0x0000000c)
> #define SSP_CR0_DSS_14 ((unsigned int) 0x0000000d)
> #define SSP_CR0_DSS_15 ((unsigned int) 0x0000000e)
> #define SSP_CR0_DSS_16 ((unsigned int) 0x0000000f)
> #define SSP_CR0_FRF_SPI ((unsigned int) 0x00000000)
> #define SSP_CR0_FRF_SSI ((unsigned int) 0x00000010)
> #define SSP_CR0_FRF_MW ((unsigned int) 0x00000020)
> #define SSP_CR0_CPOL ((unsigned int) 0x00000040)
> #define SSP_CR0_CPHA ((unsigned int) 0x00000080)
> #define SSP_CR0_SCR ((unsigned int) 0x0000ff00)
>
> #define SSP_CR1_LBM ((unsigned int) 0x00000001)
> #define SSP_CR1_SSE ((unsigned int) 0x00000002)
> #define SSP_CR1_MS ((unsigned int) 0x00000004)
> #define SSP_CR1_SOD ((unsigned int) 0x00000008)
>
> #define SSP_SR_TFE ((unsigned int) 0x00000001)
> #define SSP_SR_TNF ((unsigned int) 0x00000002)
> #define SSP_SR_RNE ((unsigned int) 0x00000004)
> #define SSP_SR_RFF ((unsigned int) 0x00000008)
> #define SSP_SR_BSY ((unsigned int) 0x00000010)
>
> #define SSP_IMSC_RORIM ((unsigned int) 0x00000001)
> #define SSP_IMSC_RTIM ((unsigned int) 0x00000002)
> #define SSP_IMSC_RXIM ((unsigned int) 0x00000004)
> #define SSP_IMSC_TXIM ((unsigned int) 0x00000008)
>
> #define SSP_RIS_RORRIS ((unsigned int) 0x00000001)
> #define SSP_RIS_RTRIS ((unsigned int) 0x00000002)
> #define SSP_RIS_RXRIS ((unsigned int) 0x00000004)
> #define SSP_RIS_TXRIS ((unsigned int) 0x00000008)
>
> #define SSP_MIS_RORMIS ((unsigned int) 0x00000001)
> #define SSP_MIS_RTMIS ((unsigned int) 0x00000002)
> #define SSP_MIS_RXMIS ((unsigned int) 0x00000004)
> #define SSP_MIS_TXMIS ((unsigned int) 0x00000008)
>
> #define SSP_ICR_RORIC ((unsigned int) 0x00000001)
> #define SSP_ICR_RTIC ((unsigned int) 0x00000002)
>

Also, here is the PINSEL code:

void spiEthChipSelect(BOOL select)
{
if (select) {
SSP_CPSR = SPI_ETH_SPEED;
GPIO0_IOCLR = SPI_ETH_SEL;
}
else
{
GPIO0_IOSET = SPI_ETH_SEL;
}
}

Here is my ENC28J60 code from Iain Dunnington (uEthernet). I
made a few changes/fixed a bug or two from the original...

#include "lpc210x.h"
#include "enc28j60.h"
#include "spi.h"
/******************************************************************************/
/** \file enc28j60.c
* \brief Driver code for enc28j60.
* \author Iain Derrington (www.kandi-electronics.com)
* \date 0.1 20/06/07 First Draft \n
* 0.2 11/07/07 Removed CS check macros. Fixed bug in writePhy
* 0.3 12.07/07 Altered for uIP 1.0
*/
/*******************************************************************************/

// define private variables

/** MAC address. Should be set using a function.*/
u8_t bytMacAddress[6] = {0x00,0xa0,0xc9,0x14,0xc8,0x29};
TXSTATUS TxStatus;

// define private functions
static u8_t ReadETHReg(u8_t); // read a ETX reg
static u8_t ReadMacReg(u8_t); // read a MAC reg
static u16_t ReadPhyReg(u8_t); // read a PHY reg
static u16_t ReadMacBuffer(u8_t * ,u16_t); //read the mac buffer
(ptrBuffer, no. of bytes)
static u8_t WriteCtrReg(u8_t,u8_t); // write to control reg
static u8_t WritePhyReg(u8_t,u16_t); // write to a phy reg
static u16_t WriteMacBuffer(u8_t *,u16_t); // write to mac buffer
static void ResetMac(void);

static u8_t SetBitField(u8_t, u8_t);
static u8_t ClrBitField(u8_t, u8_t);
static void BankSel(u8_t);
static void spitest(void);

//define usefull macros

/** MACRO for selecting or deselecting chip select for the ENC28J60.
Some HW dependancy.*/
#define SEL_MAC(x) spiEthChipSelect((x))
/** MACRO for rev B5 fix.*/
#define ERRATAFIX SetBitField(ECON1, ECON1_TXRST);ClrBitField(ECON1,
ECON1_TXRST);ClrBitField(EIR, EIR_TXERIF | EIR_TXIF)

/***********************************************************************/
/** \brief Initialise the MAC.
*
* Description: \n
* a) Setup SPI device. Assume Reb B5 for sub 8MHz operation \n
* b) Setup buffer ptrs to devide memory in In and Out mem \n
* c) Setup receive filters (accept only unicast).\n
* d) Setup MACON registers (MAC control registers)\n
* e) Setup MAC address
* f) Setup Phy registers
* \author Iain Derrington
* \date 0.1 20/06/07 First draft
*/
/**********************************************************************/

void initMAC(void)
{
u16_t test;
spiInit(); // initialise the SPI
spiResetEthernet();

ResetMac(); // erm. Resets the MAC.

// setup memory by defining ERXST and ERXND
BankSel(0); // select bank 0
WriteCtrReg(ERXSTL,(u8_t)( RXSTART & 0x00ff));
WriteCtrReg(ERXSTH,(u8_t)((RXSTART & 0xff00)>> 8));
WriteCtrReg(ERXNDL,(u8_t)( RXEND & 0x00ff));
WriteCtrReg(ERXNDH,(u8_t)((RXEND & 0xff00)>>8));

// Make sure Rx Read ptr is at the start of Rx segment
WriteCtrReg(ERXRDPTL, (u8_t)( RXSTART & 0x00ff));
WriteCtrReg(ERXRDPTH, (u8_t)((RXSTART & 0xff00)>> 8));

BankSel(1); // select bank 1
WriteCtrReg(ERXFCON,( ERXFCON_UCEN + ERXFCON_CRCEN + ERXFCON_BCEN));
// Initialise the MAC registers
BankSel(2); // select bank 2
SetBitField(MACON1, MACON1_MARXEN); // Enable reception of frames
WriteCtrReg(MACLCON2, 63);
WriteCtrReg(MACON3, MACON3_FRMLNEN + // Type / len field will be
checked
MACON3_TXCRCEN + // MAC will append valid CRC
MACON3_PADCFG0); // All small packets will be
padded

SetBitField(MACON4, MACON4_DEFER);
WriteCtrReg(MAMXFLL, (u8_t)( MAXFRAMELEN & 0x00ff)); // set max
frame len
WriteCtrReg(MAMXFLH, (u8_t)((MAXFRAMELEN & 0xff00)>>8));
WriteCtrReg(MABBIPG, 0x12); // back to back interpacket
gap. set as per data sheet
WriteCtrReg(MAIPGL , 0x12); // non back to back
interpacket gap. set as per data sheet
WriteCtrReg(MAIPGH , 0x0C);

//Program our MAC address
BankSel(3);
WriteCtrReg(MAADR1,bytMacAddress[0]);
WriteCtrReg(MAADR2,bytMacAddress[1]);
WriteCtrReg(MAADR3,bytMacAddress[2]);
WriteCtrReg(MAADR4,bytMacAddress[3]);
WriteCtrReg(MAADR5,bytMacAddress[4]);
WriteCtrReg(MAADR6,bytMacAddress[5]);

// Initialise the PHY registes
WritePhyReg(PHCON1, 0x000);
test =ReadPhyReg(PHCON1);
WritePhyReg(PHCON2, PHCON2_HDLDIS);
WriteCtrReg(ECON1, ECON1_RXEN); //Enable the chip for reception
of packets
}

/***********************************************************************/
/** \brief Writes a packet to the ENC28J60.
*
* Description: Writes ui_len bytes of data from ptrBufffer into ENC28J60.
* puts the necessary padding around the packet to make
it a legit
MAC packet.\n \n
1) Program ETXST. \n
2) Write per packet control byte.\n
3) Program ETXND.\n
4) Set ECON1.TXRTS.\n
5) Check ESTAT.TXABRT. \n

* \author Iain Derrington
* \param ptrBuffer ptr to byte buffer.
* \param ui_Len Number of bytes to write from buffer.
* \return uint True or false.
*/
/**********************************************************************/
u16_t MACWrite()
{
volatile u16_t i;
volatile u16_t address = TXSTART;
u8_t bytControl;

bytControl = 0x00;

BankSel(0); // select bank 0

WriteCtrReg(EWRPTL,(u8_t)( TXSTART & 0x00ff)); // Set write
buffer to point to start of Tx Buffer
WriteCtrReg(EWRPTH,(u8_t)((TXSTART & 0xff00)>>8));

address += WriteMacBuffer(&bytControl,1); //
write per packet control byte

address+=WriteMacBuffer(&uip_buf[0], UIP_LLH_LEN);
if(uip_len <= UIP_LLH_LEN + UIP_TCPIP_HLEN)
{
address+=WriteMacBuffer(&uip_buf[UIP_LLH_LEN], uip_len - UIP_LLH_LEN);
}
else
{
address+=WriteMacBuffer(&uip_buf[UIP_LLH_LEN], UIP_TCPIP_HLEN);
address+=WriteMacBuffer(uip_appdata, uip_len - UIP_TCPIP_HLEN -
UIP_LLH_LEN);
}

WriteCtrReg(ETXSTL,(u8_t)( TXSTART & 0x00ff)); // write ptr
to start of Tx packet
WriteCtrReg(ETXSTH,(u8_t)((TXSTART & 0xff00)>>8));

WriteCtrReg(ETXNDL, (u8_t)( address & 0x00ff)); // Tell MAC
when the end of the packet is
WriteCtrReg(ETXNDH, (u8_t)((address & 0xff00)>>8));

ClrBitField(EIR,EIR_TXIF);
SetBitField(EIE, EIE_TXIE |EIE_INTIE);

ERRATAFIX;
SetBitField(ECON1, ECON1_TXRTS); // begin
transmitting;

#if 1
{
int count = 0;
do
{
count++;
}while ((!(ReadETHReg(EIR) & (EIR_TXIF))) && (count < 30000));
// kill some time. Note: Nice place to block?
}

ClrBitField(ECON1, ECON1_TXRTS);
#else
do
{
}while (!(ReadETHReg(EIR) & (EIR_TXIF))); // kill some
time. Note: Nice place to block?
ClrBitField(ECON1, ECON1_TXRTS);

BankSel(0); // read tx
status bytes
address++; // increment ptr
to address to start of status struc
WriteCtrReg(ERDPTL, (u8_t)( address & 0x00ff)); // Setup the
buffer read ptr to read status struc
WriteCtrReg(ERDPTH, (u8_t)((address & 0xff00)>>8));
ReadMacBuffer(&TxStatus.v[0],7);

if (ReadETHReg(ESTAT) & ESTAT_TXABRT) // did
transmission get interrupted?
{
if (TxStatus.bits.LateCollision)
{
ClrBitField(ECON1, ECON1_TXRTS);
SetBitField(ECON1, ECON1_TXRTS);

ClrBitField(ESTAT,ESTAT_TXABRT | ESTAT_LATECOL);
}
ClrBitField(EIR, EIR_TXERIF | EIR_TXIF);
ClrBitField(ESTAT,ESTAT_TXABRT);

return FALSE; // packet
transmit failed. Inform calling function
} // calling
function may inquire why packet failed by calling [TO DO] function
else
{
return TRUE; // all fan
dabby dozy
}
#endif
return TRUE;
}

/***********************************************************************/
/** \brief Tries to read a packet from the ENC28J60.
*
* Description: If a valid packet is available in the ENC28J60 this
function reads the packet into a
* buffer. The memory within the ENC28J60 will then be
released. This version of the
driver does not use interrupts so this function needs
to be polled.\n \n
*
* 1) Read packet count register. If >0 then continue else return. \n
* 2) Read the current ERXRDPTR value. \n
* 3) Write this value into ERDPT. \n
* 4) First two bytes contain the ptr to the start of next packet.
Read this value in. \n
* 5) Calculate length of packet. \n
* 6) Read in status byte into private variable. \n
* 7) Read in packet and place into buffer. \n
* 8) Free up memory in the ENC. \n
*
* \author Iain Derrington
* \param ptrBuffer ptr to buffer of bytes where the packet should be
read into.
* \return u16_t, the number of complete packets in the buffer -1.

*/
/**********************************************************************/
u16_t MACRead()
{
volatile u16_t u16_t_pckLen,test;
volatile u16_t u16_t_rdptr,u16_t_wrtptr;
static u16_t nextpckptr = RXSTART;
volatile RXSTATUS ptrRxStatus;
volatile u8_t bytPacket;

BankSel(1);

bytPacket = ReadETHReg(EPKTCNT); // How many packets have
been received

if(bytPacket == 0)
return bytPacket; // No full packets received

BankSel(0);

WriteCtrReg(ERDPTL,(u8_t)( nextpckptr & 0x00ff)); //write this
value to read buffer ptr
WriteCtrReg(ERDPTH,(u8_t)((nextpckptr & 0xff00)>>8));

ReadMacBuffer((u8_t*)&ptrRxStatus.v[0],6); // read next
packet ptr + 4 status bytes
nextpckptr = ptrRxStatus.bits.NextPacket;

uip_len=ptrRxStatus.bits.ByteCount;
if (uip_len > UIP_BUFSIZE) uip_len = UIP_BUFSIZE;
ReadMacBuffer(uip_buf,uip_len); // read packet into buffer

// ptrBuffer should now
contain a MAC packet
BankSel(0);
WriteCtrReg(ERXRDPTL,ptrRxStatus.v[0]); // free up ENC memory my
adjustng the Rx Read ptr
WriteCtrReg(ERXRDPTH,ptrRxStatus.v[1]);

// decrement packet counter
SetBitField(ECON2, ECON2_PKTDEC);

return uip_len;
}

/*------------------------Private Functions-----------------------------*/

/***********************************************************************/
/** \brief ReadETHReg.
*
* Description: Reads contents of the addressed ETH reg over SPI bus.
Assumes correct bank selected.
*
*
* \author Iain Derrington
* \param bytAddress Address of register to be read
* \return byte Value of register.
*/
/**********************************************************************/
static u8_t ReadETHReg(u8_t bytAddress)
{
u8_t bytData;

if (bytAddress > 0x1F)
return FALSE; // address invalid, [TO DO]

SEL_MAC(TRUE); // ENC CS low
SPIWrite(&bytAddress,1); // write opcode
SPIRead(&bytData, 1); // read value
SEL_MAC(FALSE);

return bytData;

}

/***********************************************************************/
/** \brief ReadMacReg.
*
* Description: Read contents of addressed MAC register over SPI bus.
Assumes correct bank selected.
*
* \author Iain Derrington
* \param bytAddress Address of register to read.
* \return byte Contens of register just read.
*/
/**********************************************************************/
static u8_t ReadMacReg(u8_t bytAddress)
{
u8_t bytData;

if (bytAddress > 0x1F)
return FALSE; // address invalid, [TO DO]

SEL_MAC(TRUE); // ENC CS low

SPIWrite(&bytAddress,1); // write opcode
SPIRead(&bytData, 1); // read dummy byte
SPIRead(&bytData, 1); // read value
SEL_MAC(FALSE);

return bytData;
}

/***********************************************************************/
/** \brief Write to phy Reg.
*
* Description: Writing to PHY registers is different to writing the
other regeisters in that
the registers can not be accessed directly. This
function wraps up the requirements
for writing to the PHY reg. \n \n

1) Write address of phy reg to MIREGADR. \n
2) Write lower 8 bits of data to MIWRL. \n
3) Write upper 8 bits of data to MIWRL. \n \n
*
*
* \author Iain Derrington
* \param address
* \param data
* \return byte
*/
/**********************************************************************/
static u8_t WritePhyReg(u8_t address, u16_t data)
{
if (address > 0x14)
return FALSE;

BankSel(2);

WriteCtrReg(MIREGADR,address); // Write address of Phy reg
WriteCtrReg(MIWRL,(u8_t)data); // lower phy data
WriteCtrReg(MIWRH,((u8_t)(data >>8))); // Upper phydata

return TRUE;
}

/***********************************************************************/
/** \brief Read from PHY reg.
*
* Description: No direct access allowed to phy registers so the
folling process must take place. \n \n
* 1) Write address of phy reg to read from into MIREGADR. \n
* 2) Set MICMD.MIIRD bit and wait 10.4uS. \n
* 3) Clear MICMD.MIIRD bit. \n
* 4) Read data from MIRDL and MIRDH reg. \n
* \author Iain Derrington
* \param address
* \return uint
*/
/**********************************************************************/
static u16_t ReadPhyReg(u8_t address)
{
volatile u16_t uiData;
volatile u8_t bytStat;

do {
int count=0;
BankSel(2);
WriteCtrReg(MIREGADR,address); // Write address of phy register to
read
SetBitField(MICMD, MICMD_MIIRD); // Set rd bit
do
{
bytStat = ReadMacReg(MISTAT);
}while ((bytStat & MISTAT_BUSY) && (count++ < 3000));
} while (bytStat & MISTAT_BUSY);

ClrBitField(MICMD,MICMD_MIIRD); // Clear rd bit
uiData = (u16_t)ReadMacReg(MIRDL); // Read low data byte
uiData |=((u16_t)ReadMacReg(MIRDH)<<8); // Read high data byte

return uiData;
}

/***********************************************************************/
/** \brief Write to a control reg .
*
* Description: Writes a byte to the address register. Assumes that
correct bank has
* all ready been selected
*
* \author Iain Derrington
* \param bytAddress Address of register to be written to.
* \param bytData Data to be written.
* \returns byte
*/
/**********************************************************************/
static u8_t WriteCtrReg(u8_t bytAddress,u8_t bytData)
{
if (bytAddress > 0x1f)
{
return FALSE;
}

bytAddress |= WCR_OP; // Set opcode
SEL_MAC(TRUE); // ENC CS low
SPIWrite(&bytAddress,1); // Tx opcode and address
SPIWrite(&bytData,1); // Tx data
SEL_MAC(FALSE);

return TRUE;
}

/***********************************************************************/
/** \brief Read bytes from MAC data buffer.
*
* Description: Reads a number of bytes from the ENC28J60 internal
memory. Assumes auto increment
* is on.
*
* \author Iain Derrington
* \param bytBuffer Buffer to place data in.
* \param byt_length Number of bytes to read.
* \return uint Number of bytes read.
*/
/**********************************************************************/
static u16_t ReadMacBuffer(u8_t * bytBuffer,u16_t byt_length)
{
u8_t bytOpcode;
volatile u16_t len;

bytOpcode = RBM_OP;
SEL_MAC(TRUE); // ENC CS low

SPIWrite(&bytOpcode,1); // Tx opcode
len = SPIRead(bytBuffer, byt_length); // read bytes into buffer
SEL_MAC(FALSE); // release CS

return len;

}
/***********************************************************************/
/** \brief Write bytes to MAC data buffer.
*
* Description: Reads a number of bytes from the ENC28J60 internal
memory. Assumes auto increment
* is on.
*
* \author Iain Derrington
* \param bytBuffer
* \param ui_len
* \return uint
* \date WIP
*/
/**********************************************************************/
static u16_t WriteMacBuffer(u8_t * bytBuffer,u16_t ui_len)
{
u8_t bytOpcode;
volatile u16_t len;

bytOpcode = WBM_OP;
SEL_MAC(TRUE); // ENC CS low

SPIWrite(&bytOpcode,1); // Tx opcode
len = SPIWrite(bytBuffer, ui_len); // read bytes into buffer
SEL_MAC(FALSE); // release CS

return len;

}

/***********************************************************************/
/** \brief Set bit field.
*
* Description: Sets the bit/s at the address register. Assumes
correct bank has been selected.
*
* \author Iain Derrington
* \param bytAddress Address of registed where bit is to be set
* \param bytData Sets all the bits high.
* \return byte True or false
*/
/**********************************************************************/
static u8_t SetBitField(u8_t bytAddress, u8_t bytData)
{
if (bytAddress > 0x1f)
{
return FALSE;
}

bytAddress |= BFS_OP; // Set opcode
SEL_MAC(TRUE); // ENC CS low

SPIWrite(&bytAddress,1); // Tx opcode and address
SPIWrite(&bytData,1); // Tx data
SEL_MAC(FALSE);

return TRUE;
}

/***********************************************************************/
/** \brief Clear bit field on ctr registers.
*
* Description: Sets the bit/s at the address register. Assumes
correct bank has been selected.
*
* \author Iain Derrington
* \param bytAddress Address of registed where bit is to be set
* \param bytData Sets all the bits high.
* \return byte True or false
*/
/**********************************************************************/
static u8_t ClrBitField(u8_t bytAddress, u8_t bytData)
{
if (bytAddress > 0x1f)
{
return FALSE;
}

bytAddress |= BFC_OP; // Set opcode
SEL_MAC(TRUE); // ENC CS low

SPIWrite(&bytAddress,1); // Tx opcode and address
SPIWrite(&bytData,1); // Tx data
SEL_MAC(FALSE);

return TRUE;
}

/***********************************************************************/
/** \brief Bank Select.
*
* Description: Select the required bank within the ENC28J60
*
*
* \author Iain Derrington
* \param bank Value between 0 and 3.
* \date 0.1 09/06/07 First draft
*/
/**********************************************************************/
static void BankSel(u8_t bank)
{
volatile u8_t temp;

if (bank >3)
return;

temp = ReadETHReg(ECON1); // Read ECON1 register
temp &= ~ECON1_BSEL; // mask off the BSEL bits
temp |= bank; // set BSEL bits
WriteCtrReg(ECON1, temp); // write new values back to ENC28J60
}
/***********************************************************************/
/** \brief ResetMac.
*
* Description: Sends command to reset the MAC.
*
*
* \author Iain Derrington
*/
/**********************************************************************/
static void ResetMac(void)
{
u8_t bytOpcode = RESET_OP;
SEL_MAC(TRUE); // ENC CS low

SPIWrite(&bytOpcode,1); // Tx opcode and address
SEL_MAC(FALSE);

}

Reply by mjames_doveridge March 19, 20082008-03-19
>
> I don't use interrupt.I use poll mode you can see the code.
>

Fine - I just wondered if there was something about the SPI interrupts
that you had discovered :)
Rgds,
Martin

Reply by nader chinichian March 19, 20082008-03-19
I don't use interrupt.I use poll mode you can see the code.

Int8U SpiByte (Int8U ch)
{
while(!(SSPSR & TNF));
SSPDR = ch;
while(!(SSPSR & RNE));
return((Int8U)SSPDR);
}

void SSP_Init (void)
{
Int32U i;
volatile Int32U Dummy;

// Chip select
IO0SET |= (1<<20);
IO0DIR |= (1<<20);

IO0SET |= (1<<7);
IO0DIR |= (1<<7);
// Spi init
SSPCR0 = 0x7;
SSPCR1 = 0;
SSPIMSC = 0;
MmcSetClockFreq(10MHZ);//400KHZ);
PINSEL1_bit.P0_17 = PINSEL1_bit.P0_18 = PINSEL1_bit.P0_19 = 2;
PINSEL1_bit.P0_20 = 0;
// Enable SPI
SSPCR1 |= SSE;

for ( i = 0; i < 8; i++ )
Dummy = SSPDR; /* clear the RxFIFO */
}

mjames_doveridge wrote: >
> I am already doing this. Using SSP as an SPI port is very easy as
> long as you are doing polling io:
>

Have you specific problem with interrupts on the SPI, or is it just
that it's more awkward/complex?

Rgds,
Martin

---------------------------------
Never miss a thing. Make Yahoo your homepage.


Reply by nader chinichian March 19, 20082008-03-19
Hi,

As I see I think to work with a MMS/SD card with SSP. I did it and it work fine for me. I use IAR mmc_ll.h example. But I have problem to read the enc28j60 register via SSP.
if you work with enc28j60 I can send my code to you to see.
I don't think there is any wrong with my enc28j60 board beacuse windows can detect it and the link led on and also activity led blink for me.
so the problem must for SSP.
/*************************************************************************
* File name : mmc_ll.h
* Description : define MMC module
**************************************************************************/
#include "LPC_SSP.h"

/*************************************************************************
* Function Name: MmcChipSelect
* Parameters: Boolean Select
* Description: Mmc Chip select control
* Select = true - Chip is enable
* Select = false - Chip is disable
*************************************************************************/
void SSP_CS (unsigned int Dev, Boolean Select)
{
if (Select)
IO0CLR = Dev;
else
{
IO0SET = Dev;
// Synchronization
while(!(SSPSR & TNF));
SSPDR = 0xFF;
// Wait until tx fifo and tx shift bufer are empty
while((SSPSR & BSY));
while(!(SSPSR & RNE));
do
{
Select = SSPDR;
}
while((SSPSR & RNE));
}
}
/*************************************************************************
* Function Name: MmcSetClockFreq
* Parameters: Int32U Frequency
* Return: Int32U
* Description: Set SPI ckl frequency
*************************************************************************/
Int32U MmcSetClockFreq (Int32U Frequency)
{
Int32U Div = CCLK/Frequency;
// Check min clk divider (for master mode >= 2)
if (Div < 2)
Div = 2;
// Check max clk divider <= 254
else if (Div > 254)
Div = 254;
// Because Bit 0 is not implement
++Div;
Div &= ~1;
SSPCPSR = Div;
// Return real frequency
return(CCLK/Div);
}
/*************************************************************************
* Function Name: MmcInit
* Parameters: none
* Return: int
* 0 - no error
* 1 - speed is to high
*
* Description: Init SPI, Cart Present, Write Protect and Chip select pins
*
*************************************************************************/
void SSP_Init (void)
{
Int32U i;
volatile Int32U Dummy;

// Chip select
IO0SET |= (1<<20);
IO0DIR |= (1<<20);

IO0SET |= (1<<7);
IO0DIR |= (1<<7);
// Cart present
// Spi init
SSPCR0 = 0x7;
SSPCR1 = 0;
SSPIMSC = 0;
// Clock Freq. Identification Mode < 400kHz
MmcSetClockFreq(10MHZ); //400KHZ);
PINSEL1_bit.P0_17 = PINSEL1_bit.P0_18 = PINSEL1_bit.P0_19 = 2;
PINSEL1_bit.P0_20 = 0;
// Enable SPI
SSPCR1 |= SSE;

for ( i = 0; i < 8; i++ )
Dummy = SSPDR; /* clear the RxFIFO */
}
/*************************************************************************
* Function Name: SpiByte
* Parameters: Int8U ch
* Return: Int8U
* Description: Read byte from SPI
*************************************************************************/
Int8U SpiByte (Int8U ch)
{
while(!(SSPSR & TNF));
SSPDR = ch;
while(!(SSPSR & RNE));
return((Int8U)SSPDR);
}
/*************************************************************************
* Function Name: MmcSendBlock
* Parameters: pInt8U pData, Int32U Size
* Return: void
* Description: Read byte from SPI
*************************************************************************/
void MmcSendBlock (pInt8U pData, Int32U Size)
{
Int32U OutCount = Size;
while (OutCount)
{
while((SSPSR & TNF) && OutCount)
{
SSPDR = *pData++;
--OutCount;
}
}
while ((SSPSR & RNE) || !(SSPSR & TFE))
{
volatile Int32U Dummy = SSPDR;
}
}
/*************************************************************************
* Function Name: MmcReceiveBlock
* Parameters: pInt8U pData, Int32U Size
*
* Return: void
*
* Description: Read byte from SPI
*
*************************************************************************/
void MmcReceiveBlock (pInt8U pData, Int32U Size)
{
Int32U Delta = 0;
while (Size || Delta)
{
while((SSPSR & TNF) && (Delta < SSP_FIFO_SIZE) && Size)
{
SSPDR = 0xFF;
--Size; ++Delta;
}
while ((SSPSR & RNE))
{
*pData++ = SSPDR;
--Delta;
}
}
}

---------------------------------
Never miss a thing. Make Yahoo your homepage.


Reply by profdc9 March 19, 20082008-03-19
--- In l..., "Nader" wrote:
>
> Hello,
> I try to connect a enc28j60/ss to lpc2148 with SSP as SPI @ 15Mhz,
> but it fail to read/write with enc28j60. the enc28j60 is a little hot!
> I search only find code for SPI0 :(. So I'd like to know is anyone
> here have any experiment to connect enc28j60 to SSP of lpc2000?
>
> Thanks.
>

I am already doing this. Using SSP as an SPI port is very easy as
long as you are doing polling io:

Code to initialize SPI port:

void initSSP(void)
{
SCB_PCONP |= SCB_PCONP_PCSPI1;

SSP_CR0 = SSP_CR0_DSS_8 | SSP_CR0_FRF_SPI;
SSP_CR1 = 0x00;
SSP_IMSC = 0x00;

SSP_CPSR = SPI_MMC_SPEED;

PCB_PINSEL1 = (PCB_PINSEL1 & ~(PCB_PINSEL1_P017_MASK |
PCB_PINSEL1_P018_MASK | PCB_PINSEL1_P019_MASK));
PCB_PINSEL1 = (PCB_PINSEL1 | (PCB_PINSEL1_P017_SCK1 |
PCB_PINSEL1_P018_MISO1 | PCB_PINSEL1_P019_MOSI1));
PCB_PINSEL1 = (PCB_PINSEL1 & ~(PCB_PINSEL1_P020_MASK |
PCB_PINSEL1_P021_MASK | PCB_PINSEL1_P022_MASK));
}

Code to do SSP transfer:

U8 spiTransfer (U8 c)
{
while (!(SSP_SR & SSP_SR_TNF));
SSP_DR = c;
while (!(SSP_SR & SSP_SR_RNE));
return (U8) SSP_DR;
}

You will have to manually fiddle the chip select line yourself
though.

Dan

Definitions from JC Wren's LPC2148 demo:

#define PCB_PINSEL1 (*(pREG32 (0xe002c004)))
#define PCB_PINSEL1_P016_GPIO ((unsigned int) 0x00000000)
#define PCB_PINSEL1_P016_EINT0 ((unsigned int) 0x00000001)
#define PCB_PINSEL1_P016_MAT02 ((unsigned int) 0x00000002)
#define PCB_PINSEL1_P016_CAP02 ((unsigned int) 0x00000003)
#define PCB_PINSEL1_P016_MASK ((unsigned int) 0x00000003)

#define PCB_PINSEL1_P017_GPIO ((unsigned int) 0x00000000)
#define PCB_PINSEL1_P017_CAP12 ((unsigned int) 0x00000004)
#define PCB_PINSEL1_P017_SCK1 ((unsigned int) 0x00000008)
#define PCB_PINSEL1_P017_MAT12 ((unsigned int) 0x0000000c)
#define PCB_PINSEL1_P017_MASK ((unsigned int) 0x0000000c)

#define PCB_PINSEL1_P018_GPIO ((unsigned int) 0x00000000)
#define PCB_PINSEL1_P018_CAP13 ((unsigned int) 0x00000010)
#define PCB_PINSEL1_P018_MISO1 ((unsigned int) 0x00000020)
#define PCB_PINSEL1_P018_MAT13 ((unsigned int) 0x00000030)
#define PCB_PINSEL1_P018_MASK ((unsigned int) 0x00000030)

#define PCB_PINSEL1_P019_GPIO ((unsigned int) 0x00000000)
#define PCB_PINSEL1_P019_MAT12 ((unsigned int) 0x00000040)
#define PCB_PINSEL1_P019_MOSI1 ((unsigned int) 0x00000080)
#define PCB_PINSEL1_P019_CAP12 ((unsigned int) 0x000000c0)
#define PCB_PINSEL1_P019_MASK ((unsigned int) 0x000000c0)

#define PCB_PINSEL1_P020_GPIO ((unsigned int) 0x00000000)
#define PCB_PINSEL1_P020_MAT13 ((unsigned int) 0x00000100)
#define PCB_PINSEL1_P020_SSEL1 ((unsigned int) 0x00000200)
#define PCB_PINSEL1_P020_EINT3 ((unsigned int) 0x00000300)
#define PCB_PINSEL1_P020_MASK ((unsigned int) 0x00000300)

#define PCB_PINSEL1_P021_GPIO ((unsigned int) 0x00000000)
#define PCB_PINSEL1_P021_PWM5 ((unsigned int) 0x00000400)
#define PCB_PINSEL1_P021_AD16 ((unsigned int) 0x00000800)
#define PCB_PINSEL1_P021_CAP13 ((unsigned int) 0x00000c00)
#define PCB_PINSEL1_P021_MASK ((unsigned int) 0x00000c00)

#define PCB_PINSEL1_P022_GPIO ((unsigned int) 0x00000000)
#define PCB_PINSEL1_P022_AD17 ((unsigned int) 0x00001000)
#define PCB_PINSEL1_P022_CAP00 ((unsigned int) 0x00002000)
#define PCB_PINSEL1_P022_MAT00 ((unsigned int) 0x00003000)
#define PCB_PINSEL1_P022_MASK ((unsigned int) 0x00003000)

#define PCB_PINSEL1_P023_GPIO ((unsigned int) 0x00000000)
#define PCB_PINSEL1_P023_VBUS ((unsigned int) 0x00004000)
#define PCB_PINSEL1_P023_RSVD2 ((unsigned int) 0x00008000)
#define PCB_PINSEL1_P023_RSVD3 ((unsigned int) 0x0000c000)
#define PCB_PINSEL1_P023_MASK ((unsigned int) 0x0000c000)

#define PCB_PINSEL1_P024_RSVD0 ((unsigned int) 0x00000000)
#define PCB_PINSEL1_P024_RSVD1 ((unsigned int) 0x00010000)
#define PCB_PINSEL1_P024_RSVD2 ((unsigned int) 0x00020000)
#define PCB_PINSEL1_P024_RSVD3 ((unsigned int) 0x00030000)
#define PCB_PINSEL1_P024_MASK ((unsigned int) 0x00030000)

#define PCB_PINSEL1_P025_GPIO ((unsigned int) 0x00000000)
#define PCB_PINSEL1_P025_AD04 ((unsigned int) 0x00040000)
#define PCB_PINSEL1_P025_AOUT ((unsigned int) 0x00080000)
#define PCB_PINSEL1_P025_RSVD3 ((unsigned int) 0x000c0000)
#define PCB_PINSEL1_P025_MASK ((unsigned int) 0x000c0000)

#define PCB_PINSEL1_P026_RSVD0 ((unsigned int) 0x00000000)
#define PCB_PINSEL1_P026_RSVD1 ((unsigned int) 0x00100000)
#define PCB_PINSEL1_P026_RSVD2 ((unsigned int) 0x00200000)
#define PCB_PINSEL1_P026_RSVD3 ((unsigned int) 0x00300000)
#define PCB_PINSEL1_P026_MASK ((unsigned int) 0x00300000)

#define PCB_PINSEL1_P027_RSVD0 ((unsigned int) 0x00000000)
#define PCB_PINSEL1_P027_RSVD1 ((unsigned int) 0x00400000)
#define PCB_PINSEL1_P027_RSVD2 ((unsigned int) 0x00800000)
#define PCB_PINSEL1_P027_RSVD3 ((unsigned int) 0x00c00000)
#define PCB_PINSEL1_P027_MASK ((unsigned int) 0x00c00000)

#define PCB_PINSEL1_P028_GPIO ((unsigned int) 0x00000000)
#define PCB_PINSEL1_P028_AD01 ((unsigned int) 0x01000000)
#define PCB_PINSEL1_P028_CAP02 ((unsigned int) 0x02000000)
#define PCB_PINSEL1_P028_MAT02 ((unsigned int) 0x03000000)
#define PCB_PINSEL1_P028_MASK ((unsigned int) 0x03000000)

#define PCB_PINSEL1_P029_GPIO ((unsigned int) 0x00000000)
#define PCB_PINSEL1_P029_AD02 ((unsigned int) 0x04000000)
#define PCB_PINSEL1_P029_CAP03 ((unsigned int) 0x08000000)
#define PCB_PINSEL1_P029_MAT03 ((unsigned int) 0x0c000000)
#define PCB_PINSEL1_P029_MASK ((unsigned int) 0x0c000000)

#define PCB_PINSEL1_P030_GPIO ((unsigned int) 0x00000000)
#define PCB_PINSEL1_P030_AD03 ((unsigned int) 0x10000000)
#define PCB_PINSEL1_P030_EINT3 ((unsigned int) 0x20000000)
#define PCB_PINSEL1_P030_CAP00 ((unsigned int) 0x30000000)
#define PCB_PINSEL1_P030_MASK ((unsigned int) 0x30000000)

#define PCB_PINSEL1_P031_GPIO ((unsigned int) 0x00000000)
#define PCB_PINSEL1_P031_UPLED ((unsigned int) 0x40000000)
#define PCB_PINSEL1_P031_CONNECT ((unsigned int) 0x80000000)
#define PCB_PINSEL1_P031_RSVD3 ((unsigned int) 0xc0000000)
#define PCB_PINSEL1_P031_MASK ((unsigned int) 0xc0000000)

/*##############################################################################
## SSP - Synchronous Serial Port
##############################################################################*/

#define SSP_CR0 (*(pREG32 (0xe0068000)))
#define SSP_CR1 (*(pREG32 (0xe0068004)))
#define SSP_DR (*(pREG32 (0xe0068008)))
#define SSP_SR (*(pREG32 (0xe006800C)))
#define SSP_CPSR (*(pREG32 (0xe0068010)))
#define SSP_IMSC (*(pREG32 (0xe0068014)))
#define SSP_RIS (*(pREG32 (0xe0068018)))
#define SSP_MIS (*(pREG32 (0xe006801C)))
#define SSP_ICR (*(pREG32 (0xe0068020)))

#define SSP_FIFO_DEPTH (8)

#define SSP_CR0_DSS_4 ((unsigned int) 0x00000003)
#define SSP_CR0_DSS_5 ((unsigned int) 0x00000004)
#define SSP_CR0_DSS_6 ((unsigned int) 0x00000005)
#define SSP_CR0_DSS_7 ((unsigned int) 0x00000006)
#define SSP_CR0_DSS_8 ((unsigned int) 0x00000007)
#define SSP_CR0_DSS_9 ((unsigned int) 0x00000008)
#define SSP_CR0_DSS 10 ((unsigned int) 0x00000009)
#define SSP_CR0_DSS_11 ((unsigned int) 0x0000000a)
#define SSP_CR0_DSS_12 ((unsigned int) 0x0000000b)
#define SSP_CR0_DSS_13 ((unsigned int) 0x0000000c)
#define SSP_CR0_DSS_14 ((unsigned int) 0x0000000d)
#define SSP_CR0_DSS_15 ((unsigned int) 0x0000000e)
#define SSP_CR0_DSS_16 ((unsigned int) 0x0000000f)
#define SSP_CR0_FRF_SPI ((unsigned int) 0x00000000)
#define SSP_CR0_FRF_SSI ((unsigned int) 0x00000010)
#define SSP_CR0_FRF_MW ((unsigned int) 0x00000020)
#define SSP_CR0_CPOL ((unsigned int) 0x00000040)
#define SSP_CR0_CPHA ((unsigned int) 0x00000080)
#define SSP_CR0_SCR ((unsigned int) 0x0000ff00)

#define SSP_CR1_LBM ((unsigned int) 0x00000001)
#define SSP_CR1_SSE ((unsigned int) 0x00000002)
#define SSP_CR1_MS ((unsigned int) 0x00000004)
#define SSP_CR1_SOD ((unsigned int) 0x00000008)

#define SSP_SR_TFE ((unsigned int) 0x00000001)
#define SSP_SR_TNF ((unsigned int) 0x00000002)
#define SSP_SR_RNE ((unsigned int) 0x00000004)
#define SSP_SR_RFF ((unsigned int) 0x00000008)
#define SSP_SR_BSY ((unsigned int) 0x00000010)

#define SSP_IMSC_RORIM ((unsigned int) 0x00000001)
#define SSP_IMSC_RTIM ((unsigned int) 0x00000002)
#define SSP_IMSC_RXIM ((unsigned int) 0x00000004)
#define SSP_IMSC_TXIM ((unsigned int) 0x00000008)

#define SSP_RIS_RORRIS ((unsigned int) 0x00000001)
#define SSP_RIS_RTRIS ((unsigned int) 0x00000002)
#define SSP_RIS_RXRIS ((unsigned int) 0x00000004)
#define SSP_RIS_TXRIS ((unsigned int) 0x00000008)

#define SSP_MIS_RORMIS ((unsigned int) 0x00000001)
#define SSP_MIS_RTMIS ((unsigned int) 0x00000002)
#define SSP_MIS_RXMIS ((unsigned int) 0x00000004)
#define SSP_MIS_TXMIS ((unsigned int) 0x00000008)

#define SSP_ICR_RORIC ((unsigned int) 0x00000001)
#define SSP_ICR_RTIC ((unsigned int) 0x00000002)

Reply by Nader March 19, 20082008-03-19
Hello,
I try to connect a enc28j60/ss to lpc2148 with SSP as SPI @ 15Mhz,
but it fail to read/write with enc28j60. the enc28j60 is a little hot!
I search only find code for SPI0 :(. So I'd like to know is anyone
here have any experiment to connect enc28j60 to SSP of lpc2000?

Thanks.
=======================================================================Groups related to lpc2000
=======================================================================
msp430 (388 common members)
http://groups.yahoo.com/group/msp430?v=1&t=ipt&ch=email&pub=groups&slktr0&sec=recg
Computers & Internet/Hardware: Welcome to the MSP430 User's Group! The purpose of...

AVR-Chat (177 common members)
http://groups.yahoo.com/group/AVR-Chat?v=1&t=ipt&ch=email&pub=groups&slktr1&sec=recg
Microprocessors/Microcontrollers: A place for Atmel AVR Microcontroller users to sha...

LTspice (165 common members)
http://groups.yahoo.com/group/LTspice?v=1&t=ipt&ch=email&pub=groups&slktr2&sec=recg
Engineering/Electrical: Dedicated to the exchange of information about LTs...

Homebrew_PCBs (157 common members)
http://groups.yahoo.com/group/Homebrew_PCBs?v=1&t=ipt&ch=email&pub=groups&slktr3&sec=recg
Engineering/Electrical: Designing, making, etching, soldering, printed cir...

e-embedded (151 common members)
http://groups.yahoo.com/group/e-embedded?v=1&t=ipt&ch=email&pub=groups&slktr4&sec=recg
Internet/Internet Appliances: Open-membership mailing list for embedded system d...