Last byte received from SPI slave is always zero

MateusGL
Posts: 17
Joined: Sun Feb 23, 2020 5:18 am

Last byte received from SPI slave is always zero

Postby MateusGL » Thu Oct 29, 2020 3:05 am

Hi,

I'm using an ESP32 as a SPI master to receive samples from an AD converter. At every new sample, the AD pulls an ESP32 pin to low and the SPI transaction is executed. After the transaction, the received dataframe is stored in a queue that will be read by other task. My problem is that the last received byte is always zero. I verified the signals with a logic analyzer and it should not be zero.

Below is the code of the task:

Code: Select all

void IRAM_ATTR vDataAcquisitonTask(void *pvParameters)
{
	int dataRate= ads1299_get_datarate();//get the configured datarate from the AD
	const uint32_t ulNumberOfSamples = (*((int*)pvParameters))*dataRate;// *pvParameters is the duration of the acquisiton

	uint8_t* temp_buff = heap_caps_malloc(BYTES_PER_FRAME, MALLOC_CAP_DMA|MALLOC_CAP_32BIT);
	uint8_t* zeros = heap_caps_malloc(BYTES_PER_FRAME, MALLOC_CAP_DMA|MALLOC_CAP_32BIT);
	memset(zeros,0,BYTES_PER_FRAME);

	uint32_t ulSamplesCounter = 0;

	spi_transaction_t trans_desc = {
			.rx_buffer = temp_buff,
			.tx_buffer = zeros,
			.length = 8*(BYTES_PER_FRAME)
	};

	xTaskToNotifyDRDY = xTaskGetCurrentTaskHandle();
    	gpio_intr_enable(GPIO_DRDY_PIN);//enable interrupt to identify new samples
	ads1299_rdatac(ADS_ALL);//send command to AD to prepare it to the acquisition
	spi_device_acquire_bus(spi_fast_handle, portMAX_DELAY);
	gpio_set_level(GPIO_START_PIN, 1);//set start pin high to tell the AD to start acquiring samples

	xTaskCreatePinnedToCore(vDataSendTask, "DataSend", 8*1024, &ulNumberOfSamples,
		DATA_SEND_TASK_PRIORITY, NULL, PRO_CPU_NUM);//start task that will read the queue
	
	while(ulSamplesCounter<ulNumberOfSamples)
	{
		ulTaskNotifyTake(pdTRUE, portMAX_DELAY);//waits for notification of new samples from ISR
		spi_device_polling_transmit(spi_fast_handle, &trans_desc);
		ESP_LOGI(TAG,"Last byte: %d",temp_buff[BYTES_PER_FRAME-1]);//print last received byte (always zero)
		xQueueSend(xQueue, temp_buff, portMAX_DELAY);
		ulSamplesCounter++;
	}
	//end of acquisiton
	ESP_ERROR_CHECK( gpio_set_level(GPIO_START_PIN, 0) );
	ESP_ERROR_CHECK( gpio_intr_disable(GPIO_DRDY_PIN) );
	xTaskToNotifyDRDY = NULL;
	spi_device_release_bus(spi_fast_handle);
	ads1299_sdatac(ADS_ALL);
	free(temp_buff);
	free(zeros);
	vTaskDelete(NULL);
}
The interrupt handler:

Code: Select all

static void IRAM_ATTR vGPIOISRHandler(void* arg)
{
	static BaseType_t xHigherPriorityTaskWoken;
	if(xTaskToNotifyDRDY!=NULL){
		vTaskNotifyGiveFromISR(xTaskToNotifyDRDY, &xHigherPriorityTaskWoken );
		if( xHigherPriorityTaskWoken == pdTRUE )
		{
			portYIELD_FROM_ISR();
		}
	}
}
SPI initialization (I'm initializing other device to communicate with a lower SCLK frequency of 4MHz when necessary):

Code: Select all

static int my_spi_init(void)
{
	spi_bus_config_t bus_config = {
			.mosi_io_num = GPIO_MOSI_PIN,
			.miso_io_num = GPIO_MISO_PIN,
			.sclk_io_num = GPIO_SCLK_PIN,
			.quadwp_io_num = -1,
			.quadhd_io_num = -1,
	};

	spi_device_interface_config_t dev_config_slow = {
			.mode = 1,
			.clock_speed_hz = 4000000,
			.spics_io_num = -1,
			.queue_size = 1,
	};

	spi_device_interface_config_t dev_config_fast = {
			.mode = 1,
			.clock_speed_hz = SPI_MASTER_FREQ_20M,
			.spics_io_num = -1,
			.queue_size = 1,
	};

	spi_bus_initialize(VSPI_HOST, &bus_config, 1);

	spi_bus_add_device(VSPI_HOST, &dev_config_slow, &spi_slow_handle);
	spi_bus_add_device(VSPI_HOST, &dev_config_fast, &spi_fast_handle);
	return 0;
}
If I configure the temp_buff, zeros and the length of the transaction to be one byte larger, the extra byte is ignored when sending the dataframe to the queue and everything works fine, i.e., the last byte of the dataframe is received with its right value, different from 0x00.

Does anyone know why this is happening?

Thank you,

Mateus

Who is online

Users browsing this forum: No registered users and 141 guests