I use the following code to communicate with a display:
void Display_HandleDC(spi_transaction_t* p_Transaction)
{
gpio_set_level((gpio_num_t)LCD_DC, (uint32_t)p_Transaction->user);
}
static void Display_SendCommand(const uint8_t Command)
{
spi_transaction_t t;
memset(&t, 0, sizeof(t));
t.length = 8;
t.tx_buffer = &Command;
t.user=(void*)0;
assert(spi_device_polling_transmit(_SPI, &t) == ESP_OK);
}
static void Display_SendData(const uint8_t* p_Data, uint32_t Length)
{
spi_transaction_t t;
if(Length == 0)
{
return;
}
memset(&t, 0, sizeof(t));
t.length = Length * 8;
t.tx_buffer = p_Data;
t.user=(void*)1;
assert(spi_device_polling_transmit(_SPI, &t) == ESP_OK);
}
static uint32_t Display_ReadID(void)
{
spi_transaction_t t;
Display_SendCommand(0x04);
memset(&t, 0, sizeof(t));
t.length = 4 * 8;
t.flags = SPI_TRANS_USE_RXDATA;
t.user = (void*)1;
assert(spi_device_polling_transmit(_SPI, &t) == ESP_OK);
return *(uint32_t*)t.rx_data;
}
static void Display_Write(int ypos, uint16_t *linedata)
{
static spi_transaction_t trans[6];
for(uint8_t x=0; x<6; x++)
{
memset(&trans[x], 0, sizeof(spi_transaction_t));
if ((x&1)==0) {
//Even transfers are commands
trans[x].length=8;
trans[x].user=(void*)0;
} else {
//Odd transfers are data
trans[x].length=8*4;
trans[x].user=(void*)1;
}
trans[x].flags = SPI_TRANS_USE_TXDATA;
}
trans[0].tx_data[0] = 0x2A;
trans[1].tx_data[0] = 0;
trans[1].tx_data[1] = 0;
trans[1].tx_data[2] = 320 >> 8;
trans[1].tx_data[3] = 320 & 0xFF;
trans[2].tx_data[0] = 0x2B;
trans[3].tx_data[0] = ypos >> 8;
trans[3].tx_data[1] = ypos & 0xFF;
trans[3].tx_data[2] = (ypos + 1) >> 8;
trans[3].tx_data[3] = (ypos + 1) & 0xFF;
// Write the data to memory
trans[4].tx_data[0] = 0x2C;
trans[5].tx_buffer = linedata;
trans[5].length = 320 * sizeof(uint16_t) * 8;
trans[5].flags = 0x00;
for(uint8_t x = 0; x<6; x++)
{
assert(spi_device_queue_trans(_SPI, &trans[x], portMAX_DELAY) == ESP_OK);
}
}
static void Display_Busy(void)
{
spi_transaction_t* rtrans;
for(uint8_t x=0; x<6; x++)
{
assert(spi_device_get_trans_result(_SPI, &rtrans, portMAX_DELAY) == ESP_OK);
}
}
esp_err_t Display_Init(void)
{
static uint16_t* Line;
gpio_set_direction((gpio_num_t)LCD_DC, GPIO_MODE_OUTPUT);
gpio_set_direction((gpio_num_t)LDC_RESET, GPIO_MODE_OUTPUT);
gpio_set_direction((gpio_num_t)LCD_BACKLIGHT, GPIO_MODE_OUTPUT);
if((spi_bus_initialize(HSPI_HOST, &_BusCfg, 0) != ESP_OK) || (spi_bus_add_device(HSPI_HOST, &_DevDcfg, &_SPI) != ESP_OK))
{
return ESP_FAIL;
}
Display_Reset();
ESP_LOGI(TAG, "ID: %08X", Display_ReadID());
uint32_t Commands = sizeof(_Init_Cmd_List) / sizeof(_Init_Cmd_List[0]);
ESP_LOGI(TAG, "Loading initialization commands: %u", Commands);
for(uint32_t i = 0x00; i < Commands; i++)
{
ESP_LOGI(TAG, " Command %u / %u", i + 1, Commands);
Display_SendCommand(_Init_Cmd_List[i].Command);
Display_SendData(_Init_Cmd_List[i].Data, _Init_Cmd_List[i].Length & 0x1F);
if(_Init_Cmd_List[i].Length & 0x80)
{
vTaskDelay(100 / portTICK_RATE_MS);
}
}
Line = (uint16_t*)heap_caps_malloc(320 * sizeof(uint16_t), MALLOC_CAP_DMA);
if(Line == NULL)
{
return ESP_FAIL;
}
for(uint32_t i = 0x00; i < 320; i++)
{
Line[i] = 0xF8;
}
Display_Write(0, Line);
Display_Busy();
free(Line);
return ESP_OK;
}
And this code results in the following error message:
E (1833) spi_master: check_trans_valid(801): txdata transfer > host maximum
assertion "spi_device_queue_trans(_SPI, &trans[x], portMAX_DELAY) == ESP_OK" failed: file "src/Peripherals/Display/display.cpp", line 225, function: void Display_Write(int, uint16_t*)
abort() was called at PC 0x400e47a4 on core 1
ELF file SHA256: bc86d952445723b2
Backtrace: 0x4008e8c0:0x3ffb4b30 0x4008ecb9:0x3ffb4b50 0x400e47a4:0x3ffb4b70 0x400d170d:0x3ffb4ba0 0x400d1873:0x3ffb4bc0 0x400d13ea:0x3ffb4bf0 0x400d194b:0x3ffb4c20 0x40088601:0x3ffb4c40
#0 0x4008e8c0:0x3ffb4b30 in invoke_abort at .platformio\packages\[email protected]\components\esp32/panic.c:155
#1 0x4008ecb9:0x3ffb4b50 in abort at .platformio\packages\[email protected]\components\esp32/panic.c:172
#2 0x400e47a4:0x3ffb4b70 in __assert_func at /builds/idf/crosstool-NG/.build/HOST-i686-w64-mingw32/xtensa-esp32-elf/src/newlib/newlib/libc/stdlib/assert.c:62 (discriminator 8)
#3 0x400d170d:0x3ffb4ba0 in Display_Write(int, unsigned short*) at src/Peripherals/Display/display.cpp:225 (discriminator 1)
#4 0x400d1873:0x3ffb4bc0 in Display_Init() at src/Peripherals/Display/display.cpp:288
#5 0x400d13ea:0x3ffb4bf0 in setup() at src/Application/application.cpp:21
#6 0x400d194b:0x3ffb4c20 in applicationTask(void*) at src/main.cpp:41
#7 0x40088601:0x3ffb4c40 in vPortTaskWrapper at .platformio\packages\[email protected]\components\freertos/port.c:143
But the error doesn´t occur when I change the DMA channel from 0
to 1
:
if((spi_bus_initialize(HSPI_HOST, &_BusCfg, 1) != ESP_OK) || (spi_bus_add_device(HSPI_HOST, &_DevDcfg, &_SPI) != ESP_OK))
{
return ESP_FAIL;
}
What´s the difference between both channels and why is only channel 1
working?