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.