ports: Fix accidental CPU cache invalidation.

This commit is contained in:
Kwabena W. Agyeman 2024-06-18 21:51:58 -07:00
parent df7df2ba82
commit cc823e2fbb
4 changed files with 31 additions and 8 deletions

View File

@ -404,8 +404,10 @@ vbuffer_t *framebuffer_get_head(framebuffer_flags_t flags) {
vbuffer_t *buffer = framebuffer_get_buffer(new_head); vbuffer_t *buffer = framebuffer_get_buffer(new_head);
#ifdef __DCACHE_PRESENT #ifdef __DCACHE_PRESENT
// Make sure any cached CPU reads are dropped before returning the buffer. if (flags & FB_INVALIDATE) {
SCB_InvalidateDCache_by_Addr(buffer->data, framebuffer_get_buffer_size()); // Make sure any cached CPU reads are dropped before returning the buffer.
SCB_InvalidateDCache_by_Addr(buffer->data, framebuffer_get_buffer_size());
}
#endif #endif
return buffer; return buffer;

View File

@ -40,8 +40,9 @@ typedef struct framebuffer {
extern framebuffer_t *framebuffer; extern framebuffer_t *framebuffer;
typedef enum { typedef enum {
FB_NO_FLAGS = (0 << 0), FB_NO_FLAGS = (0 << 0),
FB_PEEK = (1 << 0), // If set, will not move the head/tail. FB_PEEK = (1 << 0), // If set, will not move the head/tail.
FB_INVALIDATE = (1 << 1), // If set, invalidate the buffer on return.
} framebuffer_flags_t; } framebuffer_flags_t;
typedef struct vbuffer { typedef struct vbuffer {

View File

@ -26,6 +26,7 @@
#define DMA_LENGTH_ALIGNMENT (8) #define DMA_LENGTH_ALIGNMENT (8)
#define SENSOR_TIMEOUT_MS (3000) #define SENSOR_TIMEOUT_MS (3000)
#define MIN_EDMA_DST_INC (4)
// Sensor struct. // Sensor struct.
sensor_t sensor = {}; sensor_t sensor = {};
@ -156,6 +157,7 @@ int sensor_abort(bool fifo_flush, bool in_irq) {
CSI_DisableInterrupts(CSI, CSI_IRQ_FLAGS); CSI_DisableInterrupts(CSI, CSI_IRQ_FLAGS);
CSI_REG_CR3(CSI) &= ~CSI_CR3_DMA_REQ_EN_RFF_MASK; CSI_REG_CR3(CSI) &= ~CSI_CR3_DMA_REQ_EN_RFF_MASK;
CSI_REG_CR18(CSI) &= ~CSI_CR18_CSI_ENABLE_MASK; CSI_REG_CR18(CSI) &= ~CSI_CR18_CSI_ENABLE_MASK;
dest_inc_size = 0;
sensor.first_line = false; sensor.first_line = false;
sensor.drop_frame = false; sensor.drop_frame = false;
sensor.last_frame_ms = 0; sensor.last_frame_ms = 0;
@ -208,7 +210,7 @@ int sensor_dma_memcpy(void *dma, void *dst, void *src, int bpp, bool transposed)
// beats. Additionally, the CSI hardware lacks cropping so we cannot align the source address. // beats. Additionally, the CSI hardware lacks cropping so we cannot align the source address.
// Given this, performance will be lacking on cropped images. So much so that we do not use // Given this, performance will be lacking on cropped images. So much so that we do not use
// the EDMA for anything less than 4-byte transfers otherwise you get sensor timeout errors. // the EDMA for anything less than 4-byte transfers otherwise you get sensor timeout errors.
if (dest_inc_size < 4) { if (dest_inc_size < MIN_EDMA_DST_INC) {
return -1; return -1;
} }
@ -468,7 +470,16 @@ int sensor_snapshot(sensor_t *sensor, image_t *image, uint32_t flags) {
} }
#endif #endif
vbuffer_t *buffer = framebuffer_get_head(FB_NO_FLAGS); framebuffer_flags_t fb_flags = FB_NO_FLAGS;
#if defined(OMV_CSI_DMA)
// dest_inc_size will be less than MIN_EDMA_DST_INC if the EDMA is not initialized or unusable.
if (dest_inc_size >= MIN_EDMA_DST_INC) {
fb_flags = FB_INVALIDATE;
}
#endif
vbuffer_t *buffer = framebuffer_get_head(fb_flags);
// Wait for the DMA to finish the transfer. // Wait for the DMA to finish the transfer.
for (mp_uint_t ticks = mp_hal_ticks_ms(); buffer == NULL;) { for (mp_uint_t ticks = mp_hal_ticks_ms(); buffer == NULL;) {
MICROPY_EVENT_POLL_HOOK MICROPY_EVENT_POLL_HOOK
@ -483,7 +494,7 @@ int sensor_snapshot(sensor_t *sensor, image_t *image, uint32_t flags) {
return SENSOR_ERROR_CAPTURE_TIMEOUT; return SENSOR_ERROR_CAPTURE_TIMEOUT;
} }
buffer = framebuffer_get_head(FB_NO_FLAGS); buffer = framebuffer_get_head(fb_flags);
} }
// We're done receiving data. // We're done receiving data.

View File

@ -825,10 +825,19 @@ int sensor_snapshot(sensor_t *sensor, image_t *image, uint32_t flags) {
__HAL_DCMI_ENABLE_IT(&DCMIHandle, DCMI_IT_FRAME); __HAL_DCMI_ENABLE_IT(&DCMIHandle, DCMI_IT_FRAME);
} }
framebuffer_flags_t fb_flags = FB_NO_FLAGS;
#if defined(OMV_MDMA_CHANNEL_DCMI_0)
// DCMI_MDMA_Handle0.State will be HAL_MDMA_STATE_RESET if the MDMA is not initialized.
if (DCMI_MDMA_Handle0.State != HAL_MDMA_STATE_RESET) {
fb_flags = FB_INVALIDATE;
}
#endif
vbuffer_t *buffer = NULL; vbuffer_t *buffer = NULL;
// Wait for the frame data. __WFI() below will exit right on time because of DCMI_IT_FRAME. // Wait for the frame data. __WFI() below will exit right on time because of DCMI_IT_FRAME.
// While waiting SysTick will trigger allowing us to timeout. // While waiting SysTick will trigger allowing us to timeout.
for (uint32_t tick_start = HAL_GetTick(); !(buffer = framebuffer_get_head(FB_NO_FLAGS)); ) { for (uint32_t tick_start = HAL_GetTick(); !(buffer = framebuffer_get_head(fb_flags)); ) {
__WFI(); __WFI();
// If we haven't exited this loop before the timeout then we need to abort the transfer. // If we haven't exited this loop before the timeout then we need to abort the transfer.