This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

NFR52832 SPI Long Transfer Problem

To All,

From reading the datasheet I understand that nfr52832 spi can only send/receive up to 255 bytes at once. And to work around this a list method is used. Because I am writing/reading to a NAND flash, which has a page size of 2076 bytes, to save power by minimizing the number of write/read operations I would need to implement this method.

To test this on a smaller dataset, I have set the max buffer for both tx and rx to be 10, then try and write/read a dataset that is 30 bytes long. However I just cant get it to work, I keep getting wierd data from the NAND flash when trying to read back the data stored on it. Below is my code to illustrate this.

What I have done is to separate the spi transfer into long read and long write functions, for sending/reading a lot of data. The spi handler is used to count how many frames have been sent so for example to send a data set of 30 bytes + instruction with a buffer size of 10, 4 frames would be required. So every time a SPI_END event triggers the spi handler, it increases the frame counter by one, then manually starts the next transfer. (the reason for the manual start is that I cant get spi_short to work).

Code For Spi Handler:

    void spi_event_handler(nrf_drv_spi_evt_t const * p_event)
    {		
		if( long_transfer) // If Long transfer enabled
		{
			transfer_cnt++;  // Counter for number of frames transferred 
			if(transfer_cnt <= n_transfer)			//if number of frames transferred = total length / Buffer size
			{
			  
				nrf_spim_task_trigger(spi.p_registers, NRF_SPIM_TASK_START);  // Manually start next transfer 
				
				SEGGER_RTT_printf(0, "In Spi Interrupt: \r\n");
			}else{
				
				//nrf_spim_shorts_disable(spi.p_registers, NRF_SPIM_SHORT_END_START_MASK);
				spi_xfer_done = true;   
			}
		}else{
			spi_xfer_done = true;
		}
		
     }

Code For Long Write:

SPI_STATUS Serialize_SPI_long(uint8_t* tx_buf, 
               uint8_t tx_len,
							 uint8_t* rx_buf,
							 uint8_t rx_len)
                
{
	SEGGER_RTT_printf(0, "Long Write Transfer: \r\n");	
	transfer_cnt = 0;       //Counter for number of frames transferred
	long_transfer = true;   //Enable long transfer
	uint16_t total_len = rx_len + tx_len;                // synchronous transfer, total length = rx len + tx len
	SEGGER_RTT_printf(0, "length: %d\r\n", total_len );		
	SEGGER_RTT_printf(0, "Buffer Size: %d\r\n", BUFFERSIZE ); 
	n_transfer = ceil((double)total_len/BUFFERSIZE);			// Number of frames to transfer = total length/ buffer size
	
	SEGGER_RTT_printf(0, "Total No tranfers: %d\r\n", n_transfer );
		
	uint8_t tx_array[n_transfer][BUFFERSIZE];      // 2D array buffer
	
  for(uint16_t i = 0; i < total_len; i++)        // Set all elements to 0x00;
	{
		tx_array[i/BUFFERSIZE][i%BUFFERSIZE] =  0x00;

	}

	
	
	for(uint16_t i = 0; i < tx_len; i++)								// Copy data form tx_buf to tx_array 					
	{
		tx_array[i/BUFFERSIZE][i%BUFFERSIZE] =  tx_buf[i];
	
	}
	

		
	spi_xfer_done = false;
	//nrf_spim_shorts_enable(spi.p_registers, NRF_SPIM_SHORT_END_START_MASK);
	
	nrf_drv_spi_xfer_desc_t spi_xfer_NAND_desc = NRF_DRV_SPI_SINGLE_XFER( tx_array[0], BUFFERSIZE, rx_buf, rx_len);  
	nrf_gpio_pin_clear( SPIM0_SS_PIN );			// Manually toggle select line																													
	APP_ERROR_CHECK(nrf_drv_spi_xfer(&spi, &spi_xfer_NAND_desc, NRF_DRV_SPI_FLAG_TX_POSTINC));  //Start transfer with Tx postinc flag

	while(!spi_xfer_done)
	{
			__WFE();
	}
	
	nrf_gpio_pin_set( SPIM0_SS_PIN );      //Manually toggle select line 
	
	memcpy(rx_buf, rx_buf+tx_len, rx_len);  //Reformat rx buf to get rid of the packets received during tx transfer
	
	
	return RetSpiSuccess;
}

Code For Long Read:

SPI_STATUS Serialize_SPI_long2(uint8_t* tx_buf, 
               uint8_t tx_len,
							 uint8_t* rx_buf,
							 uint8_t rx_len)
                
{
	SEGGER_RTT_printf(0, "Long Read Transfer: \r\n");	
	transfer_cnt = 0; //Counter for number of frames transferred
	long_transfer = true;  //Enable long transfer
	uint16_t total_len = rx_len + tx_len;       // synchronous transfer, total length = rx len + tx len
	SEGGER_RTT_printf(0, "length: %d\r\n", total_len ); 
	SEGGER_RTT_printf(0, "Buffer Size: %d\r\n", BUFFERSIZE ); 
	n_transfer = ceil((double)total_len/BUFFERSIZE);   // Number of frames to transfer = total length/ buffer size

	SEGGER_RTT_printf(0, "Total No tranfers: %d\r\n", n_transfer );
	

	uint8_t rx_array[n_transfer][BUFFERSIZE];	       // 2D array buffer

	for(uint16_t i = 0; i < total_len; i++)         // Set all elements to 0x00;
	{
		rx_array[i/BUFFERSIZE][i%BUFFERSIZE] =  0x00;
		
	}
	
		
	spi_xfer_done = false;
	
	//nrf_spim_shorts_enable(spi.p_registers, NRF_SPIM_SHORT_END_START_MASK);
	nrf_drv_spi_xfer_desc_t spi_xfer_NAND_desc = NRF_DRV_SPI_SINGLE_XFER( tx_buf, tx_len, rx_array[0], BUFFERSIZE);
	nrf_gpio_pin_clear( SPIM0_SS_PIN ); //Manually toggle select line
	APP_ERROR_CHECK(nrf_drv_spi_xfer(&spi, &spi_xfer_NAND_desc,NRF_DRV_SPI_FLAG_RX_POSTINC));  //Start transfer with Rx postinc flag

	while(!spi_xfer_done)
	{
			__WFE();
	}
	
	nrf_gpio_pin_set( SPIM0_SS_PIN ); //Manually toggle select line
	
	
	for(uint16_t i = 0; i < total_len; i++) //Flatten rx 2d array to 1D rx buf
	{
		rx_buf[i] =  rx_array[i/BUFFERSIZE][i%BUFFERSIZE];
		
	}
	
	memcpy(rx_buf, rx_buf+tx_len, rx_len);  //Reformat rx buf to get rid of the packets received during tx transfer
	
		
	return RetSpiSuccess;
}

Output from RTT: image description

The data sent (written into the NAND) should match with data received( read from the NAND), if I increase the buffer size then the data match better, if buffersize > dataset then they match. Which I do not understand why.

Output from RTT buffersize 20 data size 30: image description

Output form RTT buffersize 50 data size 30: image description

I am pretty sure the problem is due to long read function, because if I use long transfer to write data to NAND flash, but normal spi transfer to read the data then I get the correct reading.

Thank you so much for the help.

Regards, Bryan

Related