Skip to content

Commit 984999f

Browse files
authored
Create workaround for DMA failing on ESP32-S3 when WiFi is started (#625)
* Create workaround for DMA failing on ESP32-S3 when WiFi is started Relates to #620 * Add comment explaining the workaround
1 parent 8ee9c75 commit 984999f

File tree

3 files changed

+66
-21
lines changed

3 files changed

+66
-21
lines changed

driver/cam_hal.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,16 @@ camera_fb_t *cam_take(TickType_t timeout)
474474
camera_fb_t *dma_buffer = NULL;
475475
TickType_t start = xTaskGetTickCount();
476476
xQueueReceive(cam_obj->frame_buffer_queue, (void *)&dma_buffer, timeout);
477+
#if CONFIG_IDF_TARGET_ESP32S3
478+
// Currently (22.01.2024) there is a bug in ESP-IDF v5.2, that causes
479+
// GDMA to fall into a strange state if it is running while WiFi STA is connecting.
480+
// This code tries to reset GDMA if frame is not received, to try and help with
481+
// this case. It is possible to have some side effects too, though none come to mind
482+
if (!dma_buffer) {
483+
ll_cam_dma_reset(cam_obj);
484+
xQueueReceive(cam_obj->frame_buffer_queue, (void *)&dma_buffer, timeout);
485+
}
486+
#endif
477487
if (dma_buffer) {
478488
if(cam_obj->jpeg_mode){
479489
// find the end marker for JPEG. Data after that can be discarded
@@ -498,6 +508,9 @@ camera_fb_t *cam_take(TickType_t timeout)
498508
return dma_buffer;
499509
} else {
500510
ESP_LOGW(TAG, "Failed to get the frame on time!");
511+
// #if CONFIG_IDF_TARGET_ESP32S3
512+
// ll_cam_dma_print_state(cam_obj);
513+
// #endif
501514
}
502515
return NULL;
503516
}

target/esp32s3/ll_cam.c

Lines changed: 49 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,54 @@
3939

4040
static const char *TAG = "s3 ll_cam";
4141

42+
void ll_cam_dma_print_state(cam_obj_t *cam)
43+
{
44+
esp_rom_printf("dma_infifo_status[%u] :\n", cam->dma_num);
45+
esp_rom_printf(" infifo_full_l1 : %lu\n", GDMA.channel[cam->dma_num].in.infifo_status.infifo_full_l1);
46+
esp_rom_printf(" infifo_empty_l1 : %lu\n", GDMA.channel[cam->dma_num].in.infifo_status.infifo_empty_l1);
47+
esp_rom_printf(" infifo_full_l2 : %lu\n", GDMA.channel[cam->dma_num].in.infifo_status.infifo_full_l2);
48+
esp_rom_printf(" infifo_empty_l2 : %lu\n", GDMA.channel[cam->dma_num].in.infifo_status.infifo_empty_l2);
49+
esp_rom_printf(" infifo_full_l3 : %lu\n", GDMA.channel[cam->dma_num].in.infifo_status.infifo_full_l3);
50+
esp_rom_printf(" infifo_empty_l3 : %lu\n", GDMA.channel[cam->dma_num].in.infifo_status.infifo_empty_l3);
51+
esp_rom_printf(" infifo_cnt_l1 : %lu\n", GDMA.channel[cam->dma_num].in.infifo_status.infifo_cnt_l1);
52+
esp_rom_printf(" infifo_cnt_l2 : %lu\n", GDMA.channel[cam->dma_num].in.infifo_status.infifo_cnt_l2);
53+
esp_rom_printf(" infifo_cnt_l3 : %lu\n", GDMA.channel[cam->dma_num].in.infifo_status.infifo_cnt_l3);
54+
esp_rom_printf(" in_remain_under_1b_l3: %lu\n", GDMA.channel[cam->dma_num].in.infifo_status.in_remain_under_1b_l3);
55+
esp_rom_printf(" in_remain_under_2b_l3: %lu\n", GDMA.channel[cam->dma_num].in.infifo_status.in_remain_under_2b_l3);
56+
esp_rom_printf(" in_remain_under_3b_l3: %lu\n", GDMA.channel[cam->dma_num].in.infifo_status.in_remain_under_3b_l3);
57+
esp_rom_printf(" in_remain_under_4b_l3: %lu\n", GDMA.channel[cam->dma_num].in.infifo_status.in_remain_under_4b_l3);
58+
esp_rom_printf(" in_buf_hungry : %lu\n", GDMA.channel[cam->dma_num].in.infifo_status.in_buf_hungry);
59+
esp_rom_printf("dma_state[%u] :\n", cam->dma_num);
60+
esp_rom_printf(" dscr_addr : 0x%lx\n", GDMA.channel[cam->dma_num].in.state.dscr_addr);
61+
esp_rom_printf(" in_dscr_state : %lu\n", GDMA.channel[cam->dma_num].in.state.in_dscr_state);
62+
esp_rom_printf(" in_state : %lu\n", GDMA.channel[cam->dma_num].in.state.in_state);
63+
}
64+
65+
void ll_cam_dma_reset(cam_obj_t *cam)
66+
{
67+
68+
GDMA.channel[cam->dma_num].in.int_clr.val = ~0;
69+
GDMA.channel[cam->dma_num].in.int_ena.val = 0;
70+
71+
GDMA.channel[cam->dma_num].in.conf0.val = 0;
72+
GDMA.channel[cam->dma_num].in.conf0.in_rst = 1;
73+
GDMA.channel[cam->dma_num].in.conf0.in_rst = 0;
74+
75+
//internal SRAM only
76+
if (!cam->psram_mode) {
77+
GDMA.channel[cam->dma_num].in.conf0.indscr_burst_en = 1;
78+
GDMA.channel[cam->dma_num].in.conf0.in_data_burst_en = 1;
79+
}
80+
81+
GDMA.channel[cam->dma_num].in.conf1.in_check_owner = 0;
82+
// GDMA.channel[cam->dma_num].in.conf1.in_ext_mem_bk_size = 2;
83+
84+
GDMA.channel[cam->dma_num].in.peri_sel.sel = 5;
85+
//GDMA.channel[cam->dma_num].in.pri.rx_pri = 1;//rx prio 0-15
86+
//GDMA.channel[cam->dma_num].in.sram_size.in_size = 6;//This register is used to configure the size of L2 Tx FIFO for Rx channel. 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.
87+
//GDMA.channel[cam->dma_num].in.wight.rx_weight = 7;//The weight of Rx channel 0-15
88+
}
89+
4290
static void IRAM_ATTR ll_cam_vsync_isr(void *arg)
4391
{
4492
//DBG_PIN_SET(1);
@@ -164,27 +212,7 @@ static esp_err_t ll_cam_dma_init(cam_obj_t *cam)
164212
REG_SET_BIT(SYSTEM_PERIP_RST_EN1_REG, SYSTEM_DMA_RST);
165213
REG_CLR_BIT(SYSTEM_PERIP_RST_EN1_REG, SYSTEM_DMA_RST);
166214
}
167-
168-
GDMA.channel[cam->dma_num].in.int_clr.val = ~0;
169-
GDMA.channel[cam->dma_num].in.int_ena.val = 0;
170-
171-
GDMA.channel[cam->dma_num].in.conf0.val = 0;
172-
GDMA.channel[cam->dma_num].in.conf0.in_rst = 1;
173-
GDMA.channel[cam->dma_num].in.conf0.in_rst = 0;
174-
175-
//internal SRAM only
176-
if (!cam->psram_mode) {
177-
GDMA.channel[cam->dma_num].in.conf0.indscr_burst_en = 1;
178-
GDMA.channel[cam->dma_num].in.conf0.in_data_burst_en = 1;
179-
}
180-
181-
GDMA.channel[cam->dma_num].in.conf1.in_check_owner = 0;
182-
// GDMA.channel[cam->dma_num].in.conf1.in_ext_mem_bk_size = 2;
183-
184-
GDMA.channel[cam->dma_num].in.peri_sel.sel = 5;
185-
//GDMA.channel[cam->dma_num].in.pri.rx_pri = 1;//rx prio 0-15
186-
//GDMA.channel[cam->dma_num].in.sram_size.in_size = 6;//This register is used to configure the size of L2 Tx FIFO for Rx channel. 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.
187-
//GDMA.channel[cam->dma_num].in.wight.rx_weight = 7;//The weight of Rx channel 0-15
215+
ll_cam_dma_reset(cam);
188216
return ESP_OK;
189217
}
190218

target/private_include/ll_cam.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,10 @@ uint8_t ll_cam_get_dma_align(cam_obj_t *cam);
142142
bool ll_cam_dma_sizes(cam_obj_t *cam);
143143
size_t ll_cam_memcpy(cam_obj_t *cam, uint8_t *out, const uint8_t *in, size_t len);
144144
esp_err_t ll_cam_set_sample_mode(cam_obj_t *cam, pixformat_t pix_format, uint32_t xclk_freq_hz, uint16_t sensor_pid);
145+
#if CONFIG_IDF_TARGET_ESP32S3
146+
void ll_cam_dma_print_state(cam_obj_t *cam);
147+
void ll_cam_dma_reset(cam_obj_t *cam);
148+
#endif
145149

146150
// implemented in cam_hal
147151
void ll_cam_send_event(cam_obj_t *cam, cam_event_t cam_event, BaseType_t * HPTaskAwoken);

0 commit comments

Comments
 (0)