Skip to content

Commit

Permalink
mm: Support multi-heap memory
Browse files Browse the repository at this point in the history
There are two cases to use multi-heap regions.
1. continuous physical RAM but want to split regions
2. separated physical RAMs but want to use for heap

Signed-off-by: jc_.kim <[email protected]>
  • Loading branch information
jeongchanKim committed Nov 16, 2018
1 parent fb8366e commit 7ea39b8
Show file tree
Hide file tree
Showing 43 changed files with 617 additions and 183 deletions.
2 changes: 1 addition & 1 deletion apps/system/utils/kdbg_heapinfo.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ int kdbg_heapinfo(int argc, char **args)
goto usage;
}

struct mm_heap_s *user_heap = mm_get_heap_info();
struct mm_heap_s *user_heap = mm_get_heap_info(BASE_HEAP);
while ((option = getopt(argc, args, "iap:fg")) != ERROR) {
switch (option) {
case 'i':
Expand Down
8 changes: 4 additions & 4 deletions docs/HowToConfigureMemory.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
> [Multi-Heap Support](#multi-heap-support)
## Configuration
There are two configurations to configure memory, CONFIG_RAM_START and CONFIG_RAM_SIZE.
There are two configurations to configure memory, CONFIG_RAM_REGIONx_START and CONFIG_RAM_REGIONx_SIZE.
Menuconfig helps to change them as shown below:
```
cd $TIZENRT_BASEDIR
Expand All @@ -17,10 +17,10 @@ Find configs with following step:
```
Hardware Configuration -> Chip selection -> Boot Memory Configuration
```
Set CONFIG_RAM_START as hexa value and set CONFIG_RAM_SIZE as decimal value.
Set CONFIG_RAM_REGIONx_START as hexa value and set CONFIG_RAM_REGIONx_SIZE as decimal value in bytes.
```
CONFIG_RAM_START=0x02023800
CONFIG_RAM_SIZE=968704
CONFIG_RAM_REGIONx_START=0x02023800
CONFIG_RAM_REGIONx_SIZE=968704
```
Heap allocation will use these values for setting heap start and end address.

Expand Down
55 changes: 42 additions & 13 deletions docs/HowToUseMultiHeap.md
Original file line number Diff line number Diff line change
@@ -1,30 +1,59 @@
# How to use(add) Multi-heap Regions
# How to use(add) Multi-heap

There are two cases to use multi-heap regions.
1. continuous physical RAM but want to split regions
There are two cases to use multi-heap.
1. continuous physical RAM but want to split regions
2. separated physical RAMs but want to use for heap

To use multi-heap regions, find below two steps.
To use multi-heap, please find three steps as shown below:
- [Set number of Regions](#1-set-number-of-regions)
- [Set number of Heaps](#2-set-number-of-heaps)
- [Set Region start address, size and heap index](#3-set-region-start-address-size-and-heap-index)

## Set number of Heap regions
## 1. Set number of Regions

Set **CONFIG_MM_REGIONS** value which shows how many regions are.
```
Memory Management -> Number of memory regions -> change a number over 2
```
When CONFIG_MM_REGIONS has over 2, RAMx_START and RAMx_SIZE configs come out.

## Set RAM start address and size
## 2. Set number of Heaps

Set start addresses, **CONFIG_RAMx_START** with hexa values and sizes, **CONFIG_RAMx_SIZE** with decimal values of new heap regions.
Set **CONFIG_MM_NHEAPS** value which indicates how many heaps are.
```
Hardware Configuration -> Chip Selection -> List of start address for additional heap region -> set values
Hardware Configuration -> Chip Selection -> List of size for additional heap region -> set values
Memory Management -> Number of heaps -> change a number over 2
```

<U>For a detailed description of **REGION** and **HEAP**, please see the link below.</U>
[Terms for REGION and HEAP](#example-of-multi-heap-usage)

## 3. Set Region start address, size and heap index

Set start addresses, **CONFIG_RAM_REGIONx_START** with hexa values, set sizes, **CONFIG_RAM_REGIONx_SIZE** with decimal values(in bytes) of new heap, and set indexes, **CONFIG_RAM_REGIONx_HEAP_INDEX** with decimal values of new heap.
**CONFIG_RAM_REGIONx_HEAP_INDEX** can be start from 0.
```
Hardware Configuration -> Chip Selection -> List of start address for RAM region -> set values
Hardware Configuration -> Chip Selection -> List of size for RAM region
Hardware Configuration -> Chip Selection -> List of heap index for RAM region
```
Each region is separated by ```','``` as shown below example:
```
0x02000000,0x4000000
100,200
0x02000000,0x04000000,0x07000000
100,400,200
0,1,0
```

Based on above configurations, *up_addregion()* function sets new regions automatically.

## Example of Multi-heap Usage
If there are 3 physical RAMs, and want to use them as 4-heaps like below.
![MultiHeap1](./media/multiheap_1.png)
In this case, **CONFIG_MM_REGIONS** should be set to 6, and **CONFIG_MM_NHEAPS** should be set to 4.
![MultiHeap2](./media/multiheap_2.png)
```
CONFIG_MM_REGIONS=6
CONFIG_MM_NHEAPS=4
CONFIG_RAM_REGIONx_START="0x1000,0x1400,0x3000,0x3800,0x7000,0x7100"
CONFIG_RAM_REGIONx_SIZE="1024,512,2048,512,256,4096"
CONFIG_RAM_REGIONx_HEAP_INDEX="0,1,1,2,2,3"
```

Based on above configurations, *up_addregion* function sets new regions automatically.
Binary file added docs/media/multiheap_1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/media/multiheap_2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 0 additions & 2 deletions os/Directories.mk
Original file line number Diff line number Diff line change
Expand Up @@ -144,9 +144,7 @@ NONFSDIRS = kernel $(ARCH_SRC) $(TINYARA_ADDONS)
FSDIRS = fs drivers
CONTEXTDIRS = $(APPDIR)
CONTEXTDIRS += $(TOOLSDIR)
ifeq ($(CONFIG_HEAPINFO_USER_GROUP),y)
CONTEXTDIRS += mm
endif
ifeq ($(CONFIG_ENABLE_IOTIVITY),y)
CONTEXTDIRS += $(EXTDIR)$(DELIM)iotivity
endif
Expand Down
58 changes: 24 additions & 34 deletions os/arch/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -712,16 +712,6 @@ config BOOT_COPYTORAM
endchoice

menu "Boot Memory Configuration"

config RAM_START
hex "Primary RAM start address (physical)"
default 0x0
---help---
The physical start address of primary installed RAM. "Primary" RAM
refers to the RAM that you link program code into. If program code
does not execute out of RAM but from FLASH, then you may designate
any block of RAM as "primary."

config RAM_VSTART
hex "Primary RAM start address (virtual)"
default 0x0
Expand All @@ -732,40 +722,40 @@ config RAM_VSTART
does not execute out of RAM but from FLASH, then you may designate
any block of RAM as "primary."

config RAM_SIZE
int "Primary RAM size"
default 0
---help---
The size in bytes of the installed primary RAM. "Primary" RAM
refers to the RAM that you link program code into. If program code
does not execute out of RAM but from FLASH, then you may designate
any block of RAM as "primary."

config RAMx_START
string "List of start address for additional heap region"
config RAM_REGIONx_START
string "An address or list of start address for RAM region"
default "0x00000000,"
depends on MM_REGIONS != 1
---help---
The start address list of the additional heap regions.
When you want to use separated heap region in a physical RAM or
two different physical RAMs, set MM_REGIONS first at memory
management, and then set hexa values at RAMx_START and RAMx_SIZE
The address or address list of the RAM regions.
If you want to use more than two RAMs physically, or
if you want to divide RAM into multiple heaps,
set MM_REGIONS first at memory management, and then
set hexa values at RAM_REGIONx_START and RAM_REGIONx_SIZE
to support several heap regions.
Each region is separated by ',' as shown in example.
If it will be an address list, the addresses should be given
by increasing order, and each region is separated by ',' as shown in example.
i.e. "0x02000000,0x4000000"

config RAMx_SIZE
string "List of size for additional heap region"
config RAM_REGIONx_SIZE
string "A size or list of size for RAM region"
default "0,"
depends on MM_REGIONS != 1
---help---
The size list of additional heap region.
Refer RAMx_START content. One different thing is this has
The size list of RAM region.
Refer RAM_REGIONx_START content. One different thing is this has
decimal values (START has hexa values).
This should have same number of list element with RAMx_START's.
Each region is separated by ',' as shown in example.
This should have same number of list element with RAM_REGIONx_START's.
If it will be an list, each region is separated by ',' as shown in example.
i.e. "100,200"

config RAM_REGIONx_HEAP_INDEX
string "List of heap index for RAM region"
default "0,"
depends on MM_NHEAPS != 1
---help---
The heap index list of RAM region.
It means that its region can be handled to the index-th heap.
Index can be from 0 to (MM_NHEAPS-1).

config DDR
bool "Use DDR memory"
default n
Expand Down
36 changes: 16 additions & 20 deletions os/arch/arm/src/common/up_allocateheap.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@

#include <sys/types.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
#include <assert.h>
#include <debug.h>

Expand All @@ -66,9 +68,11 @@

#include <arch/board/board.h>

#if CONFIG_MM_REGIONS > 1
#include <tinyara/mm/mm.h>
#include <tinyara/kmalloc.h>
#endif
#include <tinyara/mm/heap_regioninfo.h>

bool heapx_is_init[CONFIG_MM_NHEAPS];

#if defined(CONFIG_BUILD_PROTECTED) && defined(CONFIG_MM_KERNEL_HEAP)
#include <string.h>
Expand Down Expand Up @@ -161,9 +165,9 @@ void up_allocate_heap(FAR void **heap_start, size_t *heap_size)

uintptr_t ubss_start = (uintptr_t)USERSPACE->us_bssstart;
uintptr_t ubase = (uintptr_t)USERSPACE->us_bssend;
size_t usize = CONFIG_RAM_END - ubase;
size_t usize = REGION_END - ubase;

DEBUGASSERT(ubase < (uintptr_t)CONFIG_RAM_END);
DEBUGASSERT(ubase < (uintptr_t)(REGION_END);

/* zero initialize the user space bss section */
memset((void *)ubss_start, 0, (ubase - ubss_start));
Expand All @@ -178,7 +182,8 @@ void up_allocate_heap(FAR void **heap_start, size_t *heap_size)

board_led_on(LED_HEAPALLOCATE);
*heap_start = (FAR void *)(g_idle_topstack & ~(0x7));
*heap_size = CONFIG_RAM_END - (uint32_t)(*heap_start);
*heap_size = REGION_END - (uint32_t)(*heap_start);

#endif
}

Expand Down Expand Up @@ -212,23 +217,14 @@ void up_allocate_kheap(FAR void **heap_start, size_t *heap_size)
void up_addregion(void)
{
int region_cnt;
char *mem_start = CONFIG_RAMx_START;
char *mem_size = CONFIG_RAMx_SIZE;

for (region_cnt = 0; region_cnt < CONFIG_MM_REGIONS - 1; region_cnt++) {
if (!*mem_start || !*mem_size) {
dbg("Fail to add %dth heap region\n", region_cnt + 1);
break;
}
kumm_addregion((void *)strtol(mem_start, &mem_start, 16), (size_t)strtol(mem_size, &mem_size, 0));

if (*mem_start == ',') {
mem_start++;
}

if (*mem_size == ',') {
mem_size++;
for (region_cnt = 1; region_cnt < CONFIG_MM_REGIONS; region_cnt++) {
if (heapx_is_init[regionx_heap_idx[region_cnt]] != true) {
mm_initialize(&g_mmheap[regionx_heap_idx[region_cnt]], regionx_start[region_cnt], regionx_size[region_cnt]);
heapx_is_init[regionx_heap_idx[region_cnt]] = true;
continue;
}
mm_addregion(&g_mmheap[regionx_heap_idx[region_cnt]], regionx_start[region_cnt], regionx_size[region_cnt]);
}
}
#endif
4 changes: 0 additions & 4 deletions os/arch/arm/src/common/up_initialize.c
Original file line number Diff line number Diff line change
Expand Up @@ -166,10 +166,6 @@ void up_initialize(void)

up_color_intstack();

/* Add any extra memory fragments to the memory manager */

up_addregion();

/* Initialize the interrupt subsystem */

up_irqinitialize();
Expand Down
8 changes: 0 additions & 8 deletions os/arch/arm/src/common/up_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -504,14 +504,6 @@ void up_l2ccinitialize(void);
#define up_l2ccinitialize()
#endif

/* Memory management ********************************************************/

#if CONFIG_MM_REGIONS > 1
void up_addregion(void);
#else
#define up_addregion()
#endif

/* Watchdog timer ***********************************************************/

void up_wdtinit(void);
Expand Down
24 changes: 13 additions & 11 deletions os/arch/arm/src/tiva/tiva_allocateheap.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@
#include <tinyara/arch.h>
#include <tinyara/board.h>
#include <tinyara/userspace.h>
#include <tinyara/mm/mm.h>
#include <tinyara/mm/heap_regioninfo.h>

#include <arch/board/board.h>

Expand Down Expand Up @@ -130,21 +132,21 @@ void up_allocate_heap(FAR void **heap_start, size_t *heap_size)
*/

uintptr_t ubase = (uintptr_t) USERSPACE->us_bssend + CONFIG_MM_KERNEL_HEAPSIZE;
size_t usize = CONFIG_RAM_END - ubase;
size_t usize = REGION_END - ubase;
int log2;

DEBUGASSERT(ubase < (uintptr_t) CONFIG_RAM_END);
DEBUGASSERT(ubase < (uintptr_t)(REGION_END);

/* Adjust that size to account for MPU alignment requirements.
* NOTE that there is an implicit assumption that the CONFIG_RAM_END
* NOTE that there is an implicit assumption that the RAM_END(REGION_START + REGION_SIZE)
* is aligned to the MPU requirement.
*/

log2 = (int)mpu_log2regionfloor(usize);
DEBUGASSERT((CONFIG_RAM_END & ((1 << log2) - 1)) == 0);
DEBUGASSERT((REGION_END & ((1 << log2) - 1)) == 0);

usize = (1 << log2);
ubase = CONFIG_RAM_END - usize;
ubase = REGION_END - usize;

/* Return the user-space heap settings */

Expand All @@ -161,7 +163,7 @@ void up_allocate_heap(FAR void **heap_start, size_t *heap_size)

board_led_on(LED_HEAPALLOCATE);
*heap_start = (FAR void *)g_idle_topstack;
*heap_size = CONFIG_RAM_END - g_idle_topstack;
*heap_size = REGION_END - (uint32_t)(*heap_start);
#endif
}

Expand All @@ -184,21 +186,21 @@ void up_allocate_kheap(FAR void **heap_start, size_t *heap_size)
*/

uintptr_t ubase = (uintptr_t) USERSPACE->us_bssend + CONFIG_MM_KERNEL_HEAPSIZE;
size_t usize = CONFIG_RAM_END - ubase;
size_t usize = REGION_END - ubase;
int log2;

DEBUGASSERT(ubase < (uintptr_t) CONFIG_RAM_END);
DEBUGASSERT(ubase < (uintptr_t)(REGION_END));

/* Adjust that size to account for MPU alignment requirements.
* NOTE that there is an implicit assumption that the CONFIG_RAM_END
* NOTE that there is an implicit assumption that the RAM_END(REGION_START + REGION_SIZE)
* is aligned to the MPU requirement.
*/

log2 = (int)mpu_log2regionfloor(usize);
DEBUGASSERT((CONFIG_RAM_END & ((1 << log2) - 1)) == 0);
DEBUGASSERT((REGION_END & ((1 << log2) - 1)) == 0);

usize = (1 << log2);
ubase = CONFIG_RAM_END - usize;
ubase = REGION_END - usize;

/* Return the kernel heap settings (i.e., the part of the heap region
* that was not dedicated to the user heap).
Expand Down
3 changes: 2 additions & 1 deletion os/arch/arm/src/tiva/tiva_irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@

#include <tinyara/irq.h>
#include <tinyara/arch.h>
#include <tinyara/mm/heap_regioninfo.h>
#include <arch/irq.h>

#include "nvic.h"
Expand Down Expand Up @@ -358,7 +359,7 @@ void up_irqinitialize(void)
#endif

#ifdef CONFIG_ARCH_CHIP_CC3200
putreg32((uint32_t) CONFIG_RAM_START, NVIC_VECTAB);
putreg32((uint32_t)REGION_START, NVIC_VECTAB);
#endif

/* Set all interrupts (and exceptions) to the default priority */
Expand Down
Loading

0 comments on commit 7ea39b8

Please sign in to comment.