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 @$(MAKE) -C src/user
@echo " INITRD" @echo " INITRD"
@tools/rba initrd.img $$(find 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) @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: 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]); task_sleep(args[1]);
else if (args[0] == 1) else if (args[0] == 1)
udelay(args[1]); udelay(args[1]);
else if (args[0] == 2)
*((unsigned int *)args[1]) = ticks;
} }
void clock_init(void) void clock_init(void)

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

@ -26,6 +26,9 @@ void vfs_svc(uint32_t *args)
case 3: case 3:
*((int *)args[4]) = vfs_read(args[1], args[2], (uint8_t *)args[3]); *((int *)args[4]) = vfs_read(args[1], args[2], (uint8_t *)args[3]);
break; break;
case 4:
*((int *)args[4]) = vfs_write(args[1], args[2], (const uint8_t *)args[3]);
break;
default: default:
break; break;
} }
@ -141,8 +144,30 @@ uint32_t vfs_read(int fd, uint32_t count, uint8_t *buffer)
VFS_EOF)) VFS_EOF))
return 0; return 0;
uint32_t ret = vfs_volumes[vfs_files[fd].vol].funcs->read(vfs_files[fd].fsinfo, uint32_t ret = vfs_volumes[vfs_files[fd].vol].funcs->read(
count, buffer); 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) if (ret < count)
vfs_files[fd].flags |= VFS_EOF; 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_open(const char *path, uint32_t flags);
int vfs_close(int fd); int vfs_close(int fd);
uint32_t vfs_read(int fd, uint32_t count, uint8_t *buffer); 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_ #endif // VFS_H_

@ -24,8 +24,10 @@ REGDEPFILES := $(patsubst %,$(BUILDDIR)/%.d,$(REGFILES))
# All files belonging to the source distribution # All files belonging to the source distribution
ALLFILES := $(SRCFILES) $(HDRFILES) $(AUXFILES) 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 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 .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) $(BUILDDIR)/pdclib.a: $(OBJFILES)
@echo " AR $@" @echo " AR $@"
@ar rc $(BUILDDIR)/pdclib.a $? @arm-none-eabi-ar rc $(BUILDDIR)/pdclib.a $?
@echo @echo
tests: testdrivers tests: testdrivers

@ -1,12 +1,9 @@
#ifndef SYSCALLS_H_ #include "syscalls.h"
#define SYSCALLS_H_
#include <stdint.h>
// //
// Task-related calls // Task-related calls
inline void _exit(int code) void _exit(int code)
{ {
register uint32_t r1 __asm("r1") = code; register uint32_t r1 __asm("r1") = code;
__asm("\ __asm("\
@ -16,7 +13,7 @@ inline void _exit(int code)
" :: "r" (r1)); " :: "r" (r1));
} }
inline int fork(void) int fork(void)
{ {
int ret = 0; int ret = 0;
register uint32_t r1 __asm("r1") = (uint32_t)&ret; register uint32_t r1 __asm("r1") = (uint32_t)&ret;
@ -28,7 +25,7 @@ inline int fork(void)
return ret; return ret;
} }
inline int getpid(void) int getpid(void)
{ {
int ret = 0; int ret = 0;
register uint32_t r1 __asm("r1") = (uint32_t)&ret; register uint32_t r1 __asm("r1") = (uint32_t)&ret;
@ -40,7 +37,7 @@ inline int getpid(void)
return ret; return ret;
} }
inline void *sbrk(unsigned int bytes) void *sbrk(unsigned int bytes)
{ {
void *ret = 0; void *ret = 0;
register uint32_t r1 __asm("r1") = bytes; register uint32_t r1 __asm("r1") = bytes;
@ -55,32 +52,34 @@ inline void *sbrk(unsigned int bytes)
} }
// //
// File-related calls // Clock-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 void delay(unsigned int ms)
#define VFS_FILE_OPEN (1 << 0) {
// Indicates read permission on file register uint32_t r1 __asm("r1") = ms;
#define VFS_FILE_READ (1 << 1) __asm("\
// Indicates write permission on file mov r0, 0; \
#define VFS_FILE_WRITE (1 << 2) mov r1, %0; \
// Set if EOF has been reached svc 2; \
#define VFS_EOF (1 << 3) " :: "r" (r1));
}
#define EOF (-1)
struct dirent { unsigned int ticks(void)
char name[32]; {
}; 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; int ret = 0;
register uint32_t r1 __asm("r1") = (uint32_t)funcs; 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; return ret;
} }
inline int open(const char *path, uint32_t flags) int open(const char *path, uint32_t flags)
{ {
int ret = 0; int ret = 0;
register uint32_t r1 __asm("r1") = (uint32_t)path; register uint32_t r1 __asm("r1") = (uint32_t)path;
@ -112,7 +111,7 @@ inline int open(const char *path, uint32_t flags)
return ret; return ret;
} }
inline int close(int fd) int close(int fd)
{ {
int ret = 0; int ret = 0;
register uint32_t r1 __asm("r1") = fd; register uint32_t r1 __asm("r1") = fd;
@ -123,9 +122,10 @@ inline int close(int fd)
mov r2, %1; \ mov r2, %1; \
svc 3; \ svc 3; \
" :: "r" (r1), "r" (r2)); " :: "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; int ret = 0;
register uint32_t r1 __asm("r1") = fd; register uint32_t r1 __asm("r1") = fd;
@ -143,4 +143,21 @@ inline int read(int fd, uint32_t count, uint8_t *buffer)
return ret; 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. /* This is an example implementation of remove() fit for use with POSIX kernels.
*/ */
#include <stdio.h> #include <syscalls.h>
#ifndef REGTEST #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 struct _PDCLIB_file_t * _PDCLIB_filelist;
extern int unlink( const char * pathname ); //extern int unlink( const char * pathname );
int remove( const char * pathname ) int remove( const char * pathname )
{ {
int rc; // int rc;
struct _PDCLIB_file_t * current = _PDCLIB_filelist; // struct _PDCLIB_file_t * current = _PDCLIB_filelist;
while ( current != NULL ) // while ( current != NULL )
{ // {
if ( ( current->filename != NULL ) && ( strcmp( current->filename, pathname ) == 0 ) ) // if ( ( current->filename != NULL ) && ( strcmp( current->filename, pathname ) == 0 ) )
{ // {
return EOF; // return EOF;
} // }
current = current->next; // current = current->next;
} // }
if ( ( rc = unlink( pathname ) ) == -1 ) // if ( ( rc = unlink( pathname ) ) == -1 )
{ // {
switch ( errno ) // switch ( errno )
{ // {
/* See the comments on implementation-defined errno values in // /* See the comments on implementation-defined errno values in
<_PDCLIB_config.h>. // <_PDCLIB_config.h>.
*/ // */
case EACCES: // case EACCES:
case EFAULT: // case EFAULT:
case EIO: // case EIO:
case EISDIR: // case EISDIR:
case ELOOP: // case ELOOP:
case ENAMETOOLONG: // case ENAMETOOLONG:
case ENOENT: // case ENOENT:
case ENOMEM: // case ENOMEM:
case ENOTDIR: // case ENOTDIR:
case EPERM: // case EPERM:
case EROFS: // case EROFS:
_PDCLIB_errno = _PDCLIB_ERROR; // _PDCLIB_errno = _PDCLIB_ERROR;
break; // break;
default: // default:
/* This should be something like EUNKNOWN. */ /* This should be something like EUNKNOWN. */
_PDCLIB_errno = _PDCLIB_ERROR; _PDCLIB_errno = _PDCLIB_ERROR;
break; // break;
} // }
} // }
return rc; // return rc;
return EOF;
} }
#endif #endif

@ -4,20 +4,20 @@
Permission is granted to use, modify, and / or redistribute at will. Permission is granted to use, modify, and / or redistribute at will.
*/ */
#include <stdio.h> //#include <stdio.h>
#ifndef REGTEST #ifndef REGTEST
#include "pdclib/_PDCLIB_glue.h" #include "pdclib/_PDCLIB_glue.h"
#include <inttypes.h> //#include <inttypes.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> //#include <string.h>
//
#include <sys/types.h> //#include <sys/types.h>
#include <sys/stat.h> //#include <sys/stat.h>
#include <fcntl.h> //#include <fcntl.h>
#include <unistd.h> //#include <unistd.h>
extern struct _PDCLIB_file_t * _PDCLIB_filelist; extern struct _PDCLIB_file_t * _PDCLIB_filelist;
@ -26,61 +26,61 @@ extern struct _PDCLIB_file_t * _PDCLIB_filelist;
*/ */
struct _PDCLIB_file_t * tmpfile( void ) struct _PDCLIB_file_t * tmpfile( void )
{ {
FILE * rc; // FILE * rc;
/* This is the chosen way to get high-quality randomness. Replace as // /* This is the chosen way to get high-quality randomness. Replace as
appropriate. // appropriate.
*/ // */
FILE * randomsource = fopen( "/proc/sys/kernel/random/uuid", "rb" ); // FILE * randomsource = fopen( "/proc/sys/kernel/random/uuid", "rb" );
char filename[ L_tmpnam ]; // char filename[ L_tmpnam ];
_PDCLIB_fd_t fd; // _PDCLIB_fd_t fd;
if ( randomsource == NULL ) // 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 );
return NULL; return NULL;
} // }
rc->status = _PDCLIB_filemode( "wb+" ) | _IOLBF | _PDCLIB_DELONCLOSE; // for ( ;; )
rc->handle = fd; // {
rc->ungetbuf = (unsigned char *)rc + sizeof( struct _PDCLIB_file_t ); // /* Get a filename candidate. What constitutes a valid filename and
rc->filename = (char *)rc->ungetbuf + _PDCLIB_UNGETCBUFSIZE; // where temporary files are usually located is platform-dependent,
rc->buffer = rc->filename + L_tmpnam; // which is one reason why this function is located in the platform
strcpy( rc->filename, filename ); // overlay. The other reason is that a *good* implementation should
rc->bufsize = BUFSIZ; // use high-quality randomness instead of a pseudo-random sequence to
rc->bufidx = 0; // generate the filename candidate, which is *also* platform-dependent.
rc->ungetidx = 0; // */
rc->next = _PDCLIB_filelist; // unsigned int random;
_PDCLIB_filelist = rc; // fscanf( randomsource, "%u", &random );
return rc; // 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 #endif

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

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

@ -8,21 +8,18 @@
#ifndef REGTEST #ifndef REGTEST
#include <sys/time.h> #include <syscalls.h>
int timespec_get( struct timespec * ts, int base ) int timespec_get( struct timespec * ts, int base )
{ {
if ( base == TIME_UTC ) if ( base == TIME_UTC )
{ {
/* We can make do with a really thin wrapper here. */ unsigned int t = ticks();
struct timeval tv; ts->tv_sec = t / 1000;
if ( gettimeofday( &tv, NULL ) == 0 ) ts->tv_nsec = t * 1000000;
{
ts->tv_sec = tv.tv_sec;
ts->tv_nsec = tv.tv_usec * 1000;
return base; return base;
} }
}
/* Not supporting any other time base than TIME_UTC for now. */ /* Not supporting any other time base than TIME_UTC for now. */
return 0; 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/heap.h>
#include <kernel/vfs.h> #include <kernel/vfs.h>
#include "syscalls.h"
void user_delay(uint32_t ms) void user_delay(uint32_t ms)
{ {
register uint32_t r1 asm("r1") = 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); int count = vfs_read(test, 20, (uint8_t *)buf);
(void)count; (void)count;
if (fork() == 0) { // if (fork() == 0) {
while (1) { // while (1) {
gpio(GPIO_OUT, 5, 1); // gpio(GPIO_OUT, 5, 1);
user_delay(2000); // user_delay(2000);
} // }
} else { // } else {
while (1) { // while (1) {
user_delay(1000); // user_delay(1000);
gpio(GPIO_OUT, 5, 0); // gpio(GPIO_OUT, 5, 0);
user_delay(1000); // user_delay(1000);
} // }
} // }
} }

Loading…
Cancel
Save