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.

Master SPI implementation without interrupts always reads 0xFF from external flash

Other Parts Discussed in Thread: MSP430F6779

Hello,


I want to read data from an external flash via SPI in master mode without interrupts. I checked that my SPI implementation is capable of waking up the external flash, configuring its internal segmentation and it also succeeds in reading out the status register of the external flash.

However, when I want to receive data that is stored at the external flash I always receive only 0xFF. In the code this is function ext_flash_main_memory_page_read(..).

I use an Adesto AT45DB641E as the external flash and I know that it is working and that there is data stored because I can read the data via my SPI implementation that uses interrupts. However I cannot use interrupts in my bootloader and that is why I need the polling-based implementation of SPI, too.

The corresponding parts of my code are printed below.


Thank you very much for any help!!

Stefan

----->>> my code:

int main(void)
{
    // stop watchdog timer to prevent time out reset
    WDTCTL = WDTPW + WDTHOLD;

    // clear interrupt registers that may not be cleared by a PUC
    IFG2 = 0;             // USCI, Basic Timer
    SD16IV = 0;         // ADC
    DAC12_0CTL = 0;        // DAC
    TACTL = 0;            // Timer_A
    TACCTL0 = 0;        // TIMER_A0
    TACCTL1 = 0;        // TIMER_A1-3
    P1IFG = 0;            // Port1
    P2IFG = 0;            // Port2
    IFG1 = 0;            // WDT
    CACTL1 = 0;            // Comparator_A
    TBCTL = 0;            // Timer_B
    TBCCTL0 = 0;        // TIMER_B0
    TBCCTL1 = 0;        // TIMER_B1-3
    
    //set clock
    SCFQCTL = 121; // DCOCLK = (121+1)*fcrystal = 122 * 32.768 kHZ = 4,0 MHz
    SCFI0 = 0; //FLLDx=0x00; FN_x=0x0000 (0.65 to 6.1 MHz)

    FLL_CTL1 = XT2OFF; // turn off xt2 oscillator

    // configure input port on PC_CS, here used to enforce boot mode
    P2DIR = 0;
    P2OUT = 0;

    // configure SPI
    //P5
    P5DIR = BIT3; // flash CS
    P5SEL = 0x00;
       P5OUT = BIT3; // set FLASH_CS inactive high

    //P3
    P3DIR = 0;
    P3SEL = (BIT1 | BIT2 | BIT3); //SPI MOSI 1 MISO 2 SCK 3
    LCDAPCTL0 = 0x00;

    
    // application start ///////////////////
    
    // allocate memory for a buffer that is used multiple times for SPI operation and configuration
    uint8_t cmd_buf[4];

    // init SPI machinery
    spi_init();

    // wakeup flash
    cmd_buf[0] = EXT_FLASH_CMD_WAKEUP;
    if (!spi_send_receive(cmd_buf, 1))
    {
        return UPDATE_FAILED_OLD_APPLICATION_USABLE;
    }

    // set flash page size to EXT_FLASH_PAGE_SIZE bytes
    cmd_buf[0] = 0x3D;
    cmd_buf[1] = 0x2A;
    cmd_buf[2] = 0x80;
    cmd_buf[3] = 0xA6; // 256 byte mode
//    cmd_buf[3] = 0xA7; // 264 byte mode
    if (!spi_send_receive(cmd_buf, 4))
    {
        // make external flash again sleep
        cmd_buf[0] = EXT_FLASH_CMD_SLEEP;
        spi_send_receive(cmd_buf, 1);

        return UPDATE_FAILED_OLD_APPLICATION_USABLE;
    }

    // read status register
    cmd_buf[0] = 0xD7;
    if (!spi_send_receive(cmd_buf, 3))
    {
        return UPDATE_FAILED_OLD_APPLICATION_USABLE;
    }

    // size of the new program code (in bytes)
    uint16_t program_code_size = 0;

    // get size of the new program code
    if (!ext_flash_main_memory_page_read(EXT_FLASH_APPLICATION_UPDATE_LENGTH, reinterpret_cast<uint8_t*>(&program_code_size), 2))
    {
        // make external flash again sleep
        cmd_buf[0] = EXT_FLASH_CMD_SLEEP;
        spi_send_receive(cmd_buf, 1);

        // and return
        return UPDATE_FAILED_OLD_APPLICATION_USABLE;
    }
    
    ....
    ....
}

// inits the spi machinery WITHOUT interrupts
void spi_init()
{
    // hold USCI logic in reset state
    UCB0CTL1 = UCSWRST;

    // master-mode und MSB first
    UCB0CTL0 = UCMST | UCMSB;// | UCSYNC;

    // select SPI mode
    UCB0CTL0 &= ~(UCCKPH | UCCKPL); // SPI mode 0

    // clock source: SMCLK = 4,0 MHz
    UCB0CTL1 |= UCSSEL1;
    // prescaler LB
    UCB0BR0 = 0x00;

    // prescaler HB
    UCB0BR1 = 0x00;

    // set USCI state machine in operation
    UCB0CTL1 &= ~UCSWRST;
}

// sends bytes via SPI and receives new bytes within the same buffer (NO interrupts)
bool spi_send_receive(uint8_t* buf, uint8_t len)
{
    EXT_FLASH_CS_LOW; // high to low starts an operation and selects the flash because also the accelerometer is connected to SPI

    // loop over buffer
    while (len--)
    {
        // reset timeout
        uint8_t timeout = 50;

        // wait until transmit buffer is ready
        while (!(IFG2 & UCB0TXIFG));

        // write byte to transmit buffer
        UCB0TXBUF = *buf;

        // wait for new byte to be received (polling)
        while (!(IFG2 & UCB0RXIFG))
        {
            // if timeout counter is not zero yet
            if (timeout--)
            {
                // wait
                __delay_cycles(100);
            }
            else
            {
                EXT_FLASH_CS_HIGH; // stop oeration

                // return false on timeout
                return false;
            }
        }

        // read received byte
        *buf = UCB0RXBUF;

        // increase buffer pointer
        buf++;
    }

    // wait until SPI is no longer busy
    while (UCBUSY & UCB0STAT);
    // dummy read to empty any remaining data in the receive buffer
    uint8_t dummy = UCB0RXBUF;

    EXT_FLASH_CS_HIGH; // stop oeration
    return true;
}

// reads bytes from flash
uint8_t ext_flash_main_memory_page_read(const uint32_t address, uint8_t* const buf, const uint16_t len)
{
    uint8_t cmd[8];

    cmd[0] = EXT_FLASH_CMD_MMP_READ; // direct memory read without buffers
    cmd[1] = (uint8_t)((address>>16)&0xFF); // 24bit address on the flash
    cmd[2] = (uint8_t)((address>> 8)&0xFF);
    cmd[3] = (uint8_t)(address&0xFF);
    cmd[4] = EXT_FLASH_CMD_DUMMY;
    cmd[5] = EXT_FLASH_CMD_DUMMY;
    cmd[6] = EXT_FLASH_CMD_DUMMY;
    cmd[7] = EXT_FLASH_CMD_DUMMY;

    // enter dummy data of the amount of bytes we want to read
    for (uint16_t i = 0; i < len; i++)
    {
        buf[i] = EXT_FLASH_CMD_DUMMY;
    }

    EXT_FLASH_CS_LOW;

    // send command and receive unused answer of same amount
    if (!spi_send_receive(cmd, 8))
    {
        EXT_FLASH_CS_HIGH;
        return 0;
    }

    // receive the answer by sending dummy data
    if (!spi_send_receive(buf, len))
    {
        EXT_FLASH_CS_HIGH;
        return 0;
    }

    EXT_FLASH_CS_HIGH;
    return 1;
}

  • Hi Stefan,

    You've described your issue at a very high level but have not given any clues as to whether the slave device is sending valid data that isn't being read properly. Is the code getting stuck in a while loop or does it believe to be processing the data correctly? Have you changed any UCB0 register settings except for the interrupt enable bits? Please provide the MSP430 device derivative being used, oscilloscope or logic analyzer screenshots of the working solution (interrupts) vs non-working (polling), and a brief/basic code example that demonstrates the issue using simple write/read commands (the source provided above is difficult to interpret). There are also several SPI polling examples provided by the online community that you can reference.

    Regards,
    Ryan
  • Dear Ryan,

    I followed your advice to write a more basic implementation and it appeared that i was splitting the read command (for memory and programming issues) into two separate commands and toggled the CS line in between. However, toggling the CS line during a command seems to bring the flash into a clean state wherefore reading the actual data after toggling failed. It's now working!

    Thank you!

    Best,

    Stefan

  • hello sir,

     i have same problem................always getting 0xff when read data ,,,,,,,,,,,,,,,,,,,,,,,plz help me ......i m using MSP4306779 and serial flash SST26....is there any code regarding den plz send me .......my email-hitesh.mathukiya@gmail.com

  • Hi sir ,,,,,,,,,

    I have same problem can you send me code regarding that..........always read .....0xff.............................i m using MSP430f6779 and sst26 serial flash.............................plz send me mail-hitesh@gmail.com
  • hey,


    you can find my code already posted above. please make sure that you send the wakeup command to the flash before you start reading or writing data. that seems to be the major cause for that issue. Furthermore, check that you didn't run in the same trouble with the CS lines as I described above.


    best

  • Hitesh,

    You failed to ever respond to my suggestions and inquiries on your previous related post: e2e.ti.com/.../541341

    Regards,
    Ryan

**Attention** This is a public forum