When the button on the LCD is pressed, the relevant screen is displayed and data (6000 bytes) must be saved. When the button is pressed, the screen is displayed without any problem, but a DMA error occurred in the process of writing data to the memory using SPI DMA.
DMA is applied to the disp_drv callback function, and it is also applied to writing in memory (SPI).
SPI DMA works fine if you disable the DMA used for LVGL.
Is there something wrong with the DMA settings?
[SPI_DMA error]
[error flag]
DMA2_HISR: FEIF4 (FIFO Error Interrupt Flag) set
SPI5_SR: OVR (Overrun Error Flag) set
[DMA Configurations]
DMA Configuration | LVGL | SPI5_TX |
---|---|---|
DMA Stream | DMA2_Stream0 | DMA2_Stream4 |
Channel | Channel 0 | Channel 2 |
Direction | Memory to memory | Memory to peripheral |
Peripheral increment | Enable | Disable |
Memory increment | Enable | Enable |
Periph data alignment | Half Word | Byte |
Memory data alignment | Half Word | Byte |
mode | Normal (not circular) | Normal (not circular) |
Stream Priority | Very High | High |
FIFO mode | Enable,1/4 threshold,single burst | Disable |
[tft_flush_cb]
static void tft_flush_cb(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_p)
{
// lv_disp_flush_ready(drv);
// return;
SCB_CleanInvalidateDCache();
/*Truncate the area to the screen*/
int32_t act_x1 = area->x1 < 0 ? 0 : area->x1;
int32_t act_y1 = area->y1 < 0 ? 0 : area->y1;
int32_t act_x2 = area->x2 > TFT_HOR_RES - 1 ? TFT_HOR_RES - 1 : area->x2;
int32_t act_y2 = area->y2 > TFT_HOR_RES - 1 ? TFT_HOR_RES - 1 : area->y2;
x1_flush = act_x1;
y1_flush = act_y1;
x2_flush = act_x2;
y2_flush = act_y2;
y_flush_act = act_y1;
buf_to_flush = color_p;
// int32_t x, y;
// for(y = area->y1; y <= area->y2; y++) {
// for(x = area->x1; x <= area->x2; x++) {
// lcd_fb[(y * TFT_HOR_RES) + x] = *color_p;
// color_p++;
// }
// }
// lv_disp_flush_ready(drv);
// ////---------------------------------------------------------------------
//
/*Use DMA instead of DMA2D to leave it free for GPU*/
HAL_StatusTypeDef err;
err = HAL_DMA_Start_IT(&hdma_memtomem_dma2_stream0,(uint32_t)buf_to_flush, (uint32_t)&lcd_fb[y_flush_act * TFT_HOR_RES + x1_flush],
(x2_flush - x1_flush + 1));
if(err != HAL_OK)
{
while(1); /*Halt on error*/
}
}
[write data to serial flash memory W25Q128]
void data_mgmt_task(void * argument)
{
uint32_t ulNotifiedValue = 0;
uint32_t ulNotifiedValue_bef = 0;
header.curr_param_addr = PARAM_OFFSET;
header.curr_menu_addr = MENU_OFFSET;
W25qxx_EraseBlock(PARAM_BLOCK_START);
W25qxx_EraseBlock(MENU_BLOCK_START);
while(true)
{
vTaskDelay(pdMS_TO_TICKS(10));
xTaskNotifyWait(0, 0, &ulNotifiedValue, pdMS_TO_TICKS(10));
if(ulNotifiedValue_bef != ulNotifiedValue)
{
ulNotifiedValue_bef = ulNotifiedValue;
W25qxx_WriteSector(HEADER_BUF, HEADER_SECTOR_START, HEADER_OFFSET, countof(HEADER_BUF));
W25qxx_WriteBlock(PARAM_BUF, PARAM_BLOCK_START, header.curr_param_addr, countof(PARAM_BUF));
W25qxx_WriteBlock(MENU_BUF, MENU_BLOCK_START, header.curr_menu_addr, countof(MENU_BUF));
// ......
}
}
}