Application - MX35LFxGE4AB, SPI NAND Flash

出自 flip the world
於 2018年8月23日 (四) 10:20 由 Tommy (對話 | 貢獻) 所做的修訂 (已建立頁面,內容為 "thumb|200px|RPi2 with SPI NAND Flash(MX35LFxGE4AB) == HW connection == <pre> PRi2 -- MX35LFxGE4AB VCC -- VC…")
(差異) ←上個修訂 | 最新修訂 (差異) | 下個修訂→ (差異)
前往: 導覽搜尋
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

MX35LFxGE4AB cmd.jpg

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