feat(lcd_cam): add lc_dma_int value atomic protect for lcd and cam

This commit is contained in:
gaoxu
2025-07-07 14:28:31 +08:00
parent e8ff923342
commit 9a2997e25c
6 changed files with 41 additions and 9 deletions

View File

@@ -197,7 +197,9 @@ esp_err_t esp_lcd_new_i80_bus(const esp_lcd_i80_bus_config_t *bus_config, esp_lc
(uint32_t)lcd_ll_get_interrupt_status_reg(bus->hal.dev), (uint32_t)lcd_ll_get_interrupt_status_reg(bus->hal.dev),
LCD_LL_EVENT_TRANS_DONE, i80_lcd_default_isr_handler, bus, &bus->intr); LCD_LL_EVENT_TRANS_DONE, i80_lcd_default_isr_handler, bus, &bus->intr);
ESP_GOTO_ON_ERROR(ret, err, TAG, "install interrupt failed"); ESP_GOTO_ON_ERROR(ret, err, TAG, "install interrupt failed");
lcd_ll_enable_interrupt(bus->hal.dev, LCD_LL_EVENT_TRANS_DONE, false); // disable all interrupts PERIPH_RCC_ATOMIC() {
lcd_ll_enable_interrupt(bus->hal.dev, LCD_LL_EVENT_TRANS_DONE, false); // disable all interrupts
}
lcd_ll_clear_interrupt_status(bus->hal.dev, UINT32_MAX); // clear pending interrupt lcd_ll_clear_interrupt_status(bus->hal.dev, UINT32_MAX); // clear pending interrupt
// install DMA service // install DMA service
bus->max_transfer_bytes = bus_config->max_transfer_bytes; bus->max_transfer_bytes = bus_config->max_transfer_bytes;
@@ -213,8 +215,10 @@ esp_err_t esp_lcd_new_i80_bus(const esp_lcd_i80_bus_config_t *bus_config, esp_lc
lcd_ll_set_swizzle_mode(bus->hal.dev, LCD_LL_SWIZZLE_AB2BA); lcd_ll_set_swizzle_mode(bus->hal.dev, LCD_LL_SWIZZLE_AB2BA);
// number of data cycles is controlled by DMA buffer size // number of data cycles is controlled by DMA buffer size
lcd_ll_enable_output_always_on(bus->hal.dev, true); lcd_ll_enable_output_always_on(bus->hal.dev, true);
// enable trans done interrupt PERIPH_RCC_ATOMIC() {
lcd_ll_enable_interrupt(bus->hal.dev, LCD_LL_EVENT_TRANS_DONE, true); // enable trans done interrupt
lcd_ll_enable_interrupt(bus->hal.dev, LCD_LL_EVENT_TRANS_DONE, true);
}
// trigger a quick "trans done" event, and wait for the interrupt line goes active // trigger a quick "trans done" event, and wait for the interrupt line goes active
// this could ensure we go into ISR handler next time we call `esp_intr_enable` // this could ensure we go into ISR handler next time we call `esp_intr_enable`
lcd_periph_trigger_quick_trans_done_event(bus); lcd_periph_trigger_quick_trans_done_event(bus);

View File

@@ -332,7 +332,9 @@ esp_err_t esp_lcd_new_rgb_panel(const esp_lcd_rgb_panel_config_t *rgb_panel_conf
(uint32_t)lcd_ll_get_interrupt_status_reg(rgb_panel->hal.dev), (uint32_t)lcd_ll_get_interrupt_status_reg(rgb_panel->hal.dev),
LCD_LL_EVENT_VSYNC_END, rgb_lcd_default_isr_handler, rgb_panel, &rgb_panel->intr); LCD_LL_EVENT_VSYNC_END, rgb_lcd_default_isr_handler, rgb_panel, &rgb_panel->intr);
ESP_GOTO_ON_ERROR(ret, err, TAG, "install interrupt failed"); ESP_GOTO_ON_ERROR(ret, err, TAG, "install interrupt failed");
lcd_ll_enable_interrupt(rgb_panel->hal.dev, LCD_LL_EVENT_VSYNC_END, false); // disable all interrupts PERIPH_RCC_ATOMIC() {
lcd_ll_enable_interrupt(rgb_panel->hal.dev, LCD_LL_EVENT_VSYNC_END, false); // disable all interrupts
}
lcd_ll_clear_interrupt_status(rgb_panel->hal.dev, UINT32_MAX); // clear pending interrupt lcd_ll_clear_interrupt_status(rgb_panel->hal.dev, UINT32_MAX); // clear pending interrupt
// install DMA service // install DMA service
@@ -569,8 +571,10 @@ static esp_err_t rgb_panel_init(esp_lcd_panel_t *panel)
// in stream mode, after finish one frame, the LCD controller will ask for data automatically from the DMA // in stream mode, after finish one frame, the LCD controller will ask for data automatically from the DMA
// DMA should prepare the next frame data within porch region // DMA should prepare the next frame data within porch region
lcd_ll_enable_auto_next_frame(rgb_panel->hal.dev, rgb_panel->flags.stream_mode); lcd_ll_enable_auto_next_frame(rgb_panel->hal.dev, rgb_panel->flags.stream_mode);
// trigger interrupt on the end of frame PERIPH_RCC_ATOMIC() {
lcd_ll_enable_interrupt(rgb_panel->hal.dev, LCD_LL_EVENT_VSYNC_END, true); // trigger interrupt on the end of frame
lcd_ll_enable_interrupt(rgb_panel->hal.dev, LCD_LL_EVENT_VSYNC_END, true);
}
// enable intr // enable intr
esp_intr_enable(rgb_panel->intr); esp_intr_enable(rgb_panel->intr);
// start transmission // start transmission

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -593,6 +593,12 @@ static inline void cam_ll_enable_interrupt(lcd_cam_dev_t *dev, uint32_t mask, bo
dev->lc_dma_int_ena.val &= ~(mask & 0x0c); dev->lc_dma_int_ena.val &= ~(mask & 0x0c);
} }
} }
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define cam_ll_enable_interrupt(...) do { \
(void)__DECLARE_RCC_ATOMIC_ENV; \
cam_ll_enable_interrupt(__VA_ARGS__); \
} while(0)
/** /**
* @brief Get interrupt status value * @brief Get interrupt status value

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -726,6 +726,12 @@ static inline void lcd_ll_enable_interrupt(lcd_cam_dev_t *dev, uint32_t mask, bo
dev->lc_dma_int_ena.val &= ~(mask & 0x03); dev->lc_dma_int_ena.val &= ~(mask & 0x03);
} }
} }
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define lcd_ll_enable_interrupt(...) do { \
(void)__DECLARE_RCC_ATOMIC_ENV; \
lcd_ll_enable_interrupt(__VA_ARGS__); \
} while(0)
/** /**
* @brief Get interrupt status value * @brief Get interrupt status value

View File

@@ -574,6 +574,12 @@ static inline void cam_ll_enable_interrupt(lcd_cam_dev_t *dev, uint32_t mask, bo
dev->lc_dma_int_ena.val &= ~(mask & 0x0c); dev->lc_dma_int_ena.val &= ~(mask & 0x0c);
} }
} }
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define cam_ll_enable_interrupt(...) do { \
(void)__DECLARE_RCC_ATOMIC_ENV; \
cam_ll_enable_interrupt(__VA_ARGS__); \
} while(0)
/** /**
* @brief Get interrupt status value * @brief Get interrupt status value

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -709,6 +709,12 @@ static inline void lcd_ll_enable_interrupt(lcd_cam_dev_t *dev, uint32_t mask, bo
dev->lc_dma_int_ena.val &= ~(mask & 0x03); dev->lc_dma_int_ena.val &= ~(mask & 0x03);
} }
} }
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define lcd_ll_enable_interrupt(...) do { \
(void)__DECLARE_RCC_ATOMIC_ENV; \
lcd_ll_enable_interrupt(__VA_ARGS__); \
} while(0)
/** /**
* @brief Get interrupt status value * @brief Get interrupt status value