fixed pdclib for arm, can make programs for stmos

master
tcsullivan 6 years ago
parent c6ef89664b
commit e88b4f9040

@ -42,9 +42,11 @@ all:
@$(MAKE) -C src/user
@echo " INITRD"
@tools/rba initrd.img $$(find initrd/*)
@$(CROSS)$(OBJCOPY) -B arm -I binary -O elf32-littlearm initrd.img initrd.img.o
@$(CROSS)$(OBJCOPY) -B arm -I binary -O elf32-littlearm initrd.img \
initrd.img.o
@echo " LINK " $(OUT)
@$(CROSS)$(CC) $(CFLAGS) $(LFLAGS) -o $(OUT) $$(find src/ -name "*.o") initrd.img.o
@$(CROSS)$(CC) $(CFLAGS) $(LFLAGS) -o $(OUT) \
$$(find src/fs src/kernel src/user -name "*.o") initrd.img.o
clean:

@ -0,0 +1,4 @@
all:
@arm-none-eabi-gcc -mcpu=cortex-m4 -mthumb -fsigned-char -Os -nostdinc \
-I../src/pdclib/include -I../src/pdclib/platform/stmos/include \
test.c ../src/pdclib/pdclib.a -s -o test -pie

Binary file not shown.

@ -0,0 +1,8 @@
#include <stdio.h>
int main(void)
{
printf("Hello, world!\n");
return 0;
}

@ -35,6 +35,8 @@ void clock_svc(uint32_t *args)
task_sleep(args[1]);
else if (args[0] == 1)
udelay(args[1]);
else if (args[0] == 2)
*((unsigned int *)args[1]) = ticks;
}
void clock_init(void)

@ -65,6 +65,7 @@ void SVC_Handler(void) {
case 2: /* Clock-related calls
* 0 - delay
* 1 - udelay
* 2 - ticks
*/
clock_svc(args);
break;
@ -74,6 +75,7 @@ void SVC_Handler(void) {
* 1 - open
* 2 - close
* 3 - read
* 4 - write
*/
vfs_svc(args);
break;

@ -26,6 +26,9 @@ void vfs_svc(uint32_t *args)
case 3:
*((int *)args[4]) = vfs_read(args[1], args[2], (uint8_t *)args[3]);
break;
case 4:
*((int *)args[4]) = vfs_write(args[1], args[2], (const uint8_t *)args[3]);
break;
default:
break;
}
@ -141,8 +144,30 @@ uint32_t vfs_read(int fd, uint32_t count, uint8_t *buffer)
VFS_EOF))
return 0;
uint32_t ret = vfs_volumes[vfs_files[fd].vol].funcs->read(vfs_files[fd].fsinfo,
count, buffer);
uint32_t ret = vfs_volumes[vfs_files[fd].vol].funcs->read(
vfs_files[fd].fsinfo, count, buffer);
if (ret < count)
vfs_files[fd].flags |= VFS_EOF;
return ret;
}
uint32_t vfs_write(int fd, uint32_t count, const uint8_t *buffer)
{
if (fd < 0 || fd > VFS_MAX_FILES || count == 0 || buffer == 0)
return 0;
if (vfs_volumes[vfs_files[fd].vol].funcs->write == 0)
return -1;
if (vfs_files[fd].pid != task_getpid())
return 0;
// TODO append?
if ((!(vfs_files[fd].flags & VFS_FILE_WRITE)) || (vfs_files[fd].flags &
VFS_EOF))
return 0;
uint32_t ret = vfs_volumes[vfs_files[fd].vol].funcs->write(
vfs_files[fd].fsinfo, count, buffer);
if (ret < count)
vfs_files[fd].flags |= VFS_EOF;

@ -47,5 +47,6 @@ int vfs_mount(vfs_volume_funcs *funcs, uint32_t flags);
int vfs_open(const char *path, uint32_t flags);
int vfs_close(int fd);
uint32_t vfs_read(int fd, uint32_t count, uint8_t *buffer);
uint32_t vfs_write(int fd, uint32_t count, const uint8_t *buffer);
#endif // VFS_H_

@ -24,8 +24,10 @@ REGDEPFILES := $(patsubst %,$(BUILDDIR)/%.d,$(REGFILES))
# All files belonging to the source distribution
ALLFILES := $(SRCFILES) $(HDRFILES) $(AUXFILES)
CC = arm-none-eabi-gcc -mcpu=cortex-m4 -mthumb -fsigned-char --specs=nosys.specs
WARNINGS := -Wall -Wextra -pedantic -Wno-unused-parameter -Wshadow -Wpointer-arith -Wcast-align -Wwrite-strings -Wmissing-prototypes -Wmissing-declarations -Wredundant-decls -Wnested-externs -Winline -Wno-long-long -Wuninitialized -Wstrict-prototypes -Wdeclaration-after-statement
CFLAGS := -fno-builtin -g -std=c99 -I./testing -I../user -I./platform/stmos/include $(WARNINGS) $(USERFLAGS)
CFLAGS := -fno-builtin -g -std=c99 -I./testing -I./platform/stmos/include $(WARNINGS) $(USERFLAGS)
.PHONY: all clean srcdist tests testdrivers regtests regtestdrivers todos fixmes help
@ -58,7 +60,7 @@ all: $(BUILDDIR)/pdclib.a #testdrivers regtestdrivers
$(BUILDDIR)/pdclib.a: $(OBJFILES)
@echo " AR $@"
@ar rc $(BUILDDIR)/pdclib.a $?
@arm-none-eabi-ar rc $(BUILDDIR)/pdclib.a $?
@echo
tests: testdrivers

@ -1,12 +1,9 @@
#ifndef SYSCALLS_H_
#define SYSCALLS_H_
#include <stdint.h>
#include "syscalls.h"
//
// Task-related calls
inline void _exit(int code)
void _exit(int code)
{
register uint32_t r1 __asm("r1") = code;
__asm("\
@ -16,7 +13,7 @@ inline void _exit(int code)
" :: "r" (r1));
}
inline int fork(void)
int fork(void)
{
int ret = 0;
register uint32_t r1 __asm("r1") = (uint32_t)&ret;
@ -28,7 +25,7 @@ inline int fork(void)
return ret;
}
inline int getpid(void)
int getpid(void)
{
int ret = 0;
register uint32_t r1 __asm("r1") = (uint32_t)&ret;
@ -40,7 +37,7 @@ inline int getpid(void)
return ret;
}
inline void *sbrk(unsigned int bytes)
void *sbrk(unsigned int bytes)
{
void *ret = 0;
register uint32_t r1 __asm("r1") = bytes;
@ -55,32 +52,34 @@ inline void *sbrk(unsigned int bytes)
}
//
// File-related calls
// Indicates mounted volume
#define VFS_MOUNTED (1 << 0)
// Set if filesystem is read-only
#define VFS_READONLY (1 << 1)
// Clock-related calls
// Indicates an opened file
#define VFS_FILE_OPEN (1 << 0)
// Indicates read permission on file
#define VFS_FILE_READ (1 << 1)
// Indicates write permission on file
#define VFS_FILE_WRITE (1 << 2)
// Set if EOF has been reached
#define VFS_EOF (1 << 3)
#define EOF (-1)
void delay(unsigned int ms)
{
register uint32_t r1 __asm("r1") = ms;
__asm("\
mov r0, 0; \
mov r1, %0; \
svc 2; \
" :: "r" (r1));
}
struct dirent {
char name[32];
};
unsigned int ticks(void)
{
unsigned int ret = 0;
register uint32_t r1 __asm("r1") = (uint32_t)&ret;
__asm("\
mov r0, 2; \
mov r1, %0; \
svc 2; \
" :: "r" (r1));
return ret;
}
struct vfs_volume_funcs_t;
typedef struct vfs_volume_funcs_t vfs_volume_funcs;
//
// File-related calls
inline int mount(vfs_volume_funcs *funcs, uint32_t flags)
int mount(vfs_volume_funcs *funcs, uint32_t flags)
{
int ret = 0;
register uint32_t r1 __asm("r1") = (uint32_t)funcs;
@ -96,7 +95,7 @@ inline int mount(vfs_volume_funcs *funcs, uint32_t flags)
return ret;
}
inline int open(const char *path, uint32_t flags)
int open(const char *path, uint32_t flags)
{
int ret = 0;
register uint32_t r1 __asm("r1") = (uint32_t)path;
@ -112,7 +111,7 @@ inline int open(const char *path, uint32_t flags)
return ret;
}
inline int close(int fd)
int close(int fd)
{
int ret = 0;
register uint32_t r1 __asm("r1") = fd;
@ -123,9 +122,10 @@ inline int close(int fd)
mov r2, %1; \
svc 3; \
" :: "r" (r1), "r" (r2));
return ret;
}
inline int read(int fd, uint32_t count, uint8_t *buffer)
int read(int fd, uint32_t count, uint8_t *buffer)
{
int ret = 0;
register uint32_t r1 __asm("r1") = fd;
@ -143,4 +143,21 @@ inline int read(int fd, uint32_t count, uint8_t *buffer)
return ret;
}
#endif // SYSCALLS_H_
int write(int fd, uint32_t count, const uint8_t *buffer)
{
int ret = 0;
register uint32_t r1 __asm("r1") = fd;
register uint32_t r2 __asm("r2") = count;
register uint32_t r3 __asm("r3") = (uint32_t)buffer;
register uint32_t r4 __asm("r4") = (uint32_t)&ret;
__asm("\
mov r0, 4; \
mov r1, %0; \
mov r2, %1; \
mov r3, %2; \
mov r4, %3; \
svc 3; \
" :: "r" (r1), "r" (r2), "r" (r3), "r" (r4));
return ret;
}

@ -7,57 +7,58 @@
/* This is an example implementation of remove() fit for use with POSIX kernels.
*/
#include <stdio.h>
#include <syscalls.h>
#ifndef REGTEST
#include <string.h>
//#include <string.h>
#include "/usr/include/errno.h"
//#include "/usr/include/errno.h"
extern struct _PDCLIB_file_t * _PDCLIB_filelist;
extern int unlink( const char * pathname );
//extern int unlink( const char * pathname );
int remove( const char * pathname )
{
int rc;
struct _PDCLIB_file_t * current = _PDCLIB_filelist;
while ( current != NULL )
{
if ( ( current->filename != NULL ) && ( strcmp( current->filename, pathname ) == 0 ) )
{
return EOF;
}
current = current->next;
}
if ( ( rc = unlink( pathname ) ) == -1 )
{
switch ( errno )
{
/* See the comments on implementation-defined errno values in
<_PDCLIB_config.h>.
*/
case EACCES:
case EFAULT:
case EIO:
case EISDIR:
case ELOOP:
case ENAMETOOLONG:
case ENOENT:
case ENOMEM:
case ENOTDIR:
case EPERM:
case EROFS:
_PDCLIB_errno = _PDCLIB_ERROR;
break;
default:
// int rc;
// struct _PDCLIB_file_t * current = _PDCLIB_filelist;
// while ( current != NULL )
// {
// if ( ( current->filename != NULL ) && ( strcmp( current->filename, pathname ) == 0 ) )
// {
// return EOF;
// }
// current = current->next;
// }
// if ( ( rc = unlink( pathname ) ) == -1 )
// {
// switch ( errno )
// {
// /* See the comments on implementation-defined errno values in
// <_PDCLIB_config.h>.
// */
// case EACCES:
// case EFAULT:
// case EIO:
// case EISDIR:
// case ELOOP:
// case ENAMETOOLONG:
// case ENOENT:
// case ENOMEM:
// case ENOTDIR:
// case EPERM:
// case EROFS:
// _PDCLIB_errno = _PDCLIB_ERROR;
// break;
// default:
/* This should be something like EUNKNOWN. */
_PDCLIB_errno = _PDCLIB_ERROR;
break;
}
}
return rc;
// break;
// }
// }
// return rc;
return EOF;
}
#endif

@ -4,20 +4,20 @@
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <stdio.h>
//#include <stdio.h>
#ifndef REGTEST
#include "pdclib/_PDCLIB_glue.h"
#include <inttypes.h>
//#include <inttypes.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
//#include <string.h>
//
//#include <sys/types.h>
//#include <sys/stat.h>
//#include <fcntl.h>
//#include <unistd.h>
extern struct _PDCLIB_file_t * _PDCLIB_filelist;
@ -26,61 +26,61 @@ extern struct _PDCLIB_file_t * _PDCLIB_filelist;
*/
struct _PDCLIB_file_t * tmpfile( void )
{
FILE * rc;
/* This is the chosen way to get high-quality randomness. Replace as
appropriate.
*/
FILE * randomsource = fopen( "/proc/sys/kernel/random/uuid", "rb" );
char filename[ L_tmpnam ];
_PDCLIB_fd_t fd;
if ( randomsource == NULL )
{
return NULL;
}
for ( ;; )
{
/* Get a filename candidate. What constitutes a valid filename and
where temporary files are usually located is platform-dependent,
which is one reason why this function is located in the platform
overlay. The other reason is that a *good* implementation should
use high-quality randomness instead of a pseudo-random sequence to
generate the filename candidate, which is *also* platform-dependent.
*/
unsigned int random;
fscanf( randomsource, "%u", &random );
sprintf( filename, "/tmp/%u.tmp", random );
/* Check if file of this name exists. Note that fopen() is a very weak
check, which does not take e.g. access permissions into account
(file might exist but not readable). Replace with something more
appropriate.
*/
fd = open( filename, O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR );
if ( fd != -1 )
{
break;
}
close( fd );
}
fclose( randomsource );
/* See fopen(). */
if ( ( rc = calloc( 1, sizeof( struct _PDCLIB_file_t ) + _PDCLIB_UNGETCBUFSIZE + L_tmpnam + BUFSIZ ) ) == NULL )
{
/* No memory to set up FILE structure */
close( fd );
// FILE * rc;
// /* This is the chosen way to get high-quality randomness. Replace as
// appropriate.
// */
// FILE * randomsource = fopen( "/proc/sys/kernel/random/uuid", "rb" );
// char filename[ L_tmpnam ];
// _PDCLIB_fd_t fd;
// if ( randomsource == NULL )
// {
return NULL;
}
rc->status = _PDCLIB_filemode( "wb+" ) | _IOLBF | _PDCLIB_DELONCLOSE;
rc->handle = fd;
rc->ungetbuf = (unsigned char *)rc + sizeof( struct _PDCLIB_file_t );
rc->filename = (char *)rc->ungetbuf + _PDCLIB_UNGETCBUFSIZE;
rc->buffer = rc->filename + L_tmpnam;
strcpy( rc->filename, filename );
rc->bufsize = BUFSIZ;
rc->bufidx = 0;
rc->ungetidx = 0;
rc->next = _PDCLIB_filelist;
_PDCLIB_filelist = rc;
return rc;
// }
// for ( ;; )
// {
// /* Get a filename candidate. What constitutes a valid filename and
// where temporary files are usually located is platform-dependent,
// which is one reason why this function is located in the platform
// overlay. The other reason is that a *good* implementation should
// use high-quality randomness instead of a pseudo-random sequence to
// generate the filename candidate, which is *also* platform-dependent.
// */
// unsigned int random;
// fscanf( randomsource, "%u", &random );
// sprintf( filename, "/tmp/%u.tmp", random );
// /* Check if file of this name exists. Note that fopen() is a very weak
// check, which does not take e.g. access permissions into account
// (file might exist but not readable). Replace with something more
// appropriate.
// */
// fd = open( filename, O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR );
// if ( fd != -1 )
// {
// break;
// }
// close( fd );
// }
// fclose( randomsource );
// /* See fopen(). */
// if ( ( rc = calloc( 1, sizeof( struct _PDCLIB_file_t ) + _PDCLIB_UNGETCBUFSIZE + L_tmpnam + BUFSIZ ) ) == NULL )
// {
// /* No memory to set up FILE structure */
// close( fd );
// return NULL;
// }
// rc->status = _PDCLIB_filemode( "wb+" ) | _IOLBF | _PDCLIB_DELONCLOSE;
// rc->handle = fd;
// rc->ungetbuf = (unsigned char *)rc + sizeof( struct _PDCLIB_file_t );
// rc->filename = (char *)rc->ungetbuf + _PDCLIB_UNGETCBUFSIZE;
// rc->buffer = rc->filename + L_tmpnam;
// strcpy( rc->filename, filename );
// rc->bufsize = BUFSIZ;
// rc->bufidx = 0;
// rc->ungetidx = 0;
// rc->next = _PDCLIB_filelist;
// _PDCLIB_filelist = rc;
// return rc;
}
#endif

@ -8,16 +8,17 @@
#ifndef REGTEST
#include <sys/times.h>
#include <syscalls.h>
clock_t clock( void )
{
struct tms buf;
if ( times( &buf ) != (clock_t)-1 )
{
return buf.tms_utime + buf.tms_stime;
}
return -1;
return ticks();
// struct tms buf;
// if ( times( &buf ) != (clock_t)-1 )
// {
// return buf.tms_utime + buf.tms_stime;
// }
// return -1;
}
#endif

@ -8,22 +8,16 @@
#ifndef REGTEST
#include <sys/time.h>
#include <syscalls.h>
/* See comments in time.h on the semantics of time_t. */
time_t time( time_t * timer )
{
struct timeval tv;
if ( gettimeofday( &tv, NULL ) == 0 )
{
if ( timer != NULL )
{
*timer = tv.tv_sec;
}
return tv.tv_sec;
}
return -1;
if ( timer != NULL )
*timer = ticks();
return ticks();
}
#endif

@ -8,21 +8,18 @@
#ifndef REGTEST
#include <sys/time.h>
#include <syscalls.h>
int timespec_get( struct timespec * ts, int base )
{
if ( base == TIME_UTC )
{
/* We can make do with a really thin wrapper here. */
struct timeval tv;
if ( gettimeofday( &tv, NULL ) == 0 )
{
ts->tv_sec = tv.tv_sec;
ts->tv_nsec = tv.tv_usec * 1000;
return base;
}
unsigned int t = ticks();
ts->tv_sec = t / 1000;
ts->tv_nsec = t * 1000000;
return base;
}
/* Not supporting any other time base than TIME_UTC for now. */
return 0;
}

@ -0,0 +1,53 @@
#ifndef SYSCALLS_H_
#define SYSCALLS_H_
#include <stdint.h>
//
// Task-related calls
void _exit(int code);
int fork(void);
int getpid(void);
void *sbrk(unsigned int bytes);
//
// Clock-related calls
void delay(unsigned int ms);
unsigned int ticks(void);
//
// File-related calls
// Indicates mounted volume
#define VFS_MOUNTED (1 << 0)
// Set if filesystem is read-only
#define VFS_READONLY (1 << 1)
// Indicates an opened file
#define VFS_FILE_OPEN (1 << 0)
// Indicates read permission on file
#define VFS_FILE_READ (1 << 1)
// Indicates write permission on file
#define VFS_FILE_WRITE (1 << 2)
// Set if EOF has been reached
#define VFS_EOF (1 << 3)
#define EOF (-1)
struct dirent {
char name[32];
};
struct vfs_volume_funcs_t;
typedef struct vfs_volume_funcs_t vfs_volume_funcs;
int mount(vfs_volume_funcs *funcs, uint32_t flags);
int open(const char *path, uint32_t flags);
int close(int fd);
int read(int fd, uint32_t count, uint8_t *buffer);
int write(int fd, uint32_t count, const uint8_t *buffer);
#endif // SYSCALLS_H_

@ -4,8 +4,6 @@
#include <kernel/heap.h>
#include <kernel/vfs.h>
#include "syscalls.h"
void user_delay(uint32_t ms)
{
register uint32_t r1 asm("r1") = ms;
@ -26,17 +24,17 @@ void user_main(void)
int count = vfs_read(test, 20, (uint8_t *)buf);
(void)count;
if (fork() == 0) {
while (1) {
gpio(GPIO_OUT, 5, 1);
user_delay(2000);
}
} else {
while (1) {
user_delay(1000);
gpio(GPIO_OUT, 5, 0);
user_delay(1000);
}
}
// if (fork() == 0) {
// while (1) {
// gpio(GPIO_OUT, 5, 1);
// user_delay(2000);
// }
// } else {
// while (1) {
// user_delay(1000);
// gpio(GPIO_OUT, 5, 0);
// user_delay(1000);
// }
// }
}

Loading…
Cancel
Save