SPI slave speed problem
Posted: Sun Feb 13, 2022 8:07 pm
Hello group
I'm hoping to solve this SPI slave problem. I've tried with esp-idf coding and Arduino coding.
Scenario: To simplify, I have a SPI "black-box" master that sends me 2 blocks of 5 bytes (Trace 1).
I read the first block but never the second.
As I see it, I think the ~ 3nS pulse on the slave CS line (Trace 4 on the scope), in the middle of the two "5-Byte" blocks, is the problem.
I thought my best bet would be to have the slave.queue/slave.yield commands in their own task for speed but it hasn't solved the problem.
The replies are all the first block, never the second.
Thanks in advance for your suggestions.
Test Code:
#include <Arduino.h>
#include <sys/types.h>
#include <SPI.h>
#include "ESP32DMASPISlave.h"
#define HSPI_MISO -1
#define HSPI_MOSI 11
#define HSPI_SCLK 12
#define HSPI_SS 10
#define MSG5_SIZE 5U
ESP32DMASPI::Slave slave;
uint16_t ResultsHex[80] = {0};
uint8_t *slave_buffer1;
uint8_t *slave_buffer2;
constexpr uint8_t CORE_TASK_SPI_SLAVE {0};
constexpr uint8_t CORE_TASK_PROCESS_BUFFER {0};
static TaskHandle_t task_handle_wait_spi = 0;
static TaskHandle_t task_handle_process_buffer = 0;
void dump_buf(const char* title, uint8_t* buf, uint8_t len) {
printf("%4s[%2d]: ", title, len);
for (uint8_t i = 0; i < len; i++)
printf("%02X ", buf);
}
void task_wait_spi(void* pvParameters) {
while (1) {
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
slave.yield();
if (slave.remained() == 0) {
slave.queue(slave_buffer1, NULL, MSG5_SIZE);
slave.yield();
}
// delayMicroseconds(11);
xTaskNotifyGive(task_handle_process_buffer);
}
}
// int i;
void task_process_buffer(void* pvParameters) {
while (1) {
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
// printf("Avail %u, size %u\n", slave.available(), slave.size());
slave.queue(slave_buffer2, NULL, MSG5_SIZE);
xTaskNotifyGive(task_handle_wait_spi);
}
}
void setup() {
Serial.begin(115200); while (!Serial) {} ;
printf("\n* * * * * * * * * * * * * * * * * * * *\n");
printf("%s - SLAVE ", __FILE__);
printf("* * * * * * * * * * * * * * * * * * * *\n");
// pinMode(INT_PIN, INPUT_PULLUP);
pinMode(HSPI_SCLK, INPUT_PULLUP);
pinMode(HSPI_MOSI, INPUT_PULLUP);
pinMode(HSPI_SS, INPUT_PULLUP);
delay(2000);
// attachInterrupt(digitalPinToInterrupt(INT_PIN), blink, RISING);
slave_buffer1 = (uint8_t*)heap_caps_calloc(MSG5_SIZE, 1, MALLOC_CAP_DMA);
slave_buffer2 = (uint8_t*)heap_caps_calloc(MSG5_SIZE, 1, MALLOC_CAP_DMA);
memset(slave_buffer1, 0x0, MSG5_SIZE);
delay(1);
slave.setDataMode(SPI_MODE1);
slave.setMaxTransferSize(1024);
slave.setDMAChannel(2); // Auto
slave.setQueueSize(80); // transaction queue size
slave.begin(HSPI, HSPI_SCLK, HSPI_MISO, HSPI_MOSI, HSPI_SS); //SCLK, MISO, MOSI, SS
xTaskCreatePinnedToCore(task_wait_spi, "task_wait_spi", 10000, NULL, 2, &task_handle_wait_spi, CORE_TASK_SPI_SLAVE);
delay(1);
xTaskCreatePinnedToCore(task_process_buffer, "task_process_buffer", 10000, NULL, 2, &task_handle_process_buffer, CORE_TASK_PROCESS_BUFFER);
delay(1);
xTaskNotifyGive(task_handle_wait_spi);
delay(1);
}
void loop() {
dump_buf("Rx1: ", slave_buffer1, MSG5_SIZE);
dump_buf("Rx2: ", slave_buffer2, MSG5_SIZE);
printf("\n");
delay(1);
}
I'm hoping to solve this SPI slave problem. I've tried with esp-idf coding and Arduino coding.
Scenario: To simplify, I have a SPI "black-box" master that sends me 2 blocks of 5 bytes (Trace 1).
I read the first block but never the second.
As I see it, I think the ~ 3nS pulse on the slave CS line (Trace 4 on the scope), in the middle of the two "5-Byte" blocks, is the problem.
I thought my best bet would be to have the slave.queue/slave.yield commands in their own task for speed but it hasn't solved the problem.
The replies are all the first block, never the second.
Thanks in advance for your suggestions.
Test Code:
#include <Arduino.h>
#include <sys/types.h>
#include <SPI.h>
#include "ESP32DMASPISlave.h"
#define HSPI_MISO -1
#define HSPI_MOSI 11
#define HSPI_SCLK 12
#define HSPI_SS 10
#define MSG5_SIZE 5U
ESP32DMASPI::Slave slave;
uint16_t ResultsHex[80] = {0};
uint8_t *slave_buffer1;
uint8_t *slave_buffer2;
constexpr uint8_t CORE_TASK_SPI_SLAVE {0};
constexpr uint8_t CORE_TASK_PROCESS_BUFFER {0};
static TaskHandle_t task_handle_wait_spi = 0;
static TaskHandle_t task_handle_process_buffer = 0;
void dump_buf(const char* title, uint8_t* buf, uint8_t len) {
printf("%4s[%2d]: ", title, len);
for (uint8_t i = 0; i < len; i++)
printf("%02X ", buf);
}
void task_wait_spi(void* pvParameters) {
while (1) {
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
slave.yield();
if (slave.remained() == 0) {
slave.queue(slave_buffer1, NULL, MSG5_SIZE);
slave.yield();
}
// delayMicroseconds(11);
xTaskNotifyGive(task_handle_process_buffer);
}
}
// int i;
void task_process_buffer(void* pvParameters) {
while (1) {
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
// printf("Avail %u, size %u\n", slave.available(), slave.size());
slave.queue(slave_buffer2, NULL, MSG5_SIZE);
xTaskNotifyGive(task_handle_wait_spi);
}
}
void setup() {
Serial.begin(115200); while (!Serial) {} ;
printf("\n* * * * * * * * * * * * * * * * * * * *\n");
printf("%s - SLAVE ", __FILE__);
printf("* * * * * * * * * * * * * * * * * * * *\n");
// pinMode(INT_PIN, INPUT_PULLUP);
pinMode(HSPI_SCLK, INPUT_PULLUP);
pinMode(HSPI_MOSI, INPUT_PULLUP);
pinMode(HSPI_SS, INPUT_PULLUP);
delay(2000);
// attachInterrupt(digitalPinToInterrupt(INT_PIN), blink, RISING);
slave_buffer1 = (uint8_t*)heap_caps_calloc(MSG5_SIZE, 1, MALLOC_CAP_DMA);
slave_buffer2 = (uint8_t*)heap_caps_calloc(MSG5_SIZE, 1, MALLOC_CAP_DMA);
memset(slave_buffer1, 0x0, MSG5_SIZE);
delay(1);
slave.setDataMode(SPI_MODE1);
slave.setMaxTransferSize(1024);
slave.setDMAChannel(2); // Auto
slave.setQueueSize(80); // transaction queue size
slave.begin(HSPI, HSPI_SCLK, HSPI_MISO, HSPI_MOSI, HSPI_SS); //SCLK, MISO, MOSI, SS
xTaskCreatePinnedToCore(task_wait_spi, "task_wait_spi", 10000, NULL, 2, &task_handle_wait_spi, CORE_TASK_SPI_SLAVE);
delay(1);
xTaskCreatePinnedToCore(task_process_buffer, "task_process_buffer", 10000, NULL, 2, &task_handle_process_buffer, CORE_TASK_PROCESS_BUFFER);
delay(1);
xTaskNotifyGive(task_handle_wait_spi);
delay(1);
}
void loop() {
dump_buf("Rx1: ", slave_buffer1, MSG5_SIZE);
dump_buf("Rx2: ", slave_buffer2, MSG5_SIZE);
printf("\n");
delay(1);
}