This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Interfacing SPI Serial Flash to McBSP

Other Parts Discussed in Thread: TMS320VC5501

Customer is trying to interface a TI TMS320VC5501 chip through its McBSP port 0 to a AT45DB081D.  I can see data going out on the bus, I can see the reply back,.

The short version is that while I can read the chip ID, I don’t seem to be able read and write data reliably.  I’m not 100% sure that I have the McBSP port setup to talk to the chip.  I don’t get any hang-ups when I check the XDRY or RRDY lines that would indicate that the chip is not communicating, but I don’t really have a sophisticated enough scope to track the transactions.   I’m beginning to suspect that the chip isn’t getting erased properly, which is cascading write issues down the line… . 

Big question would be if you know if there is a TI McBSP setup that works well, or if there are any deviations from the SPI recommendation in Ch 6 of the TI McBSP manual that are significant for this part.

I’ve done a fair amount of SPI before, but it has been primarily low speed with PIC and 8051 microcontrollers and small EEPROMs.   And it also worked the first time, or at least the 5th time. 

  • Hi,

     

    Have customer developed a kind of driver for SPI-flash memory access? There are sequence of commands are required to read/write from/to flash.

    Reading chip ID is proper first step to establish the read capability.

    Regards,

    Hyun

  • That is the question, is there a snippet of code available that helps to properly setup the McBSP for SPI Serial Flash?

  • Hi,

    Found an example code. It's for C5502 but C5001 should be similar.

    // This code is written to interface to the AT25F512N on the 5502 EVM

     

    #include "c5502.h"

     

    #define assert_chip_select() GPIO_IODATA &= ~BIT4

    #define deassert_chip_select() GPIO_IODATA |= BIT4

    #define READ_CMD (0x3)

    #define RDID_CMD (0x1D)

    #define WREN_CMD (0x06)

    #define RDSR_CMD (0x05)

    #define PROGRAM_CMD (0x02)

    #define CHIP_ERASE_CMD (0x62)

     

    // helper functions

    static void spiflash_write_enable();

    static unsigned int spiflash_read_status_reg();

     

     

    // Function:  spiflash_init

    //

    // Input:  none

    // Return:  none

    //

    // Description:  Initializes McBSP0 and GPIO4 for SPI communication

    //

    // Other notes:  Written under assumption SYSCLK2 configured for 150 MHz

    void spiflash_init()

    {

    volatile int i;

    // Put McBSP registers in their reset state

    // Not necessary, but nice for debug when restarting same code without device reset

    MCBSP0_SPCR1 = 0;

    MCBSP0_SPCR2 = 0;

    MCBSP0_RCR1 = 0;

    MCBSP0_RCR2 = 0;

    MCBSP0_XCR1 = 0;

    MCBSP0_XCR2 = 0;

    MCBSP0_SRGR1 = 1;

    MCBSP0_SRGR2 = 0x2000;

    MCBSP0_MCR1 = 0;

    MCBSP0_MCR2 = 0;

    MCBSP0_PCR = 0;

    // Configure registers

    // McBSP fed internally by SYSCLK2 (150 MHz)

    MCBSP0_SRGR1 = 15-1; // CLKG = 150 MHz / 15 = 10 MHz

    MCBSP0_SRGR2 = 0x2000;

    MCBSP0_SPCR1 = 0x1800;

    MCBSP0_SPCR2 = 0x0300;

    MCBSP0_PCR = 0x0F0C;

    MCBSP0_RCR1 = 0x0000;

    MCBSP0_RCR2 = 0x0001;

    MCBSP0_XCR1 = 0x0000;

    MCBSP0_XCR2 = 0x0001;

    // Set GRST=1 to enable sample rate generator

    MCBSP0_SPCR2 |= BIT6;

    // Wait 2 CLKG cycles

    for (i=0; i<60; i++) {}

    // take transmitter and receiver out of reset

    MCBSP0_SPCR1 |= BIT0;

    MCBSP0_SPCR2 |= BIT0;

    // take frame sync generator out of reset

    MCBSP0_SPCR2 |= BIT7;

     

    // Wait 2 CLKG cycles

    for (i=0; i<60; i++) {}

    // Configure GPIO4 (/CS)

    GPIO_IODIR |= BIT4;

    GPIO_IODATA |= BIT4;

    }

     

     

    // Function:  spiflash_read_byte

    //

    // Input:  flash_offset - bits 23:0 represent the address in the flash being read

    // Return:  the byte of data located at address flash_offset

    unsigned int spiflash_read_byte(unsigned long int flash_offset)

    {

    unsigned int ret_val;

    assert_chip_select();

    // Send READ command

    while ( (MCBSP0_SPCR2 & BIT1) == 0 ) {} // wait for XRDY

    MCBSP0_DXR1 = READ_CMD;

    while ( (MCBSP0_SPCR1 & BIT1) == 0 ) {} // wait for RRDY to indicate write completed

    MCBSP0_DRR1; // throw away dummy data

     

    // Send address[23:16]

    while ( (MCBSP0_SPCR2 & BIT1) == 0 ) {} // wait for XRDY

    MCBSP0_DXR1 = flash_offset >> 16;

    while ( (MCBSP0_SPCR1 & BIT1) == 0 ) {} // wait for RRDY to indicate write completed

    MCBSP0_DRR1; // throw away dummy data

     

    // Send address[15:8]

    while ( (MCBSP0_SPCR2 & BIT1) == 0 ) {} // wait for XRDY

    MCBSP0_DXR1 = flash_offset >> 8;

    while ( (MCBSP0_SPCR1 & BIT1) == 0 ) {} // wait for RRDY to indicate write completed

    MCBSP0_DRR1; // throw away dummy data

     

    // Send address[7:0]

    while ( (MCBSP0_SPCR2 & BIT1) == 0 ) {} // wait for XRDY

    MCBSP0_DXR1 = flash_offset;

    while ( (MCBSP0_SPCR1 & BIT1) == 0 ) {} // wait for RRDY to indicate write completed

    MCBSP0_DRR1; // throw away dummy data

     

    // Read Byte

    while ( (MCBSP0_SPCR2 & BIT1) == 0 ) {} // wait for XRDY

    MCBSP0_DXR1 = 0; // dummy write

    while ( (MCBSP0_SPCR1 & BIT1) == 0 ) {} // wait for RRDY to get data

    ret_val = MCBSP0_DRR1;

    deassert_chip_select();

    return ret_val;

    }

     

     

     

    // Function:  spiflash_write_byte

    //

    // Inputs:  flash_offset - bits 23:0 represent the address in the flash being written

    //          data -  the byte of data being written to address flash_offset

    // Return:  None

    //

    // Notes:  The application level must ensure the byte being written has been

    //         previously erased.

    void spiflash_write_byte(unsigned long int flash_offset, unsigned int data)

    {

    spiflash_write_enable();  // sends command to enable writes to flash

    assert_chip_select();

    // Send PROGRAM command

    while ( (MCBSP0_SPCR2 & BIT1) == 0 ) {} // wait for XRDY

    MCBSP0_DXR1 = PROGRAM_CMD;

    while ( (MCBSP0_SPCR1 & BIT1) == 0 ) {} // wait for RRDY to indicate write completed

    MCBSP0_DRR1; // throw away dummy data

     

    // Send address[23:16]

    while ( (MCBSP0_SPCR2 & BIT1) == 0 ) {} // wait for XRDY

    MCBSP0_DXR1 = flash_offset >> 16;

    while ( (MCBSP0_SPCR1 & BIT1) == 0 ) {} // wait for RRDY to indicate write completed

    MCBSP0_DRR1; // throw away dummy data

     

    // Send address[15:8]

    while ( (MCBSP0_SPCR2 & BIT1) == 0 ) {} // wait for XRDY

    MCBSP0_DXR1 = flash_offset >> 8;

    while ( (MCBSP0_SPCR1 & BIT1) == 0 ) {} // wait for RRDY to indicate write completed

    MCBSP0_DRR1; // throw away dummy data

     

    // Send address[7:0]

    while ( (MCBSP0_SPCR2 & BIT1) == 0 ) {} // wait for XRDY

    MCBSP0_DXR1 = flash_offset;

    while ( (MCBSP0_SPCR1 & BIT1) == 0 ) {} // wait for RRDY to indicate write completed

    MCBSP0_DRR1; // throw away dummy data

     

    // Send data

    while ( (MCBSP0_SPCR2 & BIT1) == 0 ) {} // wait for XRDY

    MCBSP0_DXR1 = data;

    while ( (MCBSP0_SPCR1 & BIT1) == 0 ) {} // wait for RRDY to indicate write completed

    MCBSP0_DRR1; // throw away dummy data

    deassert_chip_select();

    // wait for write to complete

    while( (spiflash_read_status_reg()&1) == 1 );

     

    }

     

    // Function spiflash_chip_erase

    //

    // Inputs:  None

    // 

    // Return: None

    //

    // Note: takes about 3.5 seconds to complete

    void spiflash_chip_erase()

    {

    spiflash_write_enable();  // sends command to enable erase of flash

    assert_chip_select();

     

    // Send CHIP_ERASE command

    while ( (MCBSP0_SPCR2 & BIT1) == 0 ) {} // wait for XRDY

    MCBSP0_DXR1 = CHIP_ERASE_CMD;

    while ( (MCBSP0_SPCR1 & BIT1) == 0 ) {} // wait for RRDY to indicate write completed

    MCBSP0_DRR1; // throw away dummy data

     

    deassert_chip_select();

    // wait for write to complete

    while( (spiflash_read_status_reg()&1) == 1 );

     

    }

     

     

     

    // Function:  spiflash_read_product_id

    //

    // Input:  none

    // Return:  16-bit data, with upper 8 bits being manufacturer code

    //          and lower 8 bits being device code

    unsigned int spiflash_read_product_id()

    {

    unsigned int ret_val;

    assert_chip_select();

    // Send RDID command

    while ( (MCBSP0_SPCR2 & BIT1) == 0 ) {} // wait for XRDY

    MCBSP0_DXR1 = RDID_CMD;

    while ( (MCBSP0_SPCR1 & BIT1) == 0 ) {} // wait for RRDY to indicate write completed

    MCBSP0_DRR1; // throw away dummy data

    // Read Manufacturer Code

    while ( (MCBSP0_SPCR2 & BIT1) == 0 ) {} // wait for XRDY

    MCBSP0_DXR1 = 0; // dummy write

    while ( (MCBSP0_SPCR1 & BIT1) == 0 ) {} // wait for RRDY to get data

    ret_val = MCBSP0_DRR1 << 8; // manufacturer code (should be 0x1F)

     

    // Read Device code

    while ( (MCBSP0_SPCR2 & BIT1) == 0 ) {} // wait for XRDY

    MCBSP0_DXR1 = 0; // dummy write

    while ( (MCBSP0_SPCR1 & BIT1) == 0 ) {} // wait for RRDY to get data

    ret_val |= (MCBSP0_DRR1 & 0xFF); // manufacturer code (should be 0x1F)

    deassert_chip_select();

    return ret_val;

    }

     

    static void spiflash_write_enable()

    {

    assert_chip_select();

    // Send WREN command

    while ( (MCBSP0_SPCR2 & BIT1) == 0 ) {} // wait for XRDY

    MCBSP0_DXR1 = WREN_CMD;

    while ( (MCBSP0_SPCR1 & BIT1) == 0 ) {} // wait for RRDY to indicate write completed

    MCBSP0_DRR1; // throw away dummy data

    deassert_chip_select();

    }

     

    static unsigned int spiflash_read_status_reg()

    {

    unsigned int ret_val;

    assert_chip_select();

    // Send RDSR command

    while ( (MCBSP0_SPCR2 & BIT1) == 0 ) {} // wait for XRDY

    MCBSP0_DXR1 = RDSR_CMD;

    while ( (MCBSP0_SPCR1 & BIT1) == 0 ) {} // wait for RRDY to indicate write completed

    MCBSP0_DRR1; // throw away dummy data

     

    // Read Status Reg

    while ( (MCBSP0_SPCR2 & BIT1) == 0 ) {} // wait for XRDY

    MCBSP0_DXR1 = 0; // dummy write

    while ( (MCBSP0_SPCR1 & BIT1) == 0 ) {} // wait for RRDY to get data

    ret_val = MCBSP0_DRR1; // status register

    deassert_chip_select();

    return ret_val;

    }

     

    Regards,

    Hyun