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/ .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/**
* @ file
2013-03-31 20:48:49 +02:00
* @ ingroup lpc2387
* @ brief LPC2387 NewLib system calls implementation
2010-09-22 15:10:42 +02:00
*
2013-04-17 12:12:45 +02:00
* @ author Freie Universität Berlin , Computer Systems & Telematics
2013-03-31 20:48:49 +02:00
* @ author Michael Baar < michael . baar @ fu - berlin . de >
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
2013-03-31 20:48:49 +02:00
# define DEBUG_SYSCALLS 0
2010-09-22 15:10:42 +02:00
# if DEBUG_SYSCALLS
2013-03-31 20:48:49 +02:00
# define PRINTF(...) printf(__VA_ARGS__)
2010-09-22 15:10:42 +02:00
# 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 )
* @ {
*/
2013-03-31 20:48:49 +02:00
# define NUM_HEAPS 3 //2
2010-09-22 15:10:42 +02:00
2013-03-31 20:48:49 +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
extern uintptr_t __heap3_start ; ///< start of heap memory space
extern uintptr_t __heap3_max ; ///< maximum for end of heap memory space
2012-03-08 18:58:39 +01:00
2010-09-22 15:10:42 +02:00
2013-06-21 03:52:57 +02:00
/* current position in heap */
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
/* maximum position in heap */
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 } ;
/* current heap in use */
2013-05-16 17:10:14 +02:00
volatile static uint8_t iUsedHeap = 0 ;
2012-03-08 18:58:39 +01:00
2010-09-22 15:10:42 +02:00
/** @} */
2012-03-08 18:58:39 +01:00
/*-----------------------------------------------------------------------------------*/
2013-06-21 03:52:57 +02:00
void heap_stats ( void )
2013-03-31 20:48:49 +02:00
{
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 ] ,
2013-06-21 03:52:57 +02:00
( uint32_t ) heap_max [ i ] - ( uint32_t ) heap [ i ] , ( uint32_t ) heap_max [ i ] - ( uint32_t ) heap_start [ i ] ) ;
2012-03-08 18:58:39 +01:00
}
2013-03-31 20:48:49 +02:00
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
2013-03-31 20:48:49 +02:00
trace_number ( TRACELOG_EV_ASSERTION , line ) ;
syslog ( SL_EMERGENCY , " assert " , " %s() in %s:%u \n " , func , file , line ) ;
2012-03-08 18:58:39 +01:00
# endif
2013-06-21 03:52:57 +02:00
printf ( " #! assertion %s failed \n \t %s() in %s:%u \n " , failedexpr , func , file , line ) ;
2013-03-31 20:48:49 +02:00
_exit ( 3 ) ;
2010-09-22 15:10:42 +02:00
}
/*-----------------------------------------------------------------------------------*/
void __assert ( const char * file , int line , const char * failedexpr )
{
2013-03-31 20:48:49 +02:00
__assert_func ( file , line , " ? " , failedexpr ) ;
2010-09-22 15:10:42 +02:00
}
/*-----------------------------------------------------------------------------------*/
caddr_t _sbrk_r ( struct _reent * r , size_t incr )
{
2013-06-21 03:52:57 +02:00
if ( incr < 0 ) {
2012-03-08 18:58:39 +01:00
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 */
2013-06-21 03:52:57 +02:00
for ( ; iUsedHeap < NUM_HEAPS ; iUsedHeap + + ) {
2013-03-31 20:48:49 +02:00
caddr_t new_heap = heap [ iUsedHeap ] + incr ;
2013-06-21 03:52:57 +02:00
# ifdef MODULE_TRACELOG
2013-03-31 20:48:49 +02:00
trace_pointer ( TRACELOG_EV_MEMORY , heap [ iUsedHeap ] ) ;
2013-06-21 03:52:57 +02:00
# endif
if ( new_heap < = heap_max [ iUsedHeap ] ) {
2013-03-31 20:48:49 +02:00
caddr_t prev_heap = heap [ iUsedHeap ] ;
2013-06-21 03:52:57 +02:00
# ifdef MODULE_TRACELOG
2013-03-31 20:48:49 +02:00
trace_pointer ( TRACELOG_EV_MEMORY , new_heap ) ;
2013-06-21 03:52:57 +02:00
# endif
2013-03-31 20:48:49 +02:00
heap [ iUsedHeap ] = new_heap ;
r - > _errno = 0 ;
restoreIRQ ( cpsr ) ;
return prev_heap ;
}
}
2013-06-21 03:52:57 +02:00
2013-03-31 20:48:49 +02:00
restoreIRQ ( cpsr ) ;
2013-06-21 03:52:57 +02:00
# ifdef MODULE_TRACELOG
2013-03-31 20:48:49 +02:00
trace_string ( TRACELOG_EV_MEMORY , " heap! " ) ; // heap full
2013-06-21 03:52:57 +02:00
# endif
2013-03-31 20:48:49 +02:00
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 )
{
2013-03-31 20:48:49 +02:00
r - > _errno = 0 ;
2013-06-21 03:52:57 +02:00
if ( fd = = STDOUT_FILENO | | fd = = STDERR_FILENO ) {
2013-03-31 20:48:49 +02:00
return 1 ;
2013-06-21 03:52:57 +02:00
}
else {
2013-03-31 20:48:49 +02:00
return 0 ;
2013-06-21 03:52:57 +02:00
}
2010-09-22 15:10:42 +02:00
}
/*---------------------------------------------------------------------------*/
_off_t _lseek_r ( struct _reent * r , int fd , _off_t pos , int whence )
{
2013-03-31 20:48:49 +02:00
_off_t result = - 1 ;
PRINTF ( " lseek [%i] pos %li whence %i \n " , fd , pos , whence ) ;
2010-09-22 15:10:42 +02:00
2013-03-31 20:48:49 +02:00
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
2013-03-31 20:48:49 +02:00
PRINTF ( " lseek returned %li (0 is success) \n " , result ) ;
return result ;
2010-09-22 15:10:42 +02:00
}
/*---------------------------------------------------------------------------*/
int _open_r ( struct _reent * r , const char * name , int mode )
{
2013-03-31 20:48:49 +02:00
int ret = - 1 ;
PRINTF ( " open '%s' mode %#x \n " , name , mode ) ;
2010-09-22 15:10:42 +02:00
2013-03-31 20:48:49 +02:00
r - > _errno = ENODEV ; // no such device
2012-03-08 18:58:39 +01:00
# ifdef MODULE_FAT
2013-06-21 03:52:57 +02:00
ret = ff_open_r ( r , name , mode ) ;
2012-03-08 18:58:39 +01:00
# endif
2010-09-22 15:10:42 +02:00
2013-03-31 20:48:49 +02:00
PRINTF ( " open [%i] errno %i \n " , ret , r - > _errno ) ;
return ret ;
2010-09-22 15:10:42 +02:00
}
/*---------------------------------------------------------------------------*/
int _stat_r ( struct _reent * r , char * name , struct stat * st )
{
2013-03-31 20:48:49 +02:00
int ret = - 1 ;
PRINTF ( " _stat_r '%s' \n " , name ) ;
r - > _errno = ENODEV ; // no such device
2012-03-08 18:58:39 +01:00
# ifdef MODULE_FAT
2013-06-21 03:52:57 +02:00
ret = ff_stat_r ( r , name , st ) ;
2012-03-08 18:58:39 +01:00
# endif
2013-03-31 20:48:49 +02:00
PRINTF ( " _stat_r [%i] errno %i \n " , ret , r - > _errno ) ;
return ret ;
2010-09-22 15:10:42 +02:00
}
/*---------------------------------------------------------------------------*/
2013-06-21 03:52:57 +02:00
int _fstat_r ( struct _reent * r , int fd , struct stat * st )
2010-09-22 15:10:42 +02:00
{
2013-03-31 20:48:49 +02:00
int ret = - 1 ;
2010-09-22 15:10:42 +02:00
2013-03-31 20:48:49 +02:00
r - > _errno = 0 ;
memset ( st , 0 , sizeof ( * st ) ) ;
2013-06-21 03:52:57 +02:00
if ( fd = = STDOUT_FILENO | | fd = = STDERR_FILENO ) {
2013-03-31 20:48:49 +02:00
st - > st_mode = S_IFCHR ;
ret = 0 ;
2013-06-21 03:52:57 +02:00
}
else {
2012-03-08 18:58:39 +01:00
# ifdef MODULE_FAT
2013-03-31 20:48:49 +02:00
PRINTF ( " _fstat_r '%i' \n " , fd ) ;
2012-03-08 18:58:39 +01:00
2013-06-21 03:52:57 +02:00
ret = ff_fstat_r ( r , fd , st ) ;
2013-03-31 20:48:49 +02:00
PRINTF ( " _fstat_r [%i] errno %i \n " , ret , r - > _errno ) ;
2012-03-08 18:58:39 +01:00
# else
2013-03-31 20:48:49 +02:00
r - > _errno = ENODEV ;
2012-03-08 18:58:39 +01:00
# endif
2013-03-31 20:48:49 +02:00
}
2013-06-21 03:52:57 +02:00
2013-03-31 20:48:49 +02:00
return ret ;
2010-09-22 15:10:42 +02:00
}
/*---------------------------------------------------------------------------*/
int _write_r ( struct _reent * r , int fd , const void * data , unsigned int count )
{
2013-03-31 20:48:49 +02:00
int result = EOF ;
r - > _errno = EBADF ;
switch ( fd ) {
case STDOUT_FILENO :
case STDERR_FILENO :
2013-06-21 03:52:57 +02: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
result = fw_puts ( ( char * ) data , count ) ;
# endif
2013-03-31 20:48:49 +02:00
break ;
default :
2013-06-21 03:52:57 +02:00
# ifdef MODULE_FAT
result = ff_write_r ( r , fd , data , count ) ;
# endif
2013-03-31 20:48:49 +02:00
PRINTF ( " write [%i] data @%p count %i \n " , fd , data , count ) ;
PRINTF ( " write [%i] returned %i errno %i \n " , fd , result , r - > _errno ) ;
break ;
}
return result ;
2010-09-22 15:10:42 +02:00
}
/*---------------------------------------------------------------------------*/
int _read_r ( struct _reent * r , int fd , void * buffer , unsigned int count )
{
2013-03-31 20:48:49 +02:00
int result = - 1 ;
r - > _errno = EBADF ;
2012-03-08 18:58:39 +01:00
# ifdef MODULE_FAT
2013-03-31 20:48:49 +02:00
result = ff_read_r ( r , fd , buffer , count ) ;
2012-03-08 18:58:39 +01:00
# endif
2012-11-08 17:37:29 +01:00
PRINTF ( " read [%i] buffer @%p count %i \n " , fd , buffer , count ) ;
2013-03-31 20:48:49 +02:00
PRINTF ( " read [%i] returned %i \n " , fd , result ) ;
2013-06-21 03:52:57 +02:00
2012-11-08 17:37:29 +01:00
return result ;
2010-09-22 15:10:42 +02:00
}
/*---------------------------------------------------------------------------*/
int _close_r ( struct _reent * r , int fd )
{
2013-03-31 20:48:49 +02:00
int result = - 1 ;
r - > _errno = EBADF ;
2013-06-21 03:52:57 +02:00
# ifdef MODULE_FAT
ret = ff_close_r ( r , fd ) ;
# endif
2012-11-08 17:37:29 +01:00
PRINTF ( " close [%i] \n " , fd ) ;
2013-03-31 20:48:49 +02:00
PRINTF ( " close returned %i errno %i \n " , result , errno ) ;
2013-06-21 03:52:57 +02:00
2012-11-08 17:37:29 +01:00
return result ;
2010-09-22 15:10:42 +02:00
}
/*---------------------------------------------------------------------------*/
2013-06-21 03:52:57 +02:00
int _unlink_r ( struct _reent * r , char * path )
2010-09-22 15:10:42 +02:00
{
2013-03-31 20:48:49 +02:00
int result = - 1 ;
r - > _errno = ENODEV ;
2012-03-08 18:58:39 +01:00
# ifdef MODULE_FAT
2013-03-31 20:48:49 +02: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 ) ;
2013-03-31 20:48:49 +02:00
PRINTF ( " unlink returned %i errno %i \n " , result , errno ) ;
2013-06-21 03:52:57 +02:00
2012-11-08 17:37:29 +01:00
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
2013-03-31 20:48:49 +02:00
trace_number ( TRACELOG_EV_EXIT , n ) ;
2012-03-08 18:58:39 +01:00
# endif
2013-03-31 20:48:49 +02:00
printf ( " #! exit %i: resetting \n " , n ) ;
2010-09-22 15:10:42 +02:00
2013-03-31 20:48:49 +02:00
stdio_flush ( ) ;
arm_reset ( ) ;
2013-06-21 03:52:57 +02:00
2013-03-31 20:48:49 +02:00
while ( 1 ) ;
2010-09-22 15:10:42 +02:00
}
/*---------------------------------------------------------------------------*/
int _getpid ( void )
{
2013-03-31 20:48:49 +02:00
return active_thread - > pid ;
2010-09-22 15:10:42 +02:00
}
/*---------------------------------------------------------------------------*/
int _kill_r ( struct _reent * r , int pid , int sig )
{
2013-03-31 20:48:49 +02:00
/* not implemented */
r - > _errno = ESRCH ; // no such process
return - 1 ;
2010-09-22 15:10:42 +02:00
}
/*---------------------------------------------------------------------------*/
2013-06-21 03:52:57 +02:00
void _init ( void ) { }
void _fini ( void ) { }