ports/alif: Refactor omv_csi_init.

Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
This commit is contained in:
iabdalkader 2025-07-02 18:14:00 +02:00
parent 06c8dcda17
commit 71082ad573
3 changed files with 77 additions and 138 deletions

View File

@ -103,6 +103,11 @@ void alif_hal_init(void) {
// Configure and enable USB IRQs.
NVIC_ClearPendingIRQ(USB_IRQ_IRQn);
NVIC_SetPriority(USB_IRQ_IRQn, IRQ_PRI_USB);
#if MICROPY_PY_CSI
// Enable CSI clock and configure pins.
alif_hal_csi_init(OMV_CSI_BASE);
#endif
}
int alif_hal_i2c_init(uint32_t bus_id) {
@ -364,14 +369,15 @@ int alif_hal_pdm_deinit(uint32_t pdm_id) {
return 0;
}
int alif_hal_csi_init(CPI_Type *cpi, uint32_t mode) {
if (mode == 0) {
int alif_hal_csi_init(CPI_Type *cpi) {
// Enable CPI clock.
if (cpi == ((CPI_Type *) CPI_BASE)) {
enable_cpi_periph_clk();
} else {
enable_lpcpi_periph_clk();
}
// Configure camera sensor interface pins
// Configure CPI pins.
omv_gpio_config(OMV_CSI_D0_PIN, OMV_GPIO_MODE_ALT, OMV_GPIO_PULL_NONE, OMV_GPIO_SPEED_HIGH, -1);
omv_gpio_config(OMV_CSI_D1_PIN, OMV_GPIO_MODE_ALT, OMV_GPIO_PULL_NONE, OMV_GPIO_SPEED_HIGH, -1);
omv_gpio_config(OMV_CSI_D2_PIN, OMV_GPIO_MODE_ALT, OMV_GPIO_PULL_NONE, OMV_GPIO_SPEED_HIGH, -1);
@ -386,18 +392,6 @@ int alif_hal_csi_init(CPI_Type *cpi, uint32_t mode) {
omv_gpio_config(OMV_CSI_PXCLK_PIN, OMV_GPIO_MODE_ALT, OMV_GPIO_PULL_NONE, OMV_GPIO_SPEED_HIGH, -1);
omv_gpio_config(OMV_CSI_MXCLK_PIN, OMV_GPIO_MODE_ALT, OMV_GPIO_PULL_NONE, OMV_GPIO_SPEED_HIGH, -1);
// Configure DCMI GPIOs
#if defined(OMV_CSI_RESET_PIN)
omv_gpio_config(OMV_CSI_RESET_PIN, OMV_GPIO_MODE_OUTPUT, OMV_GPIO_PULL_DOWN, OMV_GPIO_SPEED_LOW, -1);
#endif
#if defined(OMV_CSI_FSYNC_PIN)
omv_gpio_config(OMV_CSI_FSYNC_PIN, OMV_GPIO_MODE_OUTPUT, OMV_GPIO_PULL_DOWN, OMV_GPIO_SPEED_LOW, -1);
#endif
#if defined(OMV_CSI_POWER_PIN)
omv_gpio_config(OMV_CSI_POWER_PIN, OMV_GPIO_MODE_OUTPUT, OMV_GPIO_PULL_UP, OMV_GPIO_SPEED_LOW, -1);
#endif
NVIC_SetPriority(CAM_IRQ_IRQn, IRQ_PRI_CSI);
return 0;
}

View File

@ -40,5 +40,5 @@ int alif_hal_spi_init(uint32_t bus_id, bool nss_enable, uint32_t nss_pol);
int alif_hal_spi_deinit(uint32_t bus_id);
int alif_hal_pdm_init(uint32_t pdm_id);
int alif_hal_pdm_deinit(uint32_t pdm_id);
int alif_hal_csi_init(CPI_Type *cpi, uint32_t mode);
int alif_hal_csi_init(CPI_Type *cpi);
#endif //__ALIF_HAL_H__

View File

@ -71,6 +71,66 @@
CAM_INTR_OUTFIFO_OVERRUN | \
CAM_INTR_BRESP_ERR)
static uint32_t omv_csi_get_fb_offset(omv_csi_t *csi);
void CAM_IRQHandler(void) {
uint32_t mask = 0;
omv_csi_t *csi = omv_csi_get(-1);
CPI_Type *cpi = csi->base;
uint32_t status = cpi_get_interrupt_status(cpi);
if (status & CAM_INTR_VSYNC) {
mask |= CAM_INTR_VSYNC;
}
if (status & CAM_INTR_HSYNC) {
mask |= CAM_INTR_HSYNC;
}
if (status & CAM_INTR_INFIFO_OVERRUN) {
mask |= CAM_INTR_INFIFO_OVERRUN;
omv_csi_abort(csi, true, true);
}
if (status & CAM_INTR_OUTFIFO_OVERRUN) {
mask |= CAM_INTR_OUTFIFO_OVERRUN;
omv_csi_abort(csi, true, true);
}
if (status & CAM_INTR_BRESP_ERR) {
mask |= CAM_INTR_BRESP_ERR;
omv_csi_abort(csi, true, true);
}
if (status & CAM_INTR_STOP) {
mask |= CAM_INTR_STOP;
cpi->CAM_CTRL = 0;
if (!(status & CPI_ERROR_FLAGS)) {
// Release the current framebuffer.
framebuffer_get_tail(csi->fb, FB_NO_FLAGS);
}
// Get the current framebuffer (or new tail).
vbuffer_t *buffer = framebuffer_get_tail(csi->fb, FB_PEEK);
if (buffer != NULL) {
cpi->CAM_CTRL = 0;
cpi->CAM_CTRL = CAM_CTRL_SW_RESET;
cpi->CAM_FRAME_ADDR = LocalToGlobal(buffer->data + omv_csi_get_fb_offset(csi));
cpi_irq_handler_clear_intr_status(cpi, mask);
cpi->CAM_CTRL = (CAM_CTRL_SNAPSHOT | CAM_CTRL_START | CAM_CTRL_FIFO_CLK_SEL);
}
if (csi->frame_cb.fun && !(status & CPI_ERROR_FLAGS)) {
csi->frame_cb.fun(csi->frame_cb.arg);
}
}
// Clear interrupts.
cpi_irq_handler_clear_intr_status(cpi, mask);
}
int alif_csi_config(omv_csi_t *csi, omv_csi_config_t config) {
if (config == OMV_CSI_CONFIG_INIT) {
CPI_Type *cpi = csi->base;
@ -235,13 +295,13 @@ int alif_csi_snapshot(omv_csi_t *csi, image_t *dst_image, uint32_t flags) {
cpi_irq_handler_clear_intr_status(cpi, CPI_IRQ_FLAGS);
cpi_enable_interrupt(cpi, CPI_IRQ_FLAGS);
NVIC_ClearPendingIRQ(CAM_IRQ_IRQn);
NVIC_SetPriority(CAM_IRQ_IRQn, IRQ_PRI_CSI);
NVIC_EnableIRQ(CAM_IRQ_IRQn);
// Reset CSI and start the capture.
cpi->CAM_CTRL = 0;
cpi->CAM_CTRL |= CAM_CTRL_SW_RESET;
cpi->CAM_CTRL = CAM_CTRL_SW_RESET;
cpi->CAM_CTRL = (CAM_CTRL_SNAPSHOT | CAM_CTRL_START | CAM_CTRL_FIFO_CLK_SEL);
//printf("==== reconfigured ===\n");
}
// Let the camera know we want to trigger it now.
@ -364,126 +424,11 @@ int alif_csi_snapshot(omv_csi_t *csi, image_t *dst_image, uint32_t flags) {
return 0;
}
int omv_csi_init() {
int init_ret = 0;
static omv_i2c_t i2c;
CPI_Type *base = ((CPI_Type *) CPI_BASE);
alif_hal_csi_init(base, 0);
#if defined(OMV_CSI_POWER_PIN)
omv_gpio_write(OMV_CSI_POWER_PIN, 0);
#endif
#if defined(OMV_CSI_RESET_PIN)
omv_gpio_write(OMV_CSI_RESET_PIN, 0);
#endif
// Initialize the CSIs using this driver's ops as defaults,
// which can be overridden by sensor drivers during probe.
for (size_t i=0; i<OMV_CSI_MAX_DEVICES; i++) {
omv_csi_t *csi = &csi_all[i];
memset(csi, 0, sizeof(omv_csi_t));
csi->i2c = &i2c;
csi->fb = framebuffer_get(-1);
csi->base = base;
csi->abort = alif_csi_abort;
csi->config = alif_csi_config;
csi->snapshot = alif_csi_snapshot;
csi->color_palette = rainbow_table;
}
// Configure the CSI external clock.
if (omv_csi_set_clk_frequency(OMV_CSI_CLK_FREQUENCY) != 0) {
// Failed to initialize the csi clock.
return OMV_CSI_ERROR_TIM_INIT_FAILED;
}
// Initialize the camera bus.
omv_i2c_init(&i2c, OMV_CSI_I2C_ID, OMV_CSI_I2C_SPEED);
// Detect and initialize the image csi.
if ((init_ret = omv_csi_probe(&i2c)) != 0) {
// csi probe/init failed.
return init_ret;
}
// Configure the DCMI interface.
for (size_t i=0; i<OMV_CSI_MAX_DEVICES; i++) {
omv_csi_t *csi = &csi_all[i];
if (omv_csi_config(csi, OMV_CSI_CONFIG_INIT) != 0) {
return OMV_CSI_ERROR_CSI_INIT_FAILED;
}
csi->detected = true;
}
// Clear fb_enabled flag.
JPEG_FB()->enabled = 0;
int omv_csi_ops_init(omv_csi_t *csi) {
csi->base = OMV_CSI_BASE;
csi->abort = alif_csi_abort;
csi->config = alif_csi_config;
csi->snapshot = alif_csi_snapshot;
return 0;
}
void CAM_IRQHandler(void) {
uint32_t mask = 0;
omv_csi_t *csi = omv_csi_get(-1);
CPI_Type *cpi = csi->base;
uint32_t status = cpi_get_interrupt_status(cpi);
if (status & CAM_INTR_VSYNC) {
mask |= CAM_INTR_VSYNC;
}
if (status & CAM_INTR_HSYNC) {
mask |= CAM_INTR_HSYNC;
}
if (status & CAM_INTR_INFIFO_OVERRUN) {
mask |= CAM_INTR_INFIFO_OVERRUN;
omv_csi_abort(csi, true, true);
printf("INFIFO_OVERRUN\n");
}
if (status & CAM_INTR_OUTFIFO_OVERRUN) {
mask |= CAM_INTR_OUTFIFO_OVERRUN;
omv_csi_abort(csi, true, true);
printf("OUTFIFO_OVERRUN\n");
}
if (status & CAM_INTR_BRESP_ERR) {
mask |= CAM_INTR_BRESP_ERR;
omv_csi_abort(csi, true, true);
printf("BRESP_ERR %lu\n", cpi->CAM_AXI_ERR_STAT);
}
if (status & CAM_INTR_STOP) {
mask |= CAM_INTR_STOP;
cpi->CAM_CTRL = 0;
if (!(status & CPI_ERROR_FLAGS)) {
// Release the current framebuffer.
framebuffer_get_tail(csi->fb, FB_NO_FLAGS);
}
// Get the current framebuffer (or new tail).
vbuffer_t *buffer = framebuffer_get_tail(csi->fb, FB_PEEK);
if (buffer != NULL) {
cpi->CAM_CTRL = 0;
cpi->CAM_CTRL |= CAM_CTRL_SW_RESET;
cpi->CAM_FRAME_ADDR = LocalToGlobal(buffer->data + omv_csi_get_fb_offset(csi));
cpi_irq_handler_clear_intr_status(cpi, mask);
cpi->CAM_CTRL = (CAM_CTRL_SNAPSHOT | CAM_CTRL_START | CAM_CTRL_FIFO_CLK_SEL);
}
if (csi->frame_cb.fun && !(status & CPI_ERROR_FLAGS)) {
csi->frame_cb.fun(csi->frame_cb.arg);
}
}
// Clear interrupts.
cpi_irq_handler_clear_intr_status(cpi, mask);
}
#endif // MICROPY_PY_CSI