arch/arm: (1) Add semihost support for syslog, (2) Add semihost support for HostFS

This commit is contained in:
Gregory Nutt 2018-08-23 08:00:07 -06:00
parent e2ccce1f2e
commit 0001607f71
8 changed files with 529 additions and 0 deletions

View File

@ -737,6 +737,18 @@ config DEBUG_MEMFAULT
output is sometimes helpful when debugging difficult mem fault problems,
but may be more than you typically want to see.
config ARM_SEMIHOSTING_SYSLOG
bool "Semihosting SYSLOG support"
select ARCH_SYSLOG
---help---
Enable hooks to support semihosting syslog output.
config ARM_SEMIHOSTING_HOSTFS
bool "Semihosting HostFS"
depends on FS_HOSTFS
---help---
Mount HostFS through semihosting.
if ARCH_CORTEXM0
source arch/arm/src/armv6-m/Kconfig
endif

View File

@ -218,6 +218,28 @@ static inline uintptr_t sys_call6(unsigned int nbr, uintptr_t parm1,
return reg0;
}
/* semihosting(SMH) call with call number and one parameter */
static inline long smh_call(unsigned int nbr, void *parm)
{
register long reg0 __asm__("r0") = (long)(nbr);
register long reg1 __asm__("r1") = (long)(parm);
__asm__ __volatile__
(
#if defined(__thumb__) || defined(__thumb2__)
"svc #0xab"
#else
"svc #0x123456"
#endif
: "=r"(reg0)
: "r"(reg0), "r"(reg1)
: "memory"
);
return reg0;
}
/****************************************************************************
* Public Data
****************************************************************************/

View File

@ -241,6 +241,24 @@ static inline uintptr_t sys_call6(unsigned int nbr, uintptr_t parm1,
return reg0;
}
/* semihosting(SMH) call with call number and one parameter */
static inline long smh_call(unsigned int nbr, void *parm)
{
register long reg0 __asm__("r0") = (long)(nbr);
register long reg1 __asm__("r1") = (long)(parm);
__asm__ __volatile__
(
"bkpt #0xab"
: "=r"(reg0)
: "r"(reg0), "r"(reg1)
: "memory"
);
return reg0;
}
/****************************************************************************
* Public Data
****************************************************************************/

View File

@ -218,6 +218,28 @@ static inline uintptr_t sys_call6(unsigned int nbr, uintptr_t parm1,
return reg0;
}
/* semihosting(SMH) call with call number and one parameter */
static inline long smh_call(unsigned int nbr, void *parm)
{
register long reg0 __asm__("r0") = (long)(nbr);
register long reg1 __asm__("r1") = (long)(parm);
__asm__ __volatile__
(
#if defined(__thumb__) || defined(__thumb2__)
"svc #0xab"
#else
"svc #0x123456"
#endif
: "=r"(reg0)
: "r"(reg0), "r"(reg1)
: "memory"
);
return reg0;
}
/****************************************************************************
* Public Data
****************************************************************************/

View File

@ -241,6 +241,24 @@ static inline uintptr_t sys_call6(unsigned int nbr, uintptr_t parm1,
return reg0;
}
/* semihosting(SMH) call with call number and one parameter */
static inline long smh_call(unsigned int nbr, void *parm)
{
register long reg0 __asm__("r0") = (long)(nbr);
register long reg1 __asm__("r1") = (long)(parm);
__asm__ __volatile__
(
"bkpt #0xab"
: "=r"(reg0)
: "r"(reg0), "r"(reg1)
: "memory"
);
return reg0;
}
/****************************************************************************
* Public Data
****************************************************************************/

View File

@ -218,6 +218,28 @@ static inline uintptr_t sys_call6(unsigned int nbr, uintptr_t parm1,
return reg0;
}
/* semihosting(SMH) call with call number and one parameter */
static inline long smh_call(unsigned int nbr, void *parm)
{
register long reg0 __asm__("r0") = (long)(nbr);
register long reg1 __asm__("r1") = (long)(parm);
__asm__ __volatile__
(
#if defined(__thumb__) || defined(__thumb2__)
"svc #0xab"
#else
"svc #0x123456"
#endif
: "=r"(reg0)
: "r"(reg0), "r"(reg1)
: "memory"
);
return reg0;
}
/****************************************************************************
* Public Data
****************************************************************************/

View File

@ -0,0 +1,332 @@
/****************************************************************************
* arch/arm/src/common/up_hostfs.c
*
* Copyright (C) 2018 Pinecone Inc. All rights reserved.
* Author: Xiang Xiao <xiaoxiang@pinecone.net>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <nuttx/fs/hostfs.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <syscall.h>
#include <unistd.h>
#ifdef CONFIG_ARM_SEMIHOSTING_HOSTFS
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define HOST_OPEN 0x01
#define HOST_CLOSE 0x02
#define HOST_WRITE 0x05
#define HOST_READ 0x06
#define HOST_SEEK 0x0a
#define HOST_FLEN 0x0c
#define HOST_REMOVE 0x0e
#define HOST_RENAME 0x0f
#define HOST_ERROR 0x13
/****************************************************************************
* Private Functions
****************************************************************************/
static long host_call(unsigned int nbr, void *parm)
{
long ret = smh_call(nbr, parm);
if (ret < 0)
{
long err = smh_call(HOST_ERROR, NULL);
if (err > 0)
{
ret = -err;
}
}
return ret;
}
static ssize_t host_flen(long fd)
{
return host_call(HOST_FLEN, &fd);
}
static int host_flags_to_mode(int flags)
{
static const int modeflags[] =
{
O_RDONLY,
O_RDONLY | O_BINARY,
O_RDWR,
O_RDWR | O_BINARY,
O_WRONLY | O_CREAT | O_TRUNC,
O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
O_RDWR | O_CREAT | O_TRUNC,
O_RDWR | O_CREAT | O_TRUNC | O_BINARY,
O_WRONLY | O_CREAT | O_APPEND,
O_WRONLY | O_CREAT | O_APPEND | O_BINARY,
O_RDWR | O_CREAT | O_APPEND,
O_RDWR | O_CREAT | O_APPEND | O_BINARY,
0,
};
int i;
for (i = 0; modeflags[i] != 0; i++)
{
if (modeflags[i] == flags)
{
return i;
}
}
return -EINVAL;
}
/****************************************************************************
* Public Functions
****************************************************************************/
int host_open(const char *pathname, int flags, int mode)
{
struct
{
const char *pathname;
long mode;
size_t len;
} open =
{
.pathname = pathname,
.mode = host_flags_to_mode(flags),
.len = strlen(pathname),
};
return host_call(HOST_OPEN, &open);
}
int host_close(int fd_)
{
long fd = fd_;
return host_call(HOST_CLOSE, &fd);
}
ssize_t host_read(int fd, void *buf, size_t count)
{
struct
{
long fd;
void *buf;
size_t count;
} read =
{
.fd = fd,
.buf = buf,
.count = count,
};
ssize_t ret = host_call(HOST_READ, &read);
return ret < 0 ? ret : count - ret;
}
ssize_t host_write(int fd, const void *buf, size_t count)
{
struct
{
long fd;
const void *buf;
size_t count;
} write =
{
.fd = fd,
.buf = buf,
.count = count,
};
ssize_t ret = host_call(HOST_WRITE, &write);
return ret < 0 ? ret : count - ret;
}
off_t host_lseek(int fd, off_t offset, int whence)
{
off_t ret = -ENOSYS;
if (whence == SEEK_END)
{
ret = host_flen(fd);
if (ret >= 0)
{
offset += ret;
whence = SEEK_SET;
}
}
if (whence == SEEK_SET)
{
struct
{
long fd;
size_t pos;
} seek =
{
.fd = fd,
.pos = offset,
};
ret = host_call(HOST_SEEK, &seek);
if (ret >= 0)
{
ret = offset;
}
}
return ret;
}
int host_ioctl(int fd, int request, unsigned long arg)
{
return -ENOSYS;
}
void host_sync(int fd)
{
}
int host_dup(int fd)
{
return -ENOSYS;
}
int host_fstat(int fd, struct stat *buf)
{
memset(buf, 0, sizeof(*buf));
buf->st_mode = S_IFREG | 0777;
buf->st_size = host_flen(fd);
return buf->st_size < 0 ? buf->st_size : 0;
}
int host_ftruncate(int fd, off_t length)
{
return -ENOSYS;
}
void *host_opendir(const char *name)
{
return NULL;
}
int host_readdir(void *dirp, struct dirent *entry)
{
return -ENOSYS;
}
void host_rewinddir(void *dirp)
{
}
int host_closedir(void *dirp)
{
return -ENOSYS;
}
int host_statfs(const char *path, struct statfs *buf)
{
return 0;
}
int host_unlink(const char *pathname)
{
struct
{
const char *pathname;
size_t pathname_len;
} remove =
{
.pathname = pathname,
.pathname_len = strlen(pathname),
};
return host_call(HOST_REMOVE, &remove);
}
int host_mkdir(const char *pathname, mode_t mode)
{
return -ENOSYS;
}
int host_rmdir(const char *pathname)
{
return host_unlink(pathname);
}
int host_rename(const char *oldpath, const char *newpath)
{
struct
{
const char *oldpath;
size_t oldpath_len;
const char *newpath;
size_t newpath_len;
} rename =
{
.oldpath = oldpath,
.oldpath_len = strlen(oldpath),
.newpath = newpath,
.newpath_len = strlen(newpath),
};
return host_call(HOST_RENAME, &rename);
}
int host_stat(const char *path, struct stat *buf)
{
int ret = host_open(path, O_RDONLY, 0);
if (ret >= 0)
{
int fd = ret;
ret = host_fstat(fd, buf);
host_close(fd);
}
if (ret < 0)
{
/* Since semihosting doesn't support directory yet, */
ret = 0; /* we have to assume it's a directory here. */
memset(buf, 0, sizeof(*buf));
buf->st_mode = S_IFDIR | 0777;
}
return ret;
}
#endif

View File

@ -0,0 +1,83 @@
/****************************************************************************
* arch/arm/src/common/up_semi_syslog.c
*
* Copyright (C) 2018 Pinecone Inc. All rights reserved.
* Author: Xiang Xiao <xiaoxiang@pinecone.net>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <nuttx/arch.h>
#include <syscall.h>
#include "up_internal.h"
#ifdef CONFIG_ARM_SEMIHOSTING_SYSLOG
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define SEMI_SYSLOG_WRITEC 0x03
#define SEMI_SYSLOG_WRITE0 0x04
#define SEMI_SYSLOG_READC 0x07
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: up_putc
****************************************************************************/
int up_putc(int ch)
{
smh_call(SEMI_SYSLOG_WRITEC, &ch);
return ch;
}
/****************************************************************************
* Name: up_puts
*
* Description:
* Output a string on the console
*
****************************************************************************/
void up_puts(FAR const char *str)
{
smh_call(SEMI_SYSLOG_WRITE0, (char *)str);
}
#endif