ESP32 DMA buffer size issue

takeshikawami
Posts: 3
Joined: Mon Mar 18, 2024 9:56 pm

ESP32 DMA buffer size issue

Postby takeshikawami » Tue Mar 19, 2024 3:17 am

Hello,

I am currently working on a project where I use an ESP32 as an SPI slave to receive data from another device. I follow the official ESP-IDF example for an SPI slave receiver, which can be found here:
https://github.com/espressif/esp-idf/bl ... app_main.c

I need to use a large buffer for my project. Now I set the buffer size to 1024 (buffer_size = 1024), but I anticipate needing an even larger buffer in the future.

Here is my code:

Code: Select all

// Slave as receiver for SPI communitation

#include <stdio.h>
#include <stdint.h>
#include <stddef.h>
#include <string.h>

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "freertos/queue.h"

#include "lwip/sockets.h"
#include "lwip/dns.h"
#include "lwip/netdb.h"
#include "lwip/igmp.h"

#include "esp_wifi.h"
#include "esp_system.h"
#include "esp_event.h"
#include "nvs_flash.h"
#include "soc/rtc_periph.h"
#include "driver/spi_slave.h"
#include "esp_log.h"
#include "esp_spi_flash.h"
#include "driver/gpio.h"

// Pins in use
#define GPIO_MOSI 23
#define GPIO_MISO 19
#define GPIO_SCLK 18
#define GPIO_CS 5

#define buffer_size 1024

DMA_ATTR uint32_t recvbuf[buffer_size];

//Main application
void app_main(void)
{
    //Configuration for the SPI bus
    spi_bus_config_t buscfg={
        .mosi_io_num=GPIO_MOSI,
        .miso_io_num=GPIO_MISO,
        .sclk_io_num=GPIO_SCLK,
        .quadwp_io_num = -1,
        .quadhd_io_num = -1,
    };



    //Configuration for the SPI slave interface
    spi_slave_interface_config_t slvcfg={
        .mode=1, 
        .spics_io_num=GPIO_CS,
        .queue_size=3,
        .flags=0,
    };

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

    //Initialize SPI slave interface
    spi_slave_initialize(HSPI_HOST, &buscfg, &slvcfg, SPI_DMA_CH_AUTO);

    //WORD_ALIGNED_ATTR uint32_t recvbuf[buffer_size];
    
    for (int i =0; i < buffer_size; i++){
        recvbuf[i] = 0xA5000000;
    }
    
    spi_slave_transaction_t t;
    memset(&t, 0, sizeof(t));

	printf("Slave output:\n");
    while(1) {
        t.length=buffer_size*4*8;
        t.rx_buffer=recvbuf;
        spi_slave_transmit(HSPI_HOST, &t, portMAX_DELAY);
        for (int i = 0; i < buffer_size; i++){
        printf("Received: %08lX, term %d\n", (unsigned long)recvbuf[i] & 0xFFFFFFFF, i);
        }
    }

}

Initially, I used the following buffer declaration: WORD_ALIGNED_ATTR uint32_t recvbuf[buffer_size];, but it got a stack overflow issue. After consulting https://docs.espressif.com/projects/esp ... types.html, it seems that placing DMA buffers in the stack is possible but discouraged. The documentation suggests using the DMA_ATTR macro for global or local static variables instead. So I adjusted my buffer declaration to: DMA_ATTR uint32_t recvbuf[buffer_size];

This change seemed to resolve the stack overflow problem. However, I am now facing a new issue: the buffer continuously outputs its initialized contents, even when no SS (Slave Select) and CLK (Clock) signals are applied.

I would greatly appreciate any suggestions or advice on how to resolve this issue. Additionally, I wonder if there are any examples of SPI slave implementations using larger buffers that I could refer to? That would be very helpful.
Last edited by takeshikawami on Wed Mar 27, 2024 7:23 pm, edited 1 time in total.

liaifat85
Posts: 200
Joined: Wed Dec 06, 2023 2:46 pm

Re: ESP32 DMA buffer size issue

Postby liaifat85 » Tue Mar 19, 2024 10:59 am

To allocate a larger buffer, simply adjust the buffer_size constant to your desired size. For example:

Code: Select all

#define buffer_size 2048 // or any other desired size
DMA_ATTR uint32_t recvbuf[buffer_size];

takeshikawami
Posts: 3
Joined: Mon Mar 18, 2024 9:56 pm

Re: ESP32 DMA buffer size issue

Postby takeshikawami » Tue Mar 19, 2024 6:44 pm

liaifat85 wrote:
Tue Mar 19, 2024 10:59 am
To allocate a larger buffer, simply adjust the buffer_size constant to your desired size. For example:

Code: Select all

#define buffer_size 2048 // or any other desired size
DMA_ATTR uint32_t recvbuf[buffer_size];
But when I adjust the size lager than 1023, it will keep printling out the initialized contents in the buffer even if I didn't apply any input signal such as SS and SCLK. I'm not sure if what causes this problem. But I saw in the struct spi_bus_config_t, it says that:

int max_transfer_sz
Maximum transfer size, in bytes. Defaults to 4092 if 0 when DMA enabled, or to SOC_SPI_MAXIMUM_BUFFER_SIZE if DMA is disabled.

Will the problem caused by this?

MicroController
Posts: 1706
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: ESP32 DMA buffer size issue

Postby MicroController » Wed Mar 20, 2024 8:31 am

takeshikawami wrote:
Tue Mar 19, 2024 6:44 pm
But when I adjust the size lager than 1023, it will keep printling out the initialized contents in the buffer even if I didn't apply any input signal such as SS and SCLK. I'm not sure if what causes this problem.
You may want to check the result value returned from spi_slave_transmit(...).
Haven't checked the driver's code, but chances are that you get an ESP_ERR_INVALID_ARG (or some other error result).
Note also than 1024 uint32_t's are 4096 bytes, which happens to be the maximum size for a single DMA transfer block.

takeshikawami
Posts: 3
Joined: Mon Mar 18, 2024 9:56 pm

Re: ESP32 DMA buffer size issue

Postby takeshikawami » Wed Mar 27, 2024 7:26 pm

I find someone else post a similar question and it can be solve by setting .max_transfer_sz in spi_bus_config_t to larger size. This confused me because I thought the maximum size was only 4092 before.

Who is online

Users browsing this forum: Majestic-12 [Bot] and 103 guests