From a1318926b49c7d257de2cb36c9e73ddaff9761f3 Mon Sep 17 00:00:00 2001 From: Abdelatif Guettouche Date: Thu, 17 Sep 2020 14:22:30 +0100 Subject: [PATCH] arch/xtensa/esp32: Allow internal drivers and tasks' stack to be allocated in an internal heap. Signed-off-by: Abdelatif Guettouche --- arch/xtensa/Kconfig | 10 ++ arch/xtensa/include/arch.h | 8 ++ arch/xtensa/src/common/xtensa_createstack.c | 16 ++- arch/xtensa/src/common/xtensa_initialize.c | 7 ++ arch/xtensa/src/common/xtensa_releasestack.c | 20 +++- arch/xtensa/src/esp32/Make.defs | 4 + arch/xtensa/src/esp32/esp32_allocateheap.c | 5 + arch/xtensa/src/esp32/esp32_imm.c | 119 +++++++++++++++++++ 8 files changed, 185 insertions(+), 4 deletions(-) create mode 100644 arch/xtensa/src/esp32/esp32_imm.c diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig index 81cd698420..eb195233d3 100644 --- a/arch/xtensa/Kconfig +++ b/arch/xtensa/Kconfig @@ -94,6 +94,16 @@ config XTENSA_CP_INITSET is provided by CONFIG_XTENSA_CP_INITSET. Each bit corresponds to one coprocessor with the same bit layout as for the CPENABLE register. +config XTENSA_USE_SEPERATE_IMEM + bool "Use a seperate heap for internal memory" + default n + +config XTENSA_IMEM_REGION_SIZE + hex "DRAM region size for internal use" + depends on XTENSA_USE_SEPERATE_IMEM + range 0x2000 0x28000 + default 0x28000 + source arch/xtensa/src/lx6/Kconfig if ARCH_CHIP_ESP32 source arch/xtensa/src/esp32/Kconfig diff --git a/arch/xtensa/include/arch.h b/arch/xtensa/include/arch.h index cc073a135c..1db25d4dda 100644 --- a/arch/xtensa/include/arch.h +++ b/arch/xtensa/include/arch.h @@ -91,6 +91,14 @@ extern "C" #define EXTERN extern #endif +#ifdef CONFIG_XTENSA_USE_SEPERATE_IMEM +void up_imm_initialize(void); +FAR void *up_imm_malloc(size_t size); +void up_imm_free(FAR void *mem); +FAR void *up_imm_memalign(size_t alignment, size_t size); +bool up_imm_heapmember(FAR void *mem); +#endif + #undef EXTERN #ifdef __cplusplus } diff --git a/arch/xtensa/src/common/xtensa_createstack.c b/arch/xtensa/src/common/xtensa_createstack.c index a9148fd26c..5b7c6cec17 100644 --- a/arch/xtensa/src/common/xtensa_createstack.c +++ b/arch/xtensa/src/common/xtensa_createstack.c @@ -73,6 +73,18 @@ #define STACK_ALIGN_DOWN(a) ((a) & ~STACK_ALIGN_MASK) #define STACK_ALIGN_UP(a) (((a) + STACK_ALIGN_MASK) & ~STACK_ALIGN_MASK) +#ifdef CONFIG_XTENSA_USE_SEPERATE_IMEM +# define UMM_MALLOC(s) up_imm_malloc(s) +# define UMM_MEMALIGN(a,s) up_imm_memalign(a,s) +# define UMM_FREE(p) up_imm_free(p) +# define UMM_HEAPMEMEBER(p) up_imm_heapmember(p) +#else +# define UMM_MALLOC(s) kumm_malloc(s) +# define UMM_MEMALIGN(a,s) kumm_memalign(a,s) +# define UMM_FREE(p) kumm_free(p) +# define UMM_HEAPMEMEBER(p) umm_heapmember(p) +#endif + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -183,7 +195,7 @@ int up_create_stack(FAR struct tcb_s *tcb, size_t stack_size, uint8_t ttype) /* Use the user-space allocator if this is a task or pthread */ tcb->stack_alloc_ptr = - (uint32_t *)kumm_memalign(TLS_STACK_ALIGN, stack_size); + (uint32_t *)UMM_MEMALIGN(TLS_STACK_ALIGN, stack_size); } #else /* CONFIG_TLS_ALIGNED */ @@ -199,7 +211,7 @@ int up_create_stack(FAR struct tcb_s *tcb, size_t stack_size, uint8_t ttype) { /* Use the user-space allocator if this is a task or pthread */ - tcb->stack_alloc_ptr = (uint32_t *)kumm_malloc(stack_size); + tcb->stack_alloc_ptr = (uint32_t *)UMM_MALLOC(stack_size); } #endif /* CONFIG_TLS_ALIGNED */ diff --git a/arch/xtensa/src/common/xtensa_initialize.c b/arch/xtensa/src/common/xtensa_initialize.c index 54ee18cf5a..be7ecf1d6d 100644 --- a/arch/xtensa/src/common/xtensa_initialize.c +++ b/arch/xtensa/src/common/xtensa_initialize.c @@ -108,6 +108,12 @@ void up_initialize(void) xtensa_pminitialize(); #endif + /* Initialize the internal heap */ + +#ifdef CONFIG_XTENSA_USE_SEPERATE_IMEM + up_imm_initialize(); +#endif + #ifdef CONFIG_ARCH_DMA /* Initialize the DMA subsystem if the weak function xtensa_dma_initialize * has been brought into the build @@ -208,5 +214,6 @@ void up_initialize(void) /* Initialize USB -- device and/or host */ up_usbinitialize(); + board_autoled_on(LED_IRQSENABLED); } diff --git a/arch/xtensa/src/common/xtensa_releasestack.c b/arch/xtensa/src/common/xtensa_releasestack.c index fb6ef6e470..3cc406a43a 100644 --- a/arch/xtensa/src/common/xtensa_releasestack.c +++ b/arch/xtensa/src/common/xtensa_releasestack.c @@ -47,6 +47,22 @@ #include "xtensa.h" +/**************************************************************************** + * Pre-processor Macros + ****************************************************************************/ + +#ifdef CONFIG_XTENSA_USE_SEPERATE_IMEM +# define UMM_MALLOC(s) up_imm_malloc(s) +# define UMM_MEMALIGN(a,s) up_imm_memalign(a,s) +# define UMM_FREE(p) up_imm_free(p) +# define UMM_HEAPMEMEBER(p) up_imm_heapmember(p) +#else +# define UMM_MALLOC(s) kumm_malloc(s) +# define UMM_MEMALIGN(a,s) kumm_memalign(a,s) +# define UMM_FREE(p) kumm_free(p) +# define UMM_HEAPMEMEBER(p) umm_heapmember(p) +#endif + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -103,9 +119,9 @@ void up_release_stack(FAR struct tcb_s *dtcb, uint8_t ttype) { /* Use the user-space allocator if this is a task or pthread */ - if (umm_heapmember(dtcb->stack_alloc_ptr)) + if (UMM_HEAPMEMEBER(dtcb->stack_alloc_ptr)) { - kumm_free(dtcb->stack_alloc_ptr); + UMM_FREE(dtcb->stack_alloc_ptr); } } diff --git a/arch/xtensa/src/esp32/Make.defs b/arch/xtensa/src/esp32/Make.defs index b2090daa0a..0a9f3f7345 100644 --- a/arch/xtensa/src/esp32/Make.defs +++ b/arch/xtensa/src/esp32/Make.defs @@ -99,6 +99,10 @@ endif CHIP_CSRCS += esp32_rtc.c +ifeq ($(CONFIG_XTENSA_USE_SEPERATE_IMEM),y) +CHIP_CSRCS += esp32_imm.c +endif + ifeq ($(CONFIG_ESP32_I2C),y) CHIP_CSRCS += esp32_i2c.c endif diff --git a/arch/xtensa/src/esp32/esp32_allocateheap.c b/arch/xtensa/src/esp32/esp32_allocateheap.c index c3b048ab70..1740ab6587 100644 --- a/arch/xtensa/src/esp32/esp32_allocateheap.c +++ b/arch/xtensa/src/esp32/esp32_allocateheap.c @@ -77,8 +77,13 @@ void up_allocate_heap(FAR void **heap_start, size_t *heap_size) { board_autoled_on(LED_HEAPALLOCATE); +#ifdef CONFIG_XTENSA_USE_SEPERATE_IMEM + *heap_start = (FAR void *)&_sheap + CONFIG_XTENSA_IMEM_REGION_SIZE; + *heap_size = (size_t)((uintptr_t)&_eheap - (uintptr_t)*heap_start); +#else *heap_start = (FAR void *)&_sheap; *heap_size = (size_t)((uintptr_t)&_eheap - (uintptr_t)&_sheap); +#endif } /**************************************************************************** diff --git a/arch/xtensa/src/esp32/esp32_imm.c b/arch/xtensa/src/esp32/esp32_imm.c new file mode 100644 index 0000000000..d7487b16e9 --- /dev/null +++ b/arch/xtensa/src/esp32/esp32_imm.c @@ -0,0 +1,119 @@ +/**************************************************************************** + * arch/xtensa/src/esp32/esp32_imm.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include "xtensa.h" + +#if CONFIG_XTENSA_USE_SEPERATE_IMEM + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +struct mm_heap_s g_iheap; + +/**************************************************************************** + * Name: up_imm_initialize + * + * Description: + * Initialize the internal heap. + * + ****************************************************************************/ + +void up_imm_initialize(void) +{ + void *start; + size_t size; + + start = (FAR void *)&_sheap; + size = CONFIG_XTENSA_IMEM_REGION_SIZE; + mm_initialize(&g_iheap, start, size); +} + +/**************************************************************************** + * Name: up_imm_malloc + * + * Description: + * Allocate memory from the internal heap. + * + ****************************************************************************/ + +FAR void *up_imm_malloc(size_t size) +{ + return mm_malloc(&g_iheap, size); +} + +/**************************************************************************** + * Name: up_imm_free + * + * Description: + * Free memory from the internal heap. + * + ****************************************************************************/ + +void up_imm_free(FAR void *mem) +{ + mm_free(&g_iheap, mem); +} + +/**************************************************************************** + * Name: up_imm_memalign + * + * Description: + * memalign requests more than enough space from malloc, finds a region + * within that chunk that meets the alignment request and then frees any + * leading or trailing space. + * + * The alignment argument must be a power of two (not checked). 8-byte + * alignment is guaranteed by normal malloc calls. + * + ****************************************************************************/ + +FAR void *up_imm_memalign(size_t alignment, size_t size) +{ + return mm_memalign(&g_iheap, alignment, size); +} + +/**************************************************************************** + * Name: up_imm_heapmember + * + * Description: + * Check if an address lies in the internal heap. + * + * Parameters: + * mem - The address to check + * + * Return Value: + * true if the address is a member of the internal heap. false if not + * + ****************************************************************************/ + +bool up_imm_heapmember(FAR void *mem) +{ + return mm_heapmember(&g_iheap, mem); +} +#endif /* CONFIG_XTENSA_USE_SEPERATE_IMEM */