LPCXpresso LPC1227でMARYボードAPIを流用したSPIライブラリ
Cortex-M0でもDMAが動くLPC1227ですが、FatFsを移植しDMA化したいと思います。
まずは、DMAなしでSPIを動かすところからはじめたいと思いました。
LPC1768/1769の時は、CMSISに準拠したペリフェラルドライバライブラリが提供されていましたが、現時点ではまだ完全にはありません。*1
そうなると、今のところは自前でライブラリ初期化ルーチンをこさえる必要がありますが、やっぱりMARY基板のライブラリが便利なのでこのドライバ下層部分に沿った仕様にします。
具体的にはCQ出版のMARY基板のウェブページからダウンロードできるCQ.zip内のspi.cと同じ関数を作ります。(spi.hはそのまま流用)
でも、LPC122xとLPC11xxで多少異なるので、その部分の修正をしました。
こんな感じ
#ifdef __USE_CMSIS #include "LPC122x.h" #endif #include "ssp.h" // <--SPI.hのこと。リネームした //=================== // Define Constants //=================== #define SSP_BUFSIZE 16 #define SSP_FIFOSIZE 8 void SSP_Init(unsigned int bitlen,unsigned int speed,unsigned spi_type){ // SPI_Initと同じです。 unsigned int i; unsigned int DMYLP; // ------------------------------------------------------------- // spi_type = SPI_GENERIC : Control Generic SPI Slave devices // = SPI_SDCARD : Control SD/SDHC Slave devices // ------------------------------------------------------------- // speed = SPI_FAST // = SPI_SLOW // ------------------------------------------------------------- // Initialize SPI Port // PIO0_17 : MOSI // PIO0_16 : MISO // PIO0_14 : SCLK // PIO0_15 : SSEL if(spi_type == SPI_SDCARD){ LPC_GPIO0->DIR |= 1<<15; // PIO0_15:SSEL = output LPC_GPIO0->SET |= 1<<15; // PIO0_15:SSEL = 1 }else{ LPC_IOCON->PIO0_15 = 0x2 // Select function SSEL | 0<<4 // Inactive (pull-up resistor not enabled). | 0<<10 // Open-drain mode disabled. ; } LPC_IOCON->PIO0_17 = 0x2 // Select function MOSI. | 0<<4 // Inactive (pull-up resistor not enabled). | 0<<10 // Open-drain mode disabled. ; LPC_IOCON->PIO0_16 = 0x2 // Select function MISO. | 1<<4 // Pull-up resistor enabled. | 0<<10 // Open-drain mode disabled. ; LPC_IOCON->PIO0_14 = 0x2 // Select function SCK. | 0<<4 // Inactive (pull-up resistor not enabled). | 0<<10 // Open-drain mode disabled. ; // Power up SSP. LPC_SYSCON->PRESETCTRL |= 1<<0; // SSP reset de-asserted LPC_SYSCON->SYSAHBCLKCTRL |= (1UL << 11); //Enables clock for SSP. LPC_SYSCON->SSPCLKDIV |= 3<<0; //clock divider if(speed == SPI_FAST){ // bitlen = Length of Data unit // SSP type & Clock polarity:SPI mode, (CPOL,CPHA) = ( 0, 0) // Clock Frequency = 24MHz, PCLK=48MHz // PSDVSR*(SCR+1)=2, SCR=0, CPSR=2 LPC_SSP->CR0 = 0x0000 + (bitlen-1); LPC_SSP->CPSR = 2; } else{ // Data Length = bitlen // SSP type & Clock polarity:SPI mode, (CPOL,CPHA) = ( 0, 0) // Clock Frequency = 0.4MHz, PCLK=48MHz // CPSDVSR*(SCR+1)=120, SCR=3, CPSR=30 LPC_SSP->CR0 = 0x0300 + (bitlen-1); LPC_SSP->CPSR = 30; } // Zero-fill for(i=0;i<SSP_FIFOSIZE;i++) { DMYLP = LPC_SSP->DR; } // Enable SSP interruption NVIC_EnableIRQ(SSP_IRQn); NVIC_SetPriority(SSP_IRQn, 3); // Device select as master, SSP Enabled LPC_SSP->CR1 = (1<<1); //SSPCR1_SSE } //======================== // SSP Interrupt Handler //======================== void SSP_IRQHandler(void) { unsigned int regValue; regValue = LPC_SSP->MIS; // Overrun? if (regValue & (1<<0)) { LPC_SSP->ICR = 1<<0; // Clear } // Timeout? if ( regValue & (1<<1)) { LPC_SSP->ICR = 1<<1; // Clear } // Tx FIFO Half Empty? if ( regValue & (1<<3)) { // none } // Rx FIFO not FULL? if ( regValue & (1<<2)) { // none //unsigned int dummy; //while (SPI_RxData(&dummy) == 0); //dummy read } } //=============================== // SPI Transfer and Receive Data //=============================== unsigned int SPI_TxRxData(unsigned int txdata) { unsigned int rxdata; // Tx while ((LPC_SSP->SR & ((1<<1)|(1<<4))) != (1<<1)); // Send a byte LPC_SSP->DR = txdata; // Wait until the Busy bit is cleared while ( LPC_SSP->SR & (1<<4)); // Rx while ((LPC_SSP->SR & (1<<2)) != (1<<2)); rxdata = LPC_SSP->DR; return rxdata; } //====================== // SPI Transfer Data //====================== void SPI_TxData(unsigned int txdata) { SPI_TxRxData(txdata); } //====================== // SPI Receive Data //====================== unsigned int SPI_RxData(void) { unsigned int rxdata; rxdata = SPI_TxRxData(0xff); return rxdata; }
次回はFatFs移植になります。
*1:近日中にNXPのホームページからダウンロードできるようになるそうです