Hi everyone.
I’m new to RIOT OS and I using it with stm32f103c8. I want to transfer data to SPI using DMA. It’s just not clear for me what to do. Basically, I already controlling WS2812b with SPI, and want to get rid of spi_transfer_bytes calls, and hand over this job to DMA controller. There are just no info of how to do this.
#include "periph/gpio.h"
#include "periph/spi.h"
#include "ztimer.h"
#include <board.h>
#include <stdint.h>
#include "periph/cpu_dma.h"
#define LED_COUNT (60)
#define RESET_PULSE (60)
#define PIXELS_STACK_SIZE (LED_COUNT * 24 + 60)
static uint8_t PIXELS_STACK[PIXELS_STACK_SIZE];
int main(void) {
ztimer_sleep(ZTIMER_USEC, 3000000);
gpio_toggle(LED0_PIN);
spi_acquire(0, SPI_CS_UNDEF, SPI_MODE_1, KHZ(5200));
while (1) {
for (int i = 0; i < PIXELS_STACK_SIZE - RESET_PULSE; ++i) {
PIXELS_STACK[i] = 0b11111100;
}
spi_transfer_bytes(0, SPI_CS_UNDEF, false, &PIXELS_STACK, NULL, PIXELS_STACK_SIZE);
gpio_toggle(LED0_PIN);
ztimer_sleep(ZTIMER_USEC, 1000000);
for (int i = 0; i < PIXELS_STACK_SIZE - RESET_PULSE; ++i) {
PIXELS_STACK[i] = 0b10000000;
}
spi_transfer_bytes(0, SPI_CS_UNDEF, false, &PIXELS_STACK, NULL, PIXELS_STACK_SIZE);
gpio_toggle(LED0_PIN);
ztimer_sleep(ZTIMER_USEC, 1000000);
}
}
I assume that I need to call dma_configure with right params, although I’m not sure. It’s not clear for me what is destination buffer in my case.
/**
* @brief Configure a DMA stream for a new transfer
*
* @param[in] dma logical DMA stream
* @param[in] chan DMA channel (on stm32f2/4/7, CxS or unused on others)
* @param[in] src source buffer
* @param[out] dst destination buffer
* @param[in] len number of transfers to perform
* @param[in] mode DMA mode
* @param[in] flags DMA configuration
*
* @return < 0 on error, 0 on success
*/
int dma_configure(dma_t dma, int chan, const volatile void *src, volatile void *dst, size_t len,
dma_mode_t mode, uint8_t flags);
Also, I don’t understand how can I setup SPI (spi_acquire call). Maybe there already SPI implementation with using DMA? I just can’t find it.
UDP: I finally found a .c file with SPI impl on STM. I saw the usage of DMA in it. So, SPI on stm32 uses DMA already?
But I’m still curios about the destination param. Here is example from RIOT/cpu/stm32/periph/spi.c (row 264):
dma_setup(spi_config[bus].tx_dma,
spi_config[bus].tx_dma_chan,
(uint32_t*)&(dev(bus)->DR),
DMA_MEM_TO_PERIPH,
DMA_DATA_WIDTH_BYTE,
0);
dev is a function:
static inline SPI_TypeDef *dev(spi_t bus)
{
return spi_config[bus].dev;
}
What is DR? And where I can find it?