/****************************************************************************** * 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; } /*****************************************************************************/ |