I tried the example in the libdaisy documentation, and the docs are old (the NSS config is not used that way anymore) and I can’t get SPI Dma Receive working. The blocking version works just fine. I can also get Tx DMA working. The buffer is in buffer space. Anything I should look at that isn’t documented yet?
Would you be able to provide the code here (or if there’s a lot of surrounding code, a minimal reproduction)? I know you said you simply tried the example, but having the exact code you used would make potentially diagnosing an issue much easier!
Here’s the entire main.cpp:
#include "daisy_seed.h"
using namespace daisy;
#define PROC_SIZE 1024
DaisySeed hw;
static uint8_t DMA_BUFFER_MEM_SECTION usb_cb_buf[32];
static uint32_t usb_cb_count = 0;
static uint32_t usb_cb_len = 0;
static void DSY_ITCM_MEM_SECTION my_usb_cb(uint8_t *buf, uint32_t *len)
{
uint32_t n = (*len) - 1;
if((*len > 1) && (usb_cb_len + n < 30))
{
for(uint32_t i = 0; i < n; i++)
usb_cb_buf[usb_cb_len++] = buf[i];
}
usb_cb_count++;
}
SpiHandle spiHandleRx;
static void my_init_spi(SpiHandle *hspi)
{
SpiHandle::Config spiConf;
spiConf.periph = SpiHandle::Config::Peripheral::SPI_6;
spiConf.mode = SpiHandle::Config::Mode::SLAVE;
spiConf.direction = SpiHandle::Config::Direction::TWO_LINES_RX_ONLY;
spiConf.nss = SpiHandle::Config::NSS::SOFT;
//spiConf.nss = SpiHandle::Config::NSS::HARD_INPUT;
spiConf.pin_config.nss = Pin(GPIOPort::PORTA, 4);
spiConf.pin_config.sclk = Pin(GPIOPort::PORTA, 5);
spiConf.pin_config.mosi = Pin(GPIOPort::PORTA, 7);
spiConf.baud_prescaler = SpiHandle::Config::BaudPrescaler::PS_2;
spiConf.datasize = 8;
hspi->Init(spiConf);
}
static void DSY_ITCM_MEM_SECTION timer_cb(void *ptr)
{
if(ptr)
*((bool *)ptr) = true;
}
static uint32_t one_sec;
static uint32_t one_milli;
static uint32_t one_micro;
static bool timed_one_sec = false;
static bool timed_tenth_sec = false;
static void my_init_timers()
{
TimerHandle::Config T_config;
T_config = TimerHandle::Config();
T_config.dir = TimerHandle::Config::CounterDir::UP;
T_config.enable_irq = true;
TimerHandle Timer4;
T_config.periph = TimerHandle::Config::Peripheral::TIM_4;
T_config.period = 999;
Timer4.Init(T_config);
Timer4.SetPrescaler(one_micro * 100);
Timer4.SetCallback(timer_cb, (void *)&timed_tenth_sec);
Timer4.Start();
TimerHandle Timer5;
T_config.periph = TimerHandle::Config::Peripheral::TIM_5;
T_config.period = 9999;
Timer5.Init(T_config);
Timer5.SetPrescaler(one_micro * 100);
Timer5.SetCallback(timer_cb, (void *)&timed_one_sec);
Timer5.Start();
}
uint8_t DMA_BUFFER_MEM_SECTION frame_rx[PROC_SIZE];
int DSY_ITCM_MEM_SECTION main(void)
{
hw.Init(true);
hw.StartLog(); // true to wait for connection
hw.usb_handle.Init(UsbHandle::FS_INTERNAL);
System::Delay(1); // hack
hw.usb_handle.SetReceiveCallback(my_usb_cb, UsbHandle::FS_INTERNAL);
one_sec = System::GetTickFreq();
one_milli = one_sec / 1000;
one_micro = one_milli / 1000;
my_init_timers();
my_init_spi(&spiHandleRx);
uint32_t proc_count = 0;
uint32_t proc_time = 0;
uint32_t check_count = 0;
bool serial_on = true;
bool led_state = false;
bool use_dma = false;
while(true)
{
if(timed_tenth_sec)
{
timed_tenth_sec = false;
for(uint32_t i = 0; i < 1024; i++)
{
uint16_t m = 0xC5C5;
bool matched = false;
for(uint8_t j = 0; j < 8; j++)
{
uint8_t k = (m >> j) & 0xFF;
if(frame_rx[i] == k)
{
matched = true;
break;
}
}
if(!matched)
check_count++;
frame_rx[i] = 0;
}
uint32_t t0 = System::GetTick();
if(use_dma)
spiHandleRx.DmaReceive(frame_rx, PROC_SIZE, 0, 0, 0);
else
spiHandleRx.BlockingReceive(frame_rx, PROC_SIZE, 5000);
proc_time += System::GetTick() - t0;
proc_count++;
// Check for any input
if(usb_cb_count > 0)
{
usb_cb_buf[usb_cb_len] = 0;
if(usb_cb_buf[0] == 'd')
{
serial_on = !serial_on;
}
else if(usb_cb_buf[0] == 'm')
{
use_dma = !use_dma;
if(use_dma)
hw.Print("DMA ON\n");
else
hw.Print("DMA OFF\n");
}
else if(usb_cb_buf[0] == 'r')
{
my_init_spi(&spiHandleRx);
}
else
{
hw.Print("\td: toggle display on/off\n");
hw.Print("\tm: toggle DMA on/off\n");
hw.Print("\tr: Reset SPI\n");
if(use_dma)
hw.Print("\tDMA ON\n");
else
hw.Print("\tDMA OFF\n");
}
usb_cb_count = 0;
usb_cb_len = 0;
}
}
if(timed_one_sec)
{
timed_one_sec = false;
if(serial_on && proc_count)
hw.Print("PROC: %2d %6.3f %5d\n",
proc_count,
(float)proc_time / one_milli,
check_count);
proc_count = 0;
proc_time = 0;
check_count = 0;
hw.SetLed(led_state);
led_state = !led_state;
}
}
}