1
0
mirror of https://github.com/elua/elua.git synced 2025-01-08 20:56:17 +08:00

Add support for Semihosting filesystem operations

- enable file creation, reading, writing on mbed for the built-in filesystem
- implementation currently lacks support for directory listings, this will be
  added when mbed implementation details are available.

Note: this should work with other ARM arm ports that are connected to a JTAG
debugger that implements semihosting, though I have not tested it.
This commit is contained in:
James Snyder 2010-03-08 20:08:07 +00:00
parent ec738191c1
commit 5f5e01fd3b
7 changed files with 320 additions and 1 deletions

View File

@ -298,7 +298,7 @@ cdefs = cdefs + " -DLUA_OPTIMIZE_MEMORY=%d" % ( optram != 0 and 2 or 0 )
local_libs = ''
# Application files
app_files = " src/main.c src/romfs.c src/xmodem.c src/shell.c src/term.c src/common.c src/buf.c src/elua_adc.c src/dlmalloc.c src/salloc.c src/luarpc_elua_uart.c "
app_files = " src/main.c src/romfs.c src/semifs.c src/xmodem.c src/shell.c src/term.c src/common.c src/buf.c src/elua_adc.c src/dlmalloc.c src/salloc.c src/luarpc_elua_uart.c "
# Newlib related files
newlib_files = " src/newlib/devman.c src/newlib/stubs.c src/newlib/genstd.c src/newlib/stdtcp.c"

22
inc/semifs.h Normal file
View File

@ -0,0 +1,22 @@
// Semihosting filesystem
#ifndef __SEMIFS_H__
#define __SEMIFS_H__
#include "type.h"
#include "devman.h"
// ARM Semihosting Commands
#define SYS_OPEN (0x1)
#define SYS_CLOSE (0x2)
#define SYS_WRITE (0x5)
#define SYS_READ (0x6)
#define SYS_ISTTY (0x9)
#define SYS_SEEK (0xa)
#define SYS_ENSURE (0xb)
#define SYS_FLEN (0xc)
// FS functions
const DM_DEVICE* semifs_init();
#endif

68
inc/swi.h Normal file
View File

@ -0,0 +1,68 @@
/* SWI numbers for RDP (Demon) monitor. */
#define SWI_WriteC 0x0
#define SWI_Write0 0x2
#define SWI_ReadC 0x4
#define SWI_CLI 0x5
#define SWI_GetEnv 0x10
#define SWI_Exit 0x11
#define SWI_EnterOS 0x16
#define SWI_GetErrno 0x60
#define SWI_Clock 0x61
#define SWI_Time 0x63
#define SWI_Remove 0x64
#define SWI_Rename 0x65
#define SWI_Open 0x66
#define SWI_Close 0x68
#define SWI_Write 0x69
#define SWI_Read 0x6a
#define SWI_Seek 0x6b
#define SWI_Flen 0x6c
#define SWI_IsTTY 0x6e
#define SWI_TmpNam 0x6f
#define SWI_InstallHandler 0x70
#define SWI_GenerateError 0x71
/* Now the SWI numbers and reason codes for RDI (Angel) monitors. */
#define AngelSWI_ARM 0x123456
#ifdef __thumb__
#define AngelSWI 0xAB
#else
#define AngelSWI AngelSWI_ARM
#endif
/* For Thumb-2 code use the BKPT instruction instead of SWI. */
#ifdef __thumb2__
#define AngelSWIInsn "bkpt"
#define AngelSWIAsm bkpt
#else
#define AngelSWIInsn "swi"
#define AngelSWIAsm swi
#endif
/* The reason codes: */
#define AngelSWI_Reason_Open 0x01
#define AngelSWI_Reason_Close 0x02
#define AngelSWI_Reason_WriteC 0x03
#define AngelSWI_Reason_Write0 0x04
#define AngelSWI_Reason_Write 0x05
#define AngelSWI_Reason_Read 0x06
#define AngelSWI_Reason_ReadC 0x07
#define AngelSWI_Reason_IsTTY 0x09
#define AngelSWI_Reason_Seek 0x0A
#define AngelSWI_Reason_FLen 0x0C
#define AngelSWI_Reason_TmpNam 0x0D
#define AngelSWI_Reason_Remove 0x0E
#define AngelSWI_Reason_Rename 0x0F
#define AngelSWI_Reason_Clock 0x10
#define AngelSWI_Reason_Time 0x11
#define AngelSWI_Reason_System 0x12
#define AngelSWI_Reason_Errno 0x13
#define AngelSWI_Reason_GetCmdLine 0x15
#define AngelSWI_Reason_HeapInfo 0x16
#define AngelSWI_Reason_EnterSVC 0x17
#define AngelSWI_Reason_ReportException 0x18
#define ADP_Stopped_ApplicationExit ((2 << 16) + 38)
#define ADP_Stopped_RunTimeError ((2 << 16) + 35)

View File

@ -23,6 +23,7 @@ elseif pd.board() == "ELUA-PUC" then
ledpin = pio.P1_20
elseif pd.board() == "MBED" then
ledpin = mbed.pio.LED1
mbed.pio.configpin( ledpin, 0, 0, 0 )
else
print( "\nError: Unknown board " .. pd.board() .. " !" )
return

View File

@ -87,6 +87,9 @@ int main( void )
// Register the MMC filesystem
dm_register( mmcfs_init() );
// Register the Semihosting filesystem
dm_register( semifs_init() );
// Register the remote filesystem
dm_register( remotefs_init() );

View File

@ -14,6 +14,7 @@
#define BUILD_ROMFS
#define BUILD_TERM
#define BUILD_CON_GENERIC
#define BUILD_SEMIFS
//#define BUILD_LUARPC
// *****************************************************************************

224
src/semifs.c Normal file
View File

@ -0,0 +1,224 @@
// Filesystem implementation
#include "swi.h"
#include "type.h"
#include <string.h>
#include <errno.h>
#include "devman.h"
#include <stdio.h>
#include "ioctl.h"
#include "semifs.h"
#include <stdint.h>
#include <fcntl.h>
#include "platform_conf.h"
#ifdef BUILD_SEMIFS
#define SEMIFS_MAX_FDS 4
typedef struct
{
int handle;
int pos;
} poslog;
static poslog semifs_fd_table[ SEMIFS_MAX_FDS ];
static int semifs_num_fd;
static inline int
__semihost(int reason, void * arg)
{
int value;
asm volatile ("mov r0, %1; mov r1, %2; " AngelSWIInsn " %a3; mov %0, r0"
: "=r" (value) /* Outputs */
: "r" (reason), "r" (arg), "i" (AngelSWI) /* Inputs */
: "r0", "r1", "r2", "r3", "ip", "lr", "memory", "cc"
/* Clobbers r0 and r1, and lr if in supervisor mode */);
/* Accordingly to page 13-77 of ARM DUI 0040D other registers
can also be clobbered. Some memory positions may also be
changed by a system call, so they should not be kept in
registers. Note: we are assuming the manual is right and
Angel is respecting the APCS. */
return value;
}
static int semifs_find_empty_fd()
{
int i;
for (i = 0; i < SEMIFS_MAX_FDS; i ++)
if (semifs_fd_table[ i ].handle == -1)
return i;
return -1;
}
static int semifs_open_r( struct _reent *r, const char *path, int flags, int mode )
{
int aflags = 0, fd, fh;
uint32_t args[3];
if (semifs_num_fd == SEMIFS_MAX_FDS)
{
r->_errno = ENFILE;
return -1;
}
if (flags & O_RDWR)
aflags |= 2;
if (flags & O_CREAT)
aflags |= 4;
if (flags & O_TRUNC)
aflags |= 4;
if (flags & O_APPEND)
{
aflags &= ~4; /* Can't ask for w AND a; means just 'a'. */
aflags |= 8;
}
fd = semifs_find_empty_fd();
semifs_num_fd ++;
args[0] = ( uint32_t )path;
args[1] = ( uint32_t )aflags;
args[2] = ( uint32_t )strlen( path );
fh = __semihost(SYS_OPEN, args);
if (fh >= 0)
{
semifs_fd_table[ fd ].handle = fh;
semifs_fd_table[ fd ].pos = 0;
}
return fd;
}
static int semifs_close_r( struct _reent *r, int fd )
{
int fh = semifs_fd_table[ fd ].handle;
if( fd != SEMIFS_MAX_FDS )
semifs_fd_table[ fd ].handle = -1;
return __semihost(SYS_CLOSE, &fh);
}
static _ssize_t semifs_write_r( struct _reent *r, int fd, const void* ptr, size_t len )
{
int fh = semifs_fd_table[ fd ].handle, x;
uint32_t args[3];
args[0] = (uint32_t)fh;
args[1] = (uint32_t)ptr;
args[2] = (uint32_t)len;
x = __semihost(SYS_WRITE, args);
if (x == -1 || x == len)
{
r->_errno = EIO;
return -1;
}
if ( fd != SEMIFS_MAX_FDS )
semifs_fd_table[ fd ].pos += len - x;
return len - x;
}
static _ssize_t semifs_read_r( struct _reent *r, int fd, void* ptr, size_t len )
{
int fh = semifs_fd_table[ fd ].handle, x;
uint32_t args[3];
args[0] = (uint32_t)fh;
args[1] = (uint32_t)ptr;
args[2] = (uint32_t)len;
x = __semihost(SYS_READ, args);
if (x < 0)
{
r->_errno = EIO;
return -1;
}
if (fd != SEMIFS_MAX_FDS)
semifs_fd_table[ fd ].pos += len - x;
return len - x;
}
static off_t semifs_lseek_r( struct _reent *r, int fd, off_t off, int whence )
{
int fh = semifs_fd_table[ fd ].handle, res;
uint32_t args[2];
u32 newpos = 0;
switch( whence )
{
case SEEK_CUR:
// seek from current position
if (fd == SEMIFS_MAX_FDS)
return -1;
off += semifs_fd_table[ fd ].pos;
whence = SEEK_SET;
break;
case SEEK_END:
// seek from end of file
args[ 0 ] = fh;
off += __semihost(SYS_FLEN, &args);
break;
case SEEK_SET:
break;
default:
return -1;
}
// Do absolute seek
args[ 0 ] = (uint32_t)fh;
args[ 1 ] = (uint32_t)off;
res = __semihost(SYS_SEEK, args);
if (fd != SEMIFS_MAX_FDS && res == 0)
semifs_fd_table[ fd ].pos = off;
/* This is expected to return the position in the file. */
return res == 0 ? off : -1;
}
// Semihosting device descriptor structure
static DM_DEVICE semifs_device =
{
"/semi",
semifs_open_r, // open
semifs_close_r, // close
semifs_write_r, // write
semifs_read_r, // read
semifs_lseek_r, // lseek
NULL, // opendir
NULL, // readdir
NULL // closedir
};
const DM_DEVICE* semifs_init()
{
int i;
for (i = 0; i < SEMIFS_MAX_FDS; i ++)
semifs_fd_table[i].handle = -1;
return &semifs_device;
}
#else // #ifdef BUILD_SEMIFS
const DM_DEVICE* semifs_init()
{
return NULL;
}
#endif // #ifdef BUILD_SEMIFS