RAM Allocation
TWENETmcs/linker/linkscripts
.RAM Allocation
The SRAM area of TWWLIET GOLD is as follows.
BASE | TOP (End + 1) | SIZE | |
---|---|---|---|
SRAM11 | 0x0402_C000 | 0x0403_0000 | 16KB |
SRAM10 | 0x0402_8000 | 0x0402_C000 | 16KB |
SRAM9 | 0x0402_4000 | 0x0402_8000 | 16KB |
SRAM8 | 0x0402_0000 | 0x0402_4000 | 16KB |
SRAM7 | 0x0401_5000 | 0x0401_6000 | 4KB |
SRAM6 | 0x0401_4000 | 0x0401_5000 | 4KB |
SRAM5 | 0x0401_2000 | 0x0401_4000 | 8KB |
SRAM4 | 0x0401_0000 | 0x0401_2000 | 8KB |
SRAM3 | 0x0400_C000 | 0x0401_0000 | 16KB |
SRAM2 | 0x0400_8000 | 0x0400_C000 | 16KB |
SRAM1 | 0x0400_4000 | 0x0400_8000 | 16KB |
SRAM0 | 0x0400_0000 | 0x0400_4000 | 16KB |
TWENET defines the memory map as follows.
BASE | TOP | Size | Purpose | RET | Bank Name | |
---|---|---|---|---|---|---|
Application Use | 0x0400_0000 | Decided at compile time | ~64KB | Required for MMAC linking | 〇 | SRAM0..3 |
Heap | 0x0401_5000 (Changeable) | 0x0401_5C00 | 3KB | Heap area (malloc, new) | 〇 | SRAM7 |
Unused | 0x0402_0000 | 0x0402_C000 | 48KB | Unused area | SRAM8, 9, 10 SRAM11 | |
Unused | 0x0402_C000 | 0x0402_F000 | 12KB | Unused area | SRAM11 | |
Stack | 0x0402_F000 | 0x0403_0000 | 4KB | Stack area | SRAM11 | |
(BASE: Start Address, TOP: End Address + 1, RET: RAM Retention during sleep)
- The application use area is a static memory range determined at compile time. The end address can be referenced with
(uint32)&_end_fw_retention
. When sleeping, the system is set not to retain unnecessary banks based on the end address. - The heap area is a region allocated by
malloc()
and thenew
operator. Generally, repeated allocation and deallocation of this area can lead to fragmentation issues, so you should be mindful of this when implementing your application. The default setting allocates memory to SRAM bank 7. However, the last 512 bytes of bank 7 are reserved by the microcontroller’s semiconductor specifications, and the subsequent 512 bytes are reserved by TWENET.- This area can be adjusted by writing
HEAP_START=0x04014000;
andHEAP_SIZE = 8192 - BANK7_RESERVE;
inApp_User_Defs.ld
(placed directly in the build directory).HEAP_START
is the start address of the heap, andHEAP_SIZE
is the allocated size. Here are some typical combinations:- 0x04014000, 8192-BANK7_RESERVE (7KB, BANK6-7)
- 0x04012000, 16384-BANK7_RESERVE (15KB, BANK5-7)
- 0x04010000, 24576-BANK7_RESERVE (23KB, BANK4-7)
- 0x0, 0 (set the maximum area, i.e., from
_end_fw_rentention
to 0x04016000-BANK7_RESERVE, as the HEAP)
- This area can be adjusted by writing
- The unused areas are SRAM8, 9, and 10, each with 16KB.
- The stack area is set to the last 4096 bytes of SRAM11 (
0x0403_0000
) by default.- You can change the size of this area by writing
STACK_SIZE = 8192;
inApp_User_Defs.ld
(placed directly in the build directory). You can also specify the end address, such asSTACK_TOP = 0x04024000;
. - Please check
_vStackTop
and__StackLimit
in the map file created in the build directory. - This area is not retained during sleep.
- You can change the size of this area by writing
I’ve translated the text and formatted it as plain text to avoid the issue you mentioned earlier.
Setting the Retention Area during Sleep
The TWENET library is pre-configured to properly retain the necessary SRAM banks for the application use and heap areas during sleep. However, depending on the design and implementation of your application, you may want to retain banks that are not normally held. To do this, you can set the corresponding bits for any additional banks you need in the global variable G_TWENET_POWER_DOWN_RETENTION_CONFIG_ADD()
defined in the TWENETcmpt library.
For example, if you want to retain 32KB of banks 8 and 9, specify the following before calling ToCoNet_vSleep()
in the TWENET C library or the_twelite.sleep()
in the mwx library.
G_TWENET_POWER_DOWN_RETENTION_CONFIG_ADD() = PM_CFG_SRAM_BANK8_RET | PM_CFG_SRAM_BANK9_RET;
Note: Increasing the amount of retained SRAM will also increase the sleep current.
App_User_Defs.ld
Configuration Examples
If not specified, the HEAP will be from 0x0401_5000
to 0x0401_5FE0
, and the STACK will be from 0x0402_F000
to 0x0403_0000
. Below are examples for the .../build/App_User_Defs.ld
configuration.
- To allocate the maximum possible HEAP, from
_end_fw_retention
to0x0401_5FE0
:
HEAP_START = 0;
HEAP_SIZE = 0;
- To allocate HEAP in RAM6 and 7 (approx. 8KB):
HEAP_START = 0x04014000;
HEAP_SIZE = 8192 - BANK7_RESERVE;
- To set the HEAP from
_end_fw_retention
to0x0401_5000
and the STACK from0x0401_5000
to0x0401_5FE0
. (This makes BANK8..11 from0x0402_0000
to0x0403_0000
an unused area):
HEAP_TOP = 0x04015000;
HEAP_START = 0;
HEAP_SIZE = 0;
STACK_TOP = 0x04015fe0;
STACK_SIZE = 4096-BANK7_RESERVE;
Note: If both HEAP_START
and HEAP_SIZE
are 0, you can set HEAP_TOP
. In this case, HEAP_TOP
cannot be set to a region equal to or greater than 0x0402_0000
.
- To allocate 64KB for the HEAP from
0x0402_0000
and move the STACK area to a region below0x04015fe0
:
HEAP_START = 0x04020000;
HEAP_SIZE = 0x10000;
STACK_TOP = 0x04015fe0;
STACK_SIZE = 4096-BANK7_RESERVE;
OneTime_Heap.c,h
TWENETutils provides a One Time Heap for sequential memory allocation without deallocation. This makes it easy to use unused areas.
#include <OneTimeHeap.h>
OTHEAP_tsContext scOTHeap;
void setup() {
uint32 u32bytes;
void *p;
// Use the 16KB region from 0x0402_0000 to 0x0402_4000.
OTHEAP_Init(&scOTHeap, 0x04020000, 0x04024000, NULL);
Serial << crlf << "--- One Time HEAP ---";
Serial << crlf << format("start %08x", (uint32)OTHEAP_pvGetRegionStart(&scOTHeap));
Serial << crlf << format("top %08x", (uint32)OTHEAP_pvGetRegionTop(&scOTHeap));
// Allocate 100 bytes
u32bytes = 100;
Serial << crlf;
Serial << crlf << format("head %08x", (uint32)OTHEAP_pvGetHead(&scOTHeap));
p = OTHEAP_pvAlloc(&scOTHeap, u32bytes, TRUE);
// p=0x0402_0004 (The area after the 4-byte header is available)
Serial << crlf << format("alloc %dbytes [%08x->%08x)", u32bytes, (uint32)p, (uint32)p+u32bytes);
if(p) Serial << crlf << format("next %08x", *(uint32*)((uint32)p - 4));
// The header is the address of the next block (0x0402_0068)
// Allocate 10 bytes (actually 12 bytes because it's aligned to a 4-byte boundary)
u32bytes = 10;
Serial << crlf;
Serial << crlf << format("head %08x", (uint32)OTHEAP_pvGetHead(&scOTHeap));
p = OTHEAP_pvAlloc(&scOTHeap, u32bytes, TRUE);
// p=0x0402_006c
Serial << crlf << format("alloc %dbytes [%08x->%08x)", u32bytes, (uint32)p, (uint32)p+u32bytes);
if(p) Serial << crlf << format("next %08x", *(uint32*)((uint32)p - 4));
// The header is the address of the next block (0x0402_0078)
// Free the last allocated block. The address of the freed block (p=0x0402_006c)
p = OTHEAP_pvFreeLastBlock(&scOTHeap);
}