Issues with SPI Slave

mpulis
Posts: 57
Joined: Mon Aug 07, 2017 7:53 am

Issues with SPI Slave

Postby mpulis » Fri Jul 26, 2019 6:04 am

Hi all,

I'm currently working with the SPI Slave peripheral but am running into 2 issues.

1. I'm setting up a transaction using spi_slave_transmit() with the ticks_to_wait argument set to portMAX_DELAY. I'd expect the function to block there until the Master initiates a transaction, but the task continues execution normally, continuing to set up transactions. I've analyzed the chip select line and can confirm that it's inactive. Am I wrong in believing that the function should be blocking while the chip select is still inactive? The function isn't returning any errors back, so I'm unsure if anything's set up incorrectly.

2. I can receive data from the master correctly but am unable to actually transmit anything back. I've tried to set up a transaction of 2 bytes to be sent back to the Master, but the MISO line is remaining low in all transactions.

I'm currently working with an SPI Master running in Mode 0 with a clock speed of 100kHz. I've attached the code for the peripheral initialization along with the listening task.

Does anyone have an idea whether I'm doing anything wrong here?

Code: Select all

#define SPI_SLAVE_MOSI_PIN 39
#define SPI_SLAVE_MISO_PIN 32
#define SPI_SLAVE_SCK_PIN  13
#define SPI_SLAVE_CS_PIN   36

#define SPI_SLAVE_MAX_BUFER_SIZE 128

//!Initialize SPI slave interface. Pin definitions are in header file
static void spiSlaveInit()
{
	BaseType_t xReturned;
	esp_err_t err;

	gpio_config_t io_conf;

	io_conf.intr_type = GPIO_PIN_INTR_DISABLE;
	io_conf.pin_bit_mask = 1ULL<<SPI_SLAVE_MOSI_PIN;
	io_conf.mode = GPIO_MODE_INPUT;
	io_conf.pull_up_en = 0;
	io_conf.pull_down_en = 0;
	gpio_config(&io_conf);

        io_conf.intr_type = GPIO_PIN_INTR_DISABLE;
	io_conf.pin_bit_mask = 1ULL<<SPI_SLAVE_SCK_PIN;
	io_conf.mode = GPIO_MODE_INPUT;
	io_conf.pull_up_en = 0;
	io_conf.pull_down_en = 0;
	gpio_config(&io_conf);


	io_conf.intr_type = GPIO_PIN_INTR_DISABLE;
	io_conf.pin_bit_mask = 1ULL<<SPI_SLAVE_CS_PIN;
	io_conf.mode = GPIO_MODE_INPUT;
	io_conf.pull_up_en = 1;
	io_conf.pull_down_en = 0;
	gpio_config(&io_conf);

	io_conf.intr_type = GPIO_PIN_INTR_DISABLE;
	io_conf.pin_bit_mask = 1ULL<<SPI_SLAVE_MISO_PIN;
	io_conf.mode = GPIO_MODE_OUTPUT;
	io_conf.pull_up_en = 0;
	io_conf.pull_down_en = 0;
	gpio_config(&io_conf);

    //Configuration for the SPI bus
    spi_bus_config_t buscfg =
	{
        .mosi_io_num = SPI_SLAVE_MOSI_PIN,
        .miso_io_num = SPI_SLAVE_MISO_PIN,
        .sclk_io_num = SPI_SLAVE_SCK_PIN,
        .quadwp_io_num = -1,
        .quadhd_io_num = -1
    };

    //Configuration for the SPI slave interface
    spi_slave_interface_config_t slvcfg =
	{
        .mode = 0,
        .spics_io_num = SPI_SLAVE_CS_PIN,
        .queue_size = 3,
        .flags = 0,
        .post_setup_cb=NULL,
        .post_trans_cb=NULL
    };

    //Enable pull-ups on SPI lines so we don't detect rogue pulses when no master is connected.
    gpio_set_pull_mode(SPI_SLAVE_MOSI_PIN, GPIO_PULLUP_ONLY);
    gpio_set_pull_mode(SPI_SLAVE_SCK_PIN, GPIO_PULLUP_ONLY);
    gpio_set_pull_mode(SPI_SLAVE_CS_PIN, GPIO_PULLUP_ONLY);

    _shared_mem_send_buffer = pvPortMallocCaps(SPI_SLAVE_MAX_BUFER_SIZE, MALLOC_CAP_DMA);

    //Initialize SPI slave interface
    err = spi_slave_initialize(HSPI_HOST, &buscfg, &slvcfg, 0);
    if(err == ESP_OK)
    {
    	ESP_LOGI(TAG, "spiSlaveInit: Initialized SPI Slave interface");
    }

    xReturned = xTaskCreatePinnedToCore(&spiSlaveListenTask, "spiSlaveListenTask", 8192, NULL, 5, NULL, 1);
    if(pdPASS != xReturned)
    {
    	ESP_LOGE(TAG, "spiSlaveInit: Could not initialize spi slave listener task. Heap available is %d", esp_get_free_heap_size());
    }
}

//!Task which continually listens for data received over the SPI slave bus
static void spiSlaveListenTask()
{
	WORD_ALIGNED_ATTR char* recvbuf = NULL;
        WORD_ALIGNED_ATTR char dummy_buffer[32] = {0};
	spi_slave_transaction_t t;
        esp_err_t rv = ESP_OK;

        recvbuf = pvPortMallocCaps(SPI_SLAVE_MAX_BUFER_SIZE, MALLOC_CAP_DMA);

        ESP_LOGI(TAG, "spiSlaveListenTask: Starting to listen on SPI Slave interface");

	while(1)
	{
        //Set up a transaction of bytes to send/receive
        memset(&t, 0, sizeof(t));
        t.length = 32*8;
        t.tx_buffer = dummy_buffer;
        t.rx_buffer = recvbuf;

        dummy_buffer[0] = 0x0A;
        dummy_buffer[1] = 0x0B; 
        rv = spi_slave_transmit(HSPI_HOST, &t, portMAX_DELAY);
        if(ESP_OK != rv)
        {
            ESP_LOGE(TAG, "spiSlaveListenTask: Recevied error %d when setting up transaction!", rv);
        }
        ESP_LOGI(TAG, "spiSlaveListenTask: Transaction received with length of %d bytes", t.trans_len);

      //  while(!gpio_get_level(SPI_SLAVE_CS_PIN));

        if(t.trans_len > 0)
        {//received spi transaction    
           bzero(_shared_mem_send_buffer, SPI_SLAVE_MAX_BUFER_SIZE);
           miscPrintHexadecimalString((char*)recvbuf, t.trans_len/8, "SPI slave received: ");
        }
	}   
}

mpulis
Posts: 57
Joined: Mon Aug 07, 2017 7:53 am

Re: Issues with SPI Slave

Postby mpulis » Fri Jul 26, 2019 7:12 am

Update:

I've managed to get the SPI transmit working! I changed the configuration CONFIG_SPI_SLAVE_IN_IRAM to enabled. From my understanding this places the transmit function (which I would assume the function responsible for handling any data to be sent over MISO if the tx_buffer of the transaction isn't set to NULL) into IRAM apart from flash.

Is this supposed to be an issue? Unless I disabled this functionality by mistake, which I doubt since I haven't worked much on the SPI Slave peripheral, the configuration is disabled by default which I would take to mean that the peripheral should work well with the transmit functions not placed in IRAM.

domolatr
Posts: 1
Joined: Sat Apr 30, 2022 6:03 am

Re: Issues with SPI Slave

Postby domolatr » Sat Apr 30, 2022 6:05 am

mpulis wrote:
Fri Jul 26, 2019 7:12 am
Update:

I've managed to get the SPI transmit working! I changed the configuration CONFIG_SPI_SLAVE_IN_IRAM to enabled. From my understanding this places the transmit function (which I would assume the function responsible for handling any data to be sent over MISO if the tx_buffer of the transaction isn't set to NULL) into IRAM apart from flash.

Is this supposed to be an issue? Unless I disabled this functionality by mistake, which I doubt since I haven't worked much on the SPI Slave peripheral, the configuration is disabled by default which I would take to mean that the peripheral should work well with the transmit functions not placed in IRAM.
Hello could you please show, how to get SPI config into IRAM ? please share final code ;)

Who is online

Users browsing this forum: No registered users and 121 guests