mirror of
https://github.com/elua/elua.git
synced 2025-01-08 20:56:17 +08:00
Added support for multiple RAM spaces using the TLSF allocator.
This takes care of my LPC2888 board (any many other board out there) that have RAM both on the CPU itself and on a separate chip. To use it add "allocator=tlsf" to your scons build command. Even though the code for all the platform was modified, the new code should not modify the "old" allocator behaviour. Also added a new "mem" command to the shell, it gives information about the current RAM state (total, used, free). NOT YET TESTED !!! So use with care.
This commit is contained in:
parent
4901305cb9
commit
09ac410a02
@ -1,6 +1,7 @@
|
||||
import os, sys
|
||||
target = ARGUMENTS.get( 'target', 'lua' ).lower()
|
||||
cputype = ARGUMENTS.get( 'cpu', 'at91sam7x256' ).lower()
|
||||
allocator = ARGUMENTS.get( 'allocator', 'newlib' ).lower()
|
||||
|
||||
# List of platform/CPU combinations
|
||||
cpu_list = { 'at91sam7x' : [ 'at91sam7x256', 'at91sam7x512' ],
|
||||
@ -28,6 +29,8 @@ else:
|
||||
|
||||
output = 'elua_' + target + '_' + cputype
|
||||
cdefs = '-D%s' % cputype
|
||||
if allocator == 'tlsf':
|
||||
cdefs = cdefs + ' -DUSE_TLSF'
|
||||
|
||||
# Lua source files and include path
|
||||
lua_files = """lapi.c lcode.c ldebug.c ldo.c ldump.c lfunc.c lgc.c llex.c lmem.c lobject.c lopcodes.c
|
||||
@ -49,7 +52,7 @@ local_include = local_include + " -Isrc/modules -Isrc/platform/%s" % platform
|
||||
local_libs = ''
|
||||
|
||||
# Application files
|
||||
app_files = " src/romfs.c src/main.c src/xmodem.c src/shell.c src/term.c"
|
||||
app_files = " src/romfs.c src/main.c src/xmodem.c src/shell.c src/term.c src/tlsf.c"
|
||||
|
||||
# Newlib related files
|
||||
newlib_files = " src/newlib/devman.c src/newlib/stubs.c src/newlib/genstd.c"
|
||||
|
@ -152,7 +152,7 @@ u32 platform_pd_get_cpu_frequency();
|
||||
// *****************************************************************************
|
||||
// Allocator support
|
||||
|
||||
void* platform_get_first_free_ram();
|
||||
void* platform_get_last_free_ram();
|
||||
void* platform_get_first_free_ram( unsigned id );
|
||||
void* platform_get_last_free_ram( unsigned id );
|
||||
|
||||
#endif
|
||||
|
43
inc/tlsf.h
Normal file
43
inc/tlsf.h
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Two Levels Segregate Fit memory allocator (TLSF)
|
||||
* Version 2.4.3
|
||||
*
|
||||
* Written by Miguel Masmano Tello <mimastel@doctor.upv.es>
|
||||
*
|
||||
* Thanks to Ismael Ripoll for his suggestions and reviews
|
||||
*
|
||||
* Copyright (C) 2008, 2007, 2006, 2005, 2004
|
||||
*
|
||||
* This code is released using a dual license strategy: GPL/LGPL
|
||||
* You can choose the licence that better fits your requirements.
|
||||
*
|
||||
* Released under the terms of the GNU General Public License Version 2.0
|
||||
* Released under the terms of the GNU Lesser General Public License Version 2.1
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _TLSF_H_
|
||||
#define _TLSF_H_
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
extern size_t init_memory_pool(size_t, void *);
|
||||
extern size_t get_used_size(void *);
|
||||
extern size_t get_max_size(void *);
|
||||
extern void destroy_memory_pool(void *);
|
||||
extern size_t add_new_area(void *, size_t, void *);
|
||||
extern void *malloc_ex(size_t, void *);
|
||||
extern void free_ex(void *, void *);
|
||||
extern void *realloc_ex(void *, size_t, void *);
|
||||
extern void *calloc_ex(size_t, size_t, void *);
|
||||
|
||||
extern void *tlsf_malloc(size_t size);
|
||||
extern void tlsf_free(void *ptr);
|
||||
extern void *tlsf_realloc(void *ptr, size_t size);
|
||||
extern void *tlsf_calloc(size_t nelem, size_t elem_size);
|
||||
|
||||
// BogdanM - added for eLua
|
||||
void tlsf_elua_init();
|
||||
size_t tlsf_elua_get_block_size( void* ptr );
|
||||
|
||||
#endif
|
@ -11,9 +11,9 @@
|
||||
#include "build.h"
|
||||
#include "lua.h"
|
||||
#include "term.h"
|
||||
#include "tlsf.h"
|
||||
|
||||
extern char etext[];
|
||||
extern char end[];
|
||||
|
||||
// ****************************************************************************
|
||||
// XMODEM support code
|
||||
@ -163,6 +163,10 @@ int main( void )
|
||||
// This should never happen
|
||||
while( 1 );
|
||||
}
|
||||
|
||||
// Initialize the TLSF allocator
|
||||
// (if TLSF is not used, the next function does nothing)
|
||||
tlsf_elua_init();
|
||||
|
||||
// Initialize device manager
|
||||
dm_init();
|
||||
@ -176,7 +180,7 @@ int main( void )
|
||||
// Initialize terminal
|
||||
term_init( TERMINAL_LINES, TERMINAL_COLS, term_out, term_in, term_translate );
|
||||
|
||||
printf( ".text ends at %p, first free RAM is at %p, last free ram is at %p\r\n", etext, platform_get_first_free_ram(), platform_get_last_free_ram() );
|
||||
printf( ".text ends at %p\n", etext );
|
||||
|
||||
// Run the shell
|
||||
if( shell_init( XMODEM_MAX_FILE_SIZE ) == 0 )
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "devman.h"
|
||||
#include "ioctl.h"
|
||||
#include "platform.h"
|
||||
#include "tlsf.h"
|
||||
|
||||
// Utility function: look in the device manager table and find the index
|
||||
// for the given name. Returns an index into the device structure, -1 if error.
|
||||
@ -49,6 +50,7 @@ static int find_dm_entry( const char* name, char **pactname )
|
||||
}
|
||||
if( i == dm_get_num_devices() )
|
||||
return -1;
|
||||
|
||||
// Find the actual first char of the name
|
||||
preal ++;
|
||||
if( *preal == '\0' )
|
||||
@ -176,6 +178,8 @@ _ssize_t _write_r( struct _reent *r, int file, const void *ptr, size_t len )
|
||||
|
||||
// *****************************************************************************
|
||||
// _sbrk_r
|
||||
// Only used if we're using the default Newlib allocator (dlmalloc), not TLSF
|
||||
#ifndef USE_TLSF
|
||||
static char *heap_ptr;
|
||||
|
||||
void* _sbrk_r( struct _reent* r, ptrdiff_t incr )
|
||||
@ -187,8 +191,8 @@ void* _sbrk_r( struct _reent* r, ptrdiff_t incr )
|
||||
else
|
||||
{
|
||||
if( heap_ptr == NULL )
|
||||
heap_ptr = ( char* )platform_get_first_free_ram();
|
||||
if( heap_ptr + incr >= ( char* )platform_get_last_free_ram() )
|
||||
heap_ptr = ( char* )platform_get_first_free_ram( 0 );
|
||||
if( heap_ptr + incr > ( char* )platform_get_last_free_ram( 0 ) )
|
||||
ptr = ( void* )-1;
|
||||
else
|
||||
{
|
||||
@ -198,6 +202,7 @@ void* _sbrk_r( struct _reent* r, ptrdiff_t incr )
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
// *****************************************************************************
|
||||
// _lseek_r
|
||||
@ -284,5 +289,120 @@ int __svfscanf_r( struct _reent *r, FILE *stream, const char *format, va_list ap
|
||||
{
|
||||
return __svfiscanf_r( r, stream, format, ap );
|
||||
}
|
||||
#endif // #ifdef LUA_INTONLY
|
||||
|
||||
#endif
|
||||
// If USE_TLSF is defined, "redirect" allocator calls from Newlib to TLSF
|
||||
#ifdef USE_TLSF
|
||||
|
||||
// malloc: try to allocate in all the memory pools
|
||||
void* _malloc_r( struct _reent* r, size_t size )
|
||||
{
|
||||
unsigned i = 0;
|
||||
void* temp = NULL;
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
if( ( temp = platform_get_first_free_ram( i ) ) == NULL )
|
||||
break;
|
||||
if( ( temp = malloc_ex( size, temp ) ) != NULL )
|
||||
break;
|
||||
i ++;
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
|
||||
// calloc: try to allocate in all the memory pools
|
||||
void* _calloc_r( struct _reent* r, size_t nelem, size_t elem_size )
|
||||
{
|
||||
unsigned i = 0;
|
||||
void* temp = NULL;
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
if( ( temp = platform_get_first_free_ram( i ) ) == NULL )
|
||||
break;
|
||||
if( ( temp = calloc_ex( nelem, elem_size, temp ) ) != NULL )
|
||||
break;
|
||||
i ++;
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
|
||||
// free: find memory pool with the given pointer, then free it
|
||||
void _free_r( struct _reent* r, void* ptr )
|
||||
{
|
||||
unsigned i = 0;
|
||||
u32 lstart, lend;
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
if( ( lstart = ( u32 )platform_get_first_free_ram( i ) ) == 0 )
|
||||
break;
|
||||
lend = ( u32 )platform_get_last_free_ram( i );
|
||||
if( ( lstart <= ( u32 )ptr ) && ( ( u32 )ptr <= lend ) )
|
||||
{
|
||||
free_ex( ptr, ( void* )lstart );
|
||||
break;
|
||||
}
|
||||
i ++;
|
||||
}
|
||||
}
|
||||
|
||||
// realloc: this is a bit more complex. First we identify the correct memory
|
||||
// pool and try to realloc there. If this doesn't work, we try to realloc in
|
||||
// another pool before giving up.
|
||||
void* _relloc_r( struct _reent* r, void* ptr, size_t size )
|
||||
{
|
||||
void* temp;
|
||||
u32 lstart, lend;
|
||||
unsigned i = 0;
|
||||
size_t prevsize;
|
||||
|
||||
// Realloc with ptr == NULL : malloc
|
||||
// Realloc with size == 0 : free
|
||||
if( !ptr )
|
||||
return size ? _malloc_r( r, size ) : NULL;
|
||||
else if( !size )
|
||||
{
|
||||
_free_r( r, ptr );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// At this point we know that this is an actual realloc
|
||||
// Identify the memory pool
|
||||
while( 1 )
|
||||
{
|
||||
if( ( lstart = ( u32 )platform_get_first_free_ram( i ) ) == 0 )
|
||||
return NULL;
|
||||
lend = ( u32 )platform_get_last_free_ram( i );
|
||||
if( ( lstart <= ( u32 )ptr ) && ( ( u32 )ptr <= lend ) )
|
||||
break;
|
||||
i ++;
|
||||
}
|
||||
|
||||
// Easy case: realloc succeeds in the same memory pool
|
||||
if( ( temp = realloc_ex( ptr, size, ( void* )lstart ) ) != NULL )
|
||||
return temp;
|
||||
|
||||
// If realloc returned NULL, look for another pool
|
||||
prevsize = tlsf_elua_get_block_size( ptr );
|
||||
i = 0;
|
||||
while( 1 )
|
||||
{
|
||||
if( ( temp = platform_get_first_free_ram( i ) ) == NULL )
|
||||
break;
|
||||
if( ( u32 )temp != lstart )
|
||||
{
|
||||
if( ( temp = malloc_ex( size, temp ) ) != NULL )
|
||||
{
|
||||
memcpy( temp, ptr, prevsize < size ? prevsize : size );
|
||||
free_ex( ptr, ( void* )lstart );
|
||||
break;
|
||||
}
|
||||
}
|
||||
i ++;
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
|
||||
#endif // #ifdef USE_TLSF
|
||||
|
@ -381,9 +381,9 @@ u32 platform_pd_get_cpu_frequency()
|
||||
// Allocator support
|
||||
extern char end[];
|
||||
|
||||
void* platform_get_first_free_ram()
|
||||
void* platform_get_first_free_ram( unsigned id )
|
||||
{
|
||||
return ( void* )end;
|
||||
return id > 0 ? NULL : ( void* )end;
|
||||
}
|
||||
|
||||
#define SRAM_ORIGIN 0x200000
|
||||
@ -393,7 +393,7 @@ void* platform_get_first_free_ram()
|
||||
#define SRAM_SIZE 0x20000
|
||||
#endif
|
||||
|
||||
void* platform_get_last_free_ram()
|
||||
void* platform_get_last_free_ram( unsigned id )
|
||||
{
|
||||
return ( void* )( SRAM_ORIGIN + SRAM_SIZE - STACK_SIZE_TOTAL );
|
||||
return id > 0 ? NULL : ( void* )( SRAM_ORIGIN + SRAM_SIZE - STACK_SIZE_TOTAL - 1 );
|
||||
}
|
||||
|
@ -106,13 +106,13 @@ int platform_uart_recv( unsigned id, unsigned timer_id, int timeout )
|
||||
// Allocator support
|
||||
extern char end[];
|
||||
|
||||
void* platform_get_first_free_ram()
|
||||
void* platform_get_first_free_ram( unsigned id )
|
||||
{
|
||||
return ( void* )end;
|
||||
return id > 0 ? NULL : ( void* )end;
|
||||
}
|
||||
|
||||
#define MY_STACK_SIZE ( 16 * 1024 )
|
||||
void* platform_get_last_free_ram()
|
||||
void* platform_get_last_free_ram( unsigned id )
|
||||
{
|
||||
return ( void* )( lastmem - MY_STACK_SIZE );
|
||||
return id > 0 ? NULL : ( void* )( lastmem - MY_STACK_SIZE - 1 );
|
||||
}
|
||||
|
@ -458,14 +458,14 @@ u32 platform_pd_get_cpu_frequency()
|
||||
|
||||
extern char end[];
|
||||
|
||||
void* platform_get_first_free_ram()
|
||||
void* platform_get_first_free_ram( unsigned id )
|
||||
{
|
||||
return ( void* )end;
|
||||
return id > 0 ? NULL : ( void* )end;
|
||||
}
|
||||
|
||||
#define STACK_SIZE 256
|
||||
#define SRAM_SIZE ( 64 * 1024 )
|
||||
void* platform_get_last_free_ram()
|
||||
void* platform_get_last_free_ram( unsigned id )
|
||||
{
|
||||
return ( void* )( SRAM_BASE + SRAM_SIZE - STACK_SIZE );
|
||||
return id > 0 ? NULL : ( void* )( SRAM_BASE + SRAM_SIZE - STACK_SIZE - 1 );
|
||||
}
|
||||
|
@ -304,15 +304,22 @@ u32 platform_pd_get_cpu_frequency()
|
||||
|
||||
extern char end[];
|
||||
|
||||
void* platform_get_first_free_ram()
|
||||
void* platform_get_first_free_ram( unsigned id )
|
||||
{
|
||||
return ( void* )end;
|
||||
if( id > 1 )
|
||||
return NULL;
|
||||
else
|
||||
return id == 0 ? ( void* )end : ( void* )SDRAM_BASE_ADDR;
|
||||
}
|
||||
|
||||
#define SRAM_ORIGIN 0x00400000
|
||||
#define SRAM_SIZE 0x10000
|
||||
|
||||
void* platform_get_last_free_ram()
|
||||
void* platform_get_last_free_ram( unsigned id )
|
||||
{
|
||||
return ( void* )( SRAM_ORIGIN + SRAM_SIZE - STACK_SIZE_TOTAL );
|
||||
if( id > 1 )
|
||||
return NULL;
|
||||
else
|
||||
return id == 0 ? ( void* )( SRAM_ORIGIN + SRAM_SIZE - STACK_SIZE_TOTAL - 1 ) :
|
||||
( void* )( SDRAM_BASE_ADDR + SDRAM_SIZE - 1 );
|
||||
}
|
||||
|
@ -421,15 +421,15 @@ u32 platform_pd_get_cpu_frequency()
|
||||
// Allocator support
|
||||
extern char end[];
|
||||
|
||||
void* platform_get_first_free_ram()
|
||||
void* platform_get_first_free_ram( unsigned id )
|
||||
{
|
||||
return ( void* )end;
|
||||
return id > 0 ? NULL : ( void* )end;
|
||||
}
|
||||
|
||||
#define SRAM_ORIGIN 0x40000000
|
||||
#define SRAM_SIZE 0x18000
|
||||
|
||||
void* platform_get_last_free_ram()
|
||||
void* platform_get_last_free_ram( unsigned id )
|
||||
{
|
||||
return ( void* )( SRAM_ORIGIN + SRAM_SIZE - STACK_SIZE_TOTAL );
|
||||
return id > 0 ? NULL : ( void* )( SRAM_ORIGIN + SRAM_SIZE - STACK_SIZE_TOTAL - 1 );
|
||||
}
|
||||
|
30
src/shell.c
30
src/shell.c
@ -9,6 +9,9 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <malloc.h>
|
||||
#include "tlsf.h"
|
||||
#include "platform.h"
|
||||
|
||||
#include "build.h"
|
||||
#ifdef BUILD_SHELL
|
||||
@ -42,6 +45,7 @@ static void shell_help( char* args )
|
||||
printf( " lua [args] - run Lua with the given arguments\n" );
|
||||
printf( " recv - receive a file (XMODEM) and execute it\n" );
|
||||
printf( " ver - print eLua version\n" );
|
||||
printf( " mem - RAM usage data\n" );
|
||||
printf( " exit - exit from this shelll\n" );
|
||||
}
|
||||
|
||||
@ -152,6 +156,31 @@ static void shell_ver( char* args )
|
||||
printf( "For more information go to http://elua.berlios.de\n" );
|
||||
}
|
||||
|
||||
// 'mem' handler
|
||||
static void shell_mem( char* args )
|
||||
{
|
||||
unsigned i = 0;
|
||||
u32 lstart, lend;
|
||||
|
||||
args = args;
|
||||
while( 1 )
|
||||
{
|
||||
if( ( lstart = ( u32 )platform_get_first_free_ram( i ) ) == 0 )
|
||||
break;
|
||||
lend = ( u32 )platform_get_last_free_ram( i );
|
||||
printf( "Start:0x%08lX Size:%8ld ", lstart, lend - lstart + 1 );
|
||||
#ifdef USE_TLSF
|
||||
u32 temp = get_used_size( ( void* )lstart );
|
||||
printf( "Used:%8ld Free:%8ld\n", temp, lend - lstart + 1 - temp );
|
||||
#else
|
||||
struct mallinfo allocdata;
|
||||
allocdata = mallinfo();
|
||||
printf( "Used:%8ld Free:%8ld\n", ( long )allocdata.uordblks, ( long )allocdata.fordblks );
|
||||
#endif
|
||||
i ++;
|
||||
}
|
||||
}
|
||||
|
||||
// Insert shell commands here
|
||||
static const SHELL_COMMAND shell_commands[] =
|
||||
{
|
||||
@ -159,6 +188,7 @@ static const SHELL_COMMAND shell_commands[] =
|
||||
{ "lua", shell_lua },
|
||||
{ "recv", shell_recv },
|
||||
{ "ver", shell_ver },
|
||||
{ "mem", shell_mem },
|
||||
{ "exit", NULL },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
1038
src/tlsf.c
Normal file
1038
src/tlsf.c
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user