diff --git a/arch/arm/core/cortex_m/mpu/arm_core_mpu.c b/arch/arm/core/cortex_m/mpu/arm_core_mpu.c index 95c7112f9f1..859f0747bab 100644 --- a/arch/arm/core/cortex_m/mpu/arm_core_mpu.c +++ b/arch/arm/core/cortex_m/mpu/arm_core_mpu.c @@ -77,8 +77,15 @@ void _arch_configure_static_mpu_regions(void) .start = (u32_t)&_nocache_ram_start, .size = (u32_t)&_nocache_ram_size, .attr = K_MEM_PARTITION_P_RW_U_NA_NOCACHE, - } + }, #endif /* CONFIG_NOCACHE_MEMORY */ +#if defined(CONFIG_RAM_FUNCTION) + { + .start = (u32_t)&_ramfunc_ram_start, + .size = (u32_t)&_ramfunc_ram_start - (u32_t)&_ramfunc_ram_end, + .attr = K_MEM_PARTITION_P_RX_U_RX, + } +#endif /* CONFIG_RAM_FUNCTION */ }; /* Configure the static MPU regions within firmware SRAM boundaries. diff --git a/include/arch/arm/cortex_m/scripts/linker.ld b/include/arch/arm/cortex_m/scripts/linker.ld index 61b2f1f42d6..15e50bcec7b 100644 --- a/include/arch/arm/cortex_m/scripts/linker.ld +++ b/include/arch/arm/cortex_m/scripts/linker.ld @@ -368,6 +368,20 @@ SECTIONS _nocache_ram_size = _nocache_ram_end - _nocache_ram_start; #endif /* CONFIG_NOCACHE_MEMORY */ +#if defined(CONFIG_RAM_FUNCTION) + SECTION_DATA_PROLOGUE(.ramfunc,,) + { + MPU_ALIGN(_ramfunc_ram_size); + _ramfunc_ram_start = .; + *(.ramfunc) + *(".ramfunc.*") + MPU_ALIGN(_ramfunc_ram_size); + _ramfunc_ram_end = .; + } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) + _ramfunc_ram_size = _ramfunc_ram_end - _ramfunc_ram_start; + _ramfunc_rom_start = LOADADDR(.ramfunc); +#endif /* CONFIG_RAM_FUNCTION */ + #if defined(CONFIG_APP_SHARED_MEM) #define APP_SHARED_ALIGN . = ALIGN(_region_min_align); #define SMEM_PARTITION_ALIGN MPU_ALIGN diff --git a/include/linker/linker-defs.h b/include/linker/linker-defs.h index a5dcfa38826..d58b198d0b1 100644 --- a/include/linker/linker-defs.h +++ b/include/linker/linker-defs.h @@ -239,6 +239,16 @@ extern char _nocache_ram_end[]; extern char _nocache_ram_size[]; #endif /* CONFIG_NOCACHE_MEMORY */ +/* Memory owned by the kernel. Start and end will be aligned for memory + * management/protection hardware for the target architecture. + * + * All the functions with '__ramfunc' keyword will be placed into this + * sections. + */ +extern char _ramfunc_ram_start[]; +extern char _ramfunc_ram_end[]; +extern char _ramfunc_rom_start[]; + #endif /* ! _ASMLANGUAGE */ #endif /* ZEPHYR_INCLUDE_LINKER_LINKER_DEFS_H_ */ diff --git a/include/toolchain/gcc.h b/include/toolchain/gcc.h index 7fa0034d96e..297ec32af92 100644 --- a/include/toolchain/gcc.h +++ b/include/toolchain/gcc.h @@ -115,6 +115,16 @@ do { \ #define __in_section_unique(seg) ___in_section(seg, __FILE__, __COUNTER__) +#ifdef CONFIG_RAM_FUNCTION +/* Using this places a function into RAM instead of FLASH. + * Make sure '__ramfunc' are defined only when CONFIG_RAM_FUNCTION, + * so the compiler can report error if used '__ramfunc' but hadn't + * enable CONFIG_RAM_FUNCTION in Kconfig. + */ +#define __ramfunc __attribute__((noinline)) \ + __attribute__((long_call, section(".ramfunc"))) +#endif + #ifndef __packed #define __packed __attribute__((__packed__)) #endif diff --git a/kernel/Kconfig b/kernel/Kconfig index d2261067a89..6ebe719d05f 100644 --- a/kernel/Kconfig +++ b/kernel/Kconfig @@ -207,6 +207,13 @@ config ERRNO symbol. The C library must access the per-thread errno via the _get_errno() symbol. +config RAM_FUNCTION + bool "Enable __ramfunc support" + help + Using '__ramfunc' places a function into RAM instead of Flash. + Code that for example reprograms flash at runtime can't execute + from flash, in that case must placing code into RAM. + choice SCHED_ALGORITHM prompt "Scheduler priority queue algorithm" default SCHED_DUMB diff --git a/kernel/init.c b/kernel/init.c index b2eff58d396..b4166928861 100644 --- a/kernel/init.c +++ b/kernel/init.c @@ -173,6 +173,10 @@ void _data_copy(void) { (void)memcpy(&__data_ram_start, &__data_rom_start, ((u32_t) &__data_ram_end - (u32_t) &__data_ram_start)); +#ifdef CONFIG_RAM_FUNCTION + (void)memcpy(&_ramfunc_ram_start, &_ramfunc_rom_start, + ((u32_t) &_ramfunc_ram_end - (u32_t) &_ramfunc_ram_start)); +#endif #ifdef DT_CCM_BASE_ADDRESS (void)memcpy(&__ccm_data_start, &__ccm_data_rom_start, ((u32_t) &__ccm_data_end - (u32_t) &__ccm_data_start));