Переход с AVR на светодиодную ленту управления ESP32 rto с использованием 1-контактного разъема и SPI/DMA

#esp32 #led #dma #esp-idf

Вопрос:

я работаю над старым проектом, основанным на AVR, который управляет светодиодной полосой, используя 1 вывод с высокой частотой SPI в DMA. (42 светодиода)

Я преобразую код в esp-idf, но я столкнулся с некоторой проблемой, вероятно, основанной на параметрах шины/конфигурации.

Это код:

AVR:

     USART_SPI_RGB_OPTIONS.baudrate = USART_SPI_RGB_BAUDRATE;
    USART_SPI_RGB_OPTIONS.spimode = USART_SPI_RGB_CHMODE;
    USART_SPI_RGB_OPTIONS.data_order = USART_SPI_RGB_DATA_ORDER;

    usart_init_spi(USART_SPI_RGB_PORT, amp;USART_SPI_RGB_OPTIONS);


void dma_init(void){
    struct dma_channel_config dmach_conf;
    memset(amp;dmach_conf, 0, sizeof(dmach_conf));
    dma_channel_set_burst_length(amp;dmach_conf, DMA_CH_BURSTLEN_1BYTE_gc);
    dma_channel_set_transfer_count(amp;dmach_conf, DMA_BUFFER_SIZE);
    dma_channel_set_src_reload_mode(amp;dmach_conf, DMA_CH_SRCRELOAD_TRANSACTION_gc);
    dma_channel_set_dest_reload_mode(amp;dmach_conf, DMA_CH_DESTRELOAD_NONE_gc);
    dma_channel_set_src_dir_mode(amp;dmach_conf, DMA_CH_SRCDIR_INC_gc);
    dma_channel_set_source_address(amp;dmach_conf, (uint16_t)(uintptr_t)RGBMemoryMap);
    dma_channel_set_dest_dir_mode(amp;dmach_conf, DMA_CH_DESTDIR_FIXED_gc);
    dma_channel_set_destination_address(amp;dmach_conf, (uint16_t)(uintptr_t)USART_SPI_RGB_PORT.DATA);
    dma_channel_set_trigger_source(amp;dmach_conf, DMA_CH_TRIGSRC_USARTD0_DRE_gc);
    dma_channel_set_single_shot(amp;dmach_conf);
    dma_enable();
    dma_channel_write_config(DMA_CHANNEL, amp;dmach_conf);
    dma_channel_enable(DMA_CHANNEL);
}
 

ESP-IDF:

 void initSPISettings()
{
    //memset(amp;SPI_settings, 0, sizeof(SPI_settings));
    SPI_settings.host = HSPI_HOST,
    SPI_settings.dma_chan = SPI_DMA_CH2;
    
    // buscfg
    SPI_settings.buscfg.flags = 0;
    SPI_settings.buscfg.miso_io_num = -1;
    SPI_settings.buscfg.mosi_io_num = GPIO_NUM_32;
    SPI_settings.buscfg.sclk_io_num = -1;
    SPI_settings.buscfg.quadwp_io_num = -1;
    SPI_settings.buscfg.quadhd_io_num = -1;
    SPI_settings.buscfg.max_transfer_sz = LED_DMA_BUFFER_SIZE;
    
    // devcfg
    SPI_settings.devcfg.clock_speed_hz = DMA_SPEED;
    SPI_settings.devcfg.dummy_bits = 0;
    SPI_settings.devcfg.mode = 0;
    SPI_settings.devcfg.flags = SPI_DEVICE_NO_DUMMY;
    SPI_settings.devcfg.spics_io_num = -1;
    SPI_settings.devcfg.queue_size = 1;
    SPI_settings.devcfg.command_bits = 0;
    SPI_settings.devcfg.address_bits = 0;
}
void initSPI()
{
    esp_err_t err;
    
    initSPISettings();
    
    err = spi_bus_initialize(SPI_settings.host, amp;SPI_settings.buscfg, SPI_settings.dma_chan);
    ESP_ERROR_CHECK(err);

    //Attach the Accel to the SPI bus
    err = spi_bus_add_device(SPI_settings.host, amp;SPI_settings.devcfg, amp;SPI_settings.spi);
    ESP_ERROR_CHECK(err);

}

void updateRGB()
{
    spi_transaction_t t;
    esp_err_t err;
    
    printf("Start transaction to DMA...rn");

//  for (int i = (LED_DMA_BUFFER_SIZE - LED_RESET_COUNT); i < LED_DMA_BUFFER_SIZE; i  ) {
//      //Setting more bytes to 0x00 at the end of memory map to assure correct RGB init
//      ledDMAbuffer[i] = 0x00; 
//  }

    t.flags = 0;
    t.length = LED_DMA_BUFFER_SIZE * 8;    //length is in bits
    t.tx_buffer = ledDMAbuffer;
    t.rx_buffer = NULL;
    t.rxlength = 0;
    
    err = spi_device_transmit(SPI_settings.spi, amp;t);
    ESP_ERROR_CHECK(err);
}

ledDMAbuffer = heap_caps_malloc(LED_DMA_BUFFER_SIZE, MALLOC_CAP_DMA);    // Critical to be DMA memory.
 

У тебя есть какие-нибудь идеи, чего мне не хватает?
Я заполняю данные правильно (я в этом уверен). Если я попытаюсь управлять 1 светодиодом, никаких проблем не возникнет, при увеличении количества управляемых светодиодов у меня будет странное поведение (например, когда 2 светодиода мигают красным/зеленым, первый работает правильно, а второй просто красный).

Thanks to all