RPi2 with SPI NAND Flash(MX35LFxGE4AB)
HW connection
PRi2 -- MX35LFxGE4AB
VCC -- VCC(3.3V)
VCC -- HOLD(3.3V)
GPIO19(MOSI) -- SI
GPIO21(MISO) -- SO
GPIO23(CLK) -- SCLK
GPIO24(CS0) -- CS
Gnd -- Gnd
Gnd -- WP
MX35LFxGE4AB read device ID timing
Timing
Hack libbcm2835
- Add bcm2835_spi_transfernb_adv() in bcm2835.c
/* Writes an number of bytes to SPI and read an number of bytes from SPI*/
void bcm2835_spi_transfernb_adv(char* tbuf, char* rbuf, uint32_t tx_len, uint32_t rx_len)
{
volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4;
volatile uint32_t* fifo = bcm2835_spi0 + BCM2835_SPI0_FIFO/4;
uint32_t TXCnt=0;
uint32_t RXCnt=0;
/* This is Polled transfer as per section 10.6.1
// BUG ALERT: what happens if we get interupted in this section, and someone else
// accesses a different peripheral?
*/
/* Clear TX and RX fifos */
bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_CLEAR, BCM2835_SPI0_CS_CLEAR);
/* Set TA = 1 */
bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_TA, BCM2835_SPI0_CS_TA);
/* Use the FIFO's to reduce the interbyte times */
/* TX fifo not full, so add some more bytes */
while(TXCnt < len)
while((BCM2835_SPI0_CS_TXD & bcm2835_peri_read(paddr)))
{
bcm2835_peri_write_nb(fifo, tbuf[TXCnt]);
TXCnt++;
}
/* read dummy */
while(RXCnt < tx_len)
while((BCM2835_SPI0_CS_RXD & bcm2835_peri_read(paddr)))
{
rbuf[RXCnt] = bcm2835_peri_read_nb(fifo);
RXCnt++;
}
RXCnt = 0;
/* Rx fifo not empty, so get the next received bytes */
while((BCM2835_SPI0_CS_RXD & bcm2835_peri_read(paddr)))
{
rbuf[RXCnt] = bcm2835_peri_read_nb(fifo);
RXCnt++;
}
/* Wait for DONE to be set */
while (!(bcm2835_peri_read_nb(paddr) & BCM2835_SPI0_CS_DONE))
;
/* Set TA = 0, and also set the barrier */
bcm2835_peri_set_bits(paddr, 0, BCM2835_SPI0_CS_TA);
}
Example code
#include <bcm2835.h>
#include <stdio.h>
int main(int argc, char **argv)
{
int i, tx_len=2, rx_len=2;
if (!bcm2835_init())
return 1;
bcm2835_spi_begin();
bcm2835_spi_setBitOrder(BCM2835_SPI_BIT_ORDER_MSBFIRST); // The default
bcm2835_spi_setDataMode(BCM2835_SPI_MODE0); // The default
bcm2835_spi_setClockDivider(BCM2835_SPI_CLOCK_DIVIDER_512); // The default
bcm2835_spi_chipSelect(BCM2835_SPI_CS0); // The default
bcm2835_spi_setChipSelectPolarity(BCM2835_SPI_CS0, LOW); // the default
// Send a byte to the slave and simultaneously read a byte back from the slave
// If you tie MISO to MOSI, you should read back what was sent
usleep(500);
uint8_t tx_data[]={0x9f, 0x44};
static uint8_t rx_data[10]={0};
bcm2835_spi_transfernb_adv(tx_data,rx_data, tx_len, rx_len);
for(i=0;i<rx_len;i++)
printf("Read from SPI: 0x%.2X \n", rx_data[i]);
bcm2835_spi_end();
bcm2835_close();
return 0;
}