ESP32 Problem with SPI received data
Posted: Sat Sep 25, 2021 10:18 pm
Hello,
during experiments with an RFID-reader I noticed a problem with the via SPI received data.
It seems that only the first received byte is correct but not the rest.
After further tests I build a SPI test circuit with an 8bit controller and used it as SPI slave.
In addition a simple test program for the ESP32 as SPI-master was written. (parts see below)
After checking that the SPI slave works correct, it was connected to the ESP32.
The tests confirmed my assumption. The first received byte is correct and the rest not.
Due to this effect an intensive search on the internet started, but no solution was found.
Also the docs were read several times.
The SPI test program for the ESP32 was set up as described in the examples.
The SPI master sends only 32 times the letter "A" (0x41) and the SPI slave replies with the
letters from "A" to "z".
Attached are parts of the code:
//main routine to setup the SPI interface
#define SPI_SIZE 68 // 64 data bytes + x (multiple of 4)
#define SPI_PORT SPI2_HOST
#define SPI_MISO 12
#define SPI_MOSI 13
#define SPI_CLK 14
#define SPI_CS 15
#define DMA_CHAN SPI_DMA_CH_AUTO
...
spi_bus_config_t buscfg = {
.miso_io_num = SPI_MISO,
.mosi_io_num = SPI_MOSI,
.sclk_io_num = SPI_CLK,
.quadwp_io_num = -1,
.quadhd_io_num = -1,
.max_transfer_sz = 96,
};
spi_device_interface_config_t devcfg={ // config device
.command_bits = 0, // length of a command in bits
.address_bits = 0,
.dummy_bits = 0,
.clock_speed_hz = 1 * 1000 * 1000, //Clock out at 1 MHz
.mode = 0, // SPI mode 0
.duty_cycle_pos = 0, //50% duty cycle 0 = 128 50%
.spics_io_num = SPI_CS, // CS pin
.queue_size = 1, // only 1 transaction at a time
.cs_ena_pretrans = 0,
.cs_ena_posttrans = 0, //
.pre_cb = NULL,
.post_cb = NULL
};
//Initialize the SPI bus
ret=spi_bus_initialize(spihost, &buscfg, DMA_CHAN); // DMA_CHAN = SPI_DMA_CH_AUTO
ESP_ERROR_CHECK(ret);
if(ret == ESP_OK)
printf("SPI device added. \n");
else
printf("SPI device not added. \n");
xQueue = xQueueCreate(5, sizeof(int32_t));
xpara param;
param.spit = spi;
param.i = 0;
if(xQueue != NULL) {
xTaskCreate(&vtestspi, (void*) pcSPI, 4096, ¶m, 5, NULL);
}
// the loop of the program to call the SPI send and receive routine
void vtestspi(void *pcpara){
uint32_t uicnt, uilen = 32;
uint8_t uidata[SPI_SIZE] = {0x00};
uint8_t uirdata[SPI_SIZE] = {0x00};
xpara *ppara;
ppara = (xpara*) pcpara;
spi_device_handle_t spi = ppara->spit;
// loop to send and receive data
while(1) {
for(uicnt = 0; uicnt < uilen; uicnt++){
uidata[uicnt] = 65; // 0x41 = A
uirdata[uicnt] = 66; // 0x42 = B
}
vTaskDelay(3000 / portTICK_PERIOD_MS);
trx(spi, uidata, uirdata, uilen); // call the SPI send and receive routine
printf("content received uirdata \n");
fifocontent(uirdata, uilen); // display content of the received data
vTaskDelay(3000 / portTICK_PERIOD_MS);
printf("\n new lap \n");
}
return; // never reached
}
// SPI send routine
void trx (spi_device_handle_t spix, uint8_t *uidata2, uint8_t *uird2, int len){
// sending commands or data to the RFID chip
esp_err_t ret;
spi_transaction_t spi_trx;
memset(&spi_trx, 0, sizeof(spi_trx));
int lentrx;
printf("SPI Aufruf \n");
lentrx = len * 8;
spi_trx.length = lentrx;
spi_trx.rxlength = 0;
spi_trx.tx_buffer = uidata2;
spi_trx.rx_buffer = uird2;
spi_trx.flags = 0;
spi_trx.user = (void*) 0;
gpio_set_level(SPI_RST, 0); // set RST pin low to deactivate RFID module
ret=spi_device_polling_transmit(spix, &spi_trx); //Transmit!
gpio_set_level(SPI_RST, 1); // set RST pin high to deactivate RFID module
assert(ret == ESP_OK); //Should have had no issues.
if(ret != ESP_OK)
printf("SPI failed \n");
printf("Content received uird2 \n");
fifocontent(uird2, len); // print routine of the received data. example see below
printf("\n");
return;
}
The output is as follows (all figures in hex):
Content received uird2
6F 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
As we see the first byte 6F (= 0x6F = 'o') is from the slave. The following bytes (0x41) shows the content of
the transmission array. Is there a memory allocation problem.
So the question is: what is wrong?
Have I forgotten something to define.
I have used heap_caps_malloc(SPI_SIZE, MALLOC_CAP_DMA) with no change of the result.
Part of the log of the idf.py monitor:
I (248) cpu_start: ESP-IDF: v4.3
I (253) heap_init: Initializing. RAM available for dynamic allocation:
I (260) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM
I (266) heap_init: At 3FFB3230 len 0002CDD0 (179 KiB): DRAM
I (272) heap_init: At 3FFE0440 len 00003AE0 (14 KiB): D/IRAM
I (278) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
I (285) heap_init: At 4008C290 len 00013D70 (79 KiB): IRAM
I (292) spi_flash: detected chip: generic
I (296) spi_flash: flash io: dio
I (301) cpu_start: Starting scheduler on PRO CPU.
I (0) cpu_start: Starting scheduler on APP CPU.
Any help to solve the problem is appreciated.
best regards
neverendingproject
during experiments with an RFID-reader I noticed a problem with the via SPI received data.
It seems that only the first received byte is correct but not the rest.
After further tests I build a SPI test circuit with an 8bit controller and used it as SPI slave.
In addition a simple test program for the ESP32 as SPI-master was written. (parts see below)
After checking that the SPI slave works correct, it was connected to the ESP32.
The tests confirmed my assumption. The first received byte is correct and the rest not.
Due to this effect an intensive search on the internet started, but no solution was found.
Also the docs were read several times.
The SPI test program for the ESP32 was set up as described in the examples.
The SPI master sends only 32 times the letter "A" (0x41) and the SPI slave replies with the
letters from "A" to "z".
Attached are parts of the code:
//main routine to setup the SPI interface
#define SPI_SIZE 68 // 64 data bytes + x (multiple of 4)
#define SPI_PORT SPI2_HOST
#define SPI_MISO 12
#define SPI_MOSI 13
#define SPI_CLK 14
#define SPI_CS 15
#define DMA_CHAN SPI_DMA_CH_AUTO
...
spi_bus_config_t buscfg = {
.miso_io_num = SPI_MISO,
.mosi_io_num = SPI_MOSI,
.sclk_io_num = SPI_CLK,
.quadwp_io_num = -1,
.quadhd_io_num = -1,
.max_transfer_sz = 96,
};
spi_device_interface_config_t devcfg={ // config device
.command_bits = 0, // length of a command in bits
.address_bits = 0,
.dummy_bits = 0,
.clock_speed_hz = 1 * 1000 * 1000, //Clock out at 1 MHz
.mode = 0, // SPI mode 0
.duty_cycle_pos = 0, //50% duty cycle 0 = 128 50%
.spics_io_num = SPI_CS, // CS pin
.queue_size = 1, // only 1 transaction at a time
.cs_ena_pretrans = 0,
.cs_ena_posttrans = 0, //
.pre_cb = NULL,
.post_cb = NULL
};
//Initialize the SPI bus
ret=spi_bus_initialize(spihost, &buscfg, DMA_CHAN); // DMA_CHAN = SPI_DMA_CH_AUTO
ESP_ERROR_CHECK(ret);
if(ret == ESP_OK)
printf("SPI device added. \n");
else
printf("SPI device not added. \n");
xQueue = xQueueCreate(5, sizeof(int32_t));
xpara param;
param.spit = spi;
param.i = 0;
if(xQueue != NULL) {
xTaskCreate(&vtestspi, (void*) pcSPI, 4096, ¶m, 5, NULL);
}
// the loop of the program to call the SPI send and receive routine
void vtestspi(void *pcpara){
uint32_t uicnt, uilen = 32;
uint8_t uidata[SPI_SIZE] = {0x00};
uint8_t uirdata[SPI_SIZE] = {0x00};
xpara *ppara;
ppara = (xpara*) pcpara;
spi_device_handle_t spi = ppara->spit;
// loop to send and receive data
while(1) {
for(uicnt = 0; uicnt < uilen; uicnt++){
uidata[uicnt] = 65; // 0x41 = A
uirdata[uicnt] = 66; // 0x42 = B
}
vTaskDelay(3000 / portTICK_PERIOD_MS);
trx(spi, uidata, uirdata, uilen); // call the SPI send and receive routine
printf("content received uirdata \n");
fifocontent(uirdata, uilen); // display content of the received data
vTaskDelay(3000 / portTICK_PERIOD_MS);
printf("\n new lap \n");
}
return; // never reached
}
// SPI send routine
void trx (spi_device_handle_t spix, uint8_t *uidata2, uint8_t *uird2, int len){
// sending commands or data to the RFID chip
esp_err_t ret;
spi_transaction_t spi_trx;
memset(&spi_trx, 0, sizeof(spi_trx));
int lentrx;
printf("SPI Aufruf \n");
lentrx = len * 8;
spi_trx.length = lentrx;
spi_trx.rxlength = 0;
spi_trx.tx_buffer = uidata2;
spi_trx.rx_buffer = uird2;
spi_trx.flags = 0;
spi_trx.user = (void*) 0;
gpio_set_level(SPI_RST, 0); // set RST pin low to deactivate RFID module
ret=spi_device_polling_transmit(spix, &spi_trx); //Transmit!
gpio_set_level(SPI_RST, 1); // set RST pin high to deactivate RFID module
assert(ret == ESP_OK); //Should have had no issues.
if(ret != ESP_OK)
printf("SPI failed \n");
printf("Content received uird2 \n");
fifocontent(uird2, len); // print routine of the received data. example see below
printf("\n");
return;
}
The output is as follows (all figures in hex):
Content received uird2
6F 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
As we see the first byte 6F (= 0x6F = 'o') is from the slave. The following bytes (0x41) shows the content of
the transmission array. Is there a memory allocation problem.
So the question is: what is wrong?
Have I forgotten something to define.
I have used heap_caps_malloc(SPI_SIZE, MALLOC_CAP_DMA) with no change of the result.
Part of the log of the idf.py monitor:
I (248) cpu_start: ESP-IDF: v4.3
I (253) heap_init: Initializing. RAM available for dynamic allocation:
I (260) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM
I (266) heap_init: At 3FFB3230 len 0002CDD0 (179 KiB): DRAM
I (272) heap_init: At 3FFE0440 len 00003AE0 (14 KiB): D/IRAM
I (278) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
I (285) heap_init: At 4008C290 len 00013D70 (79 KiB): IRAM
I (292) spi_flash: detected chip: generic
I (296) spi_flash: flash io: dio
I (301) cpu_start: Starting scheduler on PRO CPU.
I (0) cpu_start: Starting scheduler on APP CPU.
Any help to solve the problem is appreciated.
best regards
neverendingproject