mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-01-18 12:52:44 +01:00
Merge pull request #12928 from benpicco/newlib-multiheap
sys/newlib: enable multiple heaps in _sbrk_r()
This commit is contained in:
commit
f688f84a15
@ -185,4 +185,9 @@ SECTIONS
|
|||||||
/* Round size so that we can use 4 byte copy in init */
|
/* Round size so that we can use 4 byte copy in init */
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
} > bkup-ram
|
} > bkup-ram
|
||||||
|
|
||||||
|
.heap3 (NOLOAD) : ALIGN(4) {
|
||||||
|
_sheap1 = . ;
|
||||||
|
_eheap1 = ORIGIN(bkup-ram) + LENGTH(bkup-ram);
|
||||||
|
} > bkup-ram
|
||||||
}
|
}
|
||||||
|
@ -83,6 +83,12 @@ extern unsigned __stack_irq_size;
|
|||||||
#define ISR_STACKSIZE ((unsigned) &__stack_irq_size)
|
#define ISR_STACKSIZE ((unsigned) &__stack_irq_size)
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The CPU has 4 blocks of SRAM at different addresses.
|
||||||
|
* (primary RAM, USB RAM, Ethernet RAM & Backup RAM)
|
||||||
|
*/
|
||||||
|
#define NUM_HEAPS (4)
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -175,10 +175,10 @@ SECTIONS
|
|||||||
_sram = ORIGIN(ram);
|
_sram = ORIGIN(ram);
|
||||||
_eram = ORIGIN(ram) + LENGTH(ram);
|
_eram = ORIGIN(ram) + LENGTH(ram);
|
||||||
|
|
||||||
__heap2_size = LENGTH(ram_ethernet);
|
.heap1 ALIGN(4) (NOLOAD) :
|
||||||
.heap2 (NOLOAD) :
|
|
||||||
{
|
{
|
||||||
PROVIDE(__heap2_start = . );
|
_sheap1 = ORIGIN(ram_ethernet);
|
||||||
|
_eheap1 = ORIGIN(ram_ethernet) + LENGTH(ram_ethernet);
|
||||||
} > ram_ethernet
|
} > ram_ethernet
|
||||||
|
|
||||||
. = ORIGIN(ram_usb);
|
. = ORIGIN(ram_usb);
|
||||||
@ -187,12 +187,11 @@ SECTIONS
|
|||||||
*(.usbdata)
|
*(.usbdata)
|
||||||
} > ram_usb
|
} > ram_usb
|
||||||
|
|
||||||
.heap3 ALIGN(0x1000) (NOLOAD) :
|
.heap2 ALIGN(4) (NOLOAD) :
|
||||||
{
|
{
|
||||||
__heap3_size = ORIGIN(ram_usb) + LENGTH(ram_usb) - ABSOLUTE(.);
|
_sheap2 = . ;
|
||||||
PROVIDE(__heap3_start = . );
|
_eheap2 = ORIGIN(ram_usb) + LENGTH(ram_usb);
|
||||||
} > ram_usb
|
} > ram_usb
|
||||||
__heap_size = SIZEOF(.heap3);
|
|
||||||
|
|
||||||
_sbackup_data_load = LOADADDR(.backup.data);
|
_sbackup_data_load = LOADADDR(.backup.data);
|
||||||
.backup.data : ALIGN(4) {
|
.backup.data : ALIGN(4) {
|
||||||
@ -210,4 +209,9 @@ SECTIONS
|
|||||||
/* Round size so that we can use 4 byte copy in init */
|
/* Round size so that we can use 4 byte copy in init */
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
} > ram_battery
|
} > ram_battery
|
||||||
|
|
||||||
|
.heap3 (NOLOAD) : ALIGN(4) {
|
||||||
|
_sheap3 = . ;
|
||||||
|
_eheap3 = ORIGIN(ram_battery) + LENGTH(ram_battery);
|
||||||
|
} > ram_battery
|
||||||
}
|
}
|
||||||
|
@ -126,6 +126,13 @@ as shown in the NVM Row Organization figure. */
|
|||||||
#endif
|
#endif
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The CPU has Low Power RAM that can be used as Heap
|
||||||
|
*/
|
||||||
|
#ifdef CPU_HAS_BACKUP_RAM
|
||||||
|
#define NUM_HEAPS (2)
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -56,12 +56,79 @@
|
|||||||
#include "xtimer.h"
|
#include "xtimer.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef NUM_HEAPS
|
||||||
|
#define NUM_HEAPS 1
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief manage the heap
|
* @brief manage the heap
|
||||||
*/
|
*/
|
||||||
extern char _sheap; /* start of the heap */
|
extern char _sheap; /* start of the heap */
|
||||||
extern char _eheap; /* end of the heap */
|
extern char _eheap; /* end of the heap */
|
||||||
char *heap_top = &_sheap + 4;
|
|
||||||
|
/**
|
||||||
|
* @brief Additional heap sections that may be defined in the linkerscript.
|
||||||
|
*
|
||||||
|
* The compiler should not generate references to those symbols if
|
||||||
|
* they are not used, so only provide them if additional memory sections
|
||||||
|
* that can be used as heap are available.
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
extern char _sheap1;
|
||||||
|
extern char _eheap1;
|
||||||
|
|
||||||
|
extern char _sheap2;
|
||||||
|
extern char _eheap2;
|
||||||
|
|
||||||
|
extern char _sheap3;
|
||||||
|
extern char _eheap3;
|
||||||
|
/* @} */
|
||||||
|
|
||||||
|
struct heap {
|
||||||
|
char* start;
|
||||||
|
char* end;
|
||||||
|
};
|
||||||
|
|
||||||
|
static char *heap_top[NUM_HEAPS] = {
|
||||||
|
&_sheap,
|
||||||
|
#if NUM_HEAPS > 1
|
||||||
|
&_sheap1,
|
||||||
|
#endif
|
||||||
|
#if NUM_HEAPS > 2
|
||||||
|
&_sheap2,
|
||||||
|
#endif
|
||||||
|
#if NUM_HEAPS > 3
|
||||||
|
&_sheap3,
|
||||||
|
#endif
|
||||||
|
#if NUM_HEAPS > 4
|
||||||
|
#error "Unsupported NUM_HEAPS value, edit newlib_syscalls_default/syscalls.c to add more heaps."
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct heap heaps[NUM_HEAPS] = {
|
||||||
|
{
|
||||||
|
.start = &_sheap,
|
||||||
|
.end = &_eheap
|
||||||
|
},
|
||||||
|
#if NUM_HEAPS > 1
|
||||||
|
{
|
||||||
|
.start = &_sheap1,
|
||||||
|
.end = &_eheap1
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#if NUM_HEAPS > 2
|
||||||
|
{
|
||||||
|
.start = &_sheap2,
|
||||||
|
.end = &_eheap2
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#if NUM_HEAPS > 3
|
||||||
|
{
|
||||||
|
.start = &_sheap3,
|
||||||
|
.end = &_eheap3
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
/* MIPS newlib crt implements _init,_fini and _exit and manages the heap */
|
/* MIPS newlib crt implements _init,_fini and _exit and manages the heap */
|
||||||
#ifndef __mips__
|
#ifndef __mips__
|
||||||
@ -108,15 +175,22 @@ void _exit(int n)
|
|||||||
*/
|
*/
|
||||||
void *_sbrk_r(struct _reent *r, ptrdiff_t incr)
|
void *_sbrk_r(struct _reent *r, ptrdiff_t incr)
|
||||||
{
|
{
|
||||||
|
void *res = (void*)UINTPTR_MAX;
|
||||||
unsigned int state = irq_disable();
|
unsigned int state = irq_disable();
|
||||||
void *res = heap_top;
|
|
||||||
|
|
||||||
if ((heap_top + incr > &_eheap) || (heap_top + incr < &_sheap)) {
|
for (unsigned i = 0; i < NUM_HEAPS; ++i) {
|
||||||
r->_errno = ENOMEM;
|
if ((heap_top[i] + incr > heaps[i].end) ||
|
||||||
res = (void *)-1;
|
(heap_top[i] + incr < heaps[i].start)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = heap_top[i];
|
||||||
|
heap_top[i] += incr;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
heap_top += incr;
|
if (res == (void*)UINTPTR_MAX) {
|
||||||
|
r->_errno = ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
irq_restore(state);
|
irq_restore(state);
|
||||||
|
Loading…
Reference in New Issue
Block a user