Start a SPI DMA transmission by GPIO trigger ? - ESP32-S3 Forum
Start a SPI DMA transmission by GPIO trigger ? - ESP32-S3 Forum
Dear espressif programmers,
I would like to trigger SPI DMA transmission by a GPIO - data ready DRDY falling edge from a SPI slave device. The DRDY is set by the SPI slave device every 1ms with 27 bytes of data ready to readout by the SPI master (ESP32-S3). The goal is to use DMA to automatically trigger SPI DMA transmittions in 27 bytes blocks to sequentially fill up two 1350 bytes ping-pong buffers and trigger an interrupt only when one of the ping-pong buffers is filled without the CPU interaction in each DRDY event.
1. Is it possible to directly connect a GPIO to trigger SPI DMA transmissions (e.g. by gpio_matrix_in) in ESP32-S3 ?
2. Or is it possible to use RMT module for this purpose instead ? Are there any disadvantages compared to direct GPIO-DMA connection ?
3. DMA-Controlled Configurable Segmented Transfer - is it possible to start transfer of individual segments using DMA RMT ?
4. Is there any other better solution ?
Thank you,
best regards,
Jan Kijonka
I would like to trigger SPI DMA transmission by a GPIO - data ready DRDY falling edge from a SPI slave device. The DRDY is set by the SPI slave device every 1ms with 27 bytes of data ready to readout by the SPI master (ESP32-S3). The goal is to use DMA to automatically trigger SPI DMA transmittions in 27 bytes blocks to sequentially fill up two 1350 bytes ping-pong buffers and trigger an interrupt only when one of the ping-pong buffers is filled without the CPU interaction in each DRDY event.
1. Is it possible to directly connect a GPIO to trigger SPI DMA transmissions (e.g. by gpio_matrix_in) in ESP32-S3 ?
2. Or is it possible to use RMT module for this purpose instead ? Are there any disadvantages compared to direct GPIO-DMA connection ?
3. DMA-Controlled Configurable Segmented Transfer - is it possible to start transfer of individual segments using DMA RMT ?
4. Is there any other better solution ?
Thank you,
best regards,
Jan Kijonka
-
- Posts: 54
- Joined: Thu Feb 22, 2024 3:59 pm
Re: Start a SPI DMA transmission by GPIO trigger ? - ESP32-S3 Forum
I'm not sure if you could do this with the normal SPI+DMA, but you could implement this by using the ULP, which could monitor the GPIO and do the transfer for you.
Re: Start a SPI DMA transmission by GPIO trigger ? - ESP32-S3 Forum
Thank you for the suggested solution. As I can see, the ULP coprocessor does not have the capability to use the SPI interface; it would likely have to be solved by manually generating the clock and reading data using standard GPIO. For communication, I would need a clock of at least 1 MHz. The question would be the power consumption of the ULP module, as well as the accuracy of clock generation and reading data from the SPI slave module.
I'm currently able to generate RMT events (RX_DONE or EVENT_RX_THRES) to trigger a DMA channel. If a DMA channel could trigger SPI transmittion, it could be the solution. Could be it implemented by dma linked list descriptors ?
I'm currently able to generate RMT events (RX_DONE or EVENT_RX_THRES) to trigger a DMA channel. If a DMA channel could trigger SPI transmittion, it could be the solution. Could be it implemented by dma linked list descriptors ?
Re: Start a SPI DMA transmission by GPIO trigger ? - ESP32-S3 Forum
spi-dma master can only be started programmatically
The best solution is to put spi-dma in slave mode and your spi-slave device in master mode if possible.
If not, there's no prohibition against putting both devices into slave mode.
sclk can be generated by the mcpwm module with carier filling
https://docs.espressif.com/projects/esp ... rs-by-gpio
spi-dma will receive as much data as you want, interruptions can be received from dma itself, for example after processing one dma frame (1350), if you set such frame size in linkedlist.
The best solution is to put spi-dma in slave mode and your spi-slave device in master mode if possible.
If not, there's no prohibition against putting both devices into slave mode.
sclk can be generated by the mcpwm module with carier filling
https://docs.espressif.com/projects/esp ... rs-by-gpio
spi-dma will receive as much data as you want, interruptions can be received from dma itself, for example after processing one dma frame (1350), if you set such frame size in linkedlist.
Re: Start a SPI DMA transmission by GPIO trigger ? - ESP32-S3 Forum
Thank you for suggestions for the solution! I am currently working on SPI DMA segmented transfer using one DMA channel and reading events on a GPIO pin by RMT using second DMA channel. Is it possible to synchronize DMA channels of these peripherals so that the RMT DMA channel triggers the SPI DMA channel by linked list of DMA descriptors?
PS: I came across segment-based SPI transfer in the ESP32-S3 reference manual, where a single execution of GPSPI2.cmd.usr = 1 can start any number of SPI transfers, and each segment can be configured during the DMA transfer without CPU intervention. This works.
PS: I came across segment-based SPI transfer in the ESP32-S3 reference manual, where a single execution of GPSPI2.cmd.usr = 1 can start any number of SPI transfers, and each segment can be configured during the DMA transfer without CPU intervention. This works.
Re: Start a SPI DMA transmission by GPIO trigger ? - ESP32-S3 Forum
the dma channel is nothing more than an interface between the peripheral device and the memory,
it is fully controlled by the device to which it is connected,
if the device gives a command to write/read from the memory, the dma channel executes this command
by itself the dma channel cannot start the transfer, let alone transfer control to another dma channel/device.
it is fully controlled by the device to which it is connected,
if the device gives a command to write/read from the memory, the dma channel executes this command
by itself the dma channel cannot start the transfer, let alone transfer control to another dma channel/device.
Re: Start a SPI DMA transmission by GPIO trigger ? - ESP32-S3 Forum
As I understand, my idea that the SPI descriptor would transition to the RMT descriptor, where the RMT RX END operation would be awaited (code shown below), is incorrect . Therefore, I will attempt to implement the solution using your suggested approach. I will configure the ESP32-S3 as an SPI slave, with separate generation of the CS low enable signal and SPI CLK, because my external SPI devices do not support SPI master configuration. In fact, I will have two external SPI slave devices to communicate with, where data should be read from the first SPI device (CS device1 low) on the falling edge of DRDY, and then immediately from the second SPI device (CS device2 low). Both external SPI devices are synchronized by the CLK and generate the DRDY signal simultaneously.
spi_conf_desc[0].size = 12; // Size of SPI CONF buffer
spi_conf_desc[0].length = 12;
spi_conf_desc[0].buf = (uint8_t *)&spi_conf_buffer; // CONF buffer pointer
spi_conf_desc[0].sosf = 0;
spi_conf_desc[0].eof = 0;
spi_conf_desc[0].owner = 1;
spi_conf_desc[0].qe.stqe_next = &spi_data_desc[0]; // Go to SPI TX data
spi_data_desc[0].size = 1;
spi_data_desc[0].length = 1;
spi_data_desc[0].buf = (uint8_t *)&spi_tx_buffer[0]; // SPI TX buffer pointer
spi_data_desc[0].sosf = 0;
spi_data_desc[0].eof = 0;
spi_data_desc[0].owner = 1;
spi_data_desc[0].qe.stqe_next = &rmt_data_desc[0]; // Go to RMT RX data descriptor to WAIT for RMT TX END or THRESHOLD event
rmt_data_desc[0].size = 1;
rmt_data_desc[0].length = 1;
rmt_data_desc[0].buf = (uint8_t *)&rmt_rx_buffer[0]; // RMT RX data pointer
rmt_data_desc[0].sosf = 0;
rmt_data_desc[0].eof = 0;
rmt_data_desc[0].owner = 1;
rmt_data_desc[0].qe.stqe_next = &spi_conf_desc[0]; // GO back to the SPI CONF descriptor (LOOP)
spi_conf_desc[0].size = 12; // Size of SPI CONF buffer
spi_conf_desc[0].length = 12;
spi_conf_desc[0].buf = (uint8_t *)&spi_conf_buffer; // CONF buffer pointer
spi_conf_desc[0].sosf = 0;
spi_conf_desc[0].eof = 0;
spi_conf_desc[0].owner = 1;
spi_conf_desc[0].qe.stqe_next = &spi_data_desc[0]; // Go to SPI TX data
spi_data_desc[0].size = 1;
spi_data_desc[0].length = 1;
spi_data_desc[0].buf = (uint8_t *)&spi_tx_buffer[0]; // SPI TX buffer pointer
spi_data_desc[0].sosf = 0;
spi_data_desc[0].eof = 0;
spi_data_desc[0].owner = 1;
spi_data_desc[0].qe.stqe_next = &rmt_data_desc[0]; // Go to RMT RX data descriptor to WAIT for RMT TX END or THRESHOLD event
rmt_data_desc[0].size = 1;
rmt_data_desc[0].length = 1;
rmt_data_desc[0].buf = (uint8_t *)&rmt_rx_buffer[0]; // RMT RX data pointer
rmt_data_desc[0].sosf = 0;
rmt_data_desc[0].eof = 0;
rmt_data_desc[0].owner = 1;
rmt_data_desc[0].qe.stqe_next = &spi_conf_desc[0]; // GO back to the SPI CONF descriptor (LOOP)
Re: Start a SPI DMA transmission by GPIO trigger ? - ESP32-S3 Forum
Hello,
I'm trying a basic PWM generator, but there is some problem. If I add carrier filling block (the code below), there is always only the first pulse (1 us) generated on scope. I have tried various frequencies and settings of the mcpwm timer. The PWM is generated according to assumptions, but the carrier is not filling the PWM high/or low pulse.
// Add Carrier Filling
mcpwm_carrier_config_t carrier_config = {
.clk_src = MCPWM_TIMER_CLK_SRC_DEFAULT,
.first_pulse_duration_us = 1, // First pulse 1 us
.frequency_hz = 1000000, // Frekvence carrieru 1 MHz
// .flags.invert_before_modulate = true,
.duty_cycle = 30, // 30% duty cycle
};
ESP_ERROR_CHECK(mcpwm_operator_apply_carrier(oper, &carrier_config));
I'm trying a basic PWM generator, but there is some problem. If I add carrier filling block (the code below), there is always only the first pulse (1 us) generated on scope. I have tried various frequencies and settings of the mcpwm timer. The PWM is generated according to assumptions, but the carrier is not filling the PWM high/or low pulse.
// Add Carrier Filling
mcpwm_carrier_config_t carrier_config = {
.clk_src = MCPWM_TIMER_CLK_SRC_DEFAULT,
.first_pulse_duration_us = 1, // First pulse 1 us
.frequency_hz = 1000000, // Frekvence carrieru 1 MHz
// .flags.invert_before_modulate = true,
.duty_cycle = 30, // 30% duty cycle
};
ESP_ERROR_CHECK(mcpwm_operator_apply_carrier(oper, &carrier_config));
- Attachments
-
- main.c
- (3.2 KiB) Downloaded 67 times
Re: Start a SPI DMA transmission by GPIO trigger ? - ESP32-S3 Forum
Code: Select all
.duty_cycle = 30, // 30% duty cycle
Code: Select all
.duty_cycle = 0.3, // 30% duty cycle
Re: Start a SPI DMA transmission by GPIO trigger ? - ESP32-S3 Forum
Perfect, the carrier filling works now! Thank you! I'm adding my project main file. The GPIO 5 works now as sync for three PWM signals generated on GPIO 0, GPIO2 and GPIO 4. Signal on GPIO 0 is carrier filled (could be used as SCLK for SPI) and signal on GPIO 2 or 4 could be used as CS for SPI.
Could I ask how to now configure the triggering of PWM using the falling edge of DRDY? Or is the synchronization (GPIO 5) supposed to serve as a triggering mechanism for the SPI transfer, and the PWM high level should be sufficiently long to prevent another activation of CS between two DRDY signals?
Could I ask how to now configure the triggering of PWM using the falling edge of DRDY? Or is the synchronization (GPIO 5) supposed to serve as a triggering mechanism for the SPI transfer, and the PWM high level should be sufficiently long to prevent another activation of CS between two DRDY signals?
- Attachments
-
- main_carrier.c
- (7.84 KiB) Downloaded 56 times
Who is online
Users browsing this forum: No registered users and 29 guests