ESP_Sprite wrote: ↑Fri Dec 24, 2021 1:33 am
Looked it up... the reason you can't put more into the L1FIFO is that it's tiny: only 24 bytes (which I assume is organized in 3 words). I'm not sure why data doesn't get pulled through to l2/l3fifo (especially l2fifo is larger at 128 bytes), perhaps that mechanism only starts when the peripheral starts a transaction.
EDIT: Never mind, I see that push operations only push 8 bit into the FIFO. Hmm, then I can't really explain the l1fifo behaviour you're seeing... will ask to see if the digital team knows more. By the way, it's likely that the bus between l1fifo and l2fifo is larger than 8 bit, so you'd expect the l1fifo to only empty into the l2fifo once the l2fifo collected 32 or maybe even 64 bit. You are sure the fill numbers there do not change even if you put >8 bytes into the l1fifo?
Hi @ESP_Sprite,
My observations (i don't know if they are correct or not):
L1 only transfer to L2 when L1 have 8 bytes.
L1 count unit is byte ( GDMA.channel[channel].out.outfifo_status.outfifo_cnt_l1 = 1 is equal to 1 byte )
L2 count unit is 8 byte ( GDMA.channel[channel].out.outfifo_status.outfifo_cnt_l2 = 1 is equal to 8 bytes )
L3 count uint is byte ( GDMA.channel[channel].out.outfifo_status.outfifo_cnt_l3 = 1 is equal to 1 byte )
Esp32-s3 technical reference manual: Pre-release v0.3, page 108
GDMA_OUTFIFO_CNT_L1_CHn The register stores the byte number of the data in L1 TX FIFO for TX channel 0. (RO)
GDMA_OUTFIFO_CNT_L2_CHn The register stores the byte number of the data in L2 TX FIFO for TX channel 0. (RO)
GDMA_OUTFIFO_CNT_L3_CHn The register stores the byte number of the data in L3 TX FIFO for TX channel 0. (RO)
Esp32-s3 technical reference manual: Pre-release v0.3, page 78
L1FIFO, L2FIFO and L3FIFO have fixed depth: 24, 128, and 16 bytes, respectively.
L1 size = 16 bytes
L2 size = 80 bytes
L3 size = 16 bytes
// gdma_struct.h
GDMA.sram_size[channel].out.out_size = 8; // This register is used to configure the size of L2 Tx FIFO for Tx channel 0.
// 0:16 bytes. 1:24 bytes. 2:32 bytes. 3: 40 bytes. 4: 48 bytes. 5:56 bytes. 6: 64 bytes. 7: 72 bytes. 8: 80 bytes.
All multiples of 8: ( relevant or not?! )
0: 16 bytes = 2*8
1: 24 bytes = 3*8
2: 32 bytes = 4*8
3: 40 bytes = 5*8
4: 48 bytes = 6*8
5: 56 bytes = 7*8
6: 64 bytes = 8*8
7: 72 bytes = 9*8
8: 80 bytes = 10*8
Code: Select all
void app_main(void)
{
esp_err_t r = hw_lcd_init();
printf("r = %s\n\n", esp_err_to_name(r));
uint8_t data[32];
data[0] = 0x01;
data[1] = 0x02;
data[2] = 0x04;
data[3] = 0x08;
data[4] = 0x10;
data[5] = 0x20;
data[6] = 0x40;
data[7] = 0x80;
data[8] = 0x11;
data[9] = 0x22;
while(1)
{
hw_lcd_write_n_data( 0x02, data, 10 );
vTaskDelay( pdMS_TO_TICKS(1000) );
}
}
inline void hw_lcd_write_n_data( uint32_t command, uint8_t* data, uint32_t data_len )
{
LCD_CAM.lcd_user.lcd_dout_cyclelen = data_len - 1; // 0 = 1 single byte. LCD_CAM.lcd_user.lcd_always_out_en = 0;
LCD_CAM.lcd_user.lcd_cmd = 1;
LCD_CAM.lcd_user.lcd_dout = 1;
LCD_CAM.lcd_cmd_val.lcd_cmd_value = command;
hw_lcd_dma_tx_push_n_data( 0, data, data_len );
// LCD_CAM.lcd_user.lcd_update = 1;
// LCD_CAM.lcd_user.lcd_start = 1;
}
inline void hw_lcd_dma_tx_push_n_data( uint32_t channel, uint8_t* data, uint32_t data_len )
{
printf("\x1b[31m"); // Red text
printf("dma tx idle: %s\n", hw_lcd_dma_tx_idle(0) ? "IDLE" : "BUSY" );
printf("L1_fifo: %s\n", hw_lcd_dma_L1_fifo_empty(0) ? "EMPTY" : "NOT_EMPTY" );
printf("L1_fifo: %s\n", hw_lcd_dma_L1_fifo_full(0) ? "FULL" : "NOT_FULL" );
printf("L1_count: %u\n\n", hw_lcd_dma_L1_fifo_count(0) );
printf("L2_fifo: %s\n", hw_lcd_dma_L2_fifo_empty(0) ? "EMPTY" : "NOT_EMPTY" );
printf("L2_fifo: %s\n", hw_lcd_dma_L2_fifo_full(0) ? "FULL" : "NOT_FULL" );
printf("L2_count: %u\n\n", hw_lcd_dma_L2_fifo_count(0) );
printf("L3_fifo: %s\n", hw_lcd_dma_L3_fifo_empty(0) ? "EMPTY" : "NOT_EMPTY" );
printf("L3_fifo: %s\n", hw_lcd_dma_L3_fifo_full(0) ? "FULL" : "NOT_FULL" );
printf("L3_count: %u\n\n", hw_lcd_dma_L3_fifo_count(0) );
printf("ovf_l1: %s\n", GDMA.channel[channel].out.int_raw.outfifo_ovf_l1 ? "OVERFLOW" : "NOT_OVERFLOW" );
printf("ovf_l3: %s\n", GDMA.channel[channel].out.int_raw.outfifo_ovf_l3 ? "OVERFLOW" : "NOT_OVERFLOW" );
printf("udf_l1: %s\n", GDMA.channel[channel].out.int_raw.outfifo_udf_l1 ? "UNDERLOW" : "NOT_UNDERFLOW" );
printf("udf_l3: %s\n\n\n", GDMA.channel[channel].out.int_raw.outfifo_udf_l3 ? "UNDERLOW" : "NOT_UNDERFLOW" );
uint32_t t;
bool s = 0;
for( uint32_t i = 0 ; i < data_len ; i++ )
{
// while( hw_lcd_dma_L1_fifo_full(channel) );
t = 0;
while( hw_lcd_dma_L1_fifo_full(channel) )
{
t++;
if( t == 1000 )
{
s = 1;
goto stop;
}
}
GDMA.channel[channel].out.push.outfifo_wdata = data[i];
GDMA.channel[channel].out.push.outfifo_push = 1;
}
stop:
printf("\x1b[34m"); // blue text
printf("dma tx idle: %s\n", hw_lcd_dma_tx_idle(0) ? "IDLE" : "BUSY" );
printf("L1_fifo: %s\n", hw_lcd_dma_L1_fifo_empty(0) ? "EMPTY" : "NOT_EMPTY" );
printf("L1_fifo: %s\n", hw_lcd_dma_L1_fifo_full(0) ? "FULL" : "NOT_FULL" );
printf("L1_count: %u\n\n", hw_lcd_dma_L1_fifo_count(0) );
printf("L2_fifo: %s\n", hw_lcd_dma_L2_fifo_empty(0) ? "EMPTY" : "NOT_EMPTY" );
printf("L2_fifo: %s\n", hw_lcd_dma_L2_fifo_full(0) ? "FULL" : "NOT_FULL" );
printf("L2_count: %u\n\n", hw_lcd_dma_L2_fifo_count(0) );
printf("L3_fifo: %s\n", hw_lcd_dma_L3_fifo_empty(0) ? "EMPTY" : "NOT_EMPTY" );
printf("L3_fifo: %s\n", hw_lcd_dma_L3_fifo_full(0) ? "FULL" : "NOT_FULL" );
printf("L3_count: %u\n\n", hw_lcd_dma_L3_fifo_count(0) );
printf("ovf_l1: %s\n", GDMA.channel[channel].out.int_raw.outfifo_ovf_l1 ? "OVERFLOW" : "NOT_OVERFLOW" );
printf("ovf_l3: %s\n", GDMA.channel[channel].out.int_raw.outfifo_ovf_l3 ? "OVERFLOW" : "NOT_OVERFLOW" );
printf("udf_l1: %s\n", GDMA.channel[channel].out.int_raw.outfifo_udf_l1 ? "UNDERLOW" : "NOT_UNDERFLOW" );
printf("udf_l3: %s\n\n\n", GDMA.channel[channel].out.int_raw.outfifo_udf_l3 ? "UNDERLOW" : "NOT_UNDERFLOW" );
if( s )
while(1);
}
ESP-IDF MONITOR:
Code: Select all
I (688) HW_LCD_DMA: GDMA HW Version: 0x02101180
I (695) HW_LCD: HW_LCD Information:
I (700) HW_LCD: LCD_CAM HW Version: 33566752
I (705) HW_LCD: HW_LCD_FREQ_HZ = 20 MHz
I (711) HW_LCD: WR io num = 4
I (716) HW_LCD: DC io num = 5
I (720) HW_LCD: CS io num = 6
I (725) HW_LCD: HW_LCD BUS Data Width = 8
I (730) HW_LCD: Data[0] = 7
I (735) HW_LCD: Data[1] = 15
I (739) HW_LCD: Data[2] = 16
I (744) HW_LCD: Data[3] = 17
I (748) HW_LCD: Data[4] = 18
I (753) HW_LCD: Data[5] = 8
I (757) HW_LCD: Data[6] = 3
I (762) HW_LCD: Data[7] = 46
r = ESP_OK
dma tx idle: IDLE
L1_fifo: EMPTY
L1_fifo: NOT_FULL
L1_count: 0
L2_fifo: EMPTY
L2_fifo: NOT_FULL
L2_count: 0
L3_fifo: EMPTY
L3_fifo: NOT_FULL
L3_count: 0
ovf_l1: NOT_OVERFLOW
ovf_l3: NOT_OVERFLOW
udf_l1: NOT_UNDERFLOW
udf_l3: NOT_UNDERFLOW
dma tx idle: IDLE
L1_fifo: NOT_EMPTY
L1_fifo: NOT_FULL
L1_count: 2
L2_fifo: EMPTY
L2_fifo: NOT_FULL
L2_count: 0
L3_fifo: NOT_EMPTY
L3_fifo: NOT_FULL
L3_count: 8
ovf_l1: NOT_OVERFLOW
ovf_l3: NOT_OVERFLOW
udf_l1: NOT_UNDERFLOW
udf_l3: NOT_UNDERFLOW
dma tx idle: IDLE
L1_fifo: NOT_EMPTY
L1_fifo: NOT_FULL
L1_count: 2
L2_fifo: EMPTY
L2_fifo: NOT_FULL
L2_count: 0
L3_fifo: NOT_EMPTY
L3_fifo: NOT_FULL
L3_count: 8
ovf_l1: NOT_OVERFLOW
ovf_l3: NOT_OVERFLOW
udf_l1: NOT_UNDERFLOW
udf_l3: NOT_UNDERFLOW
dma tx idle: IDLE
L1_fifo: NOT_EMPTY
L1_fifo: NOT_FULL
L1_count: 4
L2_fifo: EMPTY
L2_fifo: NOT_FULL
L2_count: 0
L3_fifo: NOT_EMPTY
L3_fifo: FULL
L3_count: 16
ovf_l1: NOT_OVERFLOW
ovf_l3: NOT_OVERFLOW
udf_l1: NOT_UNDERFLOW
udf_l3: NOT_UNDERFLOW
dma tx idle: IDLE
L1_fifo: NOT_EMPTY
L1_fifo: NOT_FULL
L1_count: 4
L2_fifo: EMPTY
L2_fifo: NOT_FULL
L2_count: 0
L3_fifo: NOT_EMPTY
L3_fifo: FULL
L3_count: 16
ovf_l1: NOT_OVERFLOW
ovf_l3: NOT_OVERFLOW
udf_l1: NOT_UNDERFLOW
udf_l3: NOT_UNDERFLOW
dma tx idle: IDLE
L1_fifo: NOT_EMPTY
L1_fifo: NOT_FULL
L1_count: 6
L2_fifo: NOT_EMPTY
L2_fifo: NOT_FULL
L2_count: 1
L3_fifo: NOT_EMPTY
L3_fifo: FULL
L3_count: 16
ovf_l1: NOT_OVERFLOW
ovf_l3: NOT_OVERFLOW
udf_l1: NOT_UNDERFLOW
udf_l3: NOT_UNDERFLOW
dma tx idle: IDLE
L1_fifo: NOT_EMPTY
L1_fifo: NOT_FULL
L1_count: 6
L2_fifo: NOT_EMPTY
L2_fifo: NOT_FULL
L2_count: 1
L3_fifo: NOT_EMPTY
L3_fifo: FULL
L3_count: 16
ovf_l1: NOT_OVERFLOW
ovf_l3: NOT_OVERFLOW
udf_l1: NOT_UNDERFLOW
udf_l3: NOT_UNDERFLOW
dma tx idle: IDLE
L1_fifo: EMPTY
L1_fifo: NOT_FULL
L1_count: 0
L2_fifo: NOT_EMPTY
L2_fifo: NOT_FULL
L2_count: 3
L3_fifo: NOT_EMPTY
L3_fifo: FULL
L3_count: 16
ovf_l1: NOT_OVERFLOW
ovf_l3: NOT_OVERFLOW
udf_l1: NOT_UNDERFLOW
udf_l3: NOT_UNDERFLOW
dma tx idle: IDLE
L1_fifo: EMPTY
L1_fifo: NOT_FULL
L1_count: 0
L2_fifo: NOT_EMPTY
L2_fifo: NOT_FULL
L2_count: 3
L3_fifo: NOT_EMPTY
L3_fifo: FULL
L3_count: 16
ovf_l1: NOT_OVERFLOW
ovf_l3: NOT_OVERFLOW
udf_l1: NOT_UNDERFLOW
udf_l3: NOT_UNDERFLOW
dma tx idle: IDLE
L1_fifo: NOT_EMPTY
L1_fifo: NOT_FULL
L1_count: 2
L2_fifo: NOT_EMPTY
L2_fifo: NOT_FULL
L2_count: 4
L3_fifo: NOT_EMPTY
L3_fifo: FULL
L3_count: 16
ovf_l1: NOT_OVERFLOW
ovf_l3: NOT_OVERFLOW
udf_l1: NOT_UNDERFLOW
udf_l3: NOT_UNDERFLOW
dma tx idle: IDLE
L1_fifo: NOT_EMPTY
L1_fifo: NOT_FULL
L1_count: 2
L2_fifo: NOT_EMPTY
L2_fifo: NOT_FULL
L2_count: 4
L3_fifo: NOT_EMPTY
L3_fifo: FULL
L3_count: 16
ovf_l1: NOT_OVERFLOW
ovf_l3: NOT_OVERFLOW
udf_l1: NOT_UNDERFLOW
udf_l3: NOT_UNDERFLOW
dma tx idle: IDLE
L1_fifo: NOT_EMPTY
L1_fifo: NOT_FULL
L1_count: 4
L2_fifo: NOT_EMPTY
L2_fifo: NOT_FULL
L2_count: 5
L3_fifo: NOT_EMPTY
L3_fifo: FULL
L3_count: 16
ovf_l1: NOT_OVERFLOW
ovf_l3: NOT_OVERFLOW
udf_l1: NOT_UNDERFLOW
udf_l3: NOT_UNDERFLOW
dma tx idle: IDLE
L1_fifo: NOT_EMPTY
L1_fifo: NOT_FULL
L1_count: 4
L2_fifo: NOT_EMPTY
L2_fifo: NOT_FULL
L2_count: 5
L3_fifo: NOT_EMPTY
L3_fifo: FULL
L3_count: 16
ovf_l1: NOT_OVERFLOW
ovf_l3: NOT_OVERFLOW
udf_l1: NOT_UNDERFLOW
udf_l3: NOT_UNDERFLOW
dma tx idle: IDLE
L1_fifo: NOT_EMPTY
L1_fifo: NOT_FULL
L1_count: 6
L2_fifo: NOT_EMPTY
L2_fifo: NOT_FULL
L2_count: 6
L3_fifo: NOT_EMPTY
L3_fifo: FULL
L3_count: 16
ovf_l1: NOT_OVERFLOW
ovf_l3: NOT_OVERFLOW
udf_l1: NOT_UNDERFLOW
udf_l3: NOT_UNDERFLOW
dma tx idle: IDLE
L1_fifo: NOT_EMPTY
L1_fifo: NOT_FULL
L1_count: 6
L2_fifo: NOT_EMPTY
L2_fifo: NOT_FULL
L2_count: 6
L3_fifo: NOT_EMPTY
L3_fifo: FULL
L3_count: 16
ovf_l1: NOT_OVERFLOW
ovf_l3: NOT_OVERFLOW
udf_l1: NOT_UNDERFLOW
udf_l3: NOT_UNDERFLOW
dma tx idle: IDLE
L1_fifo: EMPTY
L1_fifo: NOT_FULL
L1_count: 0
L2_fifo: NOT_EMPTY
L2_fifo: NOT_FULL
L2_count: 8
L3_fifo: NOT_EMPTY
L3_fifo: FULL
L3_count: 16
ovf_l1: NOT_OVERFLOW
ovf_l3: NOT_OVERFLOW
udf_l1: NOT_UNDERFLOW
udf_l3: NOT_UNDERFLOW
dma tx idle: IDLE
L1_fifo: EMPTY
L1_fifo: NOT_FULL
L1_count: 0
L2_fifo: NOT_EMPTY
L2_fifo: NOT_FULL
L2_count: 8
L3_fifo: NOT_EMPTY
L3_fifo: FULL
L3_count: 16
ovf_l1: NOT_OVERFLOW
ovf_l3: NOT_OVERFLOW
udf_l1: NOT_UNDERFLOW
udf_l3: NOT_UNDERFLOW
dma tx idle: IDLE
L1_fifo: NOT_EMPTY
L1_fifo: NOT_FULL
L1_count: 2
L2_fifo: NOT_EMPTY
L2_fifo: NOT_FULL
L2_count: 9
L3_fifo: NOT_EMPTY
L3_fifo: FULL
L3_count: 16
ovf_l1: NOT_OVERFLOW
ovf_l3: NOT_OVERFLOW
udf_l1: NOT_UNDERFLOW
udf_l3: NOT_UNDERFLOW
dma tx idle: IDLE
L1_fifo: NOT_EMPTY
L1_fifo: NOT_FULL
L1_count: 2
L2_fifo: NOT_EMPTY
L2_fifo: NOT_FULL
L2_count: 9
L3_fifo: NOT_EMPTY
L3_fifo: FULL
L3_count: 16
ovf_l1: NOT_OVERFLOW
ovf_l3: NOT_OVERFLOW
udf_l1: NOT_UNDERFLOW
udf_l3: NOT_UNDERFLOW
dma tx idle: IDLE
L1_fifo: NOT_EMPTY
L1_fifo: NOT_FULL
L1_count: 4
L2_fifo: NOT_EMPTY
L2_fifo: FULL
L2_count: 10
L3_fifo: NOT_EMPTY
L3_fifo: FULL
L3_count: 16
ovf_l1: NOT_OVERFLOW
ovf_l3: NOT_OVERFLOW
udf_l1: NOT_UNDERFLOW
udf_l3: NOT_UNDERFLOW
dma tx idle: IDLE
L1_fifo: NOT_EMPTY
L1_fifo: NOT_FULL
L1_count: 4
L2_fifo: NOT_EMPTY
L2_fifo: FULL
L2_count: 10
L3_fifo: NOT_EMPTY
L3_fifo: FULL
L3_count: 16
ovf_l1: NOT_OVERFLOW
ovf_l3: NOT_OVERFLOW
udf_l1: NOT_UNDERFLOW
udf_l3: NOT_UNDERFLOW
dma tx idle: IDLE
L1_fifo: NOT_EMPTY
L1_fifo: NOT_FULL
L1_count: 14
L2_fifo: NOT_EMPTY
L2_fifo: FULL
L2_count: 10
L3_fifo: NOT_EMPTY
L3_fifo: FULL
L3_count: 16
ovf_l1: NOT_OVERFLOW
ovf_l3: NOT_OVERFLOW
udf_l1: NOT_UNDERFLOW
udf_l3: NOT_UNDERFLOW
dma tx idle: IDLE
L1_fifo: NOT_EMPTY
L1_fifo: NOT_FULL
L1_count: 14
L2_fifo: NOT_EMPTY
L2_fifo: FULL
L2_count: 10
L3_fifo: NOT_EMPTY
L3_fifo: FULL
L3_count: 16
ovf_l1: NOT_OVERFLOW
ovf_l3: NOT_OVERFLOW
udf_l1: NOT_UNDERFLOW
udf_l3: NOT_UNDERFLOW
dma tx idle: IDLE
L1_fifo: NOT_EMPTY
L1_fifo: FULL
L1_count: 16
L2_fifo: NOT_EMPTY
L2_fifo: FULL
L2_count: 10
L3_fifo: NOT_EMPTY
L3_fifo: FULL
L3_count: 16
ovf_l1: NOT_OVERFLOW
ovf_l3: NOT_OVERFLOW
udf_l1: NOT_UNDERFLOW
udf_l3: NOT_UNDERFLOW
E (17174) task_wdt: Task watchdog got triggered. The following tasks did not reset the watchdog in time:
E (17174) task_wdt: - IDLE (CPU 0)
E (17174) task_wdt: Tasks currently running:
E (17174) task_wdt: CPU 0: main
E (17174) task_wdt: CPU 1: IDLE
E (17174) task_wdt: Print CPU 0 (current core) backtrace
Backtrace:0x42008686:0x3FC95F400x4037A78A:0x3FC95F60 0x42005F7C:0x3FCF48C0 0x42005969:0x3FCF48E0 0x420054F5:0x3FCF4900 0x420179A1:0x3FCF4940 0x4037FEF1:0x3FCF4960
0x42008686: task_wdt_isr at C:/esp-idf/components/esp_system/task_wdt.c:183 (discriminator 3)
0x4037a78a: _xt_lowint1 at C:/esp-idf/components/freertos/port/xtensa/xtensa_vectors.S:1111
0x42005f7c: hw_lcd_dma_tx_push_n_data at C:\esp32Projects\WSS_SERVER_AND_UI_INTEGRATION_S3\build/../components/ui/drv/src/hw_lcd_dma.c:720 (discriminator 4)
0x42005969: hw_lcd_write_n_data at C:\esp32Projects\WSS_SERVER_AND_UI_INTEGRATION_S3\build/../components/ui/drv/src/hw_lcd.c:635
0x420054f5: app_main at C:\esp32Projects\WSS_SERVER_AND_UI_INTEGRATION_S3\build/../main/src/main.c:84 (discriminator 1)
0x420179a1: main_task at C:/esp-idf/components/freertos/port/port_common.c:129 (discriminator 2)
0x4037fef1: vPortTaskWrapper at C:/esp-idf/components/freertos/port/xtensa/port.c:130
E (17174) task_wdt: Print CPU 1 backtrace
Backtrace:0x4037BD7D:0x3FC965400x4037A78A:0x3FC96560 0x400559DD:0x3FCF5900 |<-CORRUPTED
0x4037bd7d: esp_crosscore_isr at C:/esp-idf/components/esp_system/crosscore_int.c:92
0x4037a78a: _xt_lowint1 at C:/esp-idf/components/freertos/port/xtensa/xtensa_vectors.S:1111