ESP32 crash when transmitting value via SPI

istolemars
Posts: 3
Joined: Tue Apr 25, 2017 9:37 am

ESP32 crash when transmitting value via SPI

Postby istolemars » Tue Apr 25, 2017 9:51 am

Hi all,

Recently started using the ESP32 DevKitC and could successfully communicate in SPI. However, recently I've encountered a few problems with transmitting a simple value via SPI.

At the moment my implementation consists of a header (hal.h) and source (hal.c) file. The hal.c file has an initialisation function for setting up the SPI communication. The following code is the initialisation of the SPI master and device.

Code: Select all

    esp_err_t ret;
    spi_bus_config_t buscfg;

    buscfg.miso_io_num = SPI_MISO;
    buscfg.mosi_io_num = SPI_MOSI;
    buscfg.sclk_io_num = SPI_CLK;
    buscfg.quadwp_io_num = -1;
    buscfg.quadhd_io_num = -1;

    spi_device_interface_config_t devcfg;

    devcfg.clock_speed_hz = 10000000;
    devcfg.mode = 1;
    devcfg.spics_io_num = SPI_CS;
    devcfg.queue_size = 7;
    devcfg.flags |= SPI_DEVICE_HALFDUPLEX;

    ret = spi_bus_initialize(HSPI_HOST, &buscfg, 1);
    assert(ret==ESP_OK);

    ret = spi_bus_add_device(HSPI_HOST, &devcfg, &spi_handle);
    assert(ret==ESP_OK);
This particular initialisation works fine. Tested it in a few other programs I wrote. The spi device handle is stored in the header file so other functions can use this. Now when I try to transmit a value via SPI I get the following error:

Code: Select all

Guru Meditation Error of type InstrFetchProhibited occurred on core  0. Exception was unhandled.
Register dump:
PC      : 0x000001e6  PS      : 0x00060031  A0      : 0x40081380  A1      : 0x3ffb07e0  
0x40081380: _xt_lowint1 at xtensa_vectors.o:?

A2      : 0x3ffb43cc  A3      : 0x000001e6  A4      : 0xfa0000c0  A5      : 0x3ff64000  
A6      : 0x00000001  A7      : 0x00000004  A8      : 0x80082f60  A9      : 0xfa0000c0  
A10     : 0x3ffb40e8  A11     : 0x08000000  A12     : 0xf20000c0  A13     : 0x00000040  
A14     : 0xe00000c0  A15     : 0x00007003  SAR     : 0x0000001f  EXCCAUSE: 0x00000014  
EXCVADDR: 0x000001e4  LBEG    : 0x4000c2e0  LEND    : 0x4000c2f6  LCOUNT  : 0xffffffff  
Tried using GDB to see where the problem is but without any success. With the use of many logs I tried to trace the problem.

In driver/spi_master.c the following happens:

Code: Select all

esp_err_t spi_device_queue_trans(spi_device_handle_t handle, spi_transaction_t *trans_desc,  TickType_t ticks_to_wait)
{
    BaseType_t r;
    SPI_CHECK(handle!=NULL, "invalid dev handle", ESP_ERR_INVALID_ARG);
    SPI_CHECK((trans_desc->flags & SPI_TRANS_USE_RXDATA)==0 ||trans_desc->rxlength <= 32, "rxdata transfer > 32 bits", 
    ESP_ERR_INVALID_ARG);
    SPI_CHECK((trans_desc->flags & SPI_TRANS_USE_TXDATA)==0 ||trans_desc->length <= 32, "txdata transfer > 32 bits", 
    ESP_ERR_INVALID_ARG);
    SPI_CHECK(!((trans_desc->flags & (SPI_TRANS_MODE_DIO|SPI_TRANS_MODE_QIO)) && (handle->cfg.flags & 
    SPI_DEVICE_3WIRE)), "incompatible iface params", ESP_ERR_INVALID_ARG);
    SPI_CHECK(!((trans_desc->flags & (SPI_TRANS_MODE_DIO|SPI_TRANS_MODE_QIO)) && (!(handle->cfg.flags & 
    SPI_DEVICE_HALFDUPLEX))), "incompatible iface params", ESP_ERR_INVALID_ARG);
    r=xQueueSend(handle->trans_queue, (void*)&trans_desc, ticks_to_wait);
    if (!r) return ESP_ERR_TIMEOUT;
    ESP_LOGI(SPI_TAG,"Enable interrupt");
    esp_intr_enable(handle->host->intr);
    ESP_LOGI(SPI_TAG,"Done enabling interrupt");
    return ESP_OK;
}
When trying to enable the interrupt in the last few lines my ESP32 crashes with the error I posted above (The last log was never reached). I have the feeling something is going wrong with the spi_device_handle_t since in a different context, this program works. I'm very puzzled to how this could happen. If anyone has an idea on how to solve this it would be great!

ESP_igrr
Posts: 2067
Joined: Tue Dec 01, 2015 8:37 am

Re: ESP32 crash when transmitting value via SPI

Postby ESP_igrr » Tue Apr 25, 2017 11:15 am

Which pins are you using as SPI_MISO, SPI_MOSI, SPI_CLK?

istolemars
Posts: 3
Joined: Tue Apr 25, 2017 9:37 am

Re: ESP32 crash when transmitting value via SPI

Postby istolemars » Tue Apr 25, 2017 11:19 am

ESP_igrr wrote:Which pins are you using as SPI_MISO, SPI_MOSI, SPI_CLK?
I use the following pins:

Code: Select all

#define SPI_CLK     5
#define SPI_MISO    21
#define SPI_MOSI    22
#define SPI_CS      23
These pins worked fine for me before when setting up SPI.

ESP_igrr
Posts: 2067
Joined: Tue Dec 01, 2015 8:37 am

Re: ESP32 crash when transmitting value via SPI

Postby ESP_igrr » Tue Apr 25, 2017 11:38 am

There are a bunch of members in spi_device_interface_config_t structure which you aren't initializing, they include pre_cb and post_cb callback pointers. Because these pointers are not initialized, they contain garbage values previously present on the stack. SPI driver calls these function pointers which results in a crash.

A good practice is to use C99 designated initializers if you are allocating structures on the stack. This way of initialization guarantees that the fields which you don't specify explicitly still get initialized to zero. spi_master example in the IDF contains an example of such initializer:

Code: Select all

spi_device_interface_config_t devcfg={
        .clock_speed_hz=10000000,               //Clock out at 10 MHz
        .mode=0,                                //SPI mode 0
        .spics_io_num=PIN_NUM_CS,               //CS pin
        .queue_size=7,                          //We want to be able to queue 7 transactions at a time
        .pre_cb=ili_spi_pre_transfer_callback,  //Specify pre-transfer callback to handle D/C line
    };

istolemars
Posts: 3
Joined: Tue Apr 25, 2017 9:37 am

Re: ESP32 crash when transmitting value via SPI

Postby istolemars » Tue Apr 25, 2017 11:49 am

ESP_igrr wrote:There are a bunch of members in spi_device_interface_config_t structure which you aren't initializing, they include pre_cb and post_cb callback pointers. Because these pointers are not initialized, they contain garbage values previously present on the stack. SPI driver calls these function pointers which results in a crash.

A good practice is to use C99 designated initializers if you are allocating structures on the stack. This way of initialization guarantees that the fields which you don't specify explicitly still get initialized to zero. spi_master example in the IDF contains an example of such initializer:

Code: Select all

spi_device_interface_config_t devcfg={
        .clock_speed_hz=10000000,               //Clock out at 10 MHz
        .mode=0,                                //SPI mode 0
        .spics_io_num=PIN_NUM_CS,               //CS pin
        .queue_size=7,                          //We want to be able to queue 7 transactions at a time
        .pre_cb=ili_spi_pre_transfer_callback,  //Specify pre-transfer callback to handle D/C line
    };
Thanks a lot for helping me out! This fixed the problem for me. I tried to write some SPI communication in a C++ class once. The C99 initializers weren't allowed and I got rid of them there.

ESP_igrr
Posts: 2067
Joined: Tue Dec 01, 2015 8:37 am

Re: ESP32 crash when transmitting value via SPI

Postby ESP_igrr » Tue Apr 25, 2017 1:11 pm

In c++ you can still do

spi_device_interface_config_t devcfg={0};

and then set the fields you actually need.

Who is online

Users browsing this forum: Bing [Bot] and 102 guests