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:
parent
ec738191c1
commit
5f5e01fd3b
@ -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
22
inc/semifs.h
Normal 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
68
inc/swi.h
Normal 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)
|
@ -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
|
||||
|
@ -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() );
|
||||
|
||||
|
@ -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
224
src/semifs.c
Normal 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
|
||||
|
Loading…
x
Reference in New Issue
Block a user