/******************************************************************************
* lpc_17xx_ssp1.c: interface functions to the lpc17xx SSP for EFSL
*
* Copyright (C) 2011, MyVoice
* All Rights reserved.
*
* History
* 2011.06.27 ver 1.00 Preliminary version, first release
*
* This file contains the interface functions needed by EFSL to access the
* SD card via the SSP1 interface.
*
* This is based on te original lpc2000_spi.c file from EFSL
*
* Software License Agreement
*
* The software is owned by MyVoice CAD/CAM Services and/or its suppliers, and is
* protected under applicable copyright laws. All rights are reserved. Any
* use in violation of the foregoing restrictions may subject the user to criminal
* sanctions under applicable laws, as well as to civil liability for the breach
* of the terms and conditions of this license.
*
* THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
* USE OF THIS SOFTWARE FOR COMMERCIAL DEVELOPMENT AND/OR EDUCATION IS SUBJECT
* TO A CURRENT END USER LICENSE AGREEMENT (COMMERCIAL OR EDUCATIONAL) WITH
* MYVOICE CAD/CAM SERVICES.
*
*/
#include "LPC17xx.h"
#include "lpc17xx_ssp1.h"
#include "sd.h"
#include "config.h"
/*****************************************************************************/
// SP0SPCR Bit-Definitions
#define CPHA 3
#define CPOL 4
#define MSTR 5
// SP0SPSR Bit-Definitions
#define SR_BSY 4
#define SR_RNE 2
#define SPI_SCK_PIN 7 /* Clock P0.15 out (PINSEL0) */
#define SPI_SSEL_PIN 6 /* Card-Select P0.16 GPIO out (PINSEL1) */
#define SPI_MISO_PIN 8 /* from Card P0.17 in (PINSEL1) */
#define SPI_MOSI_PIN 9 /* to Card P0.18 out (PINSEL1) */
#define SPI_PINSEL LPC_PINCON->PINSEL0
#define SPI_SCK_FUNCMASK (3 << 14) // P0.7 - PINSEL0 [15:14]
#define SPI_SSEL_FUNCMASK (3 << 12) // P0.6 - PINSEL0 [13:12]
#define SPI_MISO_FUNCMASK (3 << 16) // P0.8 - PINSEL0 [17:16]
#define SPI_MOSI_FUNCMASK (3 << 18) // P0.9 - PINSEL0 [19:18]
#define SPI_SCK_FUNCBIT (2 << 14)
#define SPI_SSEL_FUNCBIT (0 << 12) // Note - SSEL needed as GPIO
#define SPI_MISO_FUNCBIT (2 << 16)
#define SPI_MOSI_FUNCBIT (2 << 18)
#define SPI_PRESCALE_REG LPC_SPI->SPCCR
#define SPI_PRESCALE_MIN 8
#define SELECT_CARD() LPC_GPIO0->FIOCLR = (1 << SPI_SSEL_PIN)
#define UNSELECT_CARD() LPC_GPIO0->FIOSET = (1 << SPI_SSEL_PIN)
esint8 if_initInterface(hwInterface* file, eint8* opts)
{
euint32 sc;
if_spiInit(file); /* init at low speed */
if(sd_Init(file)<0) {
DBG((TXT("Card failed to init, breaking up...\n")));
return(-1);
}
if(sd_State(file)<0){
DBG((TXT("Card didn't return the ready state, breaking up...\n")));
return(-2);
}
sd_getDriveSize(file, &sc);
file->sectorCount = sc/512;
if( (sc%512) != 0) {
file->sectorCount--;
}
DBG((TXT("Drive Size is %lu Bytes (%lu Sectors)\n"), sc, file->sectorCount));
if_spiSetSpeed(SPI_PRESCALE_MIN);
DBG((TXT("Init done...\n")));
return(0);
}
/*****************************************************************************/
esint8 if_readBuf(hwInterface* file,euint32 address,euint8* buf)
{
return(sd_readSector(file,address,buf,512));
}
/*****************************************************************************/
esint8 if_writeBuf(hwInterface* file,euint32 address,euint8* buf)
{
return(sd_writeSector(file,address, buf));
}
/*****************************************************************************/
esint8 if_setPos(hwInterface* file,euint32 address)
{
return(0);
}
/*****************************************************************************/
// Utility-functions which does not toggle CS.
// Only needed during card-init. During init
// the automatic chip-select is disabled for SSP
static euint8 my_if_spiSend(hwInterface *iface, euint8 outgoing)
{
LPC_SSP1->DR = outgoing;
while (LPC_SSP1->SR & (1 << SR_BSY));
return LPC_SSP1->DR;
}
/*****************************************************************************/
void if_spiInit(hwInterface *iface)
{
int i;
DBG((TXT("spiInit for SSP(1)\n")));
// Turn on the power
LPC_SC->PCONP |= (1<<10); // PCSSP1
// CodeRed - clock
LPC_SC->PCLKSEL0 &= ~(3<<20); // PCLK_SSP1
LPC_SC->PCLKSEL0 |= (1<<20); // PCLK_periph = CCLK
// setup GPIO
LPC_GPIO0->FIODIR |= (1 << SPI_SCK_PIN) | (1 << SPI_MOSI_PIN) | (1 << SPI_SSEL_PIN);
LPC_GPIO0->FIODIR &= ~(1 << SPI_MISO_PIN);
/*
* Set pin functions:
* P0.6 - SSEL1
* P0.7 - SCK1
* P0.8 - MISO1
* P0.9 - MOSI1
*/
LPC_PINCON->PINSEL0 &= ~(SPI_SCK_FUNCMASK | SPI_MOSI_FUNCMASK | SPI_MISO_FUNCMASK | SPI_SSEL_FUNCMASK);
LPC_PINCON->PINSEL0 |= (SPI_SCK_FUNCBIT | SPI_MOSI_FUNCBIT | SPI_MISO_FUNCBIT | SPI_SSEL_FUNCBIT );
/*
* enable SSP1-Master:
* 8 bits
* CPHA = 0 (data is sampled on the first clock edge)
* CPOL = 0 9SCK is active high)
* Send data with MSB first
*/
LPC_SSP1->CR0 = 0b00000111; /* CPHA = 0, CPOL = 0, FRF = 00, DSS = 0111 */
LPC_SSP1->CR1 = 0b0010; /* SOD = 0, MS = 0, SSE = 1, LBM = 0 */
UNSELECT_CARD();
/* Switch the SSP MOSI line to a GPIO and drive it high too. */
//CRT - P0.9 back to GPIO
// RWJ: ToDo: check!!!
LPC_PINCON->PINSEL0 &= ~(SPI_MOSI_FUNCMASK);
LPC_GPIO0->FIODIR |= (1<<SPI_MOSI_PIN);
LPC_GPIO0->FIOSET = (1<<SPI_MOSI_PIN);
// low speed during init
if_spiSetSpeed(254);
/* Send 21 spi commands with card not selected */
for (i = 0; i < 21; i++) {
my_if_spiSend(iface, 0xff);
}
LPC_PINCON->PINSEL0 |= (SPI_MOSI_FUNCBIT);
}
/*****************************************************************************/
void if_spiSetSpeed(euint8 speed)
{
speed &= 0xFE;
if (speed < SPI_PRESCALE_MIN) {
speed = SPI_PRESCALE_MIN;
}
LPC_SSP1->CPSR = speed;
}
/*****************************************************************************/
euint8 if_spiSend(hwInterface *iface, euint8 outgoing)
{
euint8 incoming;
SELECT_CARD();
LPC_SSP1->DR = outgoing;
while(!(LPC_SSP1->SR & (1 << SR_RNE)));
incoming = LPC_SSP1->DR;
UNSELECT_CARD();
return incoming;
}
/*****************************************************************************/
|