2010-09-22 15:10:42 +02:00
/******************************************************************************
Copyright 2008 , Freie Universitaet Berlin ( FUB ) . All rights reserved .
These sources were developed at the Freie Universitaet Berlin , Computer Systems
and Telematics group ( http : //cst.mi.fu-berlin.de).
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2013-03-07 20:51:26 +01:00
This file is part of RIOT .
2010-09-22 15:10:42 +02:00
This program is free software : you can redistribute it and / or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation , either version 3 of the License , or ( at your option ) any later
version .
2013-03-07 20:51:26 +01:00
RIOT is distributed in the hope that it will be useful , but WITHOUT
2010-09-22 15:10:42 +02:00
ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE . See the GNU General Public License for more details .
You should have received a copy of the GNU General Public License along with
this program . If not , see http : //www.gnu.org/licenses/ .
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
For further information and questions please use the web site
http : //scatterweb.mi.fu-berlin.de
and the mailinglist ( subscription via web site )
scatterweb @ lists . spline . inf . fu - berlin . de
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/**
* @ file
* @ ingroup lpc2387
* @ brief LPC2387 NewLib system calls implementation
*
* @ author Freie Universität Berlin , Computer Systems & Telematics , FeuerWhere project
* @ author Michael Baar < michael . baar @ fu - berlin . de >
2012-11-08 17:37:29 +01:00
* @ version $ Revision $
2010-09-22 15:10:42 +02:00
*
2012-11-08 17:37:29 +01:00
* @ note $ Id $
2010-09-22 15:10:42 +02:00
*/
# include <errno.h>
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <sys/stat.h>
# include <sys/unistd.h>
# include <stdint.h>
// core
# include "kernel.h"
2012-11-08 17:37:29 +01:00
# include "irq.h"
# include "io.h"
2012-03-08 18:58:39 +01:00
/* When using the HAL standard in and out are handled by HAL
devices . */
# if FEUERWARE_CONF_ENABLE_HAL
# include "hal.h"
# include "interface-chardevice.h"
2012-11-08 17:37:29 +01:00
# include "hal-syscalls.h"
2012-03-08 18:58:39 +01:00
# endif
2010-09-22 15:10:42 +02:00
# define DEBUG_SYSCALLS 0
# if DEBUG_SYSCALLS
# define PRINTF(...) printf(__VA_ARGS__)
# else
# define PRINTF(...)
# endif
2012-03-08 18:58:39 +01:00
# ifdef MODULE_FAT
# include "ff_ansi.h"
# endif
2010-09-22 15:10:42 +02:00
/**
* @ name Heaps ( defined in linker script )
* @ {
*/
2012-03-08 18:58:39 +01:00
# define NUM_HEAPS 3 //2
2010-09-22 15:10:42 +02:00
extern uintptr_t __heap1_start ; ///< start of heap memory space
extern uintptr_t __heap1_max ; ///< maximum for end of heap memory space
extern uintptr_t __heap2_start ; ///< start of heap memory space
extern uintptr_t __heap2_max ; ///< maximum for end of heap memory space
2012-03-08 18:58:39 +01:00
extern uintptr_t __heap3_start ; ///< start of heap memory space
extern uintptr_t __heap3_max ; ///< maximum for end of heap memory space
2010-09-22 15:10:42 +02:00
/// current position in heap
2012-03-08 18:58:39 +01:00
static caddr_t heap [ NUM_HEAPS ] = { ( caddr_t ) & __heap1_start , ( caddr_t ) & __heap3_start , ( caddr_t ) & __heap2_start } ; // add heap3 before heap2 cause Heap3 address is lower then addr of heap2
2010-09-22 15:10:42 +02:00
/// maximum position in heap
2012-03-08 18:58:39 +01:00
static const caddr_t heap_max [ NUM_HEAPS ] = { ( caddr_t ) & __heap1_max , ( caddr_t ) & __heap3_max , ( caddr_t ) & __heap2_max } ;
// start position in heap
static const caddr_t heap_start [ NUM_HEAPS ] = { ( caddr_t ) & __heap1_start , ( caddr_t ) & __heap3_start , ( caddr_t ) & __heap2_start } ;
2012-11-08 17:37:29 +01:00
2012-03-08 18:58:39 +01:00
2010-09-22 15:10:42 +02:00
/** @} */
2012-03-08 18:58:39 +01:00
/*-----------------------------------------------------------------------------------*/
void heap_stats ( void ) {
for ( int i = 0 ; i < NUM_HEAPS ; i + + )
printf ( " # heap %i: %p -- %p -> %p (%li of %li free) \n " , i , heap_start [ i ] , heap [ i ] , heap_max [ i ] ,
( uint32_t ) heap_max [ i ] - ( uint32_t ) heap [ i ] , ( uint32_t ) heap_max [ i ] - ( uint32_t ) heap_start [ i ] ) ;
}
2010-09-22 15:10:42 +02:00
/*-----------------------------------------------------------------------------------*/
void __assert_func ( const char * file , int line , const char * func , const char * failedexpr )
{
2012-03-08 18:58:39 +01:00
# if SYSLOG_CONF_ASSERT
trace_number ( TRACELOG_EV_ASSERTION , line ) ;
syslog ( SL_EMERGENCY , " assert " , " %s() in %s:%u \n " , func , file , line ) ;
# endif
2010-09-22 15:10:42 +02:00
printf ( " #! assertion %s failed \n \t %s() in %s:%u \n " , failedexpr , func , file , line ) ;
_exit ( 3 ) ;
}
/*-----------------------------------------------------------------------------------*/
void __assert ( const char * file , int line , const char * failedexpr )
{
__assert_func ( file , line , " ? " , failedexpr ) ;
}
/*-----------------------------------------------------------------------------------*/
caddr_t _sbrk_r ( struct _reent * r , size_t incr )
{
2012-03-08 18:58:39 +01:00
if ( incr < 0 )
{
puts ( " [syscalls] Negative Values for _sbrk_r are not supported " ) ;
r - > _errno = ENOMEM ;
return NULL ;
}
uint32_t cpsr = disableIRQ ( ) ;
/* check all heaps for a chunk of the requested size */
2012-11-08 17:37:29 +01:00
for ( volatile uint8_t iUsedHeap = 0 ; iUsedHeap < NUM_HEAPS ; iUsedHeap + + ) {
2012-03-08 18:58:39 +01:00
caddr_t new_heap = heap [ iUsedHeap ] + incr ;
# ifdef MODULE_TRACELOG
trace_pointer ( TRACELOG_EV_MEMORY , heap [ iUsedHeap ] ) ;
# endif
if ( new_heap < = heap_max [ iUsedHeap ] ) {
caddr_t prev_heap = heap [ iUsedHeap ] ;
# ifdef MODULE_TRACELOG
trace_pointer ( TRACELOG_EV_MEMORY , new_heap ) ;
# endif
heap [ iUsedHeap ] = new_heap ;
2010-09-22 15:10:42 +02:00
r - > _errno = 0 ;
2012-03-08 18:58:39 +01:00
restoreIRQ ( cpsr ) ;
2010-09-22 15:10:42 +02:00
return prev_heap ;
}
}
2012-03-08 18:58:39 +01:00
restoreIRQ ( cpsr ) ;
# ifdef MODULE_TRACELOG
trace_string ( TRACELOG_EV_MEMORY , " heap! " ) ; // heap full
# endif
r - > _errno = ENOMEM ;
2012-11-08 17:37:29 +01:00
return NULL ;
2010-09-22 15:10:42 +02:00
}
/*---------------------------------------------------------------------------*/
int _isatty_r ( struct _reent * r , int fd )
{
r - > _errno = 0 ;
if ( fd = = STDOUT_FILENO | | fd = = STDERR_FILENO )
return 1 ;
else
return 0 ;
}
/*---------------------------------------------------------------------------*/
_off_t _lseek_r ( struct _reent * r , int fd , _off_t pos , int whence )
{
_off_t result = - 1 ;
PRINTF ( " lseek [%i] pos %li whence %i \n " , fd , pos , whence ) ;
r - > _errno = ENODEV ;
2012-03-08 18:58:39 +01:00
# ifdef MODULE_FAT
result = ff_lseek_r ( r , fd , pos , whence ) ;
# endif
2010-09-22 15:10:42 +02:00
PRINTF ( " lseek returned %li (0 is success) \n " , result ) ;
return result ;
}
/*---------------------------------------------------------------------------*/
int _open_r ( struct _reent * r , const char * name , int mode )
{
int ret = - 1 ;
PRINTF ( " open '%s' mode %#x \n " , name , mode ) ;
2012-03-08 18:58:39 +01:00
r - > _errno = ENODEV ; // no such device
# ifdef MODULE_FAT
ret = ff_open_r ( r , name , mode ) ;
# endif
2010-09-22 15:10:42 +02:00
PRINTF ( " open [%i] errno %i \n " , ret , r - > _errno ) ;
return ret ;
}
/*---------------------------------------------------------------------------*/
int _stat_r ( struct _reent * r , char * name , struct stat * st )
{
int ret = - 1 ;
2012-03-08 18:58:39 +01:00
PRINTF ( " _stat_r '%s' \n " , name ) ;
r - > _errno = ENODEV ; // no such device
# ifdef MODULE_FAT
ret = ff_stat_r ( r , name , st ) ;
# endif
PRINTF ( " _stat_r [%i] errno %i \n " , ret , r - > _errno ) ;
2010-09-22 15:10:42 +02:00
return ret ;
}
/*---------------------------------------------------------------------------*/
int _fstat_r ( struct _reent * r , int fd , struct stat * st )
{
int ret = - 1 ;
2012-03-08 18:58:39 +01:00
r - > _errno = 0 ;
2010-09-22 15:10:42 +02:00
memset ( st , 0 , sizeof ( * st ) ) ;
if ( fd = = STDOUT_FILENO | | fd = = STDERR_FILENO ) {
st - > st_mode = S_IFCHR ;
ret = 0 ;
} else {
2012-03-08 18:58:39 +01:00
# ifdef MODULE_FAT
PRINTF ( " _fstat_r '%i' \n " , fd ) ;
ret = ff_fstat_r ( r , fd , st ) ;
PRINTF ( " _fstat_r [%i] errno %i \n " , ret , r - > _errno ) ;
# else
2010-09-22 15:10:42 +02:00
r - > _errno = ENODEV ;
2012-03-08 18:58:39 +01:00
# endif
2010-09-22 15:10:42 +02:00
}
return ret ;
}
/*---------------------------------------------------------------------------*/
int _write_r ( struct _reent * r , int fd , const void * data , unsigned int count )
{
int result = EOF ;
2012-03-08 18:58:39 +01:00
r - > _errno = EBADF ;
2010-09-22 15:10:42 +02:00
switch ( fd ) {
case STDOUT_FILENO :
case STDERR_FILENO :
2012-03-08 18:58:39 +01:00
# if FEUERWARE_CONF_ENABLE_HAL
if ( stdio ! = NULL )
result = chardevice_write ( stdio , ( char * ) data , count ) ;
else if ( hal_state = = HAL_NOT_INITIALIZED )
result = fw_puts ( ( char * ) data , count ) ;
# else
2010-09-22 15:10:42 +02:00
result = fw_puts ( ( char * ) data , count ) ;
2012-03-08 18:58:39 +01:00
# endif
2010-09-22 15:10:42 +02:00
break ;
default :
2012-03-08 18:58:39 +01:00
# ifdef MODULE_FAT
result = ff_write_r ( r , fd , data , count ) ;
# endif
2012-11-08 17:37:29 +01:00
PRINTF ( " write [%i] data @%p count %i \n " , fd , data , count ) ;
PRINTF ( " write [%i] returned %i errno %i \n " , fd , result , r - > _errno ) ;
2010-09-22 15:10:42 +02:00
break ;
}
return result ;
}
/*---------------------------------------------------------------------------*/
int _read_r ( struct _reent * r , int fd , void * buffer , unsigned int count )
{
2012-03-08 18:58:39 +01:00
int result = - 1 ;
r - > _errno = EBADF ;
# ifdef MODULE_FAT
result = ff_read_r ( r , fd , buffer , count ) ;
# endif
2012-11-08 17:37:29 +01:00
PRINTF ( " read [%i] buffer @%p count %i \n " , fd , buffer , count ) ;
PRINTF ( " read [%i] returned %i \n " , fd , result ) ;
return result ;
2010-09-22 15:10:42 +02:00
}
/*---------------------------------------------------------------------------*/
int _close_r ( struct _reent * r , int fd )
{
2012-11-08 17:37:29 +01:00
int result = - 1 ;
2012-03-08 18:58:39 +01:00
r - > _errno = EBADF ;
# ifdef MODULE_FAT
ret = ff_close_r ( r , fd ) ;
# endif
2012-11-08 17:37:29 +01:00
PRINTF ( " close [%i] \n " , fd ) ;
PRINTF ( " close returned %i errno %i \n " , result , errno ) ;
return result ;
2010-09-22 15:10:42 +02:00
}
/*---------------------------------------------------------------------------*/
int _unlink_r ( struct _reent * r , char * path )
{
2012-11-08 17:37:29 +01:00
int result = - 1 ;
2010-09-22 15:10:42 +02:00
r - > _errno = ENODEV ;
2012-03-08 18:58:39 +01:00
# ifdef MODULE_FAT
2012-11-08 17:37:29 +01:00
result = ff_unlink_r ( r , path ) ;
2012-03-08 18:58:39 +01:00
# endif
2012-11-08 17:37:29 +01:00
PRINTF ( " unlink '%s' \n " , path ) ;
PRINTF ( " unlink returned %i errno %i \n " , result , errno ) ;
return result ;
2010-09-22 15:10:42 +02:00
}
/*---------------------------------------------------------------------------*/
void _exit ( int n )
{
2012-03-08 18:58:39 +01:00
# ifdef MODULE_TRACELOG
trace_number ( TRACELOG_EV_EXIT , n ) ;
# endif
2010-09-22 15:10:42 +02:00
printf ( " #! exit %i: resetting \n " , n ) ;
stdio_flush ( ) ;
arm_reset ( ) ;
2012-03-08 18:58:39 +01:00
while ( 1 ) ;
2010-09-22 15:10:42 +02:00
}
/*---------------------------------------------------------------------------*/
int _getpid ( void )
{
2010-10-28 11:22:57 +02:00
return active_thread - > pid ;
2010-09-22 15:10:42 +02:00
}
/*---------------------------------------------------------------------------*/
int _kill_r ( struct _reent * r , int pid , int sig )
{
2012-03-08 18:58:39 +01:00
/* not implemented */
2010-09-22 15:10:42 +02:00
r - > _errno = ESRCH ; // no such process
return - 1 ;
}
/*---------------------------------------------------------------------------*/
2012-03-08 18:58:39 +01:00
void _init ( void ) { }
void _fini ( void ) { }