diff --git a/common/fb_alloc.c b/common/fb_alloc.c index 4ca2d561b..3d82a164a 100644 --- a/common/fb_alloc.c +++ b/common/fb_alloc.c @@ -39,14 +39,14 @@ static uint32_t alloc_bytes_peak; #endif #if defined(OMV_FB_OVERLAY_MEMORY) -#define FB_OVERLAY_MEMORY_FLAG 0x1 +#define FB_OVERLAY_MEMORY_FLAG 0x1 extern char _fballoc_overlay_end, _fballoc_overlay_start; static char *pointer_overlay = &_fballoc_overlay_end; #endif // fb_alloc_free_till_mark() will not free past this. // Use fb_alloc_free_till_mark_permanent() instead. -#define FB_PERMANENT_FLAG 0x2 +#define FB_PERMANENT_FLAG 0x2 char *fb_alloc_stack_pointer() { return pointer; @@ -146,7 +146,7 @@ void *fb_alloc(uint32_t size, int hints) { size = ((size + sizeof(uint32_t) - 1) / sizeof(uint32_t)) * sizeof(uint32_t); // Round Up if (hints & FB_ALLOC_CACHE_ALIGN) { - size = ((size + OMV_ALLOC_ALIGNMENT - 1) / OMV_ALLOC_ALIGNMENT) * OMV_ALLOC_ALIGNMENT; + size = OMV_ALIGN_TO(size, OMV_ALLOC_ALIGNMENT); size += OMV_ALLOC_ALIGNMENT - sizeof(uint32_t); } diff --git a/common/fb_alloc.h b/common/fb_alloc.h index e965e8d8d..973148871 100644 --- a/common/fb_alloc.h +++ b/common/fb_alloc.h @@ -30,6 +30,11 @@ #define FB_ALLOC_PREFER_SPEED 1 #define FB_ALLOC_PREFER_SIZE 2 #define FB_ALLOC_CACHE_ALIGN 4 + +#ifndef OMV_ALLOC_ALIGNMENT +#define OMV_ALLOC_ALIGNMENT (OMV_CACHE_LINE_SIZE) +#endif + char *fb_alloc_stack_pointer(); void fb_alloc_fail(); void fb_alloc_init0(); diff --git a/common/omv_common.h b/common/omv_common.h index 77c95556e..654c9c328 100644 --- a/common/omv_common.h +++ b/common/omv_common.h @@ -26,20 +26,25 @@ #ifndef __OMV_COMMON_H__ #define __OMV_COMMON_H__ -#define OMV_ATTR_ALIGNED(x, a) x __attribute__((aligned(a))) -#define OMV_ATTR_SECTION(x, s) x __attribute__((section(s))) -#define OMV_ATTR_ALWAYS_INLINE inline __attribute__((always_inline)) -#define OMV_ATTR_OPTIMIZE(o) __attribute__((optimize(o))) -#define OMV_BREAK() __asm__ volatile ("BKPT") +#define OMV_ATTR_ALIGNED(x, a) x __attribute__((aligned(a))) +#define OMV_ATTR_SECTION(x, s) x __attribute__((section(s))) +#define OMV_ATTR_ALWAYS_INLINE inline __attribute__((always_inline)) +#define OMV_ATTR_OPTIMIZE(o) __attribute__((optimize(o))) +#define OMV_ATTR_SEC_ALIGN(x, s, a) x __attribute__((section(s), aligned(a))) +#define OMV_DEBUG_BREAKPOINT() __asm__ volatile ("BKPT") -// Use 32-byte alignment on MCUs with no cache for DMA buffer alignment. #ifndef __DCACHE_PRESENT -#define OMV_ALLOC_ALIGNMENT (32) +#define OMV_CACHE_LINE_SIZE (32) #else -#define OMV_ALLOC_ALIGNMENT (__SCB_DCACHE_LINE_SIZE) +#define OMV_CACHE_LINE_SIZE (__SCB_DCACHE_LINE_SIZE) #endif -#define OMV_ATTR_ALIGNED_DMA(x) OMV_ATTR_ALIGNED(x, OMV_ALLOC_ALIGNMENT) +#ifndef OMV_DMA_ALIGNMENT +#define OMV_DMA_ALIGNMENT (OMV_CACHE_LINE_SIZE) +#endif + +#define OMV_ALIGN_TO(x, alignment) \ + ((((uintptr_t)(x)) + (alignment) - 1) & ~((uintptr_t)((alignment) - 1))) #ifdef OMV_DEBUG_PRINTF #define debug_printf(fmt, ...) \ diff --git a/common/vospi.c b/common/vospi.c index 015379685..08da11c16 100644 --- a/common/vospi.c +++ b/common/vospi.c @@ -68,7 +68,7 @@ typedef struct _vospi_state { static vospi_state_t vospi; -static uint16_t OMV_ATTR_SECTION(OMV_ATTR_ALIGNED_DMA(vospi_buf[VOSPI_BUFFER_SIZE]), OMV_VOSPI_DMA_BUFFER); +static uint16_t OMV_ATTR_SEC_ALIGN(vospi_buf[VOSPI_BUFFER_SIZE], OMV_VOSPI_DMA_BUFFER, OMV_DMA_ALIGNMENT); static void vospi_callback(omv_spi_t *spi, void *userdata, void *buf); static void vospi_resync() { diff --git a/lib/imlib/imlib.c b/lib/imlib/imlib.c index d7a78b83a..e3d3fca75 100644 --- a/lib/imlib/imlib.c +++ b/lib/imlib/imlib.c @@ -241,12 +241,12 @@ void rectangle_united(rectangle_t *dst, rectangle_t *src) { ///////////////// void image_alloc(image_t *img, size_t size) { - // Round the size up to ensure that the allocation is a multiple of the alignment in bytes. - // This ensures after address alignment that the data can be modified without affecting other cache lines. - size = ((size + OMV_ALLOC_ALIGNMENT - 1) / OMV_ALLOC_ALIGNMENT) * OMV_ALLOC_ALIGNMENT; - img->_raw = m_malloc(size + OMV_ALLOC_ALIGNMENT - 1); - // Offset the data pointer to ensure it is aligned. - img->data = (void *) (((uintptr_t) img->_raw + OMV_ALLOC_ALIGNMENT - 1) & ~(OMV_ALLOC_ALIGNMENT - 1)); + // Align the memory size to cache line. + size = OMV_ALIGN_TO(size, OMV_CACHE_LINE_SIZE); + // Allocate extra to align the pointer. + img->_raw = m_malloc(size + OMV_CACHE_LINE_SIZE - 1); + // Align the memory address to cache line. + img->data = (void *) OMV_ALIGN_TO(img->_raw, OMV_CACHE_LINE_SIZE); } void image_alloc0(image_t *img, size_t size) { diff --git a/lib/stai/stai_backend.c b/lib/stai/stai_backend.c index bd090288c..aefe61a53 100644 --- a/lib/stai/stai_backend.c +++ b/lib/stai/stai_backend.c @@ -33,6 +33,7 @@ #include #include #include "imlib_config.h" +#include "omv_common.h" #include STM32_HAL_H #include "py/runtime.h" @@ -48,8 +49,7 @@ #include "ll_aton_caches_interface.h" #include "ll_aton_reloc_network.h" -#define AI_RELOC_ALIGNMENT (32 - 1) -#define AI_RELOC_ALIGN(x) (((x) + (AI_RELOC_ALIGNMENT)) & ~(AI_RELOC_ALIGNMENT)) +#define AI_RELOC_ALIGNMENT (32) typedef struct ml_backend_state { void *exec_ram_addr; @@ -133,19 +133,19 @@ int ml_backend_init_model(py_ml_model_obj_t *model) { } // Allocate executable memory. - state->exec_ram_size = AI_RELOC_ALIGN(rt.rt_ram_xip); + state->exec_ram_size = OMV_ALIGN_TO(rt.rt_ram_xip, AI_RELOC_ALIGNMENT); state->exec_ram_addr = m_new(uint8_t, state->exec_ram_size + AI_RELOC_ALIGNMENT); // Allocate external memory. - state->ext_ram_size = AI_RELOC_ALIGN(rt.ext_ram_sz); + state->ext_ram_size = OMV_ALIGN_TO(rt.ext_ram_sz, AI_RELOC_ALIGNMENT); state->ext_ram_addr = m_new(uint8_t, state->ext_ram_size + AI_RELOC_ALIGNMENT); // Create and install the relocatable model. ll_aton_reloc_config config = { .ext_ram_size = state->ext_ram_size, - .ext_ram_addr = AI_RELOC_ALIGN((uintptr_t) state->ext_ram_addr), + .ext_ram_addr = OMV_ALIGN_TO(state->ext_ram_addr, AI_RELOC_ALIGNMENT), .exec_ram_size = state->exec_ram_size, - .exec_ram_addr = AI_RELOC_ALIGN((uintptr_t) state->exec_ram_addr), + .exec_ram_addr = OMV_ALIGN_TO(state->exec_ram_addr, AI_RELOC_ALIGNMENT), .ext_param_addr = (uintptr_t) NULL, // For COPY mode - XIP region is expected, else only RW region is requested. // In the case where the HW epoch blob is embedded in the binary image, this diff --git a/lib/tflm/tflm_backend.cc b/lib/tflm/tflm_backend.cc index 73951d7bd..078ea4b51 100644 --- a/lib/tflm/tflm_backend.cc +++ b/lib/tflm/tflm_backend.cc @@ -35,6 +35,8 @@ #include #include "imlib_config.h" +#include "omv_common.h" + #include "tensorflow/lite/micro/micro_op_resolver.h" #include "tensorflow/lite/micro/micro_mutable_op_resolver.h" #include "tensorflow/lite/micro/cortex_m_generic/debug_log_callback.h" @@ -52,8 +54,7 @@ extern "C" { using namespace tflite; #define TF_ARENA_EXTRA (512) -#define TF_ARENA_ALIGN (16 - 1) -#define TF_ARENA_ROUND(x) (((x) + TF_ARENA_ALIGN) & ~(TF_ARENA_ALIGN)) +#define TF_ARENA_ALIGN (16) typedef MicroMutableOpResolver<113> MicroOpsResolver; typedef struct ml_backend_state { @@ -238,7 +239,7 @@ int ml_backend_init_model(py_ml_model_obj_t *model) { mp_raise_msg(&mp_type_ValueError, MP_ERROR_TEXT("Failed to allocate tensors")); } // Round up the optimal arena size to a multiple of the alignment. - arena_size = TF_ARENA_ROUND(interpreter.arena_used_bytes()) + TF_ARENA_EXTRA; + arena_size = OMV_ALIGN_TO(interpreter.arena_used_bytes(), TF_ARENA_ALIGN) + TF_ARENA_EXTRA; m_free(arena_memory); // Allocate the persistent model state and interpreter. diff --git a/modules/py_fir_lepton.c b/modules/py_fir_lepton.c index c5e8948c0..53d955c30 100644 --- a/modules/py_fir_lepton.c +++ b/modules/py_fir_lepton.c @@ -81,7 +81,7 @@ static soft_timer_entry_t flir_lepton_spi_rx_timer = {}; static int fir_lepton_spi_rx_cb_tail = 0; static int fir_lepton_spi_rx_cb_expected_pid = 0; static int fir_lepton_spi_rx_cb_expected_sid = 0; -static uint16_t OMV_ATTR_SECTION(OMV_ATTR_ALIGNED_DMA(fir_lepton_buf[VOSPI_BUFFER_SIZE]), OMV_VOSPI_DMA_BUFFER); +static uint16_t OMV_ATTR_SEC_ALIGN(fir_lepton_buf[VOSPI_BUFFER_SIZE], OMV_VOSPI_DMA_BUFFER, OMV_DMA_ALIGNMENT); static void fir_lepton_spi_callback(omv_spi_t *spi, void *userdata, void *buf); static mp_obj_t fir_lepton_spi_resync_callback(mp_obj_t unused) { diff --git a/modules/py_imageio.c b/modules/py_imageio.c index 89f0b74ec..3cb084d7f 100644 --- a/modules/py_imageio.c +++ b/modules/py_imageio.c @@ -56,20 +56,12 @@ #define RGB565_FIXED_VER 11 #define NEW_PIXFORMAT_VER 20 -#ifndef __DCACHE_PRESENT -#define IMAGE_ALIGNMENT 32 // Use 32-byte alignment on MCUs with no cache for DMA buffer alignment. -#else -#define IMAGE_ALIGNMENT __SCB_DCACHE_LINE_SIZE -#endif +#define IMAGE_ALIGNMENT OMV_CACHE_LINE_SIZE #define IMAGE_T_SIZE_ALIGNED (((sizeof(uint32_t) + sizeof(image_t) + (IMAGE_ALIGNMENT) -1) \ / (IMAGE_ALIGNMENT)) \ * (IMAGE_ALIGNMENT)) -static size_t image_size_aligned(image_t *image) { - return ((image_size(image) + (IMAGE_ALIGNMENT) -1) / (IMAGE_ALIGNMENT)) * (IMAGE_ALIGNMENT); -} - typedef enum image_io_stream_type { IMAGE_IO_FILE_STREAM, IMAGE_IO_MEMORY_STREAM, @@ -579,7 +571,7 @@ static mp_obj_t py_imageio_make_new(const mp_obj_type_t *type, size_t n_args, si } stream->count = mp_obj_get_int(args[1]); - stream->size = IMAGE_T_SIZE_ALIGNED + image_size_aligned(&image); + stream->size = IMAGE_T_SIZE_ALIGNED + OMV_ALIGN_TO(image_size(&image), IMAGE_ALIGNMENT); fb_alloc_mark(); stream->buffer = fb_alloc(stream->count * stream->size, FB_ALLOC_PREFER_SIZE | FB_ALLOC_CACHE_ALIGN); diff --git a/modules/py_ml.c b/modules/py_ml.c index 1e4b6bcf5..9243492ef 100644 --- a/modules/py_ml.c +++ b/modules/py_ml.c @@ -51,13 +51,7 @@ #include "py_ml.h" #include "ulab/code/ndarray.h" -#ifndef IMLIB_ML_MODEL_ALIGN -#ifndef __DCACHE_PRESENT -#define IMLIB_ML_MODEL_ALIGN (32 - 1) -#else -#define IMLIB_ML_MODEL_ALIGN (__SCB_DCACHE_LINE_SIZE - 1) -#endif -#endif +#define IMLIB_ML_MODEL_ALIGN (OMV_CACHE_LINE_SIZE) static size_t py_ml_tuple_sum(mp_obj_tuple_t *o) { if (o->len < 1) { @@ -372,9 +366,9 @@ mp_obj_t py_ml_model_make_new(const mp_obj_type_t *type, size_t n_args, size_t n fb_alloc_mark_permanent(); } else { // Align size and memory and keep a reference to the GC block. - size_t size = (model->size + IMLIB_ML_MODEL_ALIGN) & ~IMLIB_ML_MODEL_ALIGN; - model->_raw = m_malloc(size + IMLIB_ML_MODEL_ALIGN); - model->data = (void *) (((uintptr_t) model->_raw + IMLIB_ML_MODEL_ALIGN) & ~IMLIB_ML_MODEL_ALIGN); + size_t size = OMV_ALIGN_TO(model->size, IMLIB_ML_MODEL_ALIGN); + model->_raw = m_malloc(size + IMLIB_ML_MODEL_ALIGN - 1); + model->data = (void *) OMV_ALIGN_TO(model->_raw, IMLIB_ML_MODEL_ALIGN); } // Read file data. diff --git a/ports/stm32/modules/py_audio.c b/ports/stm32/modules/py_audio.c index b76ed9f1f..e8f5e6ade 100644 --- a/ports/stm32/modules/py_audio.c +++ b/ports/stm32/modules/py_audio.c @@ -52,7 +52,7 @@ static PDM_Filter_Config_t PDM_FilterConfig[OMV_AUDIO_MAX_CHANNELS]; static PDM_Filter_Handler_t PDM_FilterHandler[OMV_AUDIO_MAX_CHANNELS]; // NOTE: BDMA can only access D3 SRAM4 memory. #define PDM_BUFFER_SIZE (16384) -uint8_t OMV_ATTR_SECTION(OMV_ATTR_ALIGNED(PDM_BUFFER[PDM_BUFFER_SIZE], 32), ".d3_dma_buffer"); +uint8_t OMV_ATTR_SEC_ALIGN(PDM_BUFFER[PDM_BUFFER_SIZE], ".d3_dma_buffer", OMV_DMA_ALIGNMENT); #elif defined(OMV_DFSDM) static DFSDM_Channel_HandleTypeDef hdfsdm; @@ -63,7 +63,7 @@ static DMA_HandleTypeDef hdma_filter[OMV_AUDIO_MAX_CHANNELS]; // NOTE: placed in D2 memory. #define PDM_BUFFER_SIZE (512 * 2) -int32_t OMV_ATTR_SECTION(OMV_ATTR_ALIGNED(PDM_BUFFER[PDM_BUFFER_SIZE], 32), ".d2_dma_buffer"); +int32_t OMV_ATTR_SEC_ALIGN(PDM_BUFFER[PDM_BUFFER_SIZE], ".d2_dma_buffer", OMV_DMA_ALIGNMENT); #define DFSDM_GAIN_FRAC_BITS (3) static int32_t dfsdm_gain = 1; @@ -74,11 +74,11 @@ static MDF_FilterConfigTypeDef hmdf_filter[OMV_AUDIO_MAX_CHANNELS]; // NOTE: Only 1 filter is supported right now. static DMA_QListTypeDef dma_queue; -static DMA_NodeTypeDef OMV_ATTR_SECTION(OMV_ATTR_ALIGNED(dma_nodes, 32), ".dma_buffer"); +static DMA_NodeTypeDef OMV_ATTR_SEC_ALIGN(dma_nodes, ".dma_buffer", OMV_DMA_ALIGNMENT); static DMA_HandleTypeDef hdma_filter[OMV_AUDIO_MAX_CHANNELS]; #define PDM_BUFFER_SIZE (512 * 2) -int32_t OMV_ATTR_SECTION(OMV_ATTR_ALIGNED(PDM_BUFFER[PDM_BUFFER_SIZE], 32), ".dma_buffer"); +int32_t OMV_ATTR_SEC_ALIGN(PDM_BUFFER[PDM_BUFFER_SIZE], ".dma_buffer", OMV_DMA_ALIGNMENT); #else #error "No audio driver defined for this board" #endif diff --git a/ports/stm32/stm_nema.c b/ports/stm32/stm_nema.c index dc2f6be61..9c49c2c5b 100644 --- a/ports/stm32/stm_nema.c +++ b/ports/stm32/stm_nema.c @@ -148,7 +148,7 @@ void nema_host_free(void *ptr) { } void *nema_host_malloc(unsigned size) { - return aligned_alloc(__SCB_DCACHE_LINE_SIZE, (size + (__SCB_DCACHE_LINE_SIZE - 1)) & ~(__SCB_DCACHE_LINE_SIZE - 1)); + return aligned_alloc(OMV_CACHE_LINE_SIZE, OMV_ALIGN_TO(size, OMV_CACHE_LINE_SIZE)); } int nema_mutex_lock(int mutex_id) {