From 9f1aff4e0ae8c5588a51c0596a68e231f67b83e7 Mon Sep 17 00:00:00 2001 From: bob Date: Tue, 21 Aug 2018 18:36:03 +1000 Subject: [PATCH] Improvements to DMA SBM image capture... - Additional TRACE output - DMA DBM now can be disabled through -D make define - Fix incorrect count of image size in DMA SBM operation - Rename some data structure members and move struct in ov5640.h --- tracker/software/cfg/pp10a/chconf.h | 2 +- tracker/software/cfg/pp10a/mcuconf.h | 28 +-- tracker/software/cfg/pp10b/chconf.h | 2 +- tracker/software/cfg/pp10b/mcuconf.h | 28 +-- tracker/software/make/pp10a.make | 2 +- tracker/software/make/pp10b.make | 2 +- tracker/software/source/config/config.c | 2 +- tracker/software/source/drivers/ov5640.c | 205 +++++++++++-------- tracker/software/source/drivers/ov5640.h | 13 +- tracker/software/source/threads/rxtx/image.c | 9 +- 10 files changed, 169 insertions(+), 124 deletions(-) diff --git a/tracker/software/cfg/pp10a/chconf.h b/tracker/software/cfg/pp10a/chconf.h index 795cb730..f49e6aec 100644 --- a/tracker/software/cfg/pp10a/chconf.h +++ b/tracker/software/cfg/pp10a/chconf.h @@ -227,7 +227,7 @@ * @note The default is @p TRUE. * @note Requires @p CH_CFG_USE_MUTEXES. */ -#define CH_CFG_USE_CONDVARS TRUE +#define CH_CFG_USE_CONDVARS FALSE /** * @brief Conditional Variables APIs with timeout. diff --git a/tracker/software/cfg/pp10a/mcuconf.h b/tracker/software/cfg/pp10a/mcuconf.h index 9ca93e0b..27c68a18 100644 --- a/tracker/software/cfg/pp10a/mcuconf.h +++ b/tracker/software/cfg/pp10a/mcuconf.h @@ -84,20 +84,22 @@ #define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 6 /* - * EXT driver system settings. + * IRQ system settings. */ -#define STM32_EXT_EXTI0_IRQ_PRIORITY 6 -#define STM32_EXT_EXTI1_IRQ_PRIORITY 6 -#define STM32_EXT_EXTI2_IRQ_PRIORITY 6 -#define STM32_EXT_EXTI3_IRQ_PRIORITY 6 -#define STM32_EXT_EXTI4_IRQ_PRIORITY 6 -#define STM32_EXT_EXTI5_9_IRQ_PRIORITY 6 -#define STM32_EXT_EXTI10_15_IRQ_PRIORITY 3 -#define STM32_EXT_EXTI16_IRQ_PRIORITY 6 -#define STM32_EXT_EXTI17_IRQ_PRIORITY 15 -#define STM32_EXT_EXTI18_IRQ_PRIORITY 6 -#define STM32_EXT_EXTI19_IRQ_PRIORITY 6 -#define STM32_EXT_EXTI22_IRQ_PRIORITY 15 +#define STM32_IRQ_EXTI0_PRIORITY 6 +#define STM32_IRQ_EXTI1_PRIORITY 6 +#define STM32_IRQ_EXTI2_PRIORITY 6 +#define STM32_IRQ_EXTI3_PRIORITY 6 +#define STM32_IRQ_EXTI4_PRIORITY 6 +#define STM32_IRQ_EXTI5_9_PRIORITY 6 +#define STM32_IRQ_EXTI10_15_PRIORITY 3 +#define STM32_IRQ_EXTI16_PRIORITY 6 +#define STM32_IRQ_EXTI17_PRIORITY 15 +#define STM32_IRQ_EXTI18_PRIORITY 6 +#define STM32_IRQ_EXTI19_PRIORITY 6 +#define STM32_IRQ_EXTI20_PRIORITY 6 +#define STM32_IRQ_EXTI21_PRIORITY 15 +#define STM32_IRQ_EXTI22_PRIORITY 15 /* * GPT driver system settings. diff --git a/tracker/software/cfg/pp10b/chconf.h b/tracker/software/cfg/pp10b/chconf.h index 795cb730..f49e6aec 100644 --- a/tracker/software/cfg/pp10b/chconf.h +++ b/tracker/software/cfg/pp10b/chconf.h @@ -227,7 +227,7 @@ * @note The default is @p TRUE. * @note Requires @p CH_CFG_USE_MUTEXES. */ -#define CH_CFG_USE_CONDVARS TRUE +#define CH_CFG_USE_CONDVARS FALSE /** * @brief Conditional Variables APIs with timeout. diff --git a/tracker/software/cfg/pp10b/mcuconf.h b/tracker/software/cfg/pp10b/mcuconf.h index 0d82d854..2585a485 100644 --- a/tracker/software/cfg/pp10b/mcuconf.h +++ b/tracker/software/cfg/pp10b/mcuconf.h @@ -80,20 +80,22 @@ #define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 6 /* - * EXT driver system settings. + * IRQ system settings. */ -#define STM32_EXT_EXTI0_IRQ_PRIORITY 6 -#define STM32_EXT_EXTI1_IRQ_PRIORITY 6 -#define STM32_EXT_EXTI2_IRQ_PRIORITY 6 -#define STM32_EXT_EXTI3_IRQ_PRIORITY 6 -#define STM32_EXT_EXTI4_IRQ_PRIORITY 6 -#define STM32_EXT_EXTI5_9_IRQ_PRIORITY 6 -#define STM32_EXT_EXTI10_15_IRQ_PRIORITY 3 -#define STM32_EXT_EXTI16_IRQ_PRIORITY 6 -#define STM32_EXT_EXTI17_IRQ_PRIORITY 15 -#define STM32_EXT_EXTI18_IRQ_PRIORITY 6 -#define STM32_EXT_EXTI19_IRQ_PRIORITY 6 -#define STM32_EXT_EXTI22_IRQ_PRIORITY 15 +#define STM32_IRQ_EXTI0_PRIORITY 6 +#define STM32_IRQ_EXTI1_PRIORITY 6 +#define STM32_IRQ_EXTI2_PRIORITY 6 +#define STM32_IRQ_EXTI3_PRIORITY 6 +#define STM32_IRQ_EXTI4_PRIORITY 6 +#define STM32_IRQ_EXTI5_9_PRIORITY 6 +#define STM32_IRQ_EXTI10_15_PRIORITY 3 +#define STM32_IRQ_EXTI16_PRIORITY 6 +#define STM32_IRQ_EXTI17_PRIORITY 15 +#define STM32_IRQ_EXTI18_PRIORITY 6 +#define STM32_IRQ_EXTI19_PRIORITY 6 +#define STM32_IRQ_EXTI20_PRIORITY 6 +#define STM32_IRQ_EXTI21_PRIORITY 15 +#define STM32_IRQ_EXTI22_PRIORITY 15 /* * GPT driver system settings. diff --git a/tracker/software/make/pp10a.make b/tracker/software/make/pp10a.make index 1a5a5358..cf74ffdb 100644 --- a/tracker/software/make/pp10a.make +++ b/tracker/software/make/pp10a.make @@ -215,7 +215,7 @@ CPPWARN = -Wall -Wextra -Wundef # List all user C define here, like -D_DEBUG=1 UDEFS = -D_GNU_SOURCE -DARM_MATH_CM4 -DSHELL_CMD_TEST_ENABLED=0 \ - -DSHELL_CMD_EXIT_ENABLED=1 -DSET_TRACE_LEVEL=5 \ + -DSHELL_CMD_EXIT_ENABLED=1 -DSET_TRACE_LEVEL=5 -DPDCMI_USE_DMA_DBM=0 \ -DSHELL_CMD_MEM_ENABLED=0 # -DDISABLE_HW_WATCHDOG=1 diff --git a/tracker/software/make/pp10b.make b/tracker/software/make/pp10b.make index 1cf80d7b..129930b3 100644 --- a/tracker/software/make/pp10b.make +++ b/tracker/software/make/pp10b.make @@ -215,7 +215,7 @@ CPPWARN = -Wall -Wextra -Wundef # List all user C define here, like -D_DEBUG=1 UDEFS = -D_GNU_SOURCE -DARM_MATH_CM4 -DSHELL_CMD_TEST_ENABLED=0 \ - -DSHELL_CMD_EXIT_ENABLED=1 -DSET_TRACE_LEVEL=5 \ + -DSHELL_CMD_EXIT_ENABLED=1 -DSET_TRACE_LEVEL=5 -DPDCMI_USE_DMA_DBM=0 \ -DSHELL_CMD_MEM_ENABLED=0 -DDISABLE_HW_WATCHDOG=1 # Define ASM defines here diff --git a/tracker/software/source/config/config.c b/tracker/software/source/config/config.c index 46012f7d..c54c175c 100644 --- a/tracker/software/source/config/config.c +++ b/tracker/software/source/config/config.c @@ -86,7 +86,7 @@ const conf_t conf_flash_default = { .img_sec = { .svc_conf = { .active = true, - .cycle = TIME_S2I(60 * 2), + .cycle = TIME_S2I(60 * 1), .init_delay = TIME_S2I(60), .send_spacing = TIME_S2I(0) }, diff --git a/tracker/software/source/drivers/ov5640.c b/tracker/software/source/drivers/ov5640.c index ccf7b5a9..4b9f0abf 100644 --- a/tracker/software/source/drivers/ov5640.c +++ b/tracker/software/source/drivers/ov5640.c @@ -728,7 +728,7 @@ uint32_t OV5640_Snapshot2RAM(uint8_t* buffer, do { size_sampled = OV5640_Capture(buffer, size); if(size_sampled > 0) { - TRACE_INFO("CAM > Image size: %d bytes", size_sampled); + TRACE_INFO("CAM > Captured %d bytes", size_sampled); return size_sampled; } /* Allow time for other threads. */ @@ -762,10 +762,10 @@ uint32_t OV5640_Snapshot2RAM(uint8_t* buffer, #endif /* !defined(dmaStreamGetCurrentTarget) */ #endif /* PDCMI_USE_DMA_DBM == TRUE */ -inline void dma_start(const stm32_dma_stream_t *dmastp) { +inline void dma_start(dma_capture_t *ppdcmi) { /* Clear any pending interrupts. */ - dmaStreamClearInterrupt(dmastp); - dmaStreamEnable(dmastp); + dmaStreamClearInterrupt(ppdcmi->dmastp); + dmaStreamEnable(ppdcmi->dmastp); } /* @@ -773,11 +773,11 @@ inline void dma_start(const stm32_dma_stream_t *dmastp) { * Note that any DMA FIFO transfer in progress will complete. * The Chibios DMAV2 driver waits for EN to clear before proceeding. */ -inline uint16_t dma_stop(const stm32_dma_stream_t *dmastp) { - dmaStreamDisable(dmastp); - uint16_t transfer = dmaStreamGetTransactionSize(dmastp); - dmaStreamRelease(dmastp); - return (PDCMI_DMA_SEGMENT_SIZE - transfer); +inline uint16_t dma_stop(dma_capture_t *ppdcmi) { + dmaStreamDisable(ppdcmi->dmastp); + uint16_t remaining = dmaStreamGetTransactionSize(ppdcmi->dmastp); + dmaStreamRelease(ppdcmi->dmastp); + return (ppdcmi->page_size - remaining); } #if PDCMI_USE_DMA_DBM == TRUE @@ -794,7 +794,7 @@ static void dma_interrupt(void *p, uint32_t flags) { /* * DMA has been terminated by initiating function. * DMA stop has already been executed. - * We shouldn't be here... + * If there was a pending interrupt can we get here? */ if(dma_control->terminate) { dmaStreamClearInterrupt(dmastp); @@ -814,8 +814,8 @@ static void dma_interrupt(void *p, uint32_t flags) { */ dma_control->timer->DIER &= ~TIM_DIER_CC1DE; dma_control->timer->CCER &= ~TIM_CCER_CC1E; - dma_control->dma_count += dma_stop(dmastp); - dma_control->pdcmi_status = PDCMI_DMA_ERROR; + dma_control->transfer_count += dma_stop(dmastp); + dma_control->pdcmi_state = PDCMI_DMA_ERROR; palDisableLineEventI(dma_control->vsync_line); dmaStreamClearInterrupt(dmastp); dma_control->terminate = true; @@ -836,12 +836,14 @@ static void dma_interrupt(void *p, uint32_t flags) { * * Since this is the last DMA buffer this may be treated as an error. * The DMA should normally be terminated by VSYNC before last buffer. + * In the case that the buffer size was too small we can be here. + * * Disable timer, DMA and flag fault. */ dma_control->timer->DIER &= ~TIM_DIER_CC1DE; dma_control->timer->CCER &= ~TIM_CCER_CC1E; - dma_control->dma_count += dma_stop(dmastp); - dma_control->pdcmi_status = PDCMI_DMA_END_BUFFER; + dma_control->transfer_count += dma_stop(dmastp); + dma_control->pdcmi_state = PDCMI_DMA_END_BUFFER; dma_control->terminate = true; palDisableLineEventI(dma_control->vsync_line); dmaStreamClearInterrupt(dmastp); @@ -856,11 +858,11 @@ static void dma_interrupt(void *p, uint32_t flags) { * Checking state of CT at TCIF may be too late because of IRQ latency. * i.e. the DMA controller may have already changed CT before IRQ is serviced. */ - dma_control->segment_address += PDCMI_DMA_SEGMENT_SIZE; + dma_control->segment_address += PDCMI_DMA_DBM_PAGE_SIZE; if (dmaStreamGetCurrentTarget(dmastp) == 0) { - dmaStreamSetMemory1(dmastp, dma_control->segment_address); + dmaStreamSetMemory1(dmastp, dma_control->page_address); } else { - dmaStreamSetMemory0(dmastp, dma_control->segment_address); + dmaStreamSetMemory0(dmastp, dma_control->page_address); } dmaStreamClearInterrupt(dmastp); chSysUnlockFromISR(); @@ -871,7 +873,7 @@ static void dma_interrupt(void *p, uint32_t flags) { * Transfer complete for this segment. */ if(dma_control->terminate != true) { - dma_control->dma_count += PDCMI_DMA_SEGMENT_SIZE; + dma_control->page_adress += dma_control->page_size; } dmaStreamClearInterrupt(dmastp); chSysUnlockFromISR(); @@ -883,10 +885,10 @@ static void dma_interrupt(void *p, uint32_t flags) { */ dma_control->timer->DIER &= ~TIM_DIER_CC1DE; dma_control->timer->CCER &= ~TIM_CCER_CC1E; - dma_control->pdcmi_status = PDCMI_DMA_UNKNOWN_IRQ; + dma_control->pdcmi_state = PDCMI_DMA_UNKNOWN_IRQ; dma_control->terminate = true; dma_stop(dmastp); - dma_control->dma_count = 0; + dma_control->transfer_count = 0; palDisableLineEventI(dma_control->vsync_line); dmaStreamClearInterrupt(dmastp); chSysUnlockFromISR(); @@ -898,9 +900,22 @@ static void dma_interrupt(void *p, uint32_t flags) { static void dma_interrupt(void *p, uint32_t flags) { dma_capture_t *dma_control = p; - const stm32_dma_stream_t *dmastp = dma_control->dmastp; + //const stm32_dma_stream_t *dmastp = dma_control->dmastp; chSysLockFromISR(); + + /* + * DMA has been terminated by initiating function. + * DMA stop has already been executed. + * If there was a pending interrupt can we get here? + */ + if(dma_control->terminate) { + dmaStreamClearInterrupt(dma_control->dmastp); + chSysUnlockFromISR(); + return; + } + dma_control->dma_flags = flags; + if(flags & (STM32_DMA_ISR_FEIF | STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) { /* * DMA transfer error, FIFO error or Direct mode error. @@ -908,10 +923,10 @@ static void dma_interrupt(void *p, uint32_t flags) { */ dma_control->timer->DIER &= ~TIM_DIER_CC1DE; dma_control->timer->CCER &= ~TIM_CCER_CC1E; - dma_control->dma_count += dma_stop(dmastp); - dma_control->pdcmi_status = PDCMI_DMA_ERROR; + dma_control->transfer_count = dma_stop(dma_control); + dma_control->pdcmi_state = PDCMI_DMA_ERROR; palDisableLineEventI(dma_control->vsync_line); - dmaStreamClearInterrupt(dmastp); + dmaStreamClearInterrupt(dma_control->dmastp); chSysUnlockFromISR(); return; } @@ -927,11 +942,11 @@ static void dma_interrupt(void *p, uint32_t flags) { */ dma_control->timer->DIER &= ~TIM_DIER_CC1DE; dma_control->timer->CCER &= ~TIM_CCER_CC1E; - dma_control->dma_count += dma_stop(dmastp); - dma_stop(dma_control->dmastp); - dma_control->pdcmi_status = PDCMI_DMA_COUNT_END; + dma_control->transfer_count = dma_stop(dma_control); + //dma_stop(dma_control->dmastp); + dma_control->pdcmi_state = PDCMI_DMA_COUNT_END; palDisableLineEventI(dma_control->vsync_line); - dmaStreamClearInterrupt(dmastp); + dmaStreamClearInterrupt(dma_control->dmastp); dma_control->terminate = true; chSysUnlockFromISR(); return; @@ -942,10 +957,10 @@ static void dma_interrupt(void *p, uint32_t flags) { */ dma_control->timer->DIER &= ~TIM_DIER_CC1DE; dma_control->timer->CCER &= ~TIM_CCER_CC1E; - dma_control->pdcmi_status = PDCMI_DMA_UNKNOWN_IRQ; - dma_control->dma_count += dma_stop(dmastp); + dma_control->pdcmi_state = PDCMI_DMA_UNKNOWN_IRQ; + dma_control->transfer_count += dma_stop(dma_control); palDisableLineEventI(dma_control->vsync_line); - dmaStreamClearInterrupt(dmastp); + dmaStreamClearInterrupt(dma_control->dmastp); chSysUnlockFromISR(); return; } @@ -960,34 +975,36 @@ static void dma_interrupt(void *p, uint32_t flags) { void mode3_vsync_cb(void *arg) { dma_capture_t *dma_control = arg; - const stm32_dma_stream_t *dmastp = dma_control->dmastp; - TIM_TypeDef *timer = dma_control->timer; + //const stm32_dma_stream_t *dmastp = dma_control->dmastp; + //TIM_TypeDef *timer = dma_control->timer; chSysLockFromISR(); - if(palReadLine(LINE_CAM_VSYNC)) { + if(palReadLine(LINE_CAM_VSYNC == PAL_HIGH)) { /* VSYNC leading edge. */ - if((timer->DIER & TIM_DIER_CC1DE) != 0) { + if((dma_control->timer->DIER & TIM_DIER_CC1DE) != 0) { + /* Timer is running so capture is enabled. */ if(!dma_control->terminate) { - /* Capture running so terminate. */ - dma_control->dma_count += dma_stop(dmastp); + /* Capture not yet terminated so do it */ + dma_control->transfer_count += dma_stop(dma_control); dma_control->timer->DIER &= ~TIM_DIER_CC1DE; dma_control->timer->CCER &= ~TIM_CCER_CC1E; palDisableLineEventI(dma_control->vsync_line); + /* If a DMA interrupt is pending then this will stop any activity. */ dma_control->terminate = true; } /* Else DMA has terminated capture. This must be a nested interrupt. */ } /* Else wait to arm timer on trailing edge. */ chSysUnlockFromISR(); return; } /* VSYNC trailing edge. */ - if((timer->DIER & TIM_DIER_CC1DE) == 0) { + if((dma_control->timer->DIER & TIM_DIER_CC1DE) == 0) { /* - * Timer not running. + * Timer is not running. * Start DMA channel if termination not set. * Enable timer trigger of DMA. */ if(!dma_control->terminate) { - dma_start(dma_control->dmastp); - timer->DIER |= TIM_DIER_CC1DE; + dma_start(dma_control); + dma_control->timer->DIER |= TIM_DIER_CC1DE; } } /* Else wait to stop timer on leading edge. */ chSysUnlockFromISR(); @@ -1063,7 +1080,7 @@ uint32_t OV5640_Capture(uint8_t* buffer, uint32_t size) { /* * Calculate the number of whole buffers. */ - if((size / PDCMI_DMA_SEGMENT_SIZE) < 2) { + if((size / PDCMI_DMA_DBM_PAGE_SIZE) < 2) { TRACE_ERROR("CAM > Capture buffer less than 2 DMA DBM segment segments"); return 0; } @@ -1122,16 +1139,19 @@ uint32_t OV5640_Capture(uint8_t* buffer, uint32_t size) { dmaStreamSetPeripheral(dma_control.dmastp, &GPIOA->IDR); #if PDCMI_USE_DMA_DBM == TRUE - dma_control.segment_address = buffer; + dma_control.page_address = buffer; dma_control.base_buffer = buffer; - dma_control.segment_count = (size / PDCMI_DMA_SEGMENT_SIZE); + dma_control.page_count = (size / PDCMI_DMA_DBM_PAGE_SIZE); + dma_control.page_size = PDCMI_DMA_DBM_PAGE_SIZE; /* * Set the initial buffer addresses. * The updating of DMA:MxAR is done in the the DMA interrupt function. */ - dmaStreamSetMemory0(dma_control.dmastp, dma_control.segment_address); - dmaStreamSetTransactionSize(dma_control.dmastp, PDCMI_DMA_SEGMENT_SIZE); + dmaStreamSetMemory0(dma_control.dmastp, dma_control.page_address); + dmaStreamSetTransactionSize(dma_control.dmastp, PDCMI_DMA_DBM_PAGE_SIZE); #else + dma_control.page_size = size; + dma_control.page_count = 1; dmaStreamSetMemory0(dma_control.dmastp, buffer); dmaStreamSetTransactionSize(dma_control.dmastp, size); #endif @@ -1141,9 +1161,9 @@ uint32_t OV5640_Capture(uint8_t* buffer, uint32_t size) { | STM32_DMA_FCR_FEIE); dmaStreamClearInterrupt(dma_control.dmastp); - dma_control.pdcmi_status = PDCMI_NO_ERROR; + dma_control.pdcmi_state = PDCMI_NO_ERROR; dma_control.dma_flags = 0; - dma_control.dma_count = 0; + dma_control.transfer_count = 0; dma_control.terminate = false; /* * Setup timer for PCLK @@ -1158,7 +1178,8 @@ uint32_t OV5640_Capture(uint8_t* buffer, uint32_t size) { /* Setup VSNC event. */ dma_control.vsync_line = LINE_CAM_VSYNC; - palSetLineCallback(LINE_CAM_VSYNC, (palcallback_t)mode3_vsync_cb, &dma_control); + palSetLineCallback(LINE_CAM_VSYNC, (palcallback_t)mode3_vsync_cb, + &dma_control); palEnableLineEvent(LINE_CAM_VSYNC, PAL_EVENT_MODE_BOTH_EDGES); /* @@ -1179,58 +1200,74 @@ uint32_t OV5640_Capture(uint8_t* buffer, uint32_t size) { if(!timeout) { palDisableLineEventI(dma_control.vsync_line); - dma_control.dma_count += dma_stop(dma_control.dmastp); + dma_control.transfer_count += dma_stop(&dma_control); dma_control.timer->DIER &= ~TIM_DIER_CC1DE; dma_control.timer->CCER &= ~TIM_CCER_CC1E; - dma_control.pdcmi_status = PDCMI_CAPTURE_TIMEOUT; + dma_control.pdcmi_state = PDCMI_CAPTURE_TIMEOUT; } OV5640_UnlockResourcesForCapture(); - if(dma_control.pdcmi_status == PDCMI_DMA_ERROR) { - if(dma_control.dma_flags & STM32_DMA_ISR_FEIF) { - TRACE_ERROR("CAM > DMA FIFO error"); - error = 0x3; - return 0; - } - if(dma_control.dma_flags & STM32_DMA_ISR_TEIF) { - TRACE_ERROR("CAM > DMA stream transfer error"); - error = 0x4; - return 0; - } - if(dma_control.dma_flags & STM32_DMA_ISR_DMEIF) { - TRACE_ERROR("CAM > DMA direct mode error"); - error = 0x5; - return 0; - } - } - if(dma_control.pdcmi_status == PDCMI_DMA_END_BUFFER) { - TRACE_ERROR("CAM > DMA ran out of buffer space"); + switch(dma_control.pdcmi_state) { + case PDCMI_DMA_ERROR: { + if(dma_control.dma_flags & STM32_DMA_ISR_FEIF) { + TRACE_ERROR("CAM > DMA FIFO error"); + error = 0x3; + return 0; + } + if(dma_control.dma_flags & STM32_DMA_ISR_TEIF) { + TRACE_ERROR("CAM > DMA stream transfer error"); + error = 0x4; + return 0; + } + if(dma_control.dma_flags & STM32_DMA_ISR_DMEIF) { + TRACE_ERROR("CAM > DMA direct mode error"); + error = 0x5; + return 0; + } + break; + } + + case PDCMI_DMA_END_BUFFER: { + TRACE_ERROR("CAM > DMA ran out of buffer space in DBM." + " Image possibly useable"); error = 0x6; - return 0; - } - if(dma_control.pdcmi_status == PDCMI_CAPTURE_TIMEOUT) { - TRACE_ERROR("CAM > DMA image terminate timeout"); + return (dma_control.transfer_count); + } + + case PDCMI_CAPTURE_TIMEOUT: { + TRACE_ERROR("CAM > DMA image capture timeout"); error = 0x7; return 0; - } - if(dma_control.pdcmi_status == PDCMI_DMA_UNKNOWN_IRQ) { - TRACE_ERROR("CAM > DMA unknown interrupt DMA I flags: %x", + } + + case PDCMI_DMA_UNKNOWN_IRQ: { + TRACE_ERROR("CAM > DMA unknown interrupt. DMA I flags: %x", dma_control.dma_flags); error = 0x8; return 0; } - if(dma_control.pdcmi_status == PDCMI_DMA_COUNT_END) { - TRACE_WARN("CAM > DMA count ended w/o VSYNC. DMA I flags: %x", + + case PDCMI_DMA_COUNT_END: { + TRACE_WARN("CAM > DMA count ended w/o VSYNC in SBM. DMA I flags: %x." + " Image possibly useable.", dma_control.dma_flags); error = 0x9; - return (dma_control.dma_count); + return (dma_control.transfer_count); } - TRACE_INFO("CAM > Capture success"); - error = 0x0; - return (dma_control.dma_count); -} + case PDCMI_NO_ERROR: { + TRACE_INFO("CAM > Capture success"); + error = 0x0; + return (dma_control.transfer_count); + } + + default: + TRACE_INFO("CAM > Unknown PDCMI state %d", dma_control->pdcmi_state); + error = 0xA; + return (dma_control.transfer_count); + } /* End switch on PDCMI state. */ +} /* End OV5640_Capture(...) */ /** * Initializes GPIO for OV5640 pseudo DCMI diff --git a/tracker/software/source/drivers/ov5640.h b/tracker/software/source/drivers/ov5640.h index a9dee86c..9abdf639 100644 --- a/tracker/software/source/drivers/ov5640.h +++ b/tracker/software/source/drivers/ov5640.h @@ -28,7 +28,7 @@ #define PDCMI_USE_DMA_DBM FALSE #endif -#define PDCMI_DMA_SEGMENT_SIZE 1024 +#define PDCMI_DMA_DBM_PAGE_SIZE 1024 #define PDCMI_DMA_FIFO_BURST_ALIGN 16 #define PDCMI_DMA_IRQ_PRIO 2 @@ -43,18 +43,19 @@ typedef enum { PDCMI_DMA_END_BUFFER, PDCMI_DMA_COUNT_END, PDCMI_CAPTURE_TIMEOUT -} pdcmi_err_code_t; +} pdcmi_state_t; typedef struct dmaControl { const stm32_dma_stream_t *dmastp; TIM_TypeDef *timer; - uint8_t *segment_address; + uint32_t page_size; + uint8_t *page_address; uint8_t *base_buffer; - uint16_t segment_count; + uint16_t page_count; volatile bool terminate; uint32_t dma_flags; - volatile pdcmi_err_code_t pdcmi_status; - uint32_t dma_count; + pdcmi_state_t pdcmi_state; + uint32_t transfer_count; ioline_t vsync_line; } dma_capture_t; diff --git a/tracker/software/source/threads/rxtx/image.c b/tracker/software/source/threads/rxtx/image.c index 8e504987..be1ebd43 100644 --- a/tracker/software/source/threads/rxtx/image.c +++ b/tracker/software/source/threads/rxtx/image.c @@ -1333,9 +1333,12 @@ void start_image_thread(img_app_conf_t *conf, const char *name) THD_WORKING_AREA_SIZE(35 * 1024), name, LOWPRIO, imgThread, conf); if(!th) { - // Print startup error, do not start watchdog for this thread - TRACE_ERROR("IMG > Could not startup thread" - " (not enough memory available)"); + // Print startup error, do not start watchdog for this thread + TRACE_ERROR("IMG > Could not startup thread" + " (not enough memory available)"); + return; } + TRACE_INFO("IMG > Image capture using DMA %s in thread %s", + PDCMI_USE_DMA_DBM ? "DBM" : "SBM", name); }