Hi all,
I'm currently trying to interface an nRF52832 with an external Flash chip via SPI
I have tried with both NAND and NOR types, specifically the MT29F2G01 from Micron and the S25FS064S from Cypress. Both of these chips implement a pretty simple Command protocol over SPI and I have had success reading and writing to both of them however I've had to implement a work around that I'm sure isn't the correct way to do things.
My problem is that for every byte I write to the device I have to read an extra byte at the start of the read. For example if I write 4 bytes to read a page (ie. the READ (0x03) command and a 3 byte address to read from) I will need to increase the number of read bytes by 4. An example can be seen in this FLASH_READ function I'm using for the Cypress device. I'm using the nrf_drv_spi driver in blocking mode (i.e. no callback function provided at init time)
static const nrf_drv_spi_t m_spi_instance = NRF_DRV_SPI_INSTANCE(1); static uint8_t m_tx_buffer[512]; static uint8_t m_rx_buffer[512]; static nrf_drv_spi_xfer_desc_t m_spi_xfer = { .p_rx_buffer = m_rx_buffer, .p_tx_buffer = m_tx_buffer, .rx_length = 0, .tx_length = 0, }; SLLD_STATUS FLASH_READ(BYTE device_num, BYTE command, ADDRESS sys_addr, BYTE *data_buffer, int Number_Of_Read_Bytes) { uint8_t tx_buffer_index = 0; //Write command byte to bus m_tx_buffer[0] = command; tx_buffer_index += 1; //Write the address if(sys_addr != ADDRESS_NOT_USED) { // Shift out the address one byte at a time in 3-bytes addressing scheme m_tx_buffer[tx_buffer_index] = (uint8_t)((sys_addr >> 16) & 0x000000FF); tx_buffer_index += 1; m_tx_buffer[tx_buffer_index] = (uint8_t)((sys_addr >> 8) & 0x000000FF); tx_buffer_index += 1; m_tx_buffer[tx_buffer_index] = (uint8_t)(sys_addr & 0x000000FF); tx_buffer_index += 1; } //Write the correct number of dummy bytes uint8_t number_of_dummy_bytes = 0; switch (command) { case SPI_FAST_READ_CMD: case SPI_FAST_READ_4B_CMD: case SPI_OTPR_CMD: case SPI_READ_SFDP_CMD: { number_of_dummy_bytes = 1; break; } case SPI_RES_CMD: { number_of_dummy_bytes = 3; break; } } for(int i = 0; i < number_of_dummy_bytes; i++) { m_tx_buffer[tx_buffer_index] = 0x00; tx_buffer_index += 1; } if (Number_Of_Read_Bytes > 0) { //Read Number_Of_Read_Bytes off the SPI bus into data_buffer //Increase number of bytes to read by the number of bytes written m_spi_xfer.rx_length = Number_Of_Read_Bytes + tx_buffer_index; m_spi_xfer.tx_length = tx_buffer_index; nrf_drv_spi_xfer(&m_spi_instance, &m_spi_xfer, 0); //memcpy is needed as the raw number of read bytes will be longer then expected by caller memcpy(data_buffer, &m_rx_buffer[tx_buffer_index], Number_Of_Read_Bytes); } return SLLD_OK; }
This work around is giving me the results I expect but it seems quite inefficient (esp. the memcpy at the end to move the read data into the buffer provided by the caller ideally I would read directly into the provided buffer) and I feel like I'm completely missing something with how the SPI transfer should be done.
Any help or explanation on how best to deal with this behaviour would be greatly appreciated.