mirror of
https://github.com/licsber/micropython.git
synced 2024-09-20 09:00:23 +08:00
cc3200: Place functions only used while booting in a special section.
Such functions are never used after MicroPython has started, and they remain in RAM wasting space. Now they are placed in a special section named "boot" which sits just before the heap, allowing us to extend the effective heap area up to the new boot section. Right now, this gives us back ~1K, but in the future, more functions might end up in there as well.
This commit is contained in:
parent
02fda44a30
commit
26cbc91373
@ -202,6 +202,7 @@ static void prvTaskExitError( void );
|
|||||||
/*
|
/*
|
||||||
* See header file for description.
|
* See header file for description.
|
||||||
*/
|
*/
|
||||||
|
__attribute__ ((section (".boot")))
|
||||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||||
{
|
{
|
||||||
/* Simulate the stack frame as it would be created by a context switch
|
/* Simulate the stack frame as it would be created by a context switch
|
||||||
@ -220,6 +221,7 @@ StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t px
|
|||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
__attribute__ ((section (".boot")))
|
||||||
static void prvTaskExitError( void )
|
static void prvTaskExitError( void )
|
||||||
{
|
{
|
||||||
/* A function that implements a task must not exit or attempt to return to
|
/* A function that implements a task must not exit or attempt to return to
|
||||||
@ -254,6 +256,7 @@ void vPortSVCHandler( void )
|
|||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
__attribute__ ((section (".boot")))
|
||||||
static void prvPortStartFirstTask( void )
|
static void prvPortStartFirstTask( void )
|
||||||
{
|
{
|
||||||
__asm volatile(
|
__asm volatile(
|
||||||
@ -274,6 +277,7 @@ static void prvPortStartFirstTask( void )
|
|||||||
/*
|
/*
|
||||||
* See header file for description.
|
* See header file for description.
|
||||||
*/
|
*/
|
||||||
|
__attribute__ ((section (".boot")))
|
||||||
BaseType_t xPortStartScheduler( void )
|
BaseType_t xPortStartScheduler( void )
|
||||||
{
|
{
|
||||||
/* configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0.
|
/* configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0.
|
||||||
@ -643,6 +647,7 @@ void xPortSysTickHandler( void )
|
|||||||
* Setup the systick timer to generate the tick interrupts at the required
|
* Setup the systick timer to generate the tick interrupts at the required
|
||||||
* frequency.
|
* frequency.
|
||||||
*/
|
*/
|
||||||
|
__attribute__ ((section (".boot")))
|
||||||
__attribute__(( weak )) void vPortSetupTimerInterrupt( void )
|
__attribute__(( weak )) void vPortSetupTimerInterrupt( void )
|
||||||
{
|
{
|
||||||
/* Calculate the constants required to configure the tick interrupt. */
|
/* Calculate the constants required to configure the tick interrupt. */
|
||||||
|
@ -515,6 +515,7 @@ static void prvResetNextTaskUnblockTime( void );
|
|||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
__attribute__ ((section (".boot")))
|
||||||
BaseType_t xTaskGenericCreate( TaskFunction_t pxTaskCode, const char * const pcName, const uint16_t usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask, StackType_t * const puxStackBuffer, const MemoryRegion_t * const xRegions ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
|
BaseType_t xTaskGenericCreate( TaskFunction_t pxTaskCode, const char * const pcName, const uint16_t usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask, StackType_t * const puxStackBuffer, const MemoryRegion_t * const xRegions ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
|
||||||
{
|
{
|
||||||
BaseType_t xReturn;
|
BaseType_t xReturn;
|
||||||
@ -1454,6 +1455,7 @@ TCB_t * pxNewTCB;
|
|||||||
#endif /* ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) ) */
|
#endif /* ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) ) */
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
__attribute__ ((section (".boot")))
|
||||||
void vTaskStartScheduler( void )
|
void vTaskStartScheduler( void )
|
||||||
{
|
{
|
||||||
BaseType_t xReturn;
|
BaseType_t xReturn;
|
||||||
@ -2700,7 +2702,7 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters )
|
|||||||
}
|
}
|
||||||
#endif /* configUSE_TICKLESS_IDLE */
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
__attribute__ ((section (".boot")))
|
||||||
static void prvInitialiseTCBVariables( TCB_t * const pxTCB, const char * const pcName, UBaseType_t uxPriority, const MemoryRegion_t * const xRegions, const uint16_t usStackDepth ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
|
static void prvInitialiseTCBVariables( TCB_t * const pxTCB, const char * const pcName, UBaseType_t uxPriority, const MemoryRegion_t * const xRegions, const uint16_t usStackDepth ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
|
||||||
{
|
{
|
||||||
UBaseType_t x;
|
UBaseType_t x;
|
||||||
@ -2809,7 +2811,7 @@ UBaseType_t x;
|
|||||||
|
|
||||||
#endif /* portUSING_MPU_WRAPPERS */
|
#endif /* portUSING_MPU_WRAPPERS */
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
__attribute__ ((section (".boot")))
|
||||||
static void prvInitialiseTaskLists( void )
|
static void prvInitialiseTaskLists( void )
|
||||||
{
|
{
|
||||||
UBaseType_t uxPriority;
|
UBaseType_t uxPriority;
|
||||||
@ -2912,7 +2914,7 @@ static void prvAddCurrentTaskToDelayedList( const TickType_t xTimeToWake )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
__attribute__ ((section (".boot")))
|
||||||
static TCB_t *prvAllocateTCBAndStack( const uint16_t usStackDepth, StackType_t * const puxStackBuffer )
|
static TCB_t *prvAllocateTCBAndStack( const uint16_t usStackDepth, StackType_t * const puxStackBuffer )
|
||||||
{
|
{
|
||||||
TCB_t *pxNewTCB;
|
TCB_t *pxNewTCB;
|
||||||
|
@ -89,6 +89,17 @@ SECTIONS
|
|||||||
. = ALIGN(8);
|
. = ALIGN(8);
|
||||||
_ebss = .;
|
_ebss = .;
|
||||||
} > SRAM
|
} > SRAM
|
||||||
|
|
||||||
|
/* place here functions that are only called during boot up, */
|
||||||
|
/* that way, we can re-use this area for the micropython heap */
|
||||||
|
.boot :
|
||||||
|
{
|
||||||
|
. = ALIGN(8);
|
||||||
|
_boot = .;
|
||||||
|
*(.boot*)
|
||||||
|
. = ALIGN(8);
|
||||||
|
_eboot = .;
|
||||||
|
} > SRAM
|
||||||
|
|
||||||
/* allocate the micropython heap */
|
/* allocate the micropython heap */
|
||||||
.heap :
|
.heap :
|
||||||
|
@ -78,7 +78,8 @@ extern void (* const g_pfnVectors[256])(void);
|
|||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
DEFINE PUBLIC FUNCTIONS
|
DEFINE PUBLIC FUNCTIONS
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
|
__attribute__ ((section (".boot")))
|
||||||
void HAL_SystemInit (void) {
|
void HAL_SystemInit (void) {
|
||||||
MAP_IntVTableBaseSet((unsigned long)&g_pfnVectors[0]);
|
MAP_IntVTableBaseSet((unsigned long)&g_pfnVectors[0]);
|
||||||
|
|
||||||
|
@ -60,6 +60,7 @@ extern uint32_t __init_data;
|
|||||||
// Forward declaration of the default fault handlers.
|
// Forward declaration of the default fault handlers.
|
||||||
//
|
//
|
||||||
//*****************************************************************************
|
//*****************************************************************************
|
||||||
|
__attribute__ ((section (".boot")))
|
||||||
void ResetISR(void);
|
void ResetISR(void);
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
static void NmiSR(void) __attribute__( ( naked ) );
|
static void NmiSR(void) __attribute__( ( naked ) );
|
||||||
|
@ -59,6 +59,7 @@ OsiTaskHandle mpTaskHandle;
|
|||||||
DEFINE PUBLIC FUNCTIONS
|
DEFINE PUBLIC FUNCTIONS
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
|
__attribute__ ((section (".boot")))
|
||||||
int main (void) {
|
int main (void) {
|
||||||
|
|
||||||
// Initialize the clocks and the interrupt system
|
// Initialize the clocks and the interrupt system
|
||||||
@ -82,7 +83,6 @@ int main (void) {
|
|||||||
for ( ; ; );
|
for ( ; ; );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void stoupper (char *str) {
|
void stoupper (char *str) {
|
||||||
while (str && *str != '\0') {
|
while (str && *str != '\0') {
|
||||||
*str = (char)toupper((int)(*str));
|
*str = (char)toupper((int)(*str));
|
||||||
|
@ -51,6 +51,7 @@
|
|||||||
/// rtc.datetime((2014, 5, 1, 4, 13, 0, 0, 0))
|
/// rtc.datetime((2014, 5, 1, 4, 13, 0, 0, 0))
|
||||||
/// print(rtc.datetime())
|
/// print(rtc.datetime())
|
||||||
|
|
||||||
|
__attribute__ ((section (".boot")))
|
||||||
void pybrtc_init(void) {
|
void pybrtc_init(void) {
|
||||||
// if RTC was previously set leave it alone
|
// if RTC was previously set leave it alone
|
||||||
if (MAP_PRCMSysResetCauseGet() == PRCM_POWER_ON) {
|
if (MAP_PRCMSysResetCauseGet() == PRCM_POWER_ON) {
|
||||||
|
@ -79,6 +79,7 @@ STATIC mp_obj_t pybsd_enable (mp_obj_t self_in);
|
|||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
DECLARE PUBLIC FUNCTIONS
|
DECLARE PUBLIC FUNCTIONS
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
__attribute__ ((section (".boot")))
|
||||||
void pybsd_init0 (void) {
|
void pybsd_init0 (void) {
|
||||||
// allocate memory for the sd file system
|
// allocate memory for the sd file system
|
||||||
ASSERT ((pybsd_obj.fatfs = mem_Malloc(sizeof(FATFS))) != NULL);
|
ASSERT ((pybsd_obj.fatfs = mem_Malloc(sizeof(FATFS))) != NULL);
|
||||||
|
@ -69,9 +69,10 @@
|
|||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
DECLARE PRIVATE FUNCTIONS
|
DECLARE PRIVATE FUNCTIONS
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
STATIC void main_init_sflash_filesystem (void);
|
STATIC void mptask_pre_init (void);
|
||||||
STATIC void main_enter_ap_mode (void);
|
STATIC void mptask_init_sflash_filesystem (void);
|
||||||
STATIC void main_create_main_py (void);
|
STATIC void mptask_enter_ap_mode (void);
|
||||||
|
STATIC void mptask_create_main_py (void);
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
DECLARE PUBLIC DATA
|
DECLARE PUBLIC DATA
|
||||||
@ -100,39 +101,18 @@ void TASK_Micropython (void *pvParameters) {
|
|||||||
bool safeboot;
|
bool safeboot;
|
||||||
FRESULT res;
|
FRESULT res;
|
||||||
|
|
||||||
#if MICROPY_HW_ENABLE_RTC
|
|
||||||
pybrtc_init();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
safeboot = false;
|
safeboot = false;
|
||||||
#else
|
#else
|
||||||
safeboot = mperror_safe_boot_requested();
|
safeboot = mperror_safe_boot_requested();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Create the simple link spawn task
|
mptask_pre_init ();
|
||||||
ASSERT (OSI_OK == VStartSimpleLinkSpawnTask(SIMPLELINK_SPAWN_TASK_PRIORITY));
|
|
||||||
|
|
||||||
// Allocate memory for the flash file system
|
|
||||||
ASSERT ((sflash_fatfs = mem_Malloc(sizeof(FATFS))) != NULL);
|
|
||||||
#if MICROPY_HW_HAS_SDCARD
|
|
||||||
pybsd_init0();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
ASSERT (OSI_OK == osi_TaskCreate(TASK_Servers,
|
|
||||||
(const signed char *)"Servers",
|
|
||||||
SERVERS_STACK_SIZE, NULL, SERVERS_PRIORITY, &svTaskHandle));
|
|
||||||
#else
|
|
||||||
ASSERT (OSI_OK == osi_TaskCreate(TASK_Servers,
|
|
||||||
(const signed char *)"Servers",
|
|
||||||
SERVERS_STACK_SIZE, NULL, SERVERS_PRIORITY, NULL));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
soft_reset:
|
soft_reset:
|
||||||
|
|
||||||
// GC init
|
// GC init
|
||||||
gc_init(&_heap, &_eheap);
|
gc_init(&_boot, &_eheap);
|
||||||
|
|
||||||
// Micro Python init
|
// Micro Python init
|
||||||
mp_init();
|
mp_init();
|
||||||
@ -167,13 +147,13 @@ soft_reset:
|
|||||||
|
|
||||||
mperror_enable_heartbeat();
|
mperror_enable_heartbeat();
|
||||||
|
|
||||||
main_enter_ap_mode();
|
mptask_enter_ap_mode();
|
||||||
|
|
||||||
// enable telnet and ftp servers
|
// enable telnet and ftp servers
|
||||||
servers_enable();
|
servers_enable();
|
||||||
|
|
||||||
// initialize the serial flash file system
|
// initialize the serial flash file system
|
||||||
main_init_sflash_filesystem();
|
mptask_init_sflash_filesystem();
|
||||||
|
|
||||||
// append the SFLASH paths to the system path
|
// append the SFLASH paths to the system path
|
||||||
mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_SFLASH));
|
mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_SFLASH));
|
||||||
@ -268,8 +248,34 @@ soft_reset_exit:
|
|||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
DEFINE PRIVATE FUNCTIONS
|
DEFINE PRIVATE FUNCTIONS
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
__attribute__ ((section (".boot")))
|
||||||
|
STATIC void mptask_pre_init (void) {
|
||||||
|
#if MICROPY_HW_ENABLE_RTC
|
||||||
|
pybrtc_init();
|
||||||
|
#endif
|
||||||
|
|
||||||
STATIC void main_init_sflash_filesystem (void) {
|
// Create the simple link spawn task
|
||||||
|
ASSERT (OSI_OK == VStartSimpleLinkSpawnTask(SIMPLELINK_SPAWN_TASK_PRIORITY));
|
||||||
|
|
||||||
|
// Allocate memory for the flash file system
|
||||||
|
ASSERT ((sflash_fatfs = mem_Malloc(sizeof(FATFS))) != NULL);
|
||||||
|
|
||||||
|
#if MICROPY_HW_HAS_SDCARD
|
||||||
|
pybsd_init0();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
ASSERT (OSI_OK == osi_TaskCreate(TASK_Servers,
|
||||||
|
(const signed char *)"Servers",
|
||||||
|
SERVERS_STACK_SIZE, NULL, SERVERS_PRIORITY, &svTaskHandle));
|
||||||
|
#else
|
||||||
|
ASSERT (OSI_OK == osi_TaskCreate(TASK_Servers,
|
||||||
|
(const signed char *)"Servers",
|
||||||
|
SERVERS_STACK_SIZE, NULL, SERVERS_PRIORITY, NULL));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC void mptask_init_sflash_filesystem (void) {
|
||||||
// Initialise the local flash filesystem.
|
// Initialise the local flash filesystem.
|
||||||
// Create it if needed, and mount in on /sflash.
|
// Create it if needed, and mount in on /sflash.
|
||||||
// try to mount the flash
|
// try to mount the flash
|
||||||
@ -283,13 +289,13 @@ STATIC void main_init_sflash_filesystem (void) {
|
|||||||
__fatal_error("could not create /SFLASH file system");
|
__fatal_error("could not create /SFLASH file system");
|
||||||
}
|
}
|
||||||
// create empty main.py
|
// create empty main.py
|
||||||
main_create_main_py();
|
mptask_create_main_py();
|
||||||
} else if (res == FR_OK) {
|
} else if (res == FR_OK) {
|
||||||
// mount sucessful
|
// mount sucessful
|
||||||
FILINFO fno;
|
FILINFO fno;
|
||||||
if (FR_OK != f_stat("/SFLASH/MAIN.PY", &fno)) {
|
if (FR_OK != f_stat("/SFLASH/MAIN.PY", &fno)) {
|
||||||
// create empty main.py
|
// create empty main.py
|
||||||
main_create_main_py();
|
mptask_create_main_py();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
__fatal_error("could not create /SFLASH file system");
|
__fatal_error("could not create /SFLASH file system");
|
||||||
@ -321,14 +327,14 @@ STATIC void main_init_sflash_filesystem (void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC void main_enter_ap_mode (void) {
|
STATIC void mptask_enter_ap_mode (void) {
|
||||||
// Enable simplelink in low power mode
|
// Enable simplelink in low power mode
|
||||||
wlan_sl_enable (ROLE_AP, SERVERS_DEF_AP_SSID, strlen(SERVERS_DEF_AP_SSID), SERVERS_DEF_AP_SECURITY,
|
wlan_sl_enable (ROLE_AP, SERVERS_DEF_AP_SSID, strlen(SERVERS_DEF_AP_SSID), SERVERS_DEF_AP_SECURITY,
|
||||||
SERVERS_DEF_AP_KEY, strlen(SERVERS_DEF_AP_KEY), SERVERS_DEF_AP_CHANNEL);
|
SERVERS_DEF_AP_KEY, strlen(SERVERS_DEF_AP_KEY), SERVERS_DEF_AP_CHANNEL);
|
||||||
wlan_set_pm_policy (SL_NORMAL_POLICY);
|
wlan_set_pm_policy (SL_NORMAL_POLICY);
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC void main_create_main_py (void) {
|
STATIC void mptask_create_main_py (void) {
|
||||||
// create empty main.py
|
// create empty main.py
|
||||||
FIL fp;
|
FIL fp;
|
||||||
f_open(&fp, "/SFLASH/MAIN.PY", FA_WRITE | FA_CREATE_ALWAYS);
|
f_open(&fp, "/SFLASH/MAIN.PY", FA_WRITE | FA_CREATE_ALWAYS);
|
||||||
|
@ -275,6 +275,7 @@ OsiReturnVal_e osi_LockObjCreate(OsiLockObj_t* pLockObj)
|
|||||||
\note
|
\note
|
||||||
\warning
|
\warning
|
||||||
*/
|
*/
|
||||||
|
__attribute__ ((section (".boot")))
|
||||||
OsiReturnVal_e osi_TaskCreate(P_OSI_TASK_ENTRY pEntry,const signed char * const pcName,
|
OsiReturnVal_e osi_TaskCreate(P_OSI_TASK_ENTRY pEntry,const signed char * const pcName,
|
||||||
unsigned short usStackDepth, void *pvParameters,
|
unsigned short usStackDepth, void *pvParameters,
|
||||||
unsigned long uxPriority,OsiTaskHandle* pTaskHandle)
|
unsigned long uxPriority,OsiTaskHandle* pTaskHandle)
|
||||||
@ -449,6 +450,7 @@ void vSimpleLinkSpawnTask(void *pvParameters)
|
|||||||
\note
|
\note
|
||||||
\warning
|
\warning
|
||||||
*/
|
*/
|
||||||
|
__attribute__ ((section (".boot")))
|
||||||
OsiReturnVal_e VStartSimpleLinkSpawnTask(unsigned portBASE_TYPE uxPriority)
|
OsiReturnVal_e VStartSimpleLinkSpawnTask(unsigned portBASE_TYPE uxPriority)
|
||||||
{
|
{
|
||||||
xSimpleLinkSpawnQueue = xQueueCreate( slQUEUE_SIZE, sizeof( tSimpleLinkSpawnMsg ) );
|
xSimpleLinkSpawnQueue = xQueueCreate( slQUEUE_SIZE, sizeof( tSimpleLinkSpawnMsg ) );
|
||||||
@ -666,6 +668,7 @@ void osi_ExitCritical(void)
|
|||||||
\note
|
\note
|
||||||
\warning
|
\warning
|
||||||
*/
|
*/
|
||||||
|
__attribute__ ((section (".boot")))
|
||||||
void osi_start()
|
void osi_start()
|
||||||
{
|
{
|
||||||
vTaskStartScheduler();
|
vTaskStartScheduler();
|
||||||
|
@ -30,6 +30,8 @@ extern uint32_t _etext;
|
|||||||
extern uint32_t _sidata;
|
extern uint32_t _sidata;
|
||||||
extern uint32_t _data;
|
extern uint32_t _data;
|
||||||
extern uint32_t _edata;
|
extern uint32_t _edata;
|
||||||
|
extern uint32_t _boot;
|
||||||
|
extern uint32_t _eboot;
|
||||||
extern uint32_t _bss;
|
extern uint32_t _bss;
|
||||||
extern uint32_t _ebss;
|
extern uint32_t _ebss;
|
||||||
extern uint32_t _heap;
|
extern uint32_t _heap;
|
||||||
|
Loading…
Reference in New Issue
Block a user