読者です 読者をやめる 読者になる 読者になる

Lynx-EyEDの電音鍵盤 新館

広帯域制御屋の駄文とか

LPCXpresso LPC1227でMARYボードAPIを流用したSPIライブラリ

ARM LPCXpresso

f:id:Lynx-EyED:20110627010800j:image

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のホームページからダウンロードできるようになるそうです