diff --git a/.gitignore b/.gitignore index d4824dba833fb2ade2ee9ed04723c33fb7eacda1..4632339bc3d2f11741370a23d7b05d76f52b776a 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ main.hex main.map *.o *.a +*.d # Exclude Mac OS X temporary ._* diff --git a/Makefile b/Makefile index 6c8092c395ce60ea16c806f71d2a1011ae067d4a..32c0a7af5cea447d8e95b2b210bb17522adbdf69 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,7 @@ SUBDIRS := miosix ## List here your source files (both .s, .c and .cpp) ## SRC := \ -main.cpp +miosix/_tools/testsuite/testsuite.cpp ## ## List here additional static libraries with relative path @@ -40,6 +40,7 @@ CFLAGS := $(CFLAGS_BASE) -I. -Imiosix -Imiosix/arch/common \ -Imiosix/$(ARCH_INC) -Imiosix/$(BOARD_INC) $(INCLUDE_DIRS) AFLAGS := $(AFLAGS_BASE) LFLAGS := $(LFLAGS_BASE) +DFLAGS := -MMD -MP LINK_LIBS := $(LIBS) -L./miosix -Wl,--start-group -lmiosix -lstdc++ -lc -lm \ -lgcc -Wl,--end-group @@ -62,7 +63,7 @@ clean-recursive: done clean-topdir: - -rm $(OBJ) main.elf main.hex main.bin main.map + -rm $(OBJ) main.elf main.hex main.bin main.map $(OBJ:.o=.d) main: main.elf $(CP) -O ihex main.elf main.hex @@ -77,7 +78,10 @@ main.elf: $(OBJ) miosix/libmiosix.a $(AS) $(AFLAGS) $< -o $@ %.o : %.c - $(CC) $(CFLAGS) $< -o $@ + $(CC) $(DFLAGS) $(CFLAGS) $< -o $@ %.o : %.cpp - $(CXX) $(CXXFLAGS) $< -o $@ + $(CXX) $(DFLAGS) $(CXXFLAGS) $< -o $@ + +#pull in dependecy info for existing .o files +-include $(OBJ:.o=.d) diff --git a/app_template/Makefile b/app_template/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..4fddaa319429061ddebc665eef22f841d1318480 --- /dev/null +++ b/app_template/Makefile @@ -0,0 +1,48 @@ +## +## Makefile for writing PROGRAMS for the Miosix embedded OS +## TFT:Terraneo Federico Technlogies +## + +SRC := \ +main.c + +## Replaces both "foo.cpp"-->"foo.o" and "foo.c"-->"foo.o" +OBJ := $(addsuffix .o, $(basename $(SRC))) + +AS := arm-miosix-eabi-as +CC := arm-miosix-eabi-gcc +CXX := arm-miosix-eabi-g++ +SZ := arm-miosix-eabi-size + +AFLAGS := -mcpu=cortex-m3 -mthumb +CFLAGS := -mcpu=cortex-m3 -mthumb -mfix-cortex-m3-ldrd -fpie -msingle-pic-base \ + -ffunction-sections -O2 -Wall -c +CXXFLAGS := $(CFLAGS) +LFLAGS := -mcpu=cortex-m3 -mthumb -mfix-cortex-m3-ldrd -fpie -msingle-pic-base \ + -Wl,--gc-sections,-Map,main.map,-T./miosix.ld,-n,-pie,--spare-dynamic-tags,3 \ + -O2 -nostdlib +DFLAGS := -MMD -MP + +LINK_LIBS := -Wl,--start-group -lstdc++ -lc -lm -lgcc -Wl,--end-group + +all: $(OBJ) crt0.o + $(CXX) $(LFLAGS) -o main.elf $(OBJ) crt0.o $(LINK_LIBS) + $(SZ) main.elf + @arm-miosix-eabi-objdump -Dslx main.elf > main.txt + @mx-postlinker main.elf --ramsize=16384 --stacksize=2048 --strip-sectheader + @xxd -i main.elf | sed 's/unsigned char/const unsigned char __attribute__((aligned(8)))/' > prog3.h + +clean: + -rm $(OBJ) crt0.o main.elf main.map main.txt $(OBJ:.o=.d) + +%.o: %.s + $(AS) $(AFLAGS) $< -o $@ + +%.o : %.c + $(CC) $(DFLAGS) $(CFLAGS) $< -o $@ + +%.o : %.cpp + $(CXX) $(DFLAGS) $(CXXFLAGS) $< -o $@ + +#pull in dependecy info for existing .o files +-include $(OBJ:.o=.d) diff --git a/app_template/crt0.s b/app_template/crt0.s new file mode 100644 index 0000000000000000000000000000000000000000..d02fababb9ede48c3deac13b165ed7dfc7eda7a6 --- /dev/null +++ b/app_template/crt0.s @@ -0,0 +1,130 @@ +/* + * Startup script for writing PROGRAMS for the Miosix embedded OS + * TFT:Terraneo Federico Technlogies + */ + +.syntax unified +.cpu cortex-m3 +.thumb + +.section .text + +/** + * _start, program entry point + */ +.global _start +.type _start, %function +_start: + /* TODO: .ctor */ + bl main + /* TODO: .dtor */ + bl _exit + +/** + * _exit, terminate process + * \param v exit value + */ +.section .text._exit +.global _exit +.type _exit, %function +_exit: + movs r3, #2 + svc 0 + +/** + * open, open a file + * \param fd file descriptor + * \param file access mode + * \param xxx access permisions + * \return file descriptor or -1 if errors + */ +.section .text.open +.global open +.type open, %function +open: + movs r3, #6 + svc 0 + bx lr + +/** + * close, close a file + * \param fd file descriptor + */ +.section .text.close +.global close +.type close, %function +close: + movs r3, #7 + svc 0 + bx lr + +/** + * seek + * \param fd file descriptor + * \param pos moving offset + * \param start position, SEEK_SET, SEEK_CUR or SEEK_END +*/ +.section .text.seek +.global seek +.type seek, %function +seek: + movs r3, #8 + svc 0 + bx lr + + +/** + * system, fork and execture a program, blocking + * \param program to execute + */ +.section .text.system +.global system +.type system, %function +system: + movs r3, #9 + svc 0 + bx lr +/** + * write, write to file + * \param fd file descriptor + * \param buf data to be written + * \param len buffer length + * \return number of written bytes or -1 if errors + */ +.section .text.write +.global write +.type write, %function +write: + movs r3, #3 + svc 0 + bx lr + +/** + * read, read from file + * \param fd file descriptor + * \param buf data to be read + * \param len buffer length + * \return number of read bytes or -1 if errors + */ +.section .text.read +.global read +.type read, %function +read: + movs r3, #4 + svc 0 + bx lr + +/** + * usleep, sleep a specified number of microseconds + * \param us number of microseconds to sleep + * \return 0 on success or -1 if errors + */ +.section .text.usleep +.global usleep +.type usleep, %function +usleep: + movs r3, #5 + svc 0 + bx lr + +.end diff --git a/app_template/main.c b/app_template/main.c new file mode 100644 index 0000000000000000000000000000000000000000..0b36ae8a7f354101c0e5a9559ea0136e8a8496eb --- /dev/null +++ b/app_template/main.c @@ -0,0 +1,97 @@ +#include <unistd.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <string.h> +#include <stdio.h> +#include <stdlib.h> + +int mystrlen(const char *s) +{ + int result=0; + while(*s++) result++; + return result; +} + +int main() +{ + int i = 0; + static const char str[]="Test application:\n0=divzero\n1=sleep 5s\n2=exit\n3=bkpt\n4=dangling\n5=open\n6=system\n"; + static const char str2[]="Unexpected command\n"; + static const char okMsg[] = "Everything's shiny, Cap'n\n"; + + for(;;) + { + char result[100]; + write(1,str,mystrlen(str)); + int len=read(0,result,sizeof(result)); + if(len<1) continue; + int i=10/(int)(result[0]-'0'); + unsigned int *p=(unsigned int *)0xc0000000; + + int fp = 0; + + switch(result[0]) + { + case '0': + usleep(i); + break; + case '1': + usleep(5000000); + break; + case '2': + return 0; + case '3': + asm volatile("bkpt"); + break; + case '4': + usleep(*p); + break; + case '5': + fp = open("/test.txt", O_RDWR|O_TRUNC, 0); + + if(fp != -1){ + write(1, "File opened\n", 12); + int check = 0; + + if(write(fp, "ciao", 4) == 4){ + write(1, "Write ok\n", 9); + check |= 0x01; + } + + //close(fp); + //fp = open("/test.txt", O_RDWR, 0); + seek(fp, SEEK_SET, 0); + + if(write(fp, "123", 3) == 3){ + write(1, "Write ok\n", 9); + check |= 0x01; + } + + seek(fp, SEEK_SET, 0); + + if(read(fp, result, 100) == 4){ + write(1, "Read ok\n", 8); + check |= 0x02; + } + + if(close(fp) == 0){ + write(1, "Close ok\n", 9); + check |= 0x04; + } + + if(check == 0x07) + write(1, okMsg, mystrlen(okMsg)); + } + + + break; + case '6': + system("test"); + break; + default: + write(1,str2,mystrlen(str2)); + } + } +} diff --git a/app_template/miosix.ld b/app_template/miosix.ld new file mode 100644 index 0000000000000000000000000000000000000000..c91c803e629040b14233a8f8251a7d9952f68910 --- /dev/null +++ b/app_template/miosix.ld @@ -0,0 +1,66 @@ +/* + * Linker script for writing PROGRAMS for the Miosix embedded OS + * TFT:Terraneo Federico Technlogies + */ + +OUTPUT_FORMAT("elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) + +SECTIONS +{ + /* Here starts the first elf segment, that stays in flash */ + . = 0 + SIZEOF_HEADERS; + + .text : ALIGN(8) + { + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + } + + .rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) } + .rel.got : { *(.rel.got) } + + /* Here starts the second segment, that is copied in RAM and relocated */ + . = 0x10000000; + + .got : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) } + + /* FIXME: If this is put in the other segment, it makes it writable */ + .dynamic : { *(.dynamic) } + + /* FIXME: The compiler insists in addressing rodata relative to r9 */ + .rodata : ALIGN(8) + { + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + } + + .data : ALIGN(8) + { + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + } + + .bss : ALIGN(8) + { + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + } + + /* These are removed since are unused and increase binary size */ + /DISCARD/ : + { + *(.interp) + *(.dynsym) + *(.dynstr) + *(.hash) + *(.comment) + *(.ARM.attributes) + } +} diff --git a/app_template/prog3.h b/app_template/prog3.h new file mode 100644 index 0000000000000000000000000000000000000000..8cbd169379242039a9aa79da18fa850558e839a7 --- /dev/null +++ b/app_template/prog3.h @@ -0,0 +1,81 @@ +const unsigned char __attribute__((aligned(8))) main_elf[] = { + 0x7f, 0x45, 0x4c, 0x46, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x28, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x99, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x05, 0x34, 0x00, 0x20, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, + 0x98, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0xf2, 0x01, 0x00, 0x00, + 0xf2, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x10, 0x10, 0x01, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x9c, 0x02, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10, 0x0c, 0x00, 0x00, 0x10, + 0x28, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x02, 0xf8, + 0x00, 0xf0, 0xde, 0xf8, 0x2d, 0xe9, 0xf0, 0x4d, 0xdf, 0xf8, 0x90, 0x81, + 0x64, 0x4f, 0xdf, 0xf8, 0x94, 0xa1, 0xdf, 0xf8, 0x94, 0xb1, 0x9c, 0xb0, + 0x64, 0x4d, 0x03, 0xae, 0xc8, 0x44, 0x4f, 0x44, 0xca, 0x44, 0xcb, 0x44, + 0x09, 0xeb, 0x05, 0x03, 0x00, 0x22, 0x13, 0xf8, 0x01, 0x4f, 0x01, 0x32, + 0x00, 0x2c, 0xfa, 0xd1, 0x09, 0xeb, 0x05, 0x01, 0x01, 0x20, 0x00, 0xf0, + 0xcf, 0xf8, 0x64, 0x22, 0x20, 0x46, 0x31, 0x46, 0x00, 0xf0, 0xcd, 0xf8, + 0x00, 0x28, 0xeb, 0xdd, 0x9d, 0xf8, 0x0c, 0x30, 0x30, 0x3b, 0x06, 0x2b, + 0x75, 0xd8, 0xdf, 0xe8, 0x03, 0xf0, 0x6d, 0x66, 0x62, 0x60, 0x5a, 0x08, + 0x04, 0x00, 0x40, 0x46, 0x00, 0xf0, 0xb7, 0xf8, 0xdc, 0xe7, 0x00, 0x22, + 0x38, 0x46, 0x40, 0xf2, 0x02, 0x41, 0x00, 0xf0, 0xa7, 0xf8, 0xb0, 0xf1, + 0xff, 0x3f, 0x04, 0x46, 0xd2, 0xd0, 0x0c, 0x22, 0x01, 0x20, 0x51, 0x46, + 0x00, 0xf0, 0xaa, 0xf8, 0x04, 0x22, 0x20, 0x46, 0x59, 0x46, 0x00, 0xf0, + 0xa5, 0xf8, 0x04, 0x28, 0x65, 0xd0, 0x00, 0x21, 0x01, 0x91, 0x00, 0x21, + 0x0a, 0x46, 0x20, 0x46, 0x00, 0xf0, 0x96, 0xf8, 0x42, 0x49, 0x03, 0x22, + 0x20, 0x46, 0x49, 0x44, 0x00, 0xf0, 0x96, 0xf8, 0x03, 0x28, 0x6a, 0xd0, + 0x00, 0x22, 0x11, 0x46, 0x20, 0x46, 0x00, 0xf0, 0x89, 0xf8, 0x64, 0x22, + 0x20, 0x46, 0x31, 0x46, 0x00, 0xf0, 0x8d, 0xf8, 0x04, 0x28, 0x53, 0xd0, + 0x20, 0x46, 0x00, 0xf0, 0x7c, 0xf8, 0x04, 0x46, 0x00, 0x28, 0xa5, 0xd1, + 0x36, 0x49, 0x01, 0x20, 0x49, 0x44, 0x09, 0x22, 0x00, 0xf0, 0x7c, 0xf8, + 0x01, 0x99, 0x41, 0xf0, 0x04, 0x03, 0x07, 0x2b, 0x9a, 0xd1, 0x09, 0xeb, + 0x05, 0x03, 0x54, 0x33, 0x22, 0x46, 0x13, 0xf8, 0x01, 0x1f, 0x01, 0x32, + 0x00, 0x29, 0xfa, 0xd1, 0x09, 0xeb, 0x05, 0x01, 0x54, 0x31, 0x01, 0x20, + 0x00, 0xf0, 0x68, 0xf8, 0x8a, 0xe7, 0x4f, 0xf0, 0x40, 0x43, 0x18, 0x68, + 0x00, 0xf0, 0x68, 0xf8, 0x84, 0xe7, 0x00, 0xbe, 0x82, 0xe7, 0x00, 0x20, + 0x1c, 0xb0, 0xbd, 0xe8, 0xf0, 0x8d, 0x44, 0xf6, 0x40, 0x30, 0xc0, 0xf2, + 0x4c, 0x00, 0x00, 0xf0, 0x5b, 0xf8, 0x77, 0xe7, 0x00, 0x23, 0x0a, 0x20, + 0x90, 0xfb, 0xf3, 0xf0, 0x00, 0xf0, 0x54, 0xf8, 0x70, 0xe7, 0x09, 0xeb, + 0x05, 0x03, 0x70, 0x33, 0x00, 0x22, 0x13, 0xf8, 0x01, 0x1f, 0x01, 0x32, + 0x00, 0x29, 0xfa, 0xd1, 0x09, 0xeb, 0x05, 0x01, 0x70, 0x31, 0x01, 0x20, + 0x00, 0xf0, 0x3e, 0xf8, 0x60, 0xe7, 0x15, 0x49, 0x01, 0x20, 0x49, 0x44, + 0x09, 0x22, 0x00, 0xf0, 0x37, 0xf8, 0x01, 0x23, 0x01, 0x93, 0x92, 0xe7, + 0x11, 0x49, 0x01, 0x20, 0x49, 0x44, 0x08, 0x22, 0x00, 0xf0, 0x2e, 0xf8, + 0x01, 0x9b, 0x43, 0xf0, 0x02, 0x03, 0x01, 0x93, 0xa0, 0xe7, 0x0b, 0x49, + 0x09, 0x22, 0x01, 0x20, 0x49, 0x44, 0x00, 0xf0, 0x23, 0xf8, 0x01, 0x22, + 0x01, 0x92, 0x8b, 0xe7, 0x08, 0x01, 0x00, 0x00, 0xbc, 0x00, 0x00, 0x00, + 0xc8, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, + 0xec, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, + 0xf0, 0x00, 0x00, 0x00, 0x02, 0x23, 0x00, 0xdf, 0x06, 0x23, 0x00, 0xdf, + 0x70, 0x47, 0x07, 0x23, 0x00, 0xdf, 0x70, 0x47, 0x08, 0x23, 0x00, 0xdf, + 0x70, 0x47, 0x09, 0x23, 0x00, 0xdf, 0x70, 0x47, 0x03, 0x23, 0x00, 0xdf, + 0x70, 0x47, 0x04, 0x23, 0x00, 0xdf, 0x70, 0x47, 0x05, 0x23, 0x00, 0xdf, + 0x70, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00, 0x4d, 0x69, 0x6f, 0x73, + 0x69, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x54, 0x65, 0x73, 0x74, 0x20, 0x61, 0x70, 0x70, + 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x0a, 0x30, 0x3d, + 0x64, 0x69, 0x76, 0x7a, 0x65, 0x72, 0x6f, 0x0a, 0x31, 0x3d, 0x73, 0x6c, + 0x65, 0x65, 0x70, 0x20, 0x35, 0x73, 0x0a, 0x32, 0x3d, 0x65, 0x78, 0x69, + 0x74, 0x0a, 0x33, 0x3d, 0x62, 0x6b, 0x70, 0x74, 0x0a, 0x34, 0x3d, 0x64, + 0x61, 0x6e, 0x67, 0x6c, 0x69, 0x6e, 0x67, 0x0a, 0x35, 0x3d, 0x6f, 0x70, + 0x65, 0x6e, 0x0a, 0x36, 0x3d, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x0a, + 0x00, 0x00, 0x00, 0x00, 0x45, 0x76, 0x65, 0x72, 0x79, 0x74, 0x68, 0x69, + 0x6e, 0x67, 0x27, 0x73, 0x20, 0x73, 0x68, 0x69, 0x6e, 0x79, 0x2c, 0x20, + 0x43, 0x61, 0x70, 0x27, 0x6e, 0x0a, 0x00, 0x00, 0x55, 0x6e, 0x65, 0x78, + 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x61, + 0x6e, 0x64, 0x0a, 0x00, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x74, 0x78, + 0x74, 0x00, 0x00, 0x00, 0x46, 0x69, 0x6c, 0x65, 0x20, 0x6f, 0x70, 0x65, + 0x6e, 0x65, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x63, 0x69, 0x61, 0x6f, + 0x00, 0x00, 0x00, 0x00, 0x57, 0x72, 0x69, 0x74, 0x65, 0x20, 0x6f, 0x6b, + 0x0a, 0x00, 0x00, 0x00, 0x31, 0x32, 0x33, 0x00, 0x52, 0x65, 0x61, 0x64, + 0x20, 0x6f, 0x6b, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x43, 0x6c, 0x6f, 0x73, + 0x65, 0x20, 0x6f, 0x6b, 0x0a, 0x00, 0x00, 0x00, 0x74, 0x65, 0x73, 0x74, + 0x00, 0x00, 0x00, 0x00 +}; +unsigned int main_elf_len = 928; diff --git a/app_template_withlibs/Makefile b/app_template_withlibs/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..05bd567d879dc0630cedcc63360e2a35a0840ead --- /dev/null +++ b/app_template_withlibs/Makefile @@ -0,0 +1,52 @@ +## +## Makefile for writing PROGRAMS for the Miosix embedded OS +## TFT:Terraneo Federico Technlogies +## + +SRC := \ +main.c \ +syscallfuffa.c + +## Replaces both "foo.cpp"-->"foo.o" and "foo.c"-->"foo.o" +OBJ := $(addsuffix .o, $(basename $(SRC))) + +AS := arm-miosix-eabi-as +CC := arm-miosix-eabi-gcc +CXX := arm-miosix-eabi-g++ +SZ := arm-miosix-eabi-size + +AFLAGS := -mcpu=cortex-m3 -mthumb +CFLAGS := -mcpu=cortex-m3 -mthumb -fpie -msingle-pic-base \ + -ffunction-sections -O2 -Wall -c +CXXFLAGS := $(CFLAGS) +LFLAGS := -mcpu=cortex-m3 -mthumb -fpie -msingle-pic-base \ + -Wl,--gc-sections,-Map,main.map,-T./miosix.ld,-n,-pie,--spare-dynamic-tags,3 \ + -O2 -nostdlib +DFLAGS := -MMD -MP + +# LFLAGS := -mcpu=cortex-m3 -mthumb -fpie -msingle-pic-base \ +# -Wl,--gc-sections,-Map,main.map,-T./miosix.ld,-n,-pie,--spare-dynamic-tags,3 \ +# -O2 -nostdlib + +LINK_LIBS := -Wl,--start-group -lstdc++ -lc -lm -lgcc -Wl,--end-group + +all: $(OBJ) crt0.o + $(CXX) $(LFLAGS) -o main.elf $(OBJ) crt0.o $(LINK_LIBS) + $(SZ) main.elf + @mx-postlinker main.elf --ramsize=16384 --stacksize=2048 --strip-sectheader + @xxd -i main.elf | sed 's/unsigned char/const unsigned char __attribute__((aligned(8)))/' > prog3.h + +clean: + -rm $(OBJ) crt0.o main.elf main.map $(OBJ:.o=.d) + +%.o: %.s + $(AS) $(AFLAGS) $< -o $@ + +%.o : %.c + $(CC) $(DFLAGS) $(CFLAGS) $< -o $@ + +%.o : %.cpp + $(CXX) $(DFLAGS) $(CXXFLAGS) $< -o $@ + +#pull in dependecy info for existing .o files +-include $(OBJ:.o=.d) diff --git a/app_template_withlibs/crt0.s b/app_template_withlibs/crt0.s new file mode 100644 index 0000000000000000000000000000000000000000..2eba4bfad53dbe7d82a56e331d9c2b630a44dff7 --- /dev/null +++ b/app_template_withlibs/crt0.s @@ -0,0 +1,77 @@ +/* + * Startup script for writing PROGRAMS for the Miosix embedded OS + * TFT:Terraneo Federico Technlogies + */ + +.syntax unified +.cpu cortex-m3 +.thumb + +.section .text + +/** + * _start, program entry point + */ +.global _start +.type _start, %function +_start: + /* TODO: .ctor */ + bl main + /* TODO: .dtor */ + bl _exit + +/** + * _exit, terminate process + * \param v exit value + */ +.section .text._exit +.global _exit +.type _exit, %function +_exit: + movs r3, #2 + svc 0 + +/** + * write, write to file + * \param fd file descriptor + * \param buf data to be written + * \param len buffer length + * \return number of written bytes or -1 if errors + */ +.section .text.write +.global write +.type write, %function +write: + movs r3, #3 + svc 0 + bx lr + +/** + * read, read from file + * \param fd file descriptor + * \param buf data to be read + * \param len buffer length + * \return number of read bytes or -1 if errors + */ +.section .text.read +.global read +.type read, %function +read: + movs r3, #4 + svc 0 + bx lr + +/** + * usleep, sleep a specified number of microseconds + * \param us number of microseconds to sleep + * \return 0 on success or -1 if errors + */ +.section .text.usleep +.global usleep +.type usleep, %function +usleep: + movs r3, #5 + svc 0 + bx lr + +.end diff --git a/app_template_withlibs/main.c b/app_template_withlibs/main.c new file mode 100644 index 0000000000000000000000000000000000000000..57197b70987ae29d745ee83adf8563101cc52ccb --- /dev/null +++ b/app_template_withlibs/main.c @@ -0,0 +1,39 @@ + +#include <unistd.h> +#include <string.h> +#include <stdio.h> + +int main() +{ + printf("hello world %d\n",25); + static const char str[]="0=divzero 1=sleep 5s, 2=exit 3=bkpt 4=dangling\n"; + static const char str2[]="Unexpected command\n"; + for(;;) + { + char result[100]; + write(1,str,strlen(str)); + int len=read(0,result,sizeof(result)); + if(len<1) continue; + int i=10/(int)(result[0]-'0'); + unsigned int *p=(unsigned int *)0xc0000000; + switch(result[0]) + { + case '0': + usleep(i); + break; + case '1': + usleep(5000000); + break; + case '2': + return 0; + case '3': + asm volatile("bkpt"); + break; + case '4': + usleep(*p); + break; + default: + write(1,str2,strlen(str2)); + } + } +} diff --git a/app_template_withlibs/miosix.ld b/app_template_withlibs/miosix.ld new file mode 100644 index 0000000000000000000000000000000000000000..0b86aaf7afcbf0826cd7e60427f20b38b270696e --- /dev/null +++ b/app_template_withlibs/miosix.ld @@ -0,0 +1,77 @@ +/* + * Linker script for writing PROGRAMS for the Miosix embedded OS + * TFT:Terraneo Federico Technlogies + */ + +OUTPUT_FORMAT("elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) + +SECTIONS +{ + /* Here starts the first elf segment, that stays in flash */ + . = 0 + SIZEOF_HEADERS; + + .text : ALIGN(8) + { + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + } + + .rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) } + .rel.got : { *(.rel.got) } + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } + __exidx_end = .; + + _end = .; + PROVIDE(end = .); + + /* Here starts the second segment, that is copied in RAM and relocated */ + . = 0x10000000; + + .got : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) } + + /* FIXME: If this is put in the other segment, it makes it writable */ + .dynamic : { *(.dynamic) } + + /* FIXME: The compiler insists in addressing rodata relative to r9 */ + .rodata : ALIGN(8) + { + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + } + + .data : ALIGN(8) + { + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + } + + .bss : ALIGN(8) + { + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + } + + /* These are removed since are unused and increase binary size */ + /DISCARD/ : + { + *(.interp) + *(.dynsym) + *(.dynstr) + *(.hash) + *(.comment) + *(.ARM.attributes) + *(.debug*) + } +} diff --git a/app_template_withlibs/prog3.h b/app_template_withlibs/prog3.h new file mode 100644 index 0000000000000000000000000000000000000000..8855c4f26cea21ab280c4ea7bc96cfa06f7d8860 --- /dev/null +++ b/app_template_withlibs/prog3.h @@ -0,0 +1,40 @@ +const unsigned char __attribute__((aligned(8))) main_elf[] = { + 0x7f, 0x45, 0x4c, 0x46, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x28, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x99, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x05, 0x34, 0x00, 0x20, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, + 0x98, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00, + 0x9e, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x44, 0x01, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10, 0x0c, 0x00, 0x00, 0x10, + 0x28, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x02, 0xf8, + 0x00, 0xf0, 0x40, 0xf8, 0x70, 0xb5, 0x1d, 0x4e, 0x1d, 0x4c, 0x7e, 0x44, + 0x9a, 0xb0, 0x7c, 0x44, 0x30, 0x36, 0x4f, 0xf0, 0x40, 0x45, 0x2f, 0x22, + 0x21, 0x46, 0x01, 0x20, 0x00, 0xf0, 0x34, 0xf8, 0x64, 0x22, 0x00, 0x20, + 0x01, 0xa9, 0x00, 0xf0, 0x32, 0xf8, 0x00, 0x28, 0xf3, 0xdd, 0x9d, 0xf8, + 0x04, 0x30, 0x30, 0x3b, 0x04, 0x2b, 0x1b, 0xd8, 0xdf, 0xe8, 0x03, 0xf0, + 0x13, 0x0c, 0x09, 0x07, 0x03, 0x00, 0x28, 0x68, 0x00, 0xf0, 0x26, 0xf8, + 0xe5, 0xe7, 0x00, 0xbe, 0xe3, 0xe7, 0x00, 0x20, 0x1a, 0xb0, 0x70, 0xbd, + 0x44, 0xf6, 0x40, 0x30, 0xc0, 0xf2, 0x4c, 0x00, 0x00, 0xf0, 0x1a, 0xf8, + 0xd9, 0xe7, 0x00, 0x23, 0x0a, 0x20, 0x90, 0xfb, 0xf3, 0xf0, 0x00, 0xf0, + 0x13, 0xf8, 0xd2, 0xe7, 0x01, 0x20, 0x31, 0x46, 0x13, 0x22, 0x00, 0xf0, + 0x07, 0xf8, 0xcc, 0xe7, 0x8e, 0xff, 0xff, 0x0f, 0x8a, 0xff, 0xff, 0x0f, + 0x02, 0x23, 0x00, 0xdf, 0x03, 0x23, 0x00, 0xdf, 0x70, 0x47, 0x04, 0x23, + 0x00, 0xdf, 0x70, 0x47, 0x05, 0x23, 0x00, 0xdf, 0x70, 0x47, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00, + 0x4d, 0x69, 0x6f, 0x73, 0x69, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x3d, 0x64, 0x69, + 0x76, 0x7a, 0x65, 0x72, 0x6f, 0x20, 0x31, 0x3d, 0x73, 0x6c, 0x65, 0x65, + 0x70, 0x20, 0x35, 0x73, 0x2c, 0x20, 0x32, 0x3d, 0x65, 0x78, 0x69, 0x74, + 0x20, 0x33, 0x3d, 0x62, 0x6b, 0x70, 0x74, 0x20, 0x34, 0x3d, 0x64, 0x61, + 0x6e, 0x67, 0x6c, 0x69, 0x6e, 0x67, 0x0a, 0x00, 0x55, 0x6e, 0x65, 0x78, + 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x61, + 0x6e, 0x64, 0x0a, 0x00 +}; +unsigned int main_elf_len = 436; diff --git a/app_template_withlibs/syscallfuffa.c b/app_template_withlibs/syscallfuffa.c new file mode 100644 index 0000000000000000000000000000000000000000..3c12251f397822722314403fd61edb4ec3cd98e2 --- /dev/null +++ b/app_template_withlibs/syscallfuffa.c @@ -0,0 +1,62 @@ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <reent.h> +#include <sys/times.h> +#include <sys/stat.h> +#include <sys/fcntl.h> +#include <unistd.h> + +void pthread_mutex_unlock() {} +void pthread_mutex_lock() {} +void pthread_mutex_destroy() {} + +int __register_exitproc(int type, void (*fn)(void), void *arg, void *d) { return 0; } +void __call_exitprocs(int code, void *d) {} + +void *__dso_handle=(void*) &__dso_handle; + +void *_sbrk_r(struct _reent *ptr, ptrdiff_t incr) { return (void*)-1; } +void __malloc_lock() {} +void __malloc_unlock() {} +int _open_r(struct _reent *ptr, const char *name, int flags, int mode) { return -1; } +int _close_r(struct _reent *ptr, int fd) { return -1; } + +int _write(int fd, const void *buf, size_t cnt) +{ + return write(fd,buf,cnt); +} + +int _write_r(struct _reent *ptr, int fd, const void *buf, size_t cnt) +{ + return write(fd,buf,cnt); +} + +int _read(int fd, void *buf, size_t cnt) +{ + return read(fd,buf,cnt); +} + +int _read_r(struct _reent *ptr, int fd, void *buf, size_t cnt) +{ + return read(fd,buf,cnt); +} + +off_t _lseek(int fd, off_t pos, int whence) { return -1; } +off_t _lseek_r(struct _reent *ptr, int fd, off_t pos, int whence) { return -1; } +int _fstat(int fd, struct stat *pstat) { return -1; } +int _fstat_r(struct _reent *ptr, int fd, struct stat *pstat) { return -1; } +int _stat_r(struct _reent *ptr, const char *file, struct stat *pstat) { return -1; } +int isatty(int fd) { return -1; } +int _isatty(int fd) { return -1; } +int mkdir(const char *path, mode_t mode) { return -1; } +int _unlink_r(struct _reent *ptr, const char *file) { return -1; } +clock_t _times_r(struct _reent *ptr, struct tms *tim) { return -1; } +int _link_r(struct _reent *ptr, const char *f_old, const char *f_new) { return -1; } +int _kill(int pid, int sig) { return -1; } +int _kill_r(struct _reent* ptr, int pid, int sig) { return -1; } +int _getpid() { return 1; } +int _getpid_r(struct _reent* ptr) { return 1; } +int _fork_r(struct _reent *ptr) { return -1; } +int _wait_r(struct _reent *ptr, int *status) { return -1; } diff --git a/main_processes.cpp b/main_processes.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c11b63e18d905dcd0f432f16fefc170a170fcbfb --- /dev/null +++ b/main_processes.cpp @@ -0,0 +1,52 @@ + +#include <cstdio> +#include <sys/wait.h> +#include <signal.h> +#include "miosix.h" +#include "kernel/process.h" +#include "kernel/SystemMap.h" + +#include "app_template/prog3.h" + +using namespace std; +using namespace miosix; + +void ledThread(void *) +{ + for(;;) + { + ledOn(); + Thread::sleep(200); + ledOff(); + Thread::sleep(200); + } +} + +int main() +{ + Thread::create(ledThread,STACK_MIN); + + //SystemMap::instance().addElfProgram("test", reinterpret_cast<const unsigned int*>(test_elf), test_elf_len); + + //iprintf("SystemMap::size: %d\n", SystemMap::instance().getElfCount()); + //std::pair<const unsigned int*, unsigned int> res = SystemMap::instance().getElfProgram("test"); + //iprintf("SystemMap test entry size: %X %d\n", res.first, res.second); + + ElfProgram prog(reinterpret_cast<const unsigned int*>(main_elf),main_elf_len); + for(int i=0;;i++) + { + getchar(); + pid_t child=Process::create(prog); + int ec; + pid_t pid; + if(i%2==0) pid=Process::wait(&ec); + else pid=Process::waitpid(child,&ec,0); + iprintf("Process %d terminated\n",pid); + if(WIFEXITED(ec)) + { + iprintf("Exit code is %d\n",WEXITSTATUS(ec)); + } else if(WIFSIGNALED(ec)) { + if(WTERMSIG(ec)==SIGSEGV) iprintf("Process segfaulted\n"); + } + } +} diff --git a/miosix/Makefile b/miosix/Makefile index 344ece19bbab8a130d8c0be8f50400266b26feba..f66f581604f5d97ae6ff9e02068d66fcfcb81809 100644 --- a/miosix/Makefile +++ b/miosix/Makefile @@ -15,6 +15,10 @@ kernel/sync.cpp \ kernel/error.cpp \ kernel/pthread.cpp \ kernel/stage_2_boot.cpp \ +kernel/elf_program.cpp \ +kernel/process.cpp \ +kernel/process_pool.cpp \ +kernel/SystemMap.cpp \ kernel/scheduler/priority/priority_scheduler.cpp \ kernel/scheduler/control/control_scheduler.cpp \ kernel/scheduler/edf/edf_scheduler.cpp \ @@ -52,6 +56,7 @@ CXXFLAGS := $(CXXFLAGS_BASE) -I. -Iarch/common -I$(ARCH_INC) -I$(BOARD_INC) \ CFLAGS := $(CFLAGS_BASE) -I. -Iarch/common -I$(ARCH_INC) -I$(BOARD_INC) \ -DCOMPILING_MIOSIX AFLAGS := $(AFLAGS_BASE) +DFLAGS := -MMD -MP ## Build libmiosix.a and stage_1_boot.o (whose path is in BOOT_FILE) ## The file stage_1_boot.o is compiled separately because @@ -61,13 +66,16 @@ all: $(OBJ) $(BOOT_FILE) $(AR) rcs libmiosix.a $(OBJ) clean: - rm $(OBJ) $(BOOT_FILE) libmiosix.a + -rm $(OBJ) $(BOOT_FILE) libmiosix.a $(OBJ:.o=.d) $(BOOT_FILE:.o=.d) %.o: %.s $(AS) $(AFLAGS) $< -o $@ %.o : %.c - $(CC) $(CFLAGS) $< -o $@ + $(CC) $(DFLAGS) $(CFLAGS) $< -o $@ %.o : %.cpp - $(CXX) $(CXXFLAGS) $< -o $@ + $(CXX) $(DFLAGS) $(CXXFLAGS) $< -o $@ + +#pull in dependecy info for existing .o files +-include $(OBJ:.o=.d) diff --git a/miosix/_examples/sad_trombone/Makefile b/miosix/_examples/sad_trombone/Makefile index 9b484b4da268f9aa561a5e9c3f78b365117e79e3..30df07af82361dbefad47b3a59a9d31f159183bd 100644 --- a/miosix/_examples/sad_trombone/Makefile +++ b/miosix/_examples/sad_trombone/Makefile @@ -40,6 +40,7 @@ CFLAGS := $(CFLAGS_BASE) -I. -Imiosix -Imiosix/arch/common \ -Imiosix/$(ARCH_INC) -Imiosix/$(BOARD_INC) $(INCLUDE_DIRS) AFLAGS := $(AFLAGS_BASE) LFLAGS := $(LFLAGS_BASE) +DFLAGS := -MMD -MP LINK_LIBS := $(LIBS) -L./miosix -Wl,--start-group -lmiosix -lstdc++ -lc -lm \ -lgcc -Wl,--end-group @@ -62,7 +63,7 @@ clean-recursive: done clean-topdir: - -rm $(OBJ) main.elf main.hex main.bin main.map + -rm $(OBJ) main.elf main.hex main.bin main.map $(OBJ:.o=.d) main: main.elf $(CP) -O ihex main.elf main.hex @@ -77,7 +78,10 @@ main.elf: $(OBJ) miosix/libmiosix.a $(AS) $(AFLAGS) $< -o $@ %.o : %.c - $(CC) $(CFLAGS) $< -o $@ + $(CC) $(DFLAGS) $(CFLAGS) $< -o $@ %.o : %.cpp - $(CXX) $(CXXFLAGS) $< -o $@ + $(CXX) $(DFLAGS) $(CXXFLAGS) $< -o $@ + +#pull in dependecy info for existing .o files +-include $(OBJ:.o=.d) diff --git a/miosix/_tools/bootloaders/stm32/pc_loader/pc_loader b/miosix/_tools/bootloaders/stm32/pc_loader/pc_loader old mode 100644 new mode 100755 diff --git a/miosix/_tools/compiler/cleanup.sh b/miosix/_tools/compiler/cleanup.sh old mode 100644 new mode 100755 diff --git a/miosix/_tools/compiler/install-script.sh b/miosix/_tools/compiler/install-script.sh index 92cf02460bfa63b540141832f782469fd29107b8..4b1d710fd53a4008fca27e844115a278f080aef2 100755 --- a/miosix/_tools/compiler/install-script.sh +++ b/miosix/_tools/compiler/install-script.sh @@ -236,7 +236,15 @@ $SUDO make install 2>../log/n.txt || quit ":: Error installing gdb" cd .. -# Last thing, remove this since it's not necessary +# +# Part 10: install the postlinker +# +cd mx-postlinker +make +$SUDO make install INSTALL_DIR=$INSTALL_DIR/arm-miosix-eabi/bin +cd .. + +# Last thing, remove this since its name is not arm-miosix-eabi- $SUDO rm $INSTALL_DIR/arm-miosix-eabi/bin/arm-miosix-eabi-$GCC # If sudo not an empty variable, make symlinks to /usr/bin diff --git a/miosix/_tools/compiler/uninstall.sh b/miosix/_tools/compiler/uninstall.sh old mode 100644 new mode 100755 diff --git a/miosix/_tools/testsuite/Readme.txt b/miosix/_tools/testsuite/Readme.txt index e3305737b84bf0ba8ce7521de3db6b051e22f70a..f5682d38a09e91c2b4e6f10c696e10d818210ff5 100644 --- a/miosix/_tools/testsuite/Readme.txt +++ b/miosix/_tools/testsuite/Readme.txt @@ -1,5 +1,9 @@ -To run the testsuite, modify the Makefile from +To run the testsuite: +1) Run "build.sh" in the mpu_testsuite directory, +2) Run "build.sh testsuite" in the syscall_testsuite directory, +3) Copy testsuite.cpp from this directory into the top + level directory and modify the Makefile, from SRC := \ main.cpp @@ -7,4 +11,8 @@ main.cpp to SRC := \ -miosix/_tools/testsuite/testsuite.cpp \ No newline at end of file +testsuite.cpp + +Run "cleanup.sh" from mpu_testsuite directory to clean compilation files. + +For more information, see the Readme.txt files in the subdirectories. \ No newline at end of file diff --git a/miosix/_tools/testsuite/elf_testsuite/Readme.txt b/miosix/_tools/testsuite/elf_testsuite/Readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..0e22456e1c2d2d78199e8b1ba423aa5c56762130 --- /dev/null +++ b/miosix/_tools/testsuite/elf_testsuite/Readme.txt @@ -0,0 +1,7 @@ +aelf1 : Stack size set to 128 (stack size must be greater than MIN_PROCESS_STACK_SIZE [256]) +aelf2 : Ram size set to 65535 (ram size must be less than MAX_PROCESS_IMAGE_SIZE [64*1024]) +aelf3 : Stack size set to 1945 (stack size must be multiple of 4) +aelf4 : Ram size set to 14745 (ram size must be multiple of 4) +aelf5 : Ram size set to 200 (ram size must be greater than BLOCK_SIZE [1024]) +aelf6 : Stack size set to 32768 (data segment size + stack size must be less than ram size) +aelf7 : Stack size set to 65535 (stack size must be less than MAX_PROCESS_IMAGE_SIZE [64*1024]) \ No newline at end of file diff --git a/miosix/_tools/testsuite/elf_testsuite/aelf1.h b/miosix/_tools/testsuite/elf_testsuite/aelf1.h new file mode 100644 index 0000000000000000000000000000000000000000..66a2d790c6b0e328937e09a56af9fd344b3fc875 --- /dev/null +++ b/miosix/_tools/testsuite/elf_testsuite/aelf1.h @@ -0,0 +1,22 @@ +const unsigned char __attribute__((aligned(8))) aelf1[] = { + 0x7f, 0x45, 0x4c, 0x46, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x28, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x99, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x05, 0x34, 0x00, 0x20, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, + 0x98, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x10, 0x34, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0xb4, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10, 0x0c, 0x00, 0x00, 0x10, + 0x28, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x02, 0xf8, + 0x00, 0xf0, 0x02, 0xf8, 0x00, 0x20, 0x70, 0x47, 0x02, 0x23, 0x00, 0xdf, + 0x0c, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x80, 0x00, 0x00, 0x00, + 0x4d, 0x69, 0x6f, 0x73, 0x69, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 +}; +unsigned int aelf1_len = 220; diff --git a/miosix/_tools/testsuite/elf_testsuite/aelf2.h b/miosix/_tools/testsuite/elf_testsuite/aelf2.h new file mode 100644 index 0000000000000000000000000000000000000000..9de6257fa9314faf6a0fe684da1792954eb13243 --- /dev/null +++ b/miosix/_tools/testsuite/elf_testsuite/aelf2.h @@ -0,0 +1,22 @@ +const unsigned char __attribute__((aligned(8))) aelf2[] = { + 0x7f, 0x45, 0x4c, 0x46, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x28, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x99, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x05, 0x34, 0x00, 0x20, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, + 0x98, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x10, 0x34, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0xb4, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10, 0x0c, 0x00, 0x00, 0x10, + 0x28, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x02, 0xf8, + 0x00, 0xf0, 0x02, 0xf8, 0x00, 0x20, 0x70, 0x47, 0x02, 0x23, 0x00, 0xdf, + 0x0c, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0xFF, 0xFF, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00, + 0x4d, 0x69, 0x6f, 0x73, 0x69, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 +}; +unsigned int aelf2_len = 220; diff --git a/miosix/_tools/testsuite/elf_testsuite/aelf3.h b/miosix/_tools/testsuite/elf_testsuite/aelf3.h new file mode 100644 index 0000000000000000000000000000000000000000..e15754a4020434a385d23660ba0baa7badfb4197 --- /dev/null +++ b/miosix/_tools/testsuite/elf_testsuite/aelf3.h @@ -0,0 +1,22 @@ +const unsigned char __attribute__((aligned(8))) aelf3[] = { + 0x7f, 0x45, 0x4c, 0x46, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x28, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x99, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x05, 0x34, 0x00, 0x20, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, + 0x98, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x10, 0x34, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0xb4, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10, 0x0c, 0x00, 0x00, 0x10, + 0x28, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x02, 0xf8, + 0x00, 0xf0, 0x02, 0xf8, 0x00, 0x20, 0x70, 0x47, 0x02, 0x23, 0x00, 0xdf, + 0x0c, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x99, 0x79, 0x00, 0x00, + 0x4d, 0x69, 0x6f, 0x73, 0x69, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 +}; +unsigned int aelf3_len = 220; diff --git a/miosix/_tools/testsuite/elf_testsuite/aelf4.h b/miosix/_tools/testsuite/elf_testsuite/aelf4.h new file mode 100644 index 0000000000000000000000000000000000000000..6a93936e62b9cf38a0905f019af09353849587a6 --- /dev/null +++ b/miosix/_tools/testsuite/elf_testsuite/aelf4.h @@ -0,0 +1,22 @@ +const unsigned char __attribute__((aligned(8))) aelf4[] = { + 0x7f, 0x45, 0x4c, 0x46, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x28, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x99, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x05, 0x34, 0x00, 0x20, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, + 0x98, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x10, 0x34, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0xb4, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10, 0x0c, 0x00, 0x00, 0x10, + 0x28, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x02, 0xf8, + 0x00, 0xf0, 0x02, 0xf8, 0x00, 0x20, 0x70, 0x47, 0x02, 0x23, 0x00, 0xdf, + 0x0c, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x99, 0x39, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00, + 0x4d, 0x69, 0x6f, 0x73, 0x69, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 +}; +unsigned int aelf4_len = 220; diff --git a/miosix/_tools/testsuite/elf_testsuite/aelf5.h b/miosix/_tools/testsuite/elf_testsuite/aelf5.h new file mode 100644 index 0000000000000000000000000000000000000000..6bab559e612ec37ed4613dfaf2e21e1981959b87 --- /dev/null +++ b/miosix/_tools/testsuite/elf_testsuite/aelf5.h @@ -0,0 +1,22 @@ +const unsigned char __attribute__((aligned(8))) aelf5[] = { + 0x7f, 0x45, 0x4c, 0x46, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x28, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x99, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x05, 0x34, 0x00, 0x20, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, + 0x98, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x10, 0x34, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0xb4, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10, 0x0c, 0x00, 0x00, 0x10, + 0x28, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x02, 0xf8, + 0x00, 0xf0, 0x02, 0xf8, 0x00, 0x20, 0x70, 0x47, 0x02, 0x23, 0x00, 0xdf, + 0x0c, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00, + 0x4d, 0x69, 0x6f, 0x73, 0x69, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 +}; +unsigned int aelf5_len = 220; diff --git a/miosix/_tools/testsuite/elf_testsuite/aelf6.h b/miosix/_tools/testsuite/elf_testsuite/aelf6.h new file mode 100644 index 0000000000000000000000000000000000000000..7ab0ec68916886c90580713201f01ade80f1735e --- /dev/null +++ b/miosix/_tools/testsuite/elf_testsuite/aelf6.h @@ -0,0 +1,22 @@ +const unsigned char __attribute__((aligned(8))) aelf6[] = { + 0x7f, 0x45, 0x4c, 0x46, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x28, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x99, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x05, 0x34, 0x00, 0x20, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, + 0x98, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x10, 0x34, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0xb4, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10, 0x0c, 0x00, 0x00, 0x10, + 0x28, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x02, 0xf8, + 0x00, 0xf0, 0x02, 0xf8, 0x00, 0x20, 0x70, 0x47, 0x02, 0x23, 0x00, 0xdf, + 0x0c, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, + 0x4d, 0x69, 0x6f, 0x73, 0x69, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 +}; +unsigned int aelf6_len = 220; diff --git a/miosix/_tools/testsuite/elf_testsuite/aelf7.h b/miosix/_tools/testsuite/elf_testsuite/aelf7.h new file mode 100644 index 0000000000000000000000000000000000000000..257d4cb8bc7e5a4feda1582b5577b9fc6c2ca101 --- /dev/null +++ b/miosix/_tools/testsuite/elf_testsuite/aelf7.h @@ -0,0 +1,22 @@ +const unsigned char __attribute__((aligned(8))) aelf7[] = { + 0x7f, 0x45, 0x4c, 0x46, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x28, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x99, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x05, 0x34, 0x00, 0x20, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, + 0x98, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x10, 0x34, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0xb4, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10, 0x0c, 0x00, 0x00, 0x10, + 0x28, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x02, 0xf8, + 0x00, 0xf0, 0x02, 0xf8, 0x00, 0x20, 0x70, 0x47, 0x02, 0x23, 0x00, 0xdf, + 0x0c, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0xFF, 0xFF, 0x00, 0x00, + 0x4d, 0x69, 0x6f, 0x73, 0x69, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 +}; +unsigned int aelf7_len = 220; diff --git a/miosix/_tools/testsuite/elf_testsuite/includes.h b/miosix/_tools/testsuite/elf_testsuite/includes.h new file mode 100644 index 0000000000000000000000000000000000000000..255fcd80282b4cbfc817abdf6705293fef24d7ee --- /dev/null +++ b/miosix/_tools/testsuite/elf_testsuite/includes.h @@ -0,0 +1,10 @@ +#ifndef _APP_ELF_TESTS_ +#define _APP_ELF_TESTS_ +#include "miosix/testsuite/elf_testsuite/aelf1.h" +#include "miosix/testsuite/elf_testsuite/aelf2.h" +#include "miosix/testsuite/elf_testsuite/aelf3.h" +#include "miosix/testsuite/elf_testsuite/aelf4.h" +#include "miosix/testsuite/elf_testsuite/aelf5.h" +#include "miosix/testsuite/elf_testsuite/aelf6.h" +#include "miosix/testsuite/elf_testsuite/aelf7.h" +#endif //_APP_ELF_TESTS_ diff --git a/miosix/_tools/testsuite/mpu_testsuite/Readme.txt b/miosix/_tools/testsuite/mpu_testsuite/Readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..e8d740ca809fa0fa69025982e2dabd53385e0f9f --- /dev/null +++ b/miosix/_tools/testsuite/mpu_testsuite/Readme.txt @@ -0,0 +1,14 @@ + +To run the testsuite, run build.sh in the mpu_apps directory, +then copy mpu_testsuite.cpp from this directory into the top +level directory and modify the Makefile, from + +SRC := \ +main.cpp + +to + +SRC := \ +mpu_testsuite.cpp + +Run cleanup.sh from mpu_apps directory to clean compilation files. \ No newline at end of file diff --git a/miosix/_tools/testsuite/mpu_testsuite/build.sh b/miosix/_tools/testsuite/mpu_testsuite/build.sh new file mode 100644 index 0000000000000000000000000000000000000000..984ccdc6f7536037c32e4938932b5987687f5328 --- /dev/null +++ b/miosix/_tools/testsuite/mpu_testsuite/build.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +echo > includes.h +echo "#ifndef _APP_MPU_TESTS_" >> includes.h +echo "#define _APP_MPU_TESTS_" >> includes.h + +for i in *; +do + if test -d $i; then + cd $i && make clean && make && cp mpuTest.h "../$i.h" && cd .. + echo "#include \"miosix/testsuite/mpu_testsuite/$i.h\"" >> includes.h + sed "s/test_elf/$i\_elf/" $i.h -i + fi; +done; + +echo "#endif //_APP_MPU_TESTS_" >> includes.h diff --git a/miosix/_tools/testsuite/mpu_testsuite/cleanup.sh b/miosix/_tools/testsuite/mpu_testsuite/cleanup.sh new file mode 100644 index 0000000000000000000000000000000000000000..450e08d3c8d68e1ca8d52d2f7fe882cd4b9904ea --- /dev/null +++ b/miosix/_tools/testsuite/mpu_testsuite/cleanup.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +rm includes.h + +for i in *; +do + if test -d $i; then + rm "$i.h" + cd $i && make clean && cd .. + fi; +done; diff --git a/miosix/_tools/testsuite/mpu_testsuite/test1/Makefile b/miosix/_tools/testsuite/mpu_testsuite/test1/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..1523e24bde2cb6937bcc985c1c45062d4987cbdc --- /dev/null +++ b/miosix/_tools/testsuite/mpu_testsuite/test1/Makefile @@ -0,0 +1,48 @@ +## +## Makefile for writing PROGRAMS for the Miosix embedded OS +## TFT:Terraneo Federico Technlogies +## + +SRC := \ +main.c + +## Replaces both "foo.cpp"-->"foo.o" and "foo.c"-->"foo.o" +OBJ := $(addsuffix .o, $(basename $(SRC))) + +AS := arm-miosix-eabi-as +CC := arm-miosix-eabi-gcc +CXX := arm-miosix-eabi-g++ +SZ := arm-miosix-eabi-size + +AFLAGS := -mcpu=cortex-m3 -mthumb +CFLAGS := -mcpu=cortex-m3 -mthumb -mfix-cortex-m3-ldrd -fpie -msingle-pic-base \ + -ffunction-sections -O2 -Wall -c +CXXFLAGS := $(CFLAGS) +LFLAGS := -mcpu=cortex-m3 -mthumb -mfix-cortex-m3-ldrd -fpie -msingle-pic-base \ + -Wl,--gc-sections,-Map,test.map,-T./miosix.ld,-n,-pie,--spare-dynamic-tags,3 \ + -O2 -nostdlib +DFLAGS := -MMD -MP + +LINK_LIBS := -Wl,--start-group -lstdc++ -lc -lm -lgcc -Wl,--end-group + +all: $(OBJ) crt0.o + $(CXX) $(LFLAGS) -o test.elf $(OBJ) crt0.o $(LINK_LIBS) + $(SZ) test.elf + @arm-miosix-eabi-objdump -Dslx test.elf > test.txt + @mx-postlinker test.elf --ramsize=16384 --stacksize=2048 --strip-sectheader + @xxd -i test.elf | sed 's/unsigned char/const unsigned char __attribute__((aligned(8)))/' > mpuTest.h + +clean: + -rm $(OBJ) crt0.o test.elf test.map test.txt mpuTest.h $(OBJ:.o=.d) + +%.o: %.s + $(AS) $(AFLAGS) $< -o $@ + +%.o : %.c + $(CC) $(DFLAGS) $(CFLAGS) $< -o $@ + +%.o : %.cpp + $(CXX) $(DFLAGS) $(CXXFLAGS) $< -o $@ + +#pull in dependecy info for existing .o files +-include $(OBJ:.o=.d) diff --git a/miosix/_tools/testsuite/mpu_testsuite/test1/crt0.s b/miosix/_tools/testsuite/mpu_testsuite/test1/crt0.s new file mode 100644 index 0000000000000000000000000000000000000000..7733008e9392ded796006a94a0c1a527a94bfc1a --- /dev/null +++ b/miosix/_tools/testsuite/mpu_testsuite/test1/crt0.s @@ -0,0 +1,130 @@ +/* + * Startup script for writing PROGRAMS for the Miosix embedded OS + * TFT:Terraneo Federico Technlogies + */ + +.syntax unified +.cpu cortex-m3 +.thumb + +.section .text + +/** + * _start, program entry point + */ +.global _start +.type _start, %function +_start: + /* TODO: .ctor */ + bl main + /* TODO: .dtor */ + bl _exit + +/** + * _exit, terminate process + * \param v exit value + */ +.section .text._exit +.global _exit +.type _exit, %function +_exit: + movs r3, #2 + svc 0 + +/** + * open, open a file + * \param fd file descriptor + * \param file access mode + * \param xxx access permisions + * \return file descriptor or -1 if errors + */ +.section .text.open +.global open +.type open, %function +open: + movs r3, #6 + svc 0 + bx lr + +/** + * close, close a file + * \param fd file descriptor + */ +.section .text.close +.global close +.type close, %function +close: + movs r3, #7 + svc 0 + bx lr + +/** + * lseek + * \param fd file descriptor + * \param pos moving offset + * \param start position, SEEK_SET, SEEK_CUR or SEEK_END + +.section .text.lseek +.global lseek +.type lseek, %function + + movs r3, #8 + svc 0 + bx lr +*/ + +/** + * system, fork and execture a program, blocking + * \param program to execute + */ +.section .text.system +.global system +.type system, %function +system: + movs r3, #9 + svc 0 + bx lr +/** + * write, write to file + * \param fd file descriptor + * \param buf data to be written + * \param len buffer length + * \return number of written bytes or -1 if errors + */ +.section .text.write +.global write +.type write, %function +write: + movs r3, #3 + svc 0 + bx lr + +/** + * read, read from file + * \param fd file descriptor + * \param buf data to be read + * \param len buffer length + * \return number of read bytes or -1 if errors + */ +.section .text.read +.global read +.type read, %function +read: + movs r3, #4 + svc 0 + bx lr + +/** + * usleep, sleep a specified number of microseconds + * \param us number of microseconds to sleep + * \return 0 on success or -1 if errors + */ +.section .text.usleep +.global usleep +.type usleep, %function +usleep: + movs r3, #5 + svc 0 + bx lr + +.end diff --git a/miosix/_tools/testsuite/mpu_testsuite/test1/main.c b/miosix/_tools/testsuite/mpu_testsuite/test1/main.c new file mode 100644 index 0000000000000000000000000000000000000000..36d4f25285da2aac823dc280f630c0d9f4f245d8 --- /dev/null +++ b/miosix/_tools/testsuite/mpu_testsuite/test1/main.c @@ -0,0 +1,16 @@ +#include <unistd.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <string.h> +#include <stdio.h> + +int main() +{ + // 'address' points to a memory location allocated with ProcessPool + // and owned by the kernel. The program tries to write the location. + volatile unsigned int *address = 0x64100000; + *address = 0xbbbbbbbb; + return 0; +} diff --git a/miosix/_tools/testsuite/mpu_testsuite/test1/miosix.ld b/miosix/_tools/testsuite/mpu_testsuite/test1/miosix.ld new file mode 100644 index 0000000000000000000000000000000000000000..c91c803e629040b14233a8f8251a7d9952f68910 --- /dev/null +++ b/miosix/_tools/testsuite/mpu_testsuite/test1/miosix.ld @@ -0,0 +1,66 @@ +/* + * Linker script for writing PROGRAMS for the Miosix embedded OS + * TFT:Terraneo Federico Technlogies + */ + +OUTPUT_FORMAT("elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) + +SECTIONS +{ + /* Here starts the first elf segment, that stays in flash */ + . = 0 + SIZEOF_HEADERS; + + .text : ALIGN(8) + { + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + } + + .rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) } + .rel.got : { *(.rel.got) } + + /* Here starts the second segment, that is copied in RAM and relocated */ + . = 0x10000000; + + .got : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) } + + /* FIXME: If this is put in the other segment, it makes it writable */ + .dynamic : { *(.dynamic) } + + /* FIXME: The compiler insists in addressing rodata relative to r9 */ + .rodata : ALIGN(8) + { + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + } + + .data : ALIGN(8) + { + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + } + + .bss : ALIGN(8) + { + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + } + + /* These are removed since are unused and increase binary size */ + /DISCARD/ : + { + *(.interp) + *(.dynsym) + *(.dynstr) + *(.hash) + *(.comment) + *(.ARM.attributes) + } +} diff --git a/miosix/_tools/testsuite/mpu_testsuite/test10_1/Makefile b/miosix/_tools/testsuite/mpu_testsuite/test10_1/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..1523e24bde2cb6937bcc985c1c45062d4987cbdc --- /dev/null +++ b/miosix/_tools/testsuite/mpu_testsuite/test10_1/Makefile @@ -0,0 +1,48 @@ +## +## Makefile for writing PROGRAMS for the Miosix embedded OS +## TFT:Terraneo Federico Technlogies +## + +SRC := \ +main.c + +## Replaces both "foo.cpp"-->"foo.o" and "foo.c"-->"foo.o" +OBJ := $(addsuffix .o, $(basename $(SRC))) + +AS := arm-miosix-eabi-as +CC := arm-miosix-eabi-gcc +CXX := arm-miosix-eabi-g++ +SZ := arm-miosix-eabi-size + +AFLAGS := -mcpu=cortex-m3 -mthumb +CFLAGS := -mcpu=cortex-m3 -mthumb -mfix-cortex-m3-ldrd -fpie -msingle-pic-base \ + -ffunction-sections -O2 -Wall -c +CXXFLAGS := $(CFLAGS) +LFLAGS := -mcpu=cortex-m3 -mthumb -mfix-cortex-m3-ldrd -fpie -msingle-pic-base \ + -Wl,--gc-sections,-Map,test.map,-T./miosix.ld,-n,-pie,--spare-dynamic-tags,3 \ + -O2 -nostdlib +DFLAGS := -MMD -MP + +LINK_LIBS := -Wl,--start-group -lstdc++ -lc -lm -lgcc -Wl,--end-group + +all: $(OBJ) crt0.o + $(CXX) $(LFLAGS) -o test.elf $(OBJ) crt0.o $(LINK_LIBS) + $(SZ) test.elf + @arm-miosix-eabi-objdump -Dslx test.elf > test.txt + @mx-postlinker test.elf --ramsize=16384 --stacksize=2048 --strip-sectheader + @xxd -i test.elf | sed 's/unsigned char/const unsigned char __attribute__((aligned(8)))/' > mpuTest.h + +clean: + -rm $(OBJ) crt0.o test.elf test.map test.txt mpuTest.h $(OBJ:.o=.d) + +%.o: %.s + $(AS) $(AFLAGS) $< -o $@ + +%.o : %.c + $(CC) $(DFLAGS) $(CFLAGS) $< -o $@ + +%.o : %.cpp + $(CXX) $(DFLAGS) $(CXXFLAGS) $< -o $@ + +#pull in dependecy info for existing .o files +-include $(OBJ:.o=.d) diff --git a/miosix/_tools/testsuite/mpu_testsuite/test10_1/crt0.s b/miosix/_tools/testsuite/mpu_testsuite/test10_1/crt0.s new file mode 100644 index 0000000000000000000000000000000000000000..7733008e9392ded796006a94a0c1a527a94bfc1a --- /dev/null +++ b/miosix/_tools/testsuite/mpu_testsuite/test10_1/crt0.s @@ -0,0 +1,130 @@ +/* + * Startup script for writing PROGRAMS for the Miosix embedded OS + * TFT:Terraneo Federico Technlogies + */ + +.syntax unified +.cpu cortex-m3 +.thumb + +.section .text + +/** + * _start, program entry point + */ +.global _start +.type _start, %function +_start: + /* TODO: .ctor */ + bl main + /* TODO: .dtor */ + bl _exit + +/** + * _exit, terminate process + * \param v exit value + */ +.section .text._exit +.global _exit +.type _exit, %function +_exit: + movs r3, #2 + svc 0 + +/** + * open, open a file + * \param fd file descriptor + * \param file access mode + * \param xxx access permisions + * \return file descriptor or -1 if errors + */ +.section .text.open +.global open +.type open, %function +open: + movs r3, #6 + svc 0 + bx lr + +/** + * close, close a file + * \param fd file descriptor + */ +.section .text.close +.global close +.type close, %function +close: + movs r3, #7 + svc 0 + bx lr + +/** + * lseek + * \param fd file descriptor + * \param pos moving offset + * \param start position, SEEK_SET, SEEK_CUR or SEEK_END + +.section .text.lseek +.global lseek +.type lseek, %function + + movs r3, #8 + svc 0 + bx lr +*/ + +/** + * system, fork and execture a program, blocking + * \param program to execute + */ +.section .text.system +.global system +.type system, %function +system: + movs r3, #9 + svc 0 + bx lr +/** + * write, write to file + * \param fd file descriptor + * \param buf data to be written + * \param len buffer length + * \return number of written bytes or -1 if errors + */ +.section .text.write +.global write +.type write, %function +write: + movs r3, #3 + svc 0 + bx lr + +/** + * read, read from file + * \param fd file descriptor + * \param buf data to be read + * \param len buffer length + * \return number of read bytes or -1 if errors + */ +.section .text.read +.global read +.type read, %function +read: + movs r3, #4 + svc 0 + bx lr + +/** + * usleep, sleep a specified number of microseconds + * \param us number of microseconds to sleep + * \return 0 on success or -1 if errors + */ +.section .text.usleep +.global usleep +.type usleep, %function +usleep: + movs r3, #5 + svc 0 + bx lr + +.end diff --git a/miosix/_tools/testsuite/mpu_testsuite/test10_1/main.c b/miosix/_tools/testsuite/mpu_testsuite/test10_1/main.c new file mode 100644 index 0000000000000000000000000000000000000000..1ee253fb920330bed3f9675de9d9a9dbf88e8af9 --- /dev/null +++ b/miosix/_tools/testsuite/mpu_testsuite/test10_1/main.c @@ -0,0 +1,16 @@ +#include <unistd.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <string.h> +#include <stdio.h> + +int main() +{ + // This process goes to sleep for 2 seconds, while the second + // process tries to access the data region of this process. + unsigned int i=0; + for(i=0; i<5000000; i++) + return 0; +} diff --git a/miosix/_tools/testsuite/mpu_testsuite/test10_1/miosix.ld b/miosix/_tools/testsuite/mpu_testsuite/test10_1/miosix.ld new file mode 100644 index 0000000000000000000000000000000000000000..c91c803e629040b14233a8f8251a7d9952f68910 --- /dev/null +++ b/miosix/_tools/testsuite/mpu_testsuite/test10_1/miosix.ld @@ -0,0 +1,66 @@ +/* + * Linker script for writing PROGRAMS for the Miosix embedded OS + * TFT:Terraneo Federico Technlogies + */ + +OUTPUT_FORMAT("elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) + +SECTIONS +{ + /* Here starts the first elf segment, that stays in flash */ + . = 0 + SIZEOF_HEADERS; + + .text : ALIGN(8) + { + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + } + + .rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) } + .rel.got : { *(.rel.got) } + + /* Here starts the second segment, that is copied in RAM and relocated */ + . = 0x10000000; + + .got : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) } + + /* FIXME: If this is put in the other segment, it makes it writable */ + .dynamic : { *(.dynamic) } + + /* FIXME: The compiler insists in addressing rodata relative to r9 */ + .rodata : ALIGN(8) + { + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + } + + .data : ALIGN(8) + { + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + } + + .bss : ALIGN(8) + { + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + } + + /* These are removed since are unused and increase binary size */ + /DISCARD/ : + { + *(.interp) + *(.dynsym) + *(.dynstr) + *(.hash) + *(.comment) + *(.ARM.attributes) + } +} diff --git a/miosix/_tools/testsuite/mpu_testsuite/test10_2/Makefile b/miosix/_tools/testsuite/mpu_testsuite/test10_2/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..1523e24bde2cb6937bcc985c1c45062d4987cbdc --- /dev/null +++ b/miosix/_tools/testsuite/mpu_testsuite/test10_2/Makefile @@ -0,0 +1,48 @@ +## +## Makefile for writing PROGRAMS for the Miosix embedded OS +## TFT:Terraneo Federico Technlogies +## + +SRC := \ +main.c + +## Replaces both "foo.cpp"-->"foo.o" and "foo.c"-->"foo.o" +OBJ := $(addsuffix .o, $(basename $(SRC))) + +AS := arm-miosix-eabi-as +CC := arm-miosix-eabi-gcc +CXX := arm-miosix-eabi-g++ +SZ := arm-miosix-eabi-size + +AFLAGS := -mcpu=cortex-m3 -mthumb +CFLAGS := -mcpu=cortex-m3 -mthumb -mfix-cortex-m3-ldrd -fpie -msingle-pic-base \ + -ffunction-sections -O2 -Wall -c +CXXFLAGS := $(CFLAGS) +LFLAGS := -mcpu=cortex-m3 -mthumb -mfix-cortex-m3-ldrd -fpie -msingle-pic-base \ + -Wl,--gc-sections,-Map,test.map,-T./miosix.ld,-n,-pie,--spare-dynamic-tags,3 \ + -O2 -nostdlib +DFLAGS := -MMD -MP + +LINK_LIBS := -Wl,--start-group -lstdc++ -lc -lm -lgcc -Wl,--end-group + +all: $(OBJ) crt0.o + $(CXX) $(LFLAGS) -o test.elf $(OBJ) crt0.o $(LINK_LIBS) + $(SZ) test.elf + @arm-miosix-eabi-objdump -Dslx test.elf > test.txt + @mx-postlinker test.elf --ramsize=16384 --stacksize=2048 --strip-sectheader + @xxd -i test.elf | sed 's/unsigned char/const unsigned char __attribute__((aligned(8)))/' > mpuTest.h + +clean: + -rm $(OBJ) crt0.o test.elf test.map test.txt mpuTest.h $(OBJ:.o=.d) + +%.o: %.s + $(AS) $(AFLAGS) $< -o $@ + +%.o : %.c + $(CC) $(DFLAGS) $(CFLAGS) $< -o $@ + +%.o : %.cpp + $(CXX) $(DFLAGS) $(CXXFLAGS) $< -o $@ + +#pull in dependecy info for existing .o files +-include $(OBJ:.o=.d) diff --git a/miosix/_tools/testsuite/mpu_testsuite/test10_2/crt0.s b/miosix/_tools/testsuite/mpu_testsuite/test10_2/crt0.s new file mode 100644 index 0000000000000000000000000000000000000000..7733008e9392ded796006a94a0c1a527a94bfc1a --- /dev/null +++ b/miosix/_tools/testsuite/mpu_testsuite/test10_2/crt0.s @@ -0,0 +1,130 @@ +/* + * Startup script for writing PROGRAMS for the Miosix embedded OS + * TFT:Terraneo Federico Technlogies + */ + +.syntax unified +.cpu cortex-m3 +.thumb + +.section .text + +/** + * _start, program entry point + */ +.global _start +.type _start, %function +_start: + /* TODO: .ctor */ + bl main + /* TODO: .dtor */ + bl _exit + +/** + * _exit, terminate process + * \param v exit value + */ +.section .text._exit +.global _exit +.type _exit, %function +_exit: + movs r3, #2 + svc 0 + +/** + * open, open a file + * \param fd file descriptor + * \param file access mode + * \param xxx access permisions + * \return file descriptor or -1 if errors + */ +.section .text.open +.global open +.type open, %function +open: + movs r3, #6 + svc 0 + bx lr + +/** + * close, close a file + * \param fd file descriptor + */ +.section .text.close +.global close +.type close, %function +close: + movs r3, #7 + svc 0 + bx lr + +/** + * lseek + * \param fd file descriptor + * \param pos moving offset + * \param start position, SEEK_SET, SEEK_CUR or SEEK_END + +.section .text.lseek +.global lseek +.type lseek, %function + + movs r3, #8 + svc 0 + bx lr +*/ + +/** + * system, fork and execture a program, blocking + * \param program to execute + */ +.section .text.system +.global system +.type system, %function +system: + movs r3, #9 + svc 0 + bx lr +/** + * write, write to file + * \param fd file descriptor + * \param buf data to be written + * \param len buffer length + * \return number of written bytes or -1 if errors + */ +.section .text.write +.global write +.type write, %function +write: + movs r3, #3 + svc 0 + bx lr + +/** + * read, read from file + * \param fd file descriptor + * \param buf data to be read + * \param len buffer length + * \return number of read bytes or -1 if errors + */ +.section .text.read +.global read +.type read, %function +read: + movs r3, #4 + svc 0 + bx lr + +/** + * usleep, sleep a specified number of microseconds + * \param us number of microseconds to sleep + * \return 0 on success or -1 if errors + */ +.section .text.usleep +.global usleep +.type usleep, %function +usleep: + movs r3, #5 + svc 0 + bx lr + +.end diff --git a/miosix/_tools/testsuite/mpu_testsuite/test10_2/main.c b/miosix/_tools/testsuite/mpu_testsuite/test10_2/main.c new file mode 100644 index 0000000000000000000000000000000000000000..7f691459bc86affe5c6c061d2d0d941f89e0def9 --- /dev/null +++ b/miosix/_tools/testsuite/mpu_testsuite/test10_2/main.c @@ -0,0 +1,18 @@ +#include <unistd.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <string.h> +#include <stdio.h> + +int main() +{ + // The process tries to fill almost all the stack with an array + // and then tries to save the context by calling a syscall. + // With an array of 16344 bytes, there is no fault. + volatile unsigned char array[16345]; + array[0]=1; + usleep(2000000); + return 0; +} diff --git a/miosix/_tools/testsuite/mpu_testsuite/test10_2/miosix.ld b/miosix/_tools/testsuite/mpu_testsuite/test10_2/miosix.ld new file mode 100644 index 0000000000000000000000000000000000000000..c91c803e629040b14233a8f8251a7d9952f68910 --- /dev/null +++ b/miosix/_tools/testsuite/mpu_testsuite/test10_2/miosix.ld @@ -0,0 +1,66 @@ +/* + * Linker script for writing PROGRAMS for the Miosix embedded OS + * TFT:Terraneo Federico Technlogies + */ + +OUTPUT_FORMAT("elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) + +SECTIONS +{ + /* Here starts the first elf segment, that stays in flash */ + . = 0 + SIZEOF_HEADERS; + + .text : ALIGN(8) + { + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + } + + .rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) } + .rel.got : { *(.rel.got) } + + /* Here starts the second segment, that is copied in RAM and relocated */ + . = 0x10000000; + + .got : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) } + + /* FIXME: If this is put in the other segment, it makes it writable */ + .dynamic : { *(.dynamic) } + + /* FIXME: The compiler insists in addressing rodata relative to r9 */ + .rodata : ALIGN(8) + { + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + } + + .data : ALIGN(8) + { + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + } + + .bss : ALIGN(8) + { + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + } + + /* These are removed since are unused and increase binary size */ + /DISCARD/ : + { + *(.interp) + *(.dynsym) + *(.dynstr) + *(.hash) + *(.comment) + *(.ARM.attributes) + } +} diff --git a/miosix/_tools/testsuite/mpu_testsuite/test2/Makefile b/miosix/_tools/testsuite/mpu_testsuite/test2/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..1523e24bde2cb6937bcc985c1c45062d4987cbdc --- /dev/null +++ b/miosix/_tools/testsuite/mpu_testsuite/test2/Makefile @@ -0,0 +1,48 @@ +## +## Makefile for writing PROGRAMS for the Miosix embedded OS +## TFT:Terraneo Federico Technlogies +## + +SRC := \ +main.c + +## Replaces both "foo.cpp"-->"foo.o" and "foo.c"-->"foo.o" +OBJ := $(addsuffix .o, $(basename $(SRC))) + +AS := arm-miosix-eabi-as +CC := arm-miosix-eabi-gcc +CXX := arm-miosix-eabi-g++ +SZ := arm-miosix-eabi-size + +AFLAGS := -mcpu=cortex-m3 -mthumb +CFLAGS := -mcpu=cortex-m3 -mthumb -mfix-cortex-m3-ldrd -fpie -msingle-pic-base \ + -ffunction-sections -O2 -Wall -c +CXXFLAGS := $(CFLAGS) +LFLAGS := -mcpu=cortex-m3 -mthumb -mfix-cortex-m3-ldrd -fpie -msingle-pic-base \ + -Wl,--gc-sections,-Map,test.map,-T./miosix.ld,-n,-pie,--spare-dynamic-tags,3 \ + -O2 -nostdlib +DFLAGS := -MMD -MP + +LINK_LIBS := -Wl,--start-group -lstdc++ -lc -lm -lgcc -Wl,--end-group + +all: $(OBJ) crt0.o + $(CXX) $(LFLAGS) -o test.elf $(OBJ) crt0.o $(LINK_LIBS) + $(SZ) test.elf + @arm-miosix-eabi-objdump -Dslx test.elf > test.txt + @mx-postlinker test.elf --ramsize=16384 --stacksize=2048 --strip-sectheader + @xxd -i test.elf | sed 's/unsigned char/const unsigned char __attribute__((aligned(8)))/' > mpuTest.h + +clean: + -rm $(OBJ) crt0.o test.elf test.map test.txt mpuTest.h $(OBJ:.o=.d) + +%.o: %.s + $(AS) $(AFLAGS) $< -o $@ + +%.o : %.c + $(CC) $(DFLAGS) $(CFLAGS) $< -o $@ + +%.o : %.cpp + $(CXX) $(DFLAGS) $(CXXFLAGS) $< -o $@ + +#pull in dependecy info for existing .o files +-include $(OBJ:.o=.d) diff --git a/miosix/_tools/testsuite/mpu_testsuite/test2/crt0.s b/miosix/_tools/testsuite/mpu_testsuite/test2/crt0.s new file mode 100644 index 0000000000000000000000000000000000000000..7733008e9392ded796006a94a0c1a527a94bfc1a --- /dev/null +++ b/miosix/_tools/testsuite/mpu_testsuite/test2/crt0.s @@ -0,0 +1,130 @@ +/* + * Startup script for writing PROGRAMS for the Miosix embedded OS + * TFT:Terraneo Federico Technlogies + */ + +.syntax unified +.cpu cortex-m3 +.thumb + +.section .text + +/** + * _start, program entry point + */ +.global _start +.type _start, %function +_start: + /* TODO: .ctor */ + bl main + /* TODO: .dtor */ + bl _exit + +/** + * _exit, terminate process + * \param v exit value + */ +.section .text._exit +.global _exit +.type _exit, %function +_exit: + movs r3, #2 + svc 0 + +/** + * open, open a file + * \param fd file descriptor + * \param file access mode + * \param xxx access permisions + * \return file descriptor or -1 if errors + */ +.section .text.open +.global open +.type open, %function +open: + movs r3, #6 + svc 0 + bx lr + +/** + * close, close a file + * \param fd file descriptor + */ +.section .text.close +.global close +.type close, %function +close: + movs r3, #7 + svc 0 + bx lr + +/** + * lseek + * \param fd file descriptor + * \param pos moving offset + * \param start position, SEEK_SET, SEEK_CUR or SEEK_END + +.section .text.lseek +.global lseek +.type lseek, %function + + movs r3, #8 + svc 0 + bx lr +*/ + +/** + * system, fork and execture a program, blocking + * \param program to execute + */ +.section .text.system +.global system +.type system, %function +system: + movs r3, #9 + svc 0 + bx lr +/** + * write, write to file + * \param fd file descriptor + * \param buf data to be written + * \param len buffer length + * \return number of written bytes or -1 if errors + */ +.section .text.write +.global write +.type write, %function +write: + movs r3, #3 + svc 0 + bx lr + +/** + * read, read from file + * \param fd file descriptor + * \param buf data to be read + * \param len buffer length + * \return number of read bytes or -1 if errors + */ +.section .text.read +.global read +.type read, %function +read: + movs r3, #4 + svc 0 + bx lr + +/** + * usleep, sleep a specified number of microseconds + * \param us number of microseconds to sleep + * \return 0 on success or -1 if errors + */ +.section .text.usleep +.global usleep +.type usleep, %function +usleep: + movs r3, #5 + svc 0 + bx lr + +.end diff --git a/miosix/_tools/testsuite/mpu_testsuite/test2/main.c b/miosix/_tools/testsuite/mpu_testsuite/test2/main.c new file mode 100644 index 0000000000000000000000000000000000000000..d4bf9153e88f9559d7f670b1d22aff14310b816e --- /dev/null +++ b/miosix/_tools/testsuite/mpu_testsuite/test2/main.c @@ -0,0 +1,16 @@ +#include <unistd.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <string.h> +#include <stdio.h> + +int main() +{ + // 'address' points to a memory location allocated with ProcessPool + // and owned by the kernel. The program tries to read the location. + volatile unsigned int *address = 0x64100200; + volatile unsigned int c = *address; + return 0; +} diff --git a/miosix/_tools/testsuite/mpu_testsuite/test2/miosix.ld b/miosix/_tools/testsuite/mpu_testsuite/test2/miosix.ld new file mode 100644 index 0000000000000000000000000000000000000000..c91c803e629040b14233a8f8251a7d9952f68910 --- /dev/null +++ b/miosix/_tools/testsuite/mpu_testsuite/test2/miosix.ld @@ -0,0 +1,66 @@ +/* + * Linker script for writing PROGRAMS for the Miosix embedded OS + * TFT:Terraneo Federico Technlogies + */ + +OUTPUT_FORMAT("elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) + +SECTIONS +{ + /* Here starts the first elf segment, that stays in flash */ + . = 0 + SIZEOF_HEADERS; + + .text : ALIGN(8) + { + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + } + + .rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) } + .rel.got : { *(.rel.got) } + + /* Here starts the second segment, that is copied in RAM and relocated */ + . = 0x10000000; + + .got : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) } + + /* FIXME: If this is put in the other segment, it makes it writable */ + .dynamic : { *(.dynamic) } + + /* FIXME: The compiler insists in addressing rodata relative to r9 */ + .rodata : ALIGN(8) + { + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + } + + .data : ALIGN(8) + { + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + } + + .bss : ALIGN(8) + { + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + } + + /* These are removed since are unused and increase binary size */ + /DISCARD/ : + { + *(.interp) + *(.dynsym) + *(.dynstr) + *(.hash) + *(.comment) + *(.ARM.attributes) + } +} diff --git a/miosix/_tools/testsuite/mpu_testsuite/test3/Makefile b/miosix/_tools/testsuite/mpu_testsuite/test3/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..1523e24bde2cb6937bcc985c1c45062d4987cbdc --- /dev/null +++ b/miosix/_tools/testsuite/mpu_testsuite/test3/Makefile @@ -0,0 +1,48 @@ +## +## Makefile for writing PROGRAMS for the Miosix embedded OS +## TFT:Terraneo Federico Technlogies +## + +SRC := \ +main.c + +## Replaces both "foo.cpp"-->"foo.o" and "foo.c"-->"foo.o" +OBJ := $(addsuffix .o, $(basename $(SRC))) + +AS := arm-miosix-eabi-as +CC := arm-miosix-eabi-gcc +CXX := arm-miosix-eabi-g++ +SZ := arm-miosix-eabi-size + +AFLAGS := -mcpu=cortex-m3 -mthumb +CFLAGS := -mcpu=cortex-m3 -mthumb -mfix-cortex-m3-ldrd -fpie -msingle-pic-base \ + -ffunction-sections -O2 -Wall -c +CXXFLAGS := $(CFLAGS) +LFLAGS := -mcpu=cortex-m3 -mthumb -mfix-cortex-m3-ldrd -fpie -msingle-pic-base \ + -Wl,--gc-sections,-Map,test.map,-T./miosix.ld,-n,-pie,--spare-dynamic-tags,3 \ + -O2 -nostdlib +DFLAGS := -MMD -MP + +LINK_LIBS := -Wl,--start-group -lstdc++ -lc -lm -lgcc -Wl,--end-group + +all: $(OBJ) crt0.o + $(CXX) $(LFLAGS) -o test.elf $(OBJ) crt0.o $(LINK_LIBS) + $(SZ) test.elf + @arm-miosix-eabi-objdump -Dslx test.elf > test.txt + @mx-postlinker test.elf --ramsize=16384 --stacksize=2048 --strip-sectheader + @xxd -i test.elf | sed 's/unsigned char/const unsigned char __attribute__((aligned(8)))/' > mpuTest.h + +clean: + -rm $(OBJ) crt0.o test.elf test.map test.txt mpuTest.h $(OBJ:.o=.d) + +%.o: %.s + $(AS) $(AFLAGS) $< -o $@ + +%.o : %.c + $(CC) $(DFLAGS) $(CFLAGS) $< -o $@ + +%.o : %.cpp + $(CXX) $(DFLAGS) $(CXXFLAGS) $< -o $@ + +#pull in dependecy info for existing .o files +-include $(OBJ:.o=.d) diff --git a/miosix/_tools/testsuite/mpu_testsuite/test3/crt0.s b/miosix/_tools/testsuite/mpu_testsuite/test3/crt0.s new file mode 100644 index 0000000000000000000000000000000000000000..7733008e9392ded796006a94a0c1a527a94bfc1a --- /dev/null +++ b/miosix/_tools/testsuite/mpu_testsuite/test3/crt0.s @@ -0,0 +1,130 @@ +/* + * Startup script for writing PROGRAMS for the Miosix embedded OS + * TFT:Terraneo Federico Technlogies + */ + +.syntax unified +.cpu cortex-m3 +.thumb + +.section .text + +/** + * _start, program entry point + */ +.global _start +.type _start, %function +_start: + /* TODO: .ctor */ + bl main + /* TODO: .dtor */ + bl _exit + +/** + * _exit, terminate process + * \param v exit value + */ +.section .text._exit +.global _exit +.type _exit, %function +_exit: + movs r3, #2 + svc 0 + +/** + * open, open a file + * \param fd file descriptor + * \param file access mode + * \param xxx access permisions + * \return file descriptor or -1 if errors + */ +.section .text.open +.global open +.type open, %function +open: + movs r3, #6 + svc 0 + bx lr + +/** + * close, close a file + * \param fd file descriptor + */ +.section .text.close +.global close +.type close, %function +close: + movs r3, #7 + svc 0 + bx lr + +/** + * lseek + * \param fd file descriptor + * \param pos moving offset + * \param start position, SEEK_SET, SEEK_CUR or SEEK_END + +.section .text.lseek +.global lseek +.type lseek, %function + + movs r3, #8 + svc 0 + bx lr +*/ + +/** + * system, fork and execture a program, blocking + * \param program to execute + */ +.section .text.system +.global system +.type system, %function +system: + movs r3, #9 + svc 0 + bx lr +/** + * write, write to file + * \param fd file descriptor + * \param buf data to be written + * \param len buffer length + * \return number of written bytes or -1 if errors + */ +.section .text.write +.global write +.type write, %function +write: + movs r3, #3 + svc 0 + bx lr + +/** + * read, read from file + * \param fd file descriptor + * \param buf data to be read + * \param len buffer length + * \return number of read bytes or -1 if errors + */ +.section .text.read +.global read +.type read, %function +read: + movs r3, #4 + svc 0 + bx lr + +/** + * usleep, sleep a specified number of microseconds + * \param us number of microseconds to sleep + * \return 0 on success or -1 if errors + */ +.section .text.usleep +.global usleep +.type usleep, %function +usleep: + movs r3, #5 + svc 0 + bx lr + +.end diff --git a/miosix/_tools/testsuite/mpu_testsuite/test3/main.c b/miosix/_tools/testsuite/mpu_testsuite/test3/main.c new file mode 100644 index 0000000000000000000000000000000000000000..93f2819c0c91d7f9ed3d2148cc2204b405c3a5c8 --- /dev/null +++ b/miosix/_tools/testsuite/mpu_testsuite/test3/main.c @@ -0,0 +1,16 @@ +#include <unistd.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <string.h> +#include <stdio.h> + +int main() +{ + // 'address' points to a memory location allocated and owned by + // the kernel. The program tries to write the location. + volatile unsigned int *address = 0x63F0FFFF; + *address = 0xbbbbbbbb; + return 0; +} diff --git a/miosix/_tools/testsuite/mpu_testsuite/test3/miosix.ld b/miosix/_tools/testsuite/mpu_testsuite/test3/miosix.ld new file mode 100644 index 0000000000000000000000000000000000000000..c91c803e629040b14233a8f8251a7d9952f68910 --- /dev/null +++ b/miosix/_tools/testsuite/mpu_testsuite/test3/miosix.ld @@ -0,0 +1,66 @@ +/* + * Linker script for writing PROGRAMS for the Miosix embedded OS + * TFT:Terraneo Federico Technlogies + */ + +OUTPUT_FORMAT("elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) + +SECTIONS +{ + /* Here starts the first elf segment, that stays in flash */ + . = 0 + SIZEOF_HEADERS; + + .text : ALIGN(8) + { + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + } + + .rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) } + .rel.got : { *(.rel.got) } + + /* Here starts the second segment, that is copied in RAM and relocated */ + . = 0x10000000; + + .got : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) } + + /* FIXME: If this is put in the other segment, it makes it writable */ + .dynamic : { *(.dynamic) } + + /* FIXME: The compiler insists in addressing rodata relative to r9 */ + .rodata : ALIGN(8) + { + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + } + + .data : ALIGN(8) + { + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + } + + .bss : ALIGN(8) + { + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + } + + /* These are removed since are unused and increase binary size */ + /DISCARD/ : + { + *(.interp) + *(.dynsym) + *(.dynstr) + *(.hash) + *(.comment) + *(.ARM.attributes) + } +} diff --git a/miosix/_tools/testsuite/mpu_testsuite/test4/Makefile b/miosix/_tools/testsuite/mpu_testsuite/test4/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..1523e24bde2cb6937bcc985c1c45062d4987cbdc --- /dev/null +++ b/miosix/_tools/testsuite/mpu_testsuite/test4/Makefile @@ -0,0 +1,48 @@ +## +## Makefile for writing PROGRAMS for the Miosix embedded OS +## TFT:Terraneo Federico Technlogies +## + +SRC := \ +main.c + +## Replaces both "foo.cpp"-->"foo.o" and "foo.c"-->"foo.o" +OBJ := $(addsuffix .o, $(basename $(SRC))) + +AS := arm-miosix-eabi-as +CC := arm-miosix-eabi-gcc +CXX := arm-miosix-eabi-g++ +SZ := arm-miosix-eabi-size + +AFLAGS := -mcpu=cortex-m3 -mthumb +CFLAGS := -mcpu=cortex-m3 -mthumb -mfix-cortex-m3-ldrd -fpie -msingle-pic-base \ + -ffunction-sections -O2 -Wall -c +CXXFLAGS := $(CFLAGS) +LFLAGS := -mcpu=cortex-m3 -mthumb -mfix-cortex-m3-ldrd -fpie -msingle-pic-base \ + -Wl,--gc-sections,-Map,test.map,-T./miosix.ld,-n,-pie,--spare-dynamic-tags,3 \ + -O2 -nostdlib +DFLAGS := -MMD -MP + +LINK_LIBS := -Wl,--start-group -lstdc++ -lc -lm -lgcc -Wl,--end-group + +all: $(OBJ) crt0.o + $(CXX) $(LFLAGS) -o test.elf $(OBJ) crt0.o $(LINK_LIBS) + $(SZ) test.elf + @arm-miosix-eabi-objdump -Dslx test.elf > test.txt + @mx-postlinker test.elf --ramsize=16384 --stacksize=2048 --strip-sectheader + @xxd -i test.elf | sed 's/unsigned char/const unsigned char __attribute__((aligned(8)))/' > mpuTest.h + +clean: + -rm $(OBJ) crt0.o test.elf test.map test.txt mpuTest.h $(OBJ:.o=.d) + +%.o: %.s + $(AS) $(AFLAGS) $< -o $@ + +%.o : %.c + $(CC) $(DFLAGS) $(CFLAGS) $< -o $@ + +%.o : %.cpp + $(CXX) $(DFLAGS) $(CXXFLAGS) $< -o $@ + +#pull in dependecy info for existing .o files +-include $(OBJ:.o=.d) diff --git a/miosix/_tools/testsuite/mpu_testsuite/test4/crt0.s b/miosix/_tools/testsuite/mpu_testsuite/test4/crt0.s new file mode 100644 index 0000000000000000000000000000000000000000..7733008e9392ded796006a94a0c1a527a94bfc1a --- /dev/null +++ b/miosix/_tools/testsuite/mpu_testsuite/test4/crt0.s @@ -0,0 +1,130 @@ +/* + * Startup script for writing PROGRAMS for the Miosix embedded OS + * TFT:Terraneo Federico Technlogies + */ + +.syntax unified +.cpu cortex-m3 +.thumb + +.section .text + +/** + * _start, program entry point + */ +.global _start +.type _start, %function +_start: + /* TODO: .ctor */ + bl main + /* TODO: .dtor */ + bl _exit + +/** + * _exit, terminate process + * \param v exit value + */ +.section .text._exit +.global _exit +.type _exit, %function +_exit: + movs r3, #2 + svc 0 + +/** + * open, open a file + * \param fd file descriptor + * \param file access mode + * \param xxx access permisions + * \return file descriptor or -1 if errors + */ +.section .text.open +.global open +.type open, %function +open: + movs r3, #6 + svc 0 + bx lr + +/** + * close, close a file + * \param fd file descriptor + */ +.section .text.close +.global close +.type close, %function +close: + movs r3, #7 + svc 0 + bx lr + +/** + * lseek + * \param fd file descriptor + * \param pos moving offset + * \param start position, SEEK_SET, SEEK_CUR or SEEK_END + +.section .text.lseek +.global lseek +.type lseek, %function + + movs r3, #8 + svc 0 + bx lr +*/ + +/** + * system, fork and execture a program, blocking + * \param program to execute + */ +.section .text.system +.global system +.type system, %function +system: + movs r3, #9 + svc 0 + bx lr +/** + * write, write to file + * \param fd file descriptor + * \param buf data to be written + * \param len buffer length + * \return number of written bytes or -1 if errors + */ +.section .text.write +.global write +.type write, %function +write: + movs r3, #3 + svc 0 + bx lr + +/** + * read, read from file + * \param fd file descriptor + * \param buf data to be read + * \param len buffer length + * \return number of read bytes or -1 if errors + */ +.section .text.read +.global read +.type read, %function +read: + movs r3, #4 + svc 0 + bx lr + +/** + * usleep, sleep a specified number of microseconds + * \param us number of microseconds to sleep + * \return 0 on success or -1 if errors + */ +.section .text.usleep +.global usleep +.type usleep, %function +usleep: + movs r3, #5 + svc 0 + bx lr + +.end diff --git a/miosix/_tools/testsuite/mpu_testsuite/test4/main.c b/miosix/_tools/testsuite/mpu_testsuite/test4/main.c new file mode 100644 index 0000000000000000000000000000000000000000..81c73f92bde85b6f864dfc214ad1eafb33b576ad --- /dev/null +++ b/miosix/_tools/testsuite/mpu_testsuite/test4/main.c @@ -0,0 +1,16 @@ +#include <unistd.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <string.h> +#include <stdio.h> + +int main() +{ + // The process tries to allocate an array of size greater than + // the available memory and writes to it; + volatile unsigned char array[16 * 1024 + 1]; + array[0] = 0; + return 0; +} diff --git a/miosix/_tools/testsuite/mpu_testsuite/test4/miosix.ld b/miosix/_tools/testsuite/mpu_testsuite/test4/miosix.ld new file mode 100644 index 0000000000000000000000000000000000000000..c91c803e629040b14233a8f8251a7d9952f68910 --- /dev/null +++ b/miosix/_tools/testsuite/mpu_testsuite/test4/miosix.ld @@ -0,0 +1,66 @@ +/* + * Linker script for writing PROGRAMS for the Miosix embedded OS + * TFT:Terraneo Federico Technlogies + */ + +OUTPUT_FORMAT("elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) + +SECTIONS +{ + /* Here starts the first elf segment, that stays in flash */ + . = 0 + SIZEOF_HEADERS; + + .text : ALIGN(8) + { + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + } + + .rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) } + .rel.got : { *(.rel.got) } + + /* Here starts the second segment, that is copied in RAM and relocated */ + . = 0x10000000; + + .got : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) } + + /* FIXME: If this is put in the other segment, it makes it writable */ + .dynamic : { *(.dynamic) } + + /* FIXME: The compiler insists in addressing rodata relative to r9 */ + .rodata : ALIGN(8) + { + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + } + + .data : ALIGN(8) + { + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + } + + .bss : ALIGN(8) + { + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + } + + /* These are removed since are unused and increase binary size */ + /DISCARD/ : + { + *(.interp) + *(.dynsym) + *(.dynstr) + *(.hash) + *(.comment) + *(.ARM.attributes) + } +} diff --git a/miosix/_tools/testsuite/mpu_testsuite/test5/Makefile b/miosix/_tools/testsuite/mpu_testsuite/test5/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..1523e24bde2cb6937bcc985c1c45062d4987cbdc --- /dev/null +++ b/miosix/_tools/testsuite/mpu_testsuite/test5/Makefile @@ -0,0 +1,48 @@ +## +## Makefile for writing PROGRAMS for the Miosix embedded OS +## TFT:Terraneo Federico Technlogies +## + +SRC := \ +main.c + +## Replaces both "foo.cpp"-->"foo.o" and "foo.c"-->"foo.o" +OBJ := $(addsuffix .o, $(basename $(SRC))) + +AS := arm-miosix-eabi-as +CC := arm-miosix-eabi-gcc +CXX := arm-miosix-eabi-g++ +SZ := arm-miosix-eabi-size + +AFLAGS := -mcpu=cortex-m3 -mthumb +CFLAGS := -mcpu=cortex-m3 -mthumb -mfix-cortex-m3-ldrd -fpie -msingle-pic-base \ + -ffunction-sections -O2 -Wall -c +CXXFLAGS := $(CFLAGS) +LFLAGS := -mcpu=cortex-m3 -mthumb -mfix-cortex-m3-ldrd -fpie -msingle-pic-base \ + -Wl,--gc-sections,-Map,test.map,-T./miosix.ld,-n,-pie,--spare-dynamic-tags,3 \ + -O2 -nostdlib +DFLAGS := -MMD -MP + +LINK_LIBS := -Wl,--start-group -lstdc++ -lc -lm -lgcc -Wl,--end-group + +all: $(OBJ) crt0.o + $(CXX) $(LFLAGS) -o test.elf $(OBJ) crt0.o $(LINK_LIBS) + $(SZ) test.elf + @arm-miosix-eabi-objdump -Dslx test.elf > test.txt + @mx-postlinker test.elf --ramsize=16384 --stacksize=2048 --strip-sectheader + @xxd -i test.elf | sed 's/unsigned char/const unsigned char __attribute__((aligned(8)))/' > mpuTest.h + +clean: + -rm $(OBJ) crt0.o test.elf test.map test.txt mpuTest.h $(OBJ:.o=.d) + +%.o: %.s + $(AS) $(AFLAGS) $< -o $@ + +%.o : %.c + $(CC) $(DFLAGS) $(CFLAGS) $< -o $@ + +%.o : %.cpp + $(CXX) $(DFLAGS) $(CXXFLAGS) $< -o $@ + +#pull in dependecy info for existing .o files +-include $(OBJ:.o=.d) diff --git a/miosix/_tools/testsuite/mpu_testsuite/test5/crt0.s b/miosix/_tools/testsuite/mpu_testsuite/test5/crt0.s new file mode 100644 index 0000000000000000000000000000000000000000..7733008e9392ded796006a94a0c1a527a94bfc1a --- /dev/null +++ b/miosix/_tools/testsuite/mpu_testsuite/test5/crt0.s @@ -0,0 +1,130 @@ +/* + * Startup script for writing PROGRAMS for the Miosix embedded OS + * TFT:Terraneo Federico Technlogies + */ + +.syntax unified +.cpu cortex-m3 +.thumb + +.section .text + +/** + * _start, program entry point + */ +.global _start +.type _start, %function +_start: + /* TODO: .ctor */ + bl main + /* TODO: .dtor */ + bl _exit + +/** + * _exit, terminate process + * \param v exit value + */ +.section .text._exit +.global _exit +.type _exit, %function +_exit: + movs r3, #2 + svc 0 + +/** + * open, open a file + * \param fd file descriptor + * \param file access mode + * \param xxx access permisions + * \return file descriptor or -1 if errors + */ +.section .text.open +.global open +.type open, %function +open: + movs r3, #6 + svc 0 + bx lr + +/** + * close, close a file + * \param fd file descriptor + */ +.section .text.close +.global close +.type close, %function +close: + movs r3, #7 + svc 0 + bx lr + +/** + * lseek + * \param fd file descriptor + * \param pos moving offset + * \param start position, SEEK_SET, SEEK_CUR or SEEK_END + +.section .text.lseek +.global lseek +.type lseek, %function + + movs r3, #8 + svc 0 + bx lr +*/ + +/** + * system, fork and execture a program, blocking + * \param program to execute + */ +.section .text.system +.global system +.type system, %function +system: + movs r3, #9 + svc 0 + bx lr +/** + * write, write to file + * \param fd file descriptor + * \param buf data to be written + * \param len buffer length + * \return number of written bytes or -1 if errors + */ +.section .text.write +.global write +.type write, %function +write: + movs r3, #3 + svc 0 + bx lr + +/** + * read, read from file + * \param fd file descriptor + * \param buf data to be read + * \param len buffer length + * \return number of read bytes or -1 if errors + */ +.section .text.read +.global read +.type read, %function +read: + movs r3, #4 + svc 0 + bx lr + +/** + * usleep, sleep a specified number of microseconds + * \param us number of microseconds to sleep + * \return 0 on success or -1 if errors + */ +.section .text.usleep +.global usleep +.type usleep, %function +usleep: + movs r3, #5 + svc 0 + bx lr + +.end diff --git a/miosix/_tools/testsuite/mpu_testsuite/test5/main.c b/miosix/_tools/testsuite/mpu_testsuite/test5/main.c new file mode 100644 index 0000000000000000000000000000000000000000..3ab4d4fc453ef71904c9be6d033e65f792582990 --- /dev/null +++ b/miosix/_tools/testsuite/mpu_testsuite/test5/main.c @@ -0,0 +1,16 @@ +#include <unistd.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <string.h> +#include <stdio.h> + +int main() +{ + // 'address' points to a memory location inside the code + // segment of the program. The program tries to write the location. + volatile unsigned int *address = 0x64101000; + *address = 0xbbbbbbbb; + return 0; +} diff --git a/miosix/_tools/testsuite/mpu_testsuite/test5/miosix.ld b/miosix/_tools/testsuite/mpu_testsuite/test5/miosix.ld new file mode 100644 index 0000000000000000000000000000000000000000..c91c803e629040b14233a8f8251a7d9952f68910 --- /dev/null +++ b/miosix/_tools/testsuite/mpu_testsuite/test5/miosix.ld @@ -0,0 +1,66 @@ +/* + * Linker script for writing PROGRAMS for the Miosix embedded OS + * TFT:Terraneo Federico Technlogies + */ + +OUTPUT_FORMAT("elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) + +SECTIONS +{ + /* Here starts the first elf segment, that stays in flash */ + . = 0 + SIZEOF_HEADERS; + + .text : ALIGN(8) + { + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + } + + .rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) } + .rel.got : { *(.rel.got) } + + /* Here starts the second segment, that is copied in RAM and relocated */ + . = 0x10000000; + + .got : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) } + + /* FIXME: If this is put in the other segment, it makes it writable */ + .dynamic : { *(.dynamic) } + + /* FIXME: The compiler insists in addressing rodata relative to r9 */ + .rodata : ALIGN(8) + { + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + } + + .data : ALIGN(8) + { + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + } + + .bss : ALIGN(8) + { + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + } + + /* These are removed since are unused and increase binary size */ + /DISCARD/ : + { + *(.interp) + *(.dynsym) + *(.dynstr) + *(.hash) + *(.comment) + *(.ARM.attributes) + } +} diff --git a/miosix/_tools/testsuite/mpu_testsuite/test6/Makefile b/miosix/_tools/testsuite/mpu_testsuite/test6/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..1523e24bde2cb6937bcc985c1c45062d4987cbdc --- /dev/null +++ b/miosix/_tools/testsuite/mpu_testsuite/test6/Makefile @@ -0,0 +1,48 @@ +## +## Makefile for writing PROGRAMS for the Miosix embedded OS +## TFT:Terraneo Federico Technlogies +## + +SRC := \ +main.c + +## Replaces both "foo.cpp"-->"foo.o" and "foo.c"-->"foo.o" +OBJ := $(addsuffix .o, $(basename $(SRC))) + +AS := arm-miosix-eabi-as +CC := arm-miosix-eabi-gcc +CXX := arm-miosix-eabi-g++ +SZ := arm-miosix-eabi-size + +AFLAGS := -mcpu=cortex-m3 -mthumb +CFLAGS := -mcpu=cortex-m3 -mthumb -mfix-cortex-m3-ldrd -fpie -msingle-pic-base \ + -ffunction-sections -O2 -Wall -c +CXXFLAGS := $(CFLAGS) +LFLAGS := -mcpu=cortex-m3 -mthumb -mfix-cortex-m3-ldrd -fpie -msingle-pic-base \ + -Wl,--gc-sections,-Map,test.map,-T./miosix.ld,-n,-pie,--spare-dynamic-tags,3 \ + -O2 -nostdlib +DFLAGS := -MMD -MP + +LINK_LIBS := -Wl,--start-group -lstdc++ -lc -lm -lgcc -Wl,--end-group + +all: $(OBJ) crt0.o + $(CXX) $(LFLAGS) -o test.elf $(OBJ) crt0.o $(LINK_LIBS) + $(SZ) test.elf + @arm-miosix-eabi-objdump -Dslx test.elf > test.txt + @mx-postlinker test.elf --ramsize=16384 --stacksize=2048 --strip-sectheader + @xxd -i test.elf | sed 's/unsigned char/const unsigned char __attribute__((aligned(8)))/' > mpuTest.h + +clean: + -rm $(OBJ) crt0.o test.elf test.map test.txt mpuTest.h $(OBJ:.o=.d) + +%.o: %.s + $(AS) $(AFLAGS) $< -o $@ + +%.o : %.c + $(CC) $(DFLAGS) $(CFLAGS) $< -o $@ + +%.o : %.cpp + $(CXX) $(DFLAGS) $(CXXFLAGS) $< -o $@ + +#pull in dependecy info for existing .o files +-include $(OBJ:.o=.d) diff --git a/miosix/_tools/testsuite/mpu_testsuite/test6/crt0.s b/miosix/_tools/testsuite/mpu_testsuite/test6/crt0.s new file mode 100644 index 0000000000000000000000000000000000000000..7733008e9392ded796006a94a0c1a527a94bfc1a --- /dev/null +++ b/miosix/_tools/testsuite/mpu_testsuite/test6/crt0.s @@ -0,0 +1,130 @@ +/* + * Startup script for writing PROGRAMS for the Miosix embedded OS + * TFT:Terraneo Federico Technlogies + */ + +.syntax unified +.cpu cortex-m3 +.thumb + +.section .text + +/** + * _start, program entry point + */ +.global _start +.type _start, %function +_start: + /* TODO: .ctor */ + bl main + /* TODO: .dtor */ + bl _exit + +/** + * _exit, terminate process + * \param v exit value + */ +.section .text._exit +.global _exit +.type _exit, %function +_exit: + movs r3, #2 + svc 0 + +/** + * open, open a file + * \param fd file descriptor + * \param file access mode + * \param xxx access permisions + * \return file descriptor or -1 if errors + */ +.section .text.open +.global open +.type open, %function +open: + movs r3, #6 + svc 0 + bx lr + +/** + * close, close a file + * \param fd file descriptor + */ +.section .text.close +.global close +.type close, %function +close: + movs r3, #7 + svc 0 + bx lr + +/** + * lseek + * \param fd file descriptor + * \param pos moving offset + * \param start position, SEEK_SET, SEEK_CUR or SEEK_END + +.section .text.lseek +.global lseek +.type lseek, %function + + movs r3, #8 + svc 0 + bx lr +*/ + +/** + * system, fork and execture a program, blocking + * \param program to execute + */ +.section .text.system +.global system +.type system, %function +system: + movs r3, #9 + svc 0 + bx lr +/** + * write, write to file + * \param fd file descriptor + * \param buf data to be written + * \param len buffer length + * \return number of written bytes or -1 if errors + */ +.section .text.write +.global write +.type write, %function +write: + movs r3, #3 + svc 0 + bx lr + +/** + * read, read from file + * \param fd file descriptor + * \param buf data to be read + * \param len buffer length + * \return number of read bytes or -1 if errors + */ +.section .text.read +.global read +.type read, %function +read: + movs r3, #4 + svc 0 + bx lr + +/** + * usleep, sleep a specified number of microseconds + * \param us number of microseconds to sleep + * \return 0 on success or -1 if errors + */ +.section .text.usleep +.global usleep +.type usleep, %function +usleep: + movs r3, #5 + svc 0 + bx lr + +.end diff --git a/miosix/_tools/testsuite/mpu_testsuite/test6/main.c b/miosix/_tools/testsuite/mpu_testsuite/test6/main.c new file mode 100644 index 0000000000000000000000000000000000000000..ed0796b8b92e45c11cb50b74233e482f6f787cc4 --- /dev/null +++ b/miosix/_tools/testsuite/mpu_testsuite/test6/main.c @@ -0,0 +1,16 @@ +#include <unistd.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <string.h> +#include <stdio.h> + +int main() +{ + // 'address' points to a memory location between the + // code segment and the data segment. + volatile unsigned int *address = 0x64101404; + *address = 0xbbbbbbbb; + return 0; +} diff --git a/miosix/_tools/testsuite/mpu_testsuite/test6/miosix.ld b/miosix/_tools/testsuite/mpu_testsuite/test6/miosix.ld new file mode 100644 index 0000000000000000000000000000000000000000..c91c803e629040b14233a8f8251a7d9952f68910 --- /dev/null +++ b/miosix/_tools/testsuite/mpu_testsuite/test6/miosix.ld @@ -0,0 +1,66 @@ +/* + * Linker script for writing PROGRAMS for the Miosix embedded OS + * TFT:Terraneo Federico Technlogies + */ + +OUTPUT_FORMAT("elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) + +SECTIONS +{ + /* Here starts the first elf segment, that stays in flash */ + . = 0 + SIZEOF_HEADERS; + + .text : ALIGN(8) + { + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + } + + .rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) } + .rel.got : { *(.rel.got) } + + /* Here starts the second segment, that is copied in RAM and relocated */ + . = 0x10000000; + + .got : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) } + + /* FIXME: If this is put in the other segment, it makes it writable */ + .dynamic : { *(.dynamic) } + + /* FIXME: The compiler insists in addressing rodata relative to r9 */ + .rodata : ALIGN(8) + { + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + } + + .data : ALIGN(8) + { + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + } + + .bss : ALIGN(8) + { + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + } + + /* These are removed since are unused and increase binary size */ + /DISCARD/ : + { + *(.interp) + *(.dynsym) + *(.dynstr) + *(.hash) + *(.comment) + *(.ARM.attributes) + } +} diff --git a/miosix/_tools/testsuite/mpu_testsuite/test7/Makefile b/miosix/_tools/testsuite/mpu_testsuite/test7/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..1523e24bde2cb6937bcc985c1c45062d4987cbdc --- /dev/null +++ b/miosix/_tools/testsuite/mpu_testsuite/test7/Makefile @@ -0,0 +1,48 @@ +## +## Makefile for writing PROGRAMS for the Miosix embedded OS +## TFT:Terraneo Federico Technlogies +## + +SRC := \ +main.c + +## Replaces both "foo.cpp"-->"foo.o" and "foo.c"-->"foo.o" +OBJ := $(addsuffix .o, $(basename $(SRC))) + +AS := arm-miosix-eabi-as +CC := arm-miosix-eabi-gcc +CXX := arm-miosix-eabi-g++ +SZ := arm-miosix-eabi-size + +AFLAGS := -mcpu=cortex-m3 -mthumb +CFLAGS := -mcpu=cortex-m3 -mthumb -mfix-cortex-m3-ldrd -fpie -msingle-pic-base \ + -ffunction-sections -O2 -Wall -c +CXXFLAGS := $(CFLAGS) +LFLAGS := -mcpu=cortex-m3 -mthumb -mfix-cortex-m3-ldrd -fpie -msingle-pic-base \ + -Wl,--gc-sections,-Map,test.map,-T./miosix.ld,-n,-pie,--spare-dynamic-tags,3 \ + -O2 -nostdlib +DFLAGS := -MMD -MP + +LINK_LIBS := -Wl,--start-group -lstdc++ -lc -lm -lgcc -Wl,--end-group + +all: $(OBJ) crt0.o + $(CXX) $(LFLAGS) -o test.elf $(OBJ) crt0.o $(LINK_LIBS) + $(SZ) test.elf + @arm-miosix-eabi-objdump -Dslx test.elf > test.txt + @mx-postlinker test.elf --ramsize=16384 --stacksize=2048 --strip-sectheader + @xxd -i test.elf | sed 's/unsigned char/const unsigned char __attribute__((aligned(8)))/' > mpuTest.h + +clean: + -rm $(OBJ) crt0.o test.elf test.map test.txt mpuTest.h $(OBJ:.o=.d) + +%.o: %.s + $(AS) $(AFLAGS) $< -o $@ + +%.o : %.c + $(CC) $(DFLAGS) $(CFLAGS) $< -o $@ + +%.o : %.cpp + $(CXX) $(DFLAGS) $(CXXFLAGS) $< -o $@ + +#pull in dependecy info for existing .o files +-include $(OBJ:.o=.d) diff --git a/miosix/_tools/testsuite/mpu_testsuite/test7/crt0.s b/miosix/_tools/testsuite/mpu_testsuite/test7/crt0.s new file mode 100644 index 0000000000000000000000000000000000000000..7733008e9392ded796006a94a0c1a527a94bfc1a --- /dev/null +++ b/miosix/_tools/testsuite/mpu_testsuite/test7/crt0.s @@ -0,0 +1,130 @@ +/* + * Startup script for writing PROGRAMS for the Miosix embedded OS + * TFT:Terraneo Federico Technlogies + */ + +.syntax unified +.cpu cortex-m3 +.thumb + +.section .text + +/** + * _start, program entry point + */ +.global _start +.type _start, %function +_start: + /* TODO: .ctor */ + bl main + /* TODO: .dtor */ + bl _exit + +/** + * _exit, terminate process + * \param v exit value + */ +.section .text._exit +.global _exit +.type _exit, %function +_exit: + movs r3, #2 + svc 0 + +/** + * open, open a file + * \param fd file descriptor + * \param file access mode + * \param xxx access permisions + * \return file descriptor or -1 if errors + */ +.section .text.open +.global open +.type open, %function +open: + movs r3, #6 + svc 0 + bx lr + +/** + * close, close a file + * \param fd file descriptor + */ +.section .text.close +.global close +.type close, %function +close: + movs r3, #7 + svc 0 + bx lr + +/** + * lseek + * \param fd file descriptor + * \param pos moving offset + * \param start position, SEEK_SET, SEEK_CUR or SEEK_END + +.section .text.lseek +.global lseek +.type lseek, %function + + movs r3, #8 + svc 0 + bx lr +*/ + +/** + * system, fork and execture a program, blocking + * \param program to execute + */ +.section .text.system +.global system +.type system, %function +system: + movs r3, #9 + svc 0 + bx lr +/** + * write, write to file + * \param fd file descriptor + * \param buf data to be written + * \param len buffer length + * \return number of written bytes or -1 if errors + */ +.section .text.write +.global write +.type write, %function +write: + movs r3, #3 + svc 0 + bx lr + +/** + * read, read from file + * \param fd file descriptor + * \param buf data to be read + * \param len buffer length + * \return number of read bytes or -1 if errors + */ +.section .text.read +.global read +.type read, %function +read: + movs r3, #4 + svc 0 + bx lr + +/** + * usleep, sleep a specified number of microseconds + * \param us number of microseconds to sleep + * \return 0 on success or -1 if errors + */ +.section .text.usleep +.global usleep +.type usleep, %function +usleep: + movs r3, #5 + svc 0 + bx lr + +.end diff --git a/miosix/_tools/testsuite/mpu_testsuite/test7/includes.h b/miosix/_tools/testsuite/mpu_testsuite/test7/includes.h new file mode 100644 index 0000000000000000000000000000000000000000..15f9f03434f0e0839fd2fa1b8d47f9152dcdcc62 --- /dev/null +++ b/miosix/_tools/testsuite/mpu_testsuite/test7/includes.h @@ -0,0 +1,2 @@ +#include "mpu_testsuite/mpu_apps/test7.h" +#endif //_APP_MPU_TESTS_1_ diff --git a/miosix/_tools/testsuite/mpu_testsuite/test7/main.c b/miosix/_tools/testsuite/mpu_testsuite/test7/main.c new file mode 100644 index 0000000000000000000000000000000000000000..7f691459bc86affe5c6c061d2d0d941f89e0def9 --- /dev/null +++ b/miosix/_tools/testsuite/mpu_testsuite/test7/main.c @@ -0,0 +1,18 @@ +#include <unistd.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <string.h> +#include <stdio.h> + +int main() +{ + // The process tries to fill almost all the stack with an array + // and then tries to save the context by calling a syscall. + // With an array of 16344 bytes, there is no fault. + volatile unsigned char array[16345]; + array[0]=1; + usleep(2000000); + return 0; +} diff --git a/miosix/_tools/testsuite/mpu_testsuite/test7/miosix.ld b/miosix/_tools/testsuite/mpu_testsuite/test7/miosix.ld new file mode 100644 index 0000000000000000000000000000000000000000..c91c803e629040b14233a8f8251a7d9952f68910 --- /dev/null +++ b/miosix/_tools/testsuite/mpu_testsuite/test7/miosix.ld @@ -0,0 +1,66 @@ +/* + * Linker script for writing PROGRAMS for the Miosix embedded OS + * TFT:Terraneo Federico Technlogies + */ + +OUTPUT_FORMAT("elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) + +SECTIONS +{ + /* Here starts the first elf segment, that stays in flash */ + . = 0 + SIZEOF_HEADERS; + + .text : ALIGN(8) + { + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + } + + .rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) } + .rel.got : { *(.rel.got) } + + /* Here starts the second segment, that is copied in RAM and relocated */ + . = 0x10000000; + + .got : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) } + + /* FIXME: If this is put in the other segment, it makes it writable */ + .dynamic : { *(.dynamic) } + + /* FIXME: The compiler insists in addressing rodata relative to r9 */ + .rodata : ALIGN(8) + { + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + } + + .data : ALIGN(8) + { + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + } + + .bss : ALIGN(8) + { + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + } + + /* These are removed since are unused and increase binary size */ + /DISCARD/ : + { + *(.interp) + *(.dynsym) + *(.dynstr) + *(.hash) + *(.comment) + *(.ARM.attributes) + } +} diff --git a/miosix/_tools/testsuite/mpu_testsuite/test8_1/Makefile b/miosix/_tools/testsuite/mpu_testsuite/test8_1/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..1523e24bde2cb6937bcc985c1c45062d4987cbdc --- /dev/null +++ b/miosix/_tools/testsuite/mpu_testsuite/test8_1/Makefile @@ -0,0 +1,48 @@ +## +## Makefile for writing PROGRAMS for the Miosix embedded OS +## TFT:Terraneo Federico Technlogies +## + +SRC := \ +main.c + +## Replaces both "foo.cpp"-->"foo.o" and "foo.c"-->"foo.o" +OBJ := $(addsuffix .o, $(basename $(SRC))) + +AS := arm-miosix-eabi-as +CC := arm-miosix-eabi-gcc +CXX := arm-miosix-eabi-g++ +SZ := arm-miosix-eabi-size + +AFLAGS := -mcpu=cortex-m3 -mthumb +CFLAGS := -mcpu=cortex-m3 -mthumb -mfix-cortex-m3-ldrd -fpie -msingle-pic-base \ + -ffunction-sections -O2 -Wall -c +CXXFLAGS := $(CFLAGS) +LFLAGS := -mcpu=cortex-m3 -mthumb -mfix-cortex-m3-ldrd -fpie -msingle-pic-base \ + -Wl,--gc-sections,-Map,test.map,-T./miosix.ld,-n,-pie,--spare-dynamic-tags,3 \ + -O2 -nostdlib +DFLAGS := -MMD -MP + +LINK_LIBS := -Wl,--start-group -lstdc++ -lc -lm -lgcc -Wl,--end-group + +all: $(OBJ) crt0.o + $(CXX) $(LFLAGS) -o test.elf $(OBJ) crt0.o $(LINK_LIBS) + $(SZ) test.elf + @arm-miosix-eabi-objdump -Dslx test.elf > test.txt + @mx-postlinker test.elf --ramsize=16384 --stacksize=2048 --strip-sectheader + @xxd -i test.elf | sed 's/unsigned char/const unsigned char __attribute__((aligned(8)))/' > mpuTest.h + +clean: + -rm $(OBJ) crt0.o test.elf test.map test.txt mpuTest.h $(OBJ:.o=.d) + +%.o: %.s + $(AS) $(AFLAGS) $< -o $@ + +%.o : %.c + $(CC) $(DFLAGS) $(CFLAGS) $< -o $@ + +%.o : %.cpp + $(CXX) $(DFLAGS) $(CXXFLAGS) $< -o $@ + +#pull in dependecy info for existing .o files +-include $(OBJ:.o=.d) diff --git a/miosix/_tools/testsuite/mpu_testsuite/test8_1/crt0.s b/miosix/_tools/testsuite/mpu_testsuite/test8_1/crt0.s new file mode 100644 index 0000000000000000000000000000000000000000..7733008e9392ded796006a94a0c1a527a94bfc1a --- /dev/null +++ b/miosix/_tools/testsuite/mpu_testsuite/test8_1/crt0.s @@ -0,0 +1,130 @@ +/* + * Startup script for writing PROGRAMS for the Miosix embedded OS + * TFT:Terraneo Federico Technlogies + */ + +.syntax unified +.cpu cortex-m3 +.thumb + +.section .text + +/** + * _start, program entry point + */ +.global _start +.type _start, %function +_start: + /* TODO: .ctor */ + bl main + /* TODO: .dtor */ + bl _exit + +/** + * _exit, terminate process + * \param v exit value + */ +.section .text._exit +.global _exit +.type _exit, %function +_exit: + movs r3, #2 + svc 0 + +/** + * open, open a file + * \param fd file descriptor + * \param file access mode + * \param xxx access permisions + * \return file descriptor or -1 if errors + */ +.section .text.open +.global open +.type open, %function +open: + movs r3, #6 + svc 0 + bx lr + +/** + * close, close a file + * \param fd file descriptor + */ +.section .text.close +.global close +.type close, %function +close: + movs r3, #7 + svc 0 + bx lr + +/** + * lseek + * \param fd file descriptor + * \param pos moving offset + * \param start position, SEEK_SET, SEEK_CUR or SEEK_END + +.section .text.lseek +.global lseek +.type lseek, %function + + movs r3, #8 + svc 0 + bx lr +*/ + +/** + * system, fork and execture a program, blocking + * \param program to execute + */ +.section .text.system +.global system +.type system, %function +system: + movs r3, #9 + svc 0 + bx lr +/** + * write, write to file + * \param fd file descriptor + * \param buf data to be written + * \param len buffer length + * \return number of written bytes or -1 if errors + */ +.section .text.write +.global write +.type write, %function +write: + movs r3, #3 + svc 0 + bx lr + +/** + * read, read from file + * \param fd file descriptor + * \param buf data to be read + * \param len buffer length + * \return number of read bytes or -1 if errors + */ +.section .text.read +.global read +.type read, %function +read: + movs r3, #4 + svc 0 + bx lr + +/** + * usleep, sleep a specified number of microseconds + * \param us number of microseconds to sleep + * \return 0 on success or -1 if errors + */ +.section .text.usleep +.global usleep +.type usleep, %function +usleep: + movs r3, #5 + svc 0 + bx lr + +.end diff --git a/miosix/_tools/testsuite/mpu_testsuite/test8_1/includes.h b/miosix/_tools/testsuite/mpu_testsuite/test8_1/includes.h new file mode 100644 index 0000000000000000000000000000000000000000..d9e2fa61fea7aa8d1687bc591fc4c7b74258d600 --- /dev/null +++ b/miosix/_tools/testsuite/mpu_testsuite/test8_1/includes.h @@ -0,0 +1,2 @@ +#include "mpu_testsuite/mpu_apps/test8_1.h" +#endif //_APP_MPU_TESTS_1_ diff --git a/miosix/_tools/testsuite/mpu_testsuite/test8_1/main.c b/miosix/_tools/testsuite/mpu_testsuite/test8_1/main.c new file mode 100644 index 0000000000000000000000000000000000000000..6ad36ce84a30eb1766f5ef37ddf030d746144f68 --- /dev/null +++ b/miosix/_tools/testsuite/mpu_testsuite/test8_1/main.c @@ -0,0 +1,15 @@ +#include <unistd.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <string.h> +#include <stdio.h> + +int main() +{ + // This process goes to sleep for 2 seconds, while the second + // process tries to access the data region of this process. + usleep(2000000); + return 0; +} diff --git a/miosix/_tools/testsuite/mpu_testsuite/test8_1/miosix.ld b/miosix/_tools/testsuite/mpu_testsuite/test8_1/miosix.ld new file mode 100644 index 0000000000000000000000000000000000000000..c91c803e629040b14233a8f8251a7d9952f68910 --- /dev/null +++ b/miosix/_tools/testsuite/mpu_testsuite/test8_1/miosix.ld @@ -0,0 +1,66 @@ +/* + * Linker script for writing PROGRAMS for the Miosix embedded OS + * TFT:Terraneo Federico Technlogies + */ + +OUTPUT_FORMAT("elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) + +SECTIONS +{ + /* Here starts the first elf segment, that stays in flash */ + . = 0 + SIZEOF_HEADERS; + + .text : ALIGN(8) + { + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + } + + .rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) } + .rel.got : { *(.rel.got) } + + /* Here starts the second segment, that is copied in RAM and relocated */ + . = 0x10000000; + + .got : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) } + + /* FIXME: If this is put in the other segment, it makes it writable */ + .dynamic : { *(.dynamic) } + + /* FIXME: The compiler insists in addressing rodata relative to r9 */ + .rodata : ALIGN(8) + { + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + } + + .data : ALIGN(8) + { + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + } + + .bss : ALIGN(8) + { + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + } + + /* These are removed since are unused and increase binary size */ + /DISCARD/ : + { + *(.interp) + *(.dynsym) + *(.dynstr) + *(.hash) + *(.comment) + *(.ARM.attributes) + } +} diff --git a/miosix/_tools/testsuite/mpu_testsuite/test8_2/Makefile b/miosix/_tools/testsuite/mpu_testsuite/test8_2/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..1523e24bde2cb6937bcc985c1c45062d4987cbdc --- /dev/null +++ b/miosix/_tools/testsuite/mpu_testsuite/test8_2/Makefile @@ -0,0 +1,48 @@ +## +## Makefile for writing PROGRAMS for the Miosix embedded OS +## TFT:Terraneo Federico Technlogies +## + +SRC := \ +main.c + +## Replaces both "foo.cpp"-->"foo.o" and "foo.c"-->"foo.o" +OBJ := $(addsuffix .o, $(basename $(SRC))) + +AS := arm-miosix-eabi-as +CC := arm-miosix-eabi-gcc +CXX := arm-miosix-eabi-g++ +SZ := arm-miosix-eabi-size + +AFLAGS := -mcpu=cortex-m3 -mthumb +CFLAGS := -mcpu=cortex-m3 -mthumb -mfix-cortex-m3-ldrd -fpie -msingle-pic-base \ + -ffunction-sections -O2 -Wall -c +CXXFLAGS := $(CFLAGS) +LFLAGS := -mcpu=cortex-m3 -mthumb -mfix-cortex-m3-ldrd -fpie -msingle-pic-base \ + -Wl,--gc-sections,-Map,test.map,-T./miosix.ld,-n,-pie,--spare-dynamic-tags,3 \ + -O2 -nostdlib +DFLAGS := -MMD -MP + +LINK_LIBS := -Wl,--start-group -lstdc++ -lc -lm -lgcc -Wl,--end-group + +all: $(OBJ) crt0.o + $(CXX) $(LFLAGS) -o test.elf $(OBJ) crt0.o $(LINK_LIBS) + $(SZ) test.elf + @arm-miosix-eabi-objdump -Dslx test.elf > test.txt + @mx-postlinker test.elf --ramsize=16384 --stacksize=2048 --strip-sectheader + @xxd -i test.elf | sed 's/unsigned char/const unsigned char __attribute__((aligned(8)))/' > mpuTest.h + +clean: + -rm $(OBJ) crt0.o test.elf test.map test.txt mpuTest.h $(OBJ:.o=.d) + +%.o: %.s + $(AS) $(AFLAGS) $< -o $@ + +%.o : %.c + $(CC) $(DFLAGS) $(CFLAGS) $< -o $@ + +%.o : %.cpp + $(CXX) $(DFLAGS) $(CXXFLAGS) $< -o $@ + +#pull in dependecy info for existing .o files +-include $(OBJ:.o=.d) diff --git a/miosix/_tools/testsuite/mpu_testsuite/test8_2/crt0.s b/miosix/_tools/testsuite/mpu_testsuite/test8_2/crt0.s new file mode 100644 index 0000000000000000000000000000000000000000..7733008e9392ded796006a94a0c1a527a94bfc1a --- /dev/null +++ b/miosix/_tools/testsuite/mpu_testsuite/test8_2/crt0.s @@ -0,0 +1,130 @@ +/* + * Startup script for writing PROGRAMS for the Miosix embedded OS + * TFT:Terraneo Federico Technlogies + */ + +.syntax unified +.cpu cortex-m3 +.thumb + +.section .text + +/** + * _start, program entry point + */ +.global _start +.type _start, %function +_start: + /* TODO: .ctor */ + bl main + /* TODO: .dtor */ + bl _exit + +/** + * _exit, terminate process + * \param v exit value + */ +.section .text._exit +.global _exit +.type _exit, %function +_exit: + movs r3, #2 + svc 0 + +/** + * open, open a file + * \param fd file descriptor + * \param file access mode + * \param xxx access permisions + * \return file descriptor or -1 if errors + */ +.section .text.open +.global open +.type open, %function +open: + movs r3, #6 + svc 0 + bx lr + +/** + * close, close a file + * \param fd file descriptor + */ +.section .text.close +.global close +.type close, %function +close: + movs r3, #7 + svc 0 + bx lr + +/** + * lseek + * \param fd file descriptor + * \param pos moving offset + * \param start position, SEEK_SET, SEEK_CUR or SEEK_END + +.section .text.lseek +.global lseek +.type lseek, %function + + movs r3, #8 + svc 0 + bx lr +*/ + +/** + * system, fork and execture a program, blocking + * \param program to execute + */ +.section .text.system +.global system +.type system, %function +system: + movs r3, #9 + svc 0 + bx lr +/** + * write, write to file + * \param fd file descriptor + * \param buf data to be written + * \param len buffer length + * \return number of written bytes or -1 if errors + */ +.section .text.write +.global write +.type write, %function +write: + movs r3, #3 + svc 0 + bx lr + +/** + * read, read from file + * \param fd file descriptor + * \param buf data to be read + * \param len buffer length + * \return number of read bytes or -1 if errors + */ +.section .text.read +.global read +.type read, %function +read: + movs r3, #4 + svc 0 + bx lr + +/** + * usleep, sleep a specified number of microseconds + * \param us number of microseconds to sleep + * \return 0 on success or -1 if errors + */ +.section .text.usleep +.global usleep +.type usleep, %function +usleep: + movs r3, #5 + svc 0 + bx lr + +.end diff --git a/miosix/_tools/testsuite/mpu_testsuite/test8_2/main.c b/miosix/_tools/testsuite/mpu_testsuite/test8_2/main.c new file mode 100644 index 0000000000000000000000000000000000000000..b45aa841b01eb1fd3d646a7d1fd32e6e2f4e804d --- /dev/null +++ b/miosix/_tools/testsuite/mpu_testsuite/test8_2/main.c @@ -0,0 +1,16 @@ +#include <unistd.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <string.h> +#include <stdio.h> + +int main() +{ + // 'address' points to a memory location of the program 8.1. + // The program tries to write the location. + volatile int *address = 0x64104004; + *address = 0xbbbbbbbb; + return 0; +} diff --git a/miosix/_tools/testsuite/mpu_testsuite/test8_2/miosix.ld b/miosix/_tools/testsuite/mpu_testsuite/test8_2/miosix.ld new file mode 100644 index 0000000000000000000000000000000000000000..c91c803e629040b14233a8f8251a7d9952f68910 --- /dev/null +++ b/miosix/_tools/testsuite/mpu_testsuite/test8_2/miosix.ld @@ -0,0 +1,66 @@ +/* + * Linker script for writing PROGRAMS for the Miosix embedded OS + * TFT:Terraneo Federico Technlogies + */ + +OUTPUT_FORMAT("elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) + +SECTIONS +{ + /* Here starts the first elf segment, that stays in flash */ + . = 0 + SIZEOF_HEADERS; + + .text : ALIGN(8) + { + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + } + + .rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) } + .rel.got : { *(.rel.got) } + + /* Here starts the second segment, that is copied in RAM and relocated */ + . = 0x10000000; + + .got : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) } + + /* FIXME: If this is put in the other segment, it makes it writable */ + .dynamic : { *(.dynamic) } + + /* FIXME: The compiler insists in addressing rodata relative to r9 */ + .rodata : ALIGN(8) + { + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + } + + .data : ALIGN(8) + { + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + } + + .bss : ALIGN(8) + { + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + } + + /* These are removed since are unused and increase binary size */ + /DISCARD/ : + { + *(.interp) + *(.dynsym) + *(.dynstr) + *(.hash) + *(.comment) + *(.ARM.attributes) + } +} diff --git a/miosix/_tools/testsuite/mpu_testsuite/test9/Makefile b/miosix/_tools/testsuite/mpu_testsuite/test9/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..1523e24bde2cb6937bcc985c1c45062d4987cbdc --- /dev/null +++ b/miosix/_tools/testsuite/mpu_testsuite/test9/Makefile @@ -0,0 +1,48 @@ +## +## Makefile for writing PROGRAMS for the Miosix embedded OS +## TFT:Terraneo Federico Technlogies +## + +SRC := \ +main.c + +## Replaces both "foo.cpp"-->"foo.o" and "foo.c"-->"foo.o" +OBJ := $(addsuffix .o, $(basename $(SRC))) + +AS := arm-miosix-eabi-as +CC := arm-miosix-eabi-gcc +CXX := arm-miosix-eabi-g++ +SZ := arm-miosix-eabi-size + +AFLAGS := -mcpu=cortex-m3 -mthumb +CFLAGS := -mcpu=cortex-m3 -mthumb -mfix-cortex-m3-ldrd -fpie -msingle-pic-base \ + -ffunction-sections -O2 -Wall -c +CXXFLAGS := $(CFLAGS) +LFLAGS := -mcpu=cortex-m3 -mthumb -mfix-cortex-m3-ldrd -fpie -msingle-pic-base \ + -Wl,--gc-sections,-Map,test.map,-T./miosix.ld,-n,-pie,--spare-dynamic-tags,3 \ + -O2 -nostdlib +DFLAGS := -MMD -MP + +LINK_LIBS := -Wl,--start-group -lstdc++ -lc -lm -lgcc -Wl,--end-group + +all: $(OBJ) crt0.o + $(CXX) $(LFLAGS) -o test.elf $(OBJ) crt0.o $(LINK_LIBS) + $(SZ) test.elf + @arm-miosix-eabi-objdump -Dslx test.elf > test.txt + @mx-postlinker test.elf --ramsize=16384 --stacksize=2048 --strip-sectheader + @xxd -i test.elf | sed 's/unsigned char/const unsigned char __attribute__((aligned(8)))/' > mpuTest.h + +clean: + -rm $(OBJ) crt0.o test.elf test.map test.txt mpuTest.h $(OBJ:.o=.d) + +%.o: %.s + $(AS) $(AFLAGS) $< -o $@ + +%.o : %.c + $(CC) $(DFLAGS) $(CFLAGS) $< -o $@ + +%.o : %.cpp + $(CXX) $(DFLAGS) $(CXXFLAGS) $< -o $@ + +#pull in dependecy info for existing .o files +-include $(OBJ:.o=.d) diff --git a/miosix/_tools/testsuite/mpu_testsuite/test9/crt0.s b/miosix/_tools/testsuite/mpu_testsuite/test9/crt0.s new file mode 100644 index 0000000000000000000000000000000000000000..7733008e9392ded796006a94a0c1a527a94bfc1a --- /dev/null +++ b/miosix/_tools/testsuite/mpu_testsuite/test9/crt0.s @@ -0,0 +1,130 @@ +/* + * Startup script for writing PROGRAMS for the Miosix embedded OS + * TFT:Terraneo Federico Technlogies + */ + +.syntax unified +.cpu cortex-m3 +.thumb + +.section .text + +/** + * _start, program entry point + */ +.global _start +.type _start, %function +_start: + /* TODO: .ctor */ + bl main + /* TODO: .dtor */ + bl _exit + +/** + * _exit, terminate process + * \param v exit value + */ +.section .text._exit +.global _exit +.type _exit, %function +_exit: + movs r3, #2 + svc 0 + +/** + * open, open a file + * \param fd file descriptor + * \param file access mode + * \param xxx access permisions + * \return file descriptor or -1 if errors + */ +.section .text.open +.global open +.type open, %function +open: + movs r3, #6 + svc 0 + bx lr + +/** + * close, close a file + * \param fd file descriptor + */ +.section .text.close +.global close +.type close, %function +close: + movs r3, #7 + svc 0 + bx lr + +/** + * lseek + * \param fd file descriptor + * \param pos moving offset + * \param start position, SEEK_SET, SEEK_CUR or SEEK_END + +.section .text.lseek +.global lseek +.type lseek, %function + + movs r3, #8 + svc 0 + bx lr +*/ + +/** + * system, fork and execture a program, blocking + * \param program to execute + */ +.section .text.system +.global system +.type system, %function +system: + movs r3, #9 + svc 0 + bx lr +/** + * write, write to file + * \param fd file descriptor + * \param buf data to be written + * \param len buffer length + * \return number of written bytes or -1 if errors + */ +.section .text.write +.global write +.type write, %function +write: + movs r3, #3 + svc 0 + bx lr + +/** + * read, read from file + * \param fd file descriptor + * \param buf data to be read + * \param len buffer length + * \return number of read bytes or -1 if errors + */ +.section .text.read +.global read +.type read, %function +read: + movs r3, #4 + svc 0 + bx lr + +/** + * usleep, sleep a specified number of microseconds + * \param us number of microseconds to sleep + * \return 0 on success or -1 if errors + */ +.section .text.usleep +.global usleep +.type usleep, %function +usleep: + movs r3, #5 + svc 0 + bx lr + +.end diff --git a/miosix/_tools/testsuite/mpu_testsuite/test9/main.c b/miosix/_tools/testsuite/mpu_testsuite/test9/main.c new file mode 100644 index 0000000000000000000000000000000000000000..c062c0b7a5df820dbf7e601cfcf722be9203afde --- /dev/null +++ b/miosix/_tools/testsuite/mpu_testsuite/test9/main.c @@ -0,0 +1,14 @@ +#include <unistd.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <string.h> +#include <stdio.h> + +int main() +{ + //This process sleeps for 5 seconds; + usleep(5000000); + return 0; +} diff --git a/miosix/_tools/testsuite/mpu_testsuite/test9/miosix.ld b/miosix/_tools/testsuite/mpu_testsuite/test9/miosix.ld new file mode 100644 index 0000000000000000000000000000000000000000..c91c803e629040b14233a8f8251a7d9952f68910 --- /dev/null +++ b/miosix/_tools/testsuite/mpu_testsuite/test9/miosix.ld @@ -0,0 +1,66 @@ +/* + * Linker script for writing PROGRAMS for the Miosix embedded OS + * TFT:Terraneo Federico Technlogies + */ + +OUTPUT_FORMAT("elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) + +SECTIONS +{ + /* Here starts the first elf segment, that stays in flash */ + . = 0 + SIZEOF_HEADERS; + + .text : ALIGN(8) + { + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + } + + .rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) } + .rel.got : { *(.rel.got) } + + /* Here starts the second segment, that is copied in RAM and relocated */ + . = 0x10000000; + + .got : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) } + + /* FIXME: If this is put in the other segment, it makes it writable */ + .dynamic : { *(.dynamic) } + + /* FIXME: The compiler insists in addressing rodata relative to r9 */ + .rodata : ALIGN(8) + { + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + } + + .data : ALIGN(8) + { + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + } + + .bss : ALIGN(8) + { + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + } + + /* These are removed since are unused and increase binary size */ + /DISCARD/ : + { + *(.interp) + *(.dynsym) + *(.dynstr) + *(.hash) + *(.comment) + *(.ARM.attributes) + } +} diff --git a/miosix/_tools/testsuite/syscall_testsuite/build.sh b/miosix/_tools/testsuite/syscall_testsuite/build.sh new file mode 100644 index 0000000000000000000000000000000000000000..f60111a150f859290883ff94f65fcd0ccd4e5af5 --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/build.sh @@ -0,0 +1,19 @@ +#!/bin/bash + + +PREFIX="$1_" + +for i in $1_*/; do + if [ -d "$i" ]; then + echo "Building $i" + + len=${#i} + name=${i:0:len - 1} + + cd $i && + make clean && + make $2 "NAME=$name" && + cp prog3.h "../$name.h" && + cd .. + fi +done \ No newline at end of file diff --git a/miosix/_tools/testsuite/syscall_testsuite/includes.h b/miosix/_tools/testsuite/syscall_testsuite/includes.h new file mode 100644 index 0000000000000000000000000000000000000000..08007d8fed26c69b6762e06016fb4eecee489a70 --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/includes.h @@ -0,0 +1,15 @@ +#ifndef _APP_SYSCALL_TESTS_ +#define _APP_SYSCALL_TESTS_ +#include "miosix/testsuite/syscall_testsuite/testsuite_syscall.h" + #include "miosix/testsuite/syscall_testsuite/testsuite_simple.h" + #include "miosix/testsuite/syscall_testsuite/testsuite_sleep.h" + #include "miosix/testsuite/syscall_testsuite/testsuite_system.h" + + #ifdef WITH_FILESYSTEM + #include "miosix/testsuite/syscall_testsuite/testsuite_file1.h" + #include "miosix/testsuite/syscall_testsuite/testsuite_file2.h" + #include "miosix/testsuite/syscall_testsuite/testsuite_syscall_mpu_open.h" + #include "miosix/testsuite/syscall_testsuite/testsuite_syscall_mpu_read.h" + #include "miosix/testsuite/syscall_testsuite/testsuite_syscall_mpu_write.h" + #endif +#endif //_APP_SYSCALL_TESTS_ diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_file1.h b/miosix/_tools/testsuite/syscall_testsuite/testsuite_file1.h new file mode 100644 index 0000000000000000000000000000000000000000..8cc918ff39a908f43c5cb33f3e9eaa0f97c5ee50 --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_file1.h @@ -0,0 +1,32 @@ +const unsigned char __attribute__((aligned(8))) testsuite_file1_elf[] = { + 0x7f, 0x45, 0x4c, 0x46, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x28, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x99, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x05, 0x34, 0x00, 0x20, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, + 0x98, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, + 0x7e, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x18, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x10, 0x44, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x24, 0x01, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10, 0x0c, 0x00, 0x00, 0x10, + 0x28, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x02, 0xf8, + 0x00, 0xf0, 0x30, 0xf8, 0xf8, 0xb5, 0x16, 0x4f, 0x00, 0x24, 0x09, 0xeb, + 0x07, 0x03, 0x13, 0xf8, 0x01, 0x2f, 0x01, 0x34, 0x00, 0x2a, 0xfa, 0xd1, + 0x4f, 0x44, 0x38, 0x46, 0x40, 0xf2, 0x02, 0x41, 0x00, 0xf0, 0x22, 0xf8, + 0xb0, 0xf1, 0xff, 0x3f, 0x06, 0x46, 0x11, 0xd0, 0x4f, 0xf4, 0x7a, 0x75, + 0x02, 0xe0, 0x15, 0xf1, 0xff, 0x35, 0x0d, 0xd0, 0x30, 0x46, 0x39, 0x46, + 0x22, 0x46, 0x00, 0xf0, 0x19, 0xf8, 0xa0, 0x42, 0xf5, 0xd0, 0x30, 0x46, + 0x00, 0xf0, 0x11, 0xf8, 0x02, 0x20, 0xf8, 0xbd, 0x01, 0x20, 0xfc, 0xe7, + 0x30, 0x46, 0x00, 0xf0, 0x0a, 0xf8, 0x28, 0x46, 0xf7, 0xe7, 0x00, 0xbf, + 0x38, 0x00, 0x00, 0x00, 0x02, 0x23, 0x00, 0xdf, 0x06, 0x23, 0x00, 0xdf, + 0x70, 0x47, 0x07, 0x23, 0x00, 0xdf, 0x70, 0x47, 0x03, 0x23, 0x00, 0xdf, + 0x70, 0x47, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, + 0x00, 0x08, 0x00, 0x00, 0x4d, 0x69, 0x6f, 0x73, 0x69, 0x78, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x66, 0x69, 0x6c, 0x65, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0x00, 0x00 +}; +unsigned int testsuite_file1_elf_len = 348; diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_file1/Makefile b/miosix/_tools/testsuite/syscall_testsuite/testsuite_file1/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..43cfd99a8043902f2cd2b0396930093b0eb18285 --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_file1/Makefile @@ -0,0 +1,46 @@ +## +## Makefile for writing PROGRAMS for the Miosix embedded OS +## TFT:Terraneo Federico Technlogies +## + +SRC := \ +main.c + +## Replaces both "foo.cpp"-->"foo.o" and "foo.c"-->"foo.o" +OBJ := $(addsuffix .o, $(basename $(SRC))) +ELF := $(addsuffix .elf, $(NAME)) +OUT_FILE := $(addsuffix .bin, $(shell echo $(NAME) | sed "s/testsuite_//")) + +AS := arm-miosix-eabi-as +CC := arm-miosix-eabi-gcc +CXX := arm-miosix-eabi-g++ +SZ := arm-miosix-eabi-size + +AFLAGS := -mcpu=cortex-m3 -mthumb +CFLAGS := -mcpu=cortex-m3 -mthumb -mfix-cortex-m3-ldrd -fpie -msingle-pic-base \ + -ffunction-sections -O2 -Wall -c -DTEST_STRING='"$(OUT_FILE)"' -DTEST_FILE='"$(OUT_FILE)"' +CXXFLAGS := $(CFLAGS) +LFLAGS := -mcpu=cortex-m3 -mthumb -mfix-cortex-m3-ldrd -fpie -msingle-pic-base \ + -Wl,--gc-sections,-Map,test.map,-T./miosix.ld,-n,-pie,--spare-dynamic-tags,3 \ + -O2 -nostdlib + +LINK_LIBS := -Wl,--start-group -lstdc++ -lc -lm -lgcc -Wl,--end-group + +all: $(OBJ) crt0.o + $(CXX) $(LFLAGS) -o $(ELF) $(OBJ) crt0.o $(LINK_LIBS) + $(SZ) $(ELF) + @arm-miosix-eabi-objdump -Dslx $(ELF) > test.txt + @mx-postlinker $(ELF) --ramsize=16384 --stacksize=2048 --strip-sectheader + @xxd -i $(ELF) | sed 's/unsigned char/const unsigned char __attribute__((aligned(8)))/' > prog3.h + +clean: + -rm $(OBJ) crt0.o *.elf test.map test.txt + +%.o: %.s + $(AS) $(AFLAGS) $< -o $@ + +%.o : %.c + $(CC) $(CFLAGS) $< -o $@ + +%.o : %.cpp + $(CXX) $(CXXFLAGS) $< -o $@ diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_file1/crt0.s b/miosix/_tools/testsuite/syscall_testsuite/testsuite_file1/crt0.s new file mode 100644 index 0000000000000000000000000000000000000000..9959b317dcafd42e8cb82c896b3eef2e0205f7cc --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_file1/crt0.s @@ -0,0 +1,131 @@ +/* + * Startup script for writing PROGRAMS for the Miosix embedded OS + * TFT:Terraneo Federico Technlogies + */ + +.syntax unified +.cpu cortex-m3 +.thumb + +.section .text + +/** + * _start, program entry point + */ +.global _start +.type _start, %function +_start: + /* TODO: .ctor */ + bl main + /* TODO: .dtor */ + bl _exit + +/** + * _exit, terminate process + * \param v exit value + */ +.section .text._exit +.global _exit +.type _exit, %function +_exit: + movs r3, #2 + svc 0 + +/** + * open, open a file + * \param fd file descriptor + * \param file access mode + * \param xxx access permisions + * \return file descriptor or -1 if errors + */ +.section .text.open +.global open +.type open, %function +open: + movs r3, #6 + svc 0 + bx lr + +/** + * close, close a file + * \param fd file descriptor + */ +.section .text.close +.global close +.type close, %function +close: + movs r3, #7 + svc 0 + bx lr + +/** + * seek + * \param fd file descriptor + * \param pos moving offset + * \param start position, SEEK_SET, SEEK_CUR or SEEK_END +*/ +.section .text.seek +.global seek +.type seek, %function +seek: + movs r3, #8 + svc 0 + bx lr + + +/** + * system, fork and execture a program, blocking + * \param program to execute + */ +.section .text.system +.global system +.type system, %function +system: + movs r3, #9 + svc 0 + bx lr + +/** + * write, write to file + * \param fd file descriptor + * \param buf data to be written + * \param len buffer length + * \return number of written bytes or -1 if errors + */ +.section .text.write +.global write +.type write, %function +write: + movs r3, #3 + svc 0 + bx lr + +/** + * read, read from file + * \param fd file descriptor + * \param buf data to be read + * \param len buffer length + * \return number of read bytes or -1 if errors + */ +.section .text.read +.global read +.type read, %function +read: + movs r3, #4 + svc 0 + bx lr + +/** + * usleep, sleep a specified number of microseconds + * \param us number of microseconds to sleep + * \return 0 on success or -1 if errors + */ +.section .text.usleep +.global usleep +.type usleep, %function +usleep: + movs r3, #5 + svc 0 + bx lr + +.end diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_file1/main.c b/miosix/_tools/testsuite/syscall_testsuite/testsuite_file1/main.c new file mode 100644 index 0000000000000000000000000000000000000000..050cb85d8333418b320beeeae6fa6c5b9bf4b35d --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_file1/main.c @@ -0,0 +1,92 @@ +#include <unistd.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <string.h> +#include <stdio.h> + +#define error(x) (x) + +#define SIZE 1024 + +int mystrlen(const char *s){ + int result=0; + while(*s++) result++; + return result; +} + +void print(const char *s){ + write(1, s, mystrlen(s)); +} + + +char *strrev(char *str, unsigned int len){ + if(str == 0 || *str == '\0') + return str; + + char tmp = 0, *p1, *p2; + for(*p1 = str, *p2 = str + len - 1; p2 > p1; ++p1, --p2){ + tmp = *p1; + *p1 = *p2; + *p2 = tmp; + } + + return str; +} + +int fast_itoa(int value, char *pBuffer){ + char *pTmp = pBuffer; + unsigned int digitCount = 0; + + if(value == 0){ + *pTmp = '0'; + return 1; + } + + if(value < 0){ + value = -value; + *pTmp++ = '-'; + ++digitCount; + } + + while(value > 0){ + *pTmp++ = (value % 10) + '0'; + value /= 10; + ++digitCount; + } + + *pTmp = '\0'; + + strrev(pBuffer, digitCount); + return digitCount; +} + +int main(){ + int len = mystrlen(TEST_STRING); + + int fd = open(TEST_FILE, O_RDWR|O_TRUNC, 0); + + if(fd == -1) + return 1; + + char buffer[30] = {0}; + + int i = 0; + for(i = 0; i < 1000; i++){ +/* if(i % 10 == 0){ + fast_itoa(i, buffer); + print("\nProcess 1: "); + print(buffer); + } +*/ + if(write(fd, TEST_STRING, len) != len){ + close(fd); + return 2; + } + } + + close(fd); + + return 0; +} diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_file1/miosix.ld b/miosix/_tools/testsuite/syscall_testsuite/testsuite_file1/miosix.ld new file mode 100644 index 0000000000000000000000000000000000000000..c91c803e629040b14233a8f8251a7d9952f68910 --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_file1/miosix.ld @@ -0,0 +1,66 @@ +/* + * Linker script for writing PROGRAMS for the Miosix embedded OS + * TFT:Terraneo Federico Technlogies + */ + +OUTPUT_FORMAT("elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) + +SECTIONS +{ + /* Here starts the first elf segment, that stays in flash */ + . = 0 + SIZEOF_HEADERS; + + .text : ALIGN(8) + { + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + } + + .rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) } + .rel.got : { *(.rel.got) } + + /* Here starts the second segment, that is copied in RAM and relocated */ + . = 0x10000000; + + .got : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) } + + /* FIXME: If this is put in the other segment, it makes it writable */ + .dynamic : { *(.dynamic) } + + /* FIXME: The compiler insists in addressing rodata relative to r9 */ + .rodata : ALIGN(8) + { + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + } + + .data : ALIGN(8) + { + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + } + + .bss : ALIGN(8) + { + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + } + + /* These are removed since are unused and increase binary size */ + /DISCARD/ : + { + *(.interp) + *(.dynsym) + *(.dynstr) + *(.hash) + *(.comment) + *(.ARM.attributes) + } +} diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_file1/prog3.h b/miosix/_tools/testsuite/syscall_testsuite/testsuite_file1/prog3.h new file mode 100644 index 0000000000000000000000000000000000000000..8cc918ff39a908f43c5cb33f3e9eaa0f97c5ee50 --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_file1/prog3.h @@ -0,0 +1,32 @@ +const unsigned char __attribute__((aligned(8))) testsuite_file1_elf[] = { + 0x7f, 0x45, 0x4c, 0x46, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x28, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x99, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x05, 0x34, 0x00, 0x20, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, + 0x98, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, + 0x7e, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x18, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x10, 0x44, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x24, 0x01, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10, 0x0c, 0x00, 0x00, 0x10, + 0x28, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x02, 0xf8, + 0x00, 0xf0, 0x30, 0xf8, 0xf8, 0xb5, 0x16, 0x4f, 0x00, 0x24, 0x09, 0xeb, + 0x07, 0x03, 0x13, 0xf8, 0x01, 0x2f, 0x01, 0x34, 0x00, 0x2a, 0xfa, 0xd1, + 0x4f, 0x44, 0x38, 0x46, 0x40, 0xf2, 0x02, 0x41, 0x00, 0xf0, 0x22, 0xf8, + 0xb0, 0xf1, 0xff, 0x3f, 0x06, 0x46, 0x11, 0xd0, 0x4f, 0xf4, 0x7a, 0x75, + 0x02, 0xe0, 0x15, 0xf1, 0xff, 0x35, 0x0d, 0xd0, 0x30, 0x46, 0x39, 0x46, + 0x22, 0x46, 0x00, 0xf0, 0x19, 0xf8, 0xa0, 0x42, 0xf5, 0xd0, 0x30, 0x46, + 0x00, 0xf0, 0x11, 0xf8, 0x02, 0x20, 0xf8, 0xbd, 0x01, 0x20, 0xfc, 0xe7, + 0x30, 0x46, 0x00, 0xf0, 0x0a, 0xf8, 0x28, 0x46, 0xf7, 0xe7, 0x00, 0xbf, + 0x38, 0x00, 0x00, 0x00, 0x02, 0x23, 0x00, 0xdf, 0x06, 0x23, 0x00, 0xdf, + 0x70, 0x47, 0x07, 0x23, 0x00, 0xdf, 0x70, 0x47, 0x03, 0x23, 0x00, 0xdf, + 0x70, 0x47, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, + 0x00, 0x08, 0x00, 0x00, 0x4d, 0x69, 0x6f, 0x73, 0x69, 0x78, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x66, 0x69, 0x6c, 0x65, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0x00, 0x00 +}; +unsigned int testsuite_file1_elf_len = 348; diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_file1/test.txt b/miosix/_tools/testsuite/syscall_testsuite/testsuite_file1/test.txt new file mode 100644 index 0000000000000000000000000000000000000000..29e180990d518bce6cc26c0f293401c88542bcf4 --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_file1/test.txt @@ -0,0 +1,151 @@ + +testsuite_file1.elf: file format elf32-littlearm +testsuite_file1.elf +architecture: arm, flags 0x00000050: +HAS_SYMS, DYNAMIC +start address 0x00000099 + +Program Header: + LOAD off 0x00000098 vaddr 0x00000098 paddr 0x00000098 align 2**3 + filesz 0x0000007e memsz 0x0000007e flags r-x + LOAD off 0x00000118 vaddr 0x10000000 paddr 0x10000000 align 2**3 + filesz 0x00000044 memsz 0x00000044 flags rw- + DYNAMIC off 0x00000124 vaddr 0x1000000c paddr 0x1000000c align 2**2 + filesz 0x00000028 memsz 0x00000028 flags rw- + +Dynamic Section: + DEBUG 0x00000000 +private flags = 5000002: [Version5 EABI] [has entry point] + +Sections: +Idx Name Size VMA LMA File off Algn + 0 .text 0000007e 00000098 00000098 00000098 2**3 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 1 .got 0000000c 10000000 10000000 00000118 2**2 + CONTENTS, ALLOC, LOAD, DATA + 2 .dynamic 00000028 1000000c 1000000c 00000124 2**2 + CONTENTS, ALLOC, LOAD, DATA + 3 .rodata 0000000c 10000038 10000038 00000150 2**3 + CONTENTS, ALLOC, LOAD, READONLY, DATA +SYMBOL TABLE: +00000098 l d .text 00000000 .text +10000000 l d .got 00000000 .got +1000000c l d .dynamic 00000000 .dynamic +10000038 l d .rodata 00000000 .rodata +00000000 l df *ABS* 00000000 main.c +1000000c l O *ABS* 00000000 _DYNAMIC +10000000 l O *ABS* 00000000 _GLOBAL_OFFSET_TABLE_ +00000110 g F .text 00000000 write +00000098 g F .text 00000000 _start +000000a0 g F .text 00000060 main +00000100 g F .text 00000000 _exit +00000104 g F .text 00000000 open +0000010a g F .text 00000000 close + + +Contents of section .text: + 0098 00f002f8 00f030f8 f8b5164f 002409eb ......0....O.$.. + 00a8 070313f8 012f0134 002afad1 4f443846 ...../.4.*..OD8F + 00b8 40f20241 00f022f8 b0f1ff3f 064611d0 @..A.."....?.F.. + 00c8 4ff47a75 02e015f1 ff350dd0 30463946 O.zu.....5..0F9F + 00d8 224600f0 19f8a042 f5d03046 00f011f8 "F.....B..0F.... + 00e8 0220f8bd 0120fce7 304600f0 0af82846 . ... ..0F....(F + 00f8 f7e700bf 38000000 022300df 062300df ....8....#...#.. + 0108 70470723 00df7047 032300df 7047 pG.#..pG.#..pG +Contents of section .got: + 10000000 0c000010 00000000 00000000 ............ +Contents of section .dynamic: + 1000000c 15000000 00000000 00000000 00000000 ................ + 1000001c 00000000 00000000 00000000 00000000 ................ + 1000002c 00000000 00000000 ........ +Contents of section .rodata: + 10000038 66696c65 312e6269 6e000000 file1.bin... + +Disassembly of section .text: + +00000098 <_start>: +_start(): + 98: f000 f802 bl a0 <main> + 9c: f000 f830 bl 100 <_exit> + +000000a0 <main>: +main(): + a0: b5f8 push {r3, r4, r5, r6, r7, lr} + a2: 4f16 ldr r7, [pc, #88] ; (fc <main+0x5c>) + a4: 2400 movs r4, #0 + a6: eb09 0307 add.w r3, r9, r7 + aa: f813 2f01 ldrb.w r2, [r3, #1]! + ae: 3401 adds r4, #1 + b0: 2a00 cmp r2, #0 + b2: d1fa bne.n aa <main+0xa> + b4: 444f add r7, r9 + b6: 4638 mov r0, r7 + b8: f240 4102 movw r1, #1026 ; 0x402 + bc: f000 f822 bl 104 <open> + c0: f1b0 3fff cmp.w r0, #4294967295 ; 0xffffffff + c4: 4606 mov r6, r0 + c6: d011 beq.n ec <main+0x4c> + c8: f44f 757a mov.w r5, #1000 ; 0x3e8 + cc: e002 b.n d4 <main+0x34> + ce: f115 35ff adds.w r5, r5, #4294967295 ; 0xffffffff + d2: d00d beq.n f0 <main+0x50> + d4: 4630 mov r0, r6 + d6: 4639 mov r1, r7 + d8: 4622 mov r2, r4 + da: f000 f819 bl 110 <write> + de: 42a0 cmp r0, r4 + e0: d0f5 beq.n ce <main+0x2e> + e2: 4630 mov r0, r6 + e4: f000 f811 bl 10a <close> + e8: 2002 movs r0, #2 + ea: bdf8 pop {r3, r4, r5, r6, r7, pc} + ec: 2001 movs r0, #1 + ee: e7fc b.n ea <main+0x4a> + f0: 4630 mov r0, r6 + f2: f000 f80a bl 10a <close> + f6: 4628 mov r0, r5 + f8: e7f7 b.n ea <main+0x4a> + fa: bf00 nop + fc: 00000038 andeq r0, r0, r8, lsr r0 + +00000100 <_exit>: +_exit(): + 100: 2302 movs r3, #2 + 102: df00 svc 0 + +00000104 <open>: +open(): + 104: 2306 movs r3, #6 + 106: df00 svc 0 + 108: 4770 bx lr + +0000010a <close>: +close(): + 10a: 2307 movs r3, #7 + 10c: df00 svc 0 + 10e: 4770 bx lr + +00000110 <write>: +write(): + 110: 2303 movs r3, #3 + 112: df00 svc 0 + 114: 4770 bx lr + +Disassembly of section .got: + +10000000 <.got>: +10000000: 1000000c andne r0, r0, ip + ... + +Disassembly of section .dynamic: + +1000000c <.dynamic>: +1000000c: 00000015 andeq r0, r0, r5, lsl r0 + ... + +Disassembly of section .rodata: + +10000038 <.rodata>: +10000038: 656c6966 strbvs r6, [ip, #-2406]! ; 0x966 +1000003c: 69622e31 stmdbvs r2!, {r0, r4, r5, r9, sl, fp, sp}^ +10000040: 0000006e andeq r0, r0, lr, rrx diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_file2.h b/miosix/_tools/testsuite/syscall_testsuite/testsuite_file2.h new file mode 100644 index 0000000000000000000000000000000000000000..ddab5d4cace1fc0bdfbee7550a5f6347b10f9c42 --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_file2.h @@ -0,0 +1,32 @@ +const unsigned char __attribute__((aligned(8))) testsuite_file2_elf[] = { + 0x7f, 0x45, 0x4c, 0x46, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x28, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x99, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x05, 0x34, 0x00, 0x20, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, + 0x98, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, + 0x7e, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x18, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x10, 0x44, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x24, 0x01, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10, 0x0c, 0x00, 0x00, 0x10, + 0x28, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x02, 0xf8, + 0x00, 0xf0, 0x30, 0xf8, 0xf8, 0xb5, 0x16, 0x4f, 0x00, 0x24, 0x09, 0xeb, + 0x07, 0x03, 0x13, 0xf8, 0x01, 0x2f, 0x01, 0x34, 0x00, 0x2a, 0xfa, 0xd1, + 0x4f, 0x44, 0x38, 0x46, 0x40, 0xf2, 0x02, 0x41, 0x00, 0xf0, 0x22, 0xf8, + 0xb0, 0xf1, 0xff, 0x3f, 0x06, 0x46, 0x11, 0xd0, 0x4f, 0xf4, 0x7a, 0x75, + 0x02, 0xe0, 0x15, 0xf1, 0xff, 0x35, 0x0d, 0xd0, 0x30, 0x46, 0x39, 0x46, + 0x22, 0x46, 0x00, 0xf0, 0x19, 0xf8, 0xa0, 0x42, 0xf5, 0xd0, 0x30, 0x46, + 0x00, 0xf0, 0x11, 0xf8, 0x02, 0x20, 0xf8, 0xbd, 0x01, 0x20, 0xfc, 0xe7, + 0x30, 0x46, 0x00, 0xf0, 0x0a, 0xf8, 0x28, 0x46, 0xf7, 0xe7, 0x00, 0xbf, + 0x38, 0x00, 0x00, 0x00, 0x02, 0x23, 0x00, 0xdf, 0x06, 0x23, 0x00, 0xdf, + 0x70, 0x47, 0x07, 0x23, 0x00, 0xdf, 0x70, 0x47, 0x03, 0x23, 0x00, 0xdf, + 0x70, 0x47, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, + 0x00, 0x08, 0x00, 0x00, 0x4d, 0x69, 0x6f, 0x73, 0x69, 0x78, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x66, 0x69, 0x6c, 0x65, 0x32, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0x00, 0x00 +}; +unsigned int testsuite_file2_elf_len = 348; diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_file2/Makefile b/miosix/_tools/testsuite/syscall_testsuite/testsuite_file2/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..43cfd99a8043902f2cd2b0396930093b0eb18285 --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_file2/Makefile @@ -0,0 +1,46 @@ +## +## Makefile for writing PROGRAMS for the Miosix embedded OS +## TFT:Terraneo Federico Technlogies +## + +SRC := \ +main.c + +## Replaces both "foo.cpp"-->"foo.o" and "foo.c"-->"foo.o" +OBJ := $(addsuffix .o, $(basename $(SRC))) +ELF := $(addsuffix .elf, $(NAME)) +OUT_FILE := $(addsuffix .bin, $(shell echo $(NAME) | sed "s/testsuite_//")) + +AS := arm-miosix-eabi-as +CC := arm-miosix-eabi-gcc +CXX := arm-miosix-eabi-g++ +SZ := arm-miosix-eabi-size + +AFLAGS := -mcpu=cortex-m3 -mthumb +CFLAGS := -mcpu=cortex-m3 -mthumb -mfix-cortex-m3-ldrd -fpie -msingle-pic-base \ + -ffunction-sections -O2 -Wall -c -DTEST_STRING='"$(OUT_FILE)"' -DTEST_FILE='"$(OUT_FILE)"' +CXXFLAGS := $(CFLAGS) +LFLAGS := -mcpu=cortex-m3 -mthumb -mfix-cortex-m3-ldrd -fpie -msingle-pic-base \ + -Wl,--gc-sections,-Map,test.map,-T./miosix.ld,-n,-pie,--spare-dynamic-tags,3 \ + -O2 -nostdlib + +LINK_LIBS := -Wl,--start-group -lstdc++ -lc -lm -lgcc -Wl,--end-group + +all: $(OBJ) crt0.o + $(CXX) $(LFLAGS) -o $(ELF) $(OBJ) crt0.o $(LINK_LIBS) + $(SZ) $(ELF) + @arm-miosix-eabi-objdump -Dslx $(ELF) > test.txt + @mx-postlinker $(ELF) --ramsize=16384 --stacksize=2048 --strip-sectheader + @xxd -i $(ELF) | sed 's/unsigned char/const unsigned char __attribute__((aligned(8)))/' > prog3.h + +clean: + -rm $(OBJ) crt0.o *.elf test.map test.txt + +%.o: %.s + $(AS) $(AFLAGS) $< -o $@ + +%.o : %.c + $(CC) $(CFLAGS) $< -o $@ + +%.o : %.cpp + $(CXX) $(CXXFLAGS) $< -o $@ diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_file2/crt0.s b/miosix/_tools/testsuite/syscall_testsuite/testsuite_file2/crt0.s new file mode 100644 index 0000000000000000000000000000000000000000..9959b317dcafd42e8cb82c896b3eef2e0205f7cc --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_file2/crt0.s @@ -0,0 +1,131 @@ +/* + * Startup script for writing PROGRAMS for the Miosix embedded OS + * TFT:Terraneo Federico Technlogies + */ + +.syntax unified +.cpu cortex-m3 +.thumb + +.section .text + +/** + * _start, program entry point + */ +.global _start +.type _start, %function +_start: + /* TODO: .ctor */ + bl main + /* TODO: .dtor */ + bl _exit + +/** + * _exit, terminate process + * \param v exit value + */ +.section .text._exit +.global _exit +.type _exit, %function +_exit: + movs r3, #2 + svc 0 + +/** + * open, open a file + * \param fd file descriptor + * \param file access mode + * \param xxx access permisions + * \return file descriptor or -1 if errors + */ +.section .text.open +.global open +.type open, %function +open: + movs r3, #6 + svc 0 + bx lr + +/** + * close, close a file + * \param fd file descriptor + */ +.section .text.close +.global close +.type close, %function +close: + movs r3, #7 + svc 0 + bx lr + +/** + * seek + * \param fd file descriptor + * \param pos moving offset + * \param start position, SEEK_SET, SEEK_CUR or SEEK_END +*/ +.section .text.seek +.global seek +.type seek, %function +seek: + movs r3, #8 + svc 0 + bx lr + + +/** + * system, fork and execture a program, blocking + * \param program to execute + */ +.section .text.system +.global system +.type system, %function +system: + movs r3, #9 + svc 0 + bx lr + +/** + * write, write to file + * \param fd file descriptor + * \param buf data to be written + * \param len buffer length + * \return number of written bytes or -1 if errors + */ +.section .text.write +.global write +.type write, %function +write: + movs r3, #3 + svc 0 + bx lr + +/** + * read, read from file + * \param fd file descriptor + * \param buf data to be read + * \param len buffer length + * \return number of read bytes or -1 if errors + */ +.section .text.read +.global read +.type read, %function +read: + movs r3, #4 + svc 0 + bx lr + +/** + * usleep, sleep a specified number of microseconds + * \param us number of microseconds to sleep + * \return 0 on success or -1 if errors + */ +.section .text.usleep +.global usleep +.type usleep, %function +usleep: + movs r3, #5 + svc 0 + bx lr + +.end diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_file2/main.c b/miosix/_tools/testsuite/syscall_testsuite/testsuite_file2/main.c new file mode 100644 index 0000000000000000000000000000000000000000..93f4b2d17e92d049b322192644047c8cae687d95 --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_file2/main.c @@ -0,0 +1,92 @@ +#include <unistd.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <string.h> +#include <stdio.h> + +#define error(x) (x) + +#define SIZE 1024 + +int mystrlen(const char *s){ + int result=0; + while(*s++) result++; + return result; +} + +void print(const char *s){ + write(1, s, mystrlen(s)); +} + + +char *strrev(char *str, unsigned int len){ + if(str == 0 || *str == '\0') + return str; + + char tmp = 0, *p1, *p2; + for(*p1 = str, *p2 = str + len - 1; p2 > p1; ++p1, --p2){ + tmp = *p1; + *p1 = *p2; + *p2 = tmp; + } + + return str; +} + +int fast_itoa(int value, char *pBuffer){ + char *pTmp = pBuffer; + unsigned int digitCount = 0; + + if(value == 0){ + *pTmp = '0'; + return 1; + } + + if(value < 0){ + value = -value; + *pTmp++ = '-'; + ++digitCount; + } + + while(value > 0){ + *pTmp++ = (value % 10) + '0'; + value /= 10; + ++digitCount; + } + + *pTmp = '\0'; + + strrev(pBuffer, digitCount); + return digitCount; +} + +int main(){ + int len = mystrlen(TEST_STRING); + + int fd = open(TEST_FILE, O_RDWR|O_TRUNC, 0); + + if(fd == -1) + return 1; + + char buffer[30] = {0}; + + int i = 0; + for(i = 0; i < 1000; i++){ +/* if(i % 10 == 0){ + fast_itoa(i, buffer); + print("\nProcess 2: "); + print(buffer); + } + */ + if(write(fd, TEST_STRING, len) != len){ + close(fd); + return 2; + } + } + + close(fd); + + return 0; +} diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_file2/miosix.ld b/miosix/_tools/testsuite/syscall_testsuite/testsuite_file2/miosix.ld new file mode 100644 index 0000000000000000000000000000000000000000..c91c803e629040b14233a8f8251a7d9952f68910 --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_file2/miosix.ld @@ -0,0 +1,66 @@ +/* + * Linker script for writing PROGRAMS for the Miosix embedded OS + * TFT:Terraneo Federico Technlogies + */ + +OUTPUT_FORMAT("elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) + +SECTIONS +{ + /* Here starts the first elf segment, that stays in flash */ + . = 0 + SIZEOF_HEADERS; + + .text : ALIGN(8) + { + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + } + + .rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) } + .rel.got : { *(.rel.got) } + + /* Here starts the second segment, that is copied in RAM and relocated */ + . = 0x10000000; + + .got : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) } + + /* FIXME: If this is put in the other segment, it makes it writable */ + .dynamic : { *(.dynamic) } + + /* FIXME: The compiler insists in addressing rodata relative to r9 */ + .rodata : ALIGN(8) + { + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + } + + .data : ALIGN(8) + { + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + } + + .bss : ALIGN(8) + { + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + } + + /* These are removed since are unused and increase binary size */ + /DISCARD/ : + { + *(.interp) + *(.dynsym) + *(.dynstr) + *(.hash) + *(.comment) + *(.ARM.attributes) + } +} diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_file2/prog3.h b/miosix/_tools/testsuite/syscall_testsuite/testsuite_file2/prog3.h new file mode 100644 index 0000000000000000000000000000000000000000..ddab5d4cace1fc0bdfbee7550a5f6347b10f9c42 --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_file2/prog3.h @@ -0,0 +1,32 @@ +const unsigned char __attribute__((aligned(8))) testsuite_file2_elf[] = { + 0x7f, 0x45, 0x4c, 0x46, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x28, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x99, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x05, 0x34, 0x00, 0x20, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, + 0x98, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, + 0x7e, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x18, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x10, 0x44, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x24, 0x01, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10, 0x0c, 0x00, 0x00, 0x10, + 0x28, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x02, 0xf8, + 0x00, 0xf0, 0x30, 0xf8, 0xf8, 0xb5, 0x16, 0x4f, 0x00, 0x24, 0x09, 0xeb, + 0x07, 0x03, 0x13, 0xf8, 0x01, 0x2f, 0x01, 0x34, 0x00, 0x2a, 0xfa, 0xd1, + 0x4f, 0x44, 0x38, 0x46, 0x40, 0xf2, 0x02, 0x41, 0x00, 0xf0, 0x22, 0xf8, + 0xb0, 0xf1, 0xff, 0x3f, 0x06, 0x46, 0x11, 0xd0, 0x4f, 0xf4, 0x7a, 0x75, + 0x02, 0xe0, 0x15, 0xf1, 0xff, 0x35, 0x0d, 0xd0, 0x30, 0x46, 0x39, 0x46, + 0x22, 0x46, 0x00, 0xf0, 0x19, 0xf8, 0xa0, 0x42, 0xf5, 0xd0, 0x30, 0x46, + 0x00, 0xf0, 0x11, 0xf8, 0x02, 0x20, 0xf8, 0xbd, 0x01, 0x20, 0xfc, 0xe7, + 0x30, 0x46, 0x00, 0xf0, 0x0a, 0xf8, 0x28, 0x46, 0xf7, 0xe7, 0x00, 0xbf, + 0x38, 0x00, 0x00, 0x00, 0x02, 0x23, 0x00, 0xdf, 0x06, 0x23, 0x00, 0xdf, + 0x70, 0x47, 0x07, 0x23, 0x00, 0xdf, 0x70, 0x47, 0x03, 0x23, 0x00, 0xdf, + 0x70, 0x47, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, + 0x00, 0x08, 0x00, 0x00, 0x4d, 0x69, 0x6f, 0x73, 0x69, 0x78, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x66, 0x69, 0x6c, 0x65, 0x32, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0x00, 0x00 +}; +unsigned int testsuite_file2_elf_len = 348; diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_file2/test.txt b/miosix/_tools/testsuite/syscall_testsuite/testsuite_file2/test.txt new file mode 100644 index 0000000000000000000000000000000000000000..f7d071064a572b83ac6ab49834ffa054d70e7588 --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_file2/test.txt @@ -0,0 +1,151 @@ + +testsuite_file2.elf: file format elf32-littlearm +testsuite_file2.elf +architecture: arm, flags 0x00000050: +HAS_SYMS, DYNAMIC +start address 0x00000099 + +Program Header: + LOAD off 0x00000098 vaddr 0x00000098 paddr 0x00000098 align 2**3 + filesz 0x0000007e memsz 0x0000007e flags r-x + LOAD off 0x00000118 vaddr 0x10000000 paddr 0x10000000 align 2**3 + filesz 0x00000044 memsz 0x00000044 flags rw- + DYNAMIC off 0x00000124 vaddr 0x1000000c paddr 0x1000000c align 2**2 + filesz 0x00000028 memsz 0x00000028 flags rw- + +Dynamic Section: + DEBUG 0x00000000 +private flags = 5000002: [Version5 EABI] [has entry point] + +Sections: +Idx Name Size VMA LMA File off Algn + 0 .text 0000007e 00000098 00000098 00000098 2**3 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 1 .got 0000000c 10000000 10000000 00000118 2**2 + CONTENTS, ALLOC, LOAD, DATA + 2 .dynamic 00000028 1000000c 1000000c 00000124 2**2 + CONTENTS, ALLOC, LOAD, DATA + 3 .rodata 0000000c 10000038 10000038 00000150 2**3 + CONTENTS, ALLOC, LOAD, READONLY, DATA +SYMBOL TABLE: +00000098 l d .text 00000000 .text +10000000 l d .got 00000000 .got +1000000c l d .dynamic 00000000 .dynamic +10000038 l d .rodata 00000000 .rodata +00000000 l df *ABS* 00000000 main.c +1000000c l O *ABS* 00000000 _DYNAMIC +10000000 l O *ABS* 00000000 _GLOBAL_OFFSET_TABLE_ +00000110 g F .text 00000000 write +00000098 g F .text 00000000 _start +000000a0 g F .text 00000060 main +00000100 g F .text 00000000 _exit +00000104 g F .text 00000000 open +0000010a g F .text 00000000 close + + +Contents of section .text: + 0098 00f002f8 00f030f8 f8b5164f 002409eb ......0....O.$.. + 00a8 070313f8 012f0134 002afad1 4f443846 ...../.4.*..OD8F + 00b8 40f20241 00f022f8 b0f1ff3f 064611d0 @..A.."....?.F.. + 00c8 4ff47a75 02e015f1 ff350dd0 30463946 O.zu.....5..0F9F + 00d8 224600f0 19f8a042 f5d03046 00f011f8 "F.....B..0F.... + 00e8 0220f8bd 0120fce7 304600f0 0af82846 . ... ..0F....(F + 00f8 f7e700bf 38000000 022300df 062300df ....8....#...#.. + 0108 70470723 00df7047 032300df 7047 pG.#..pG.#..pG +Contents of section .got: + 10000000 0c000010 00000000 00000000 ............ +Contents of section .dynamic: + 1000000c 15000000 00000000 00000000 00000000 ................ + 1000001c 00000000 00000000 00000000 00000000 ................ + 1000002c 00000000 00000000 ........ +Contents of section .rodata: + 10000038 66696c65 322e6269 6e000000 file2.bin... + +Disassembly of section .text: + +00000098 <_start>: +_start(): + 98: f000 f802 bl a0 <main> + 9c: f000 f830 bl 100 <_exit> + +000000a0 <main>: +main(): + a0: b5f8 push {r3, r4, r5, r6, r7, lr} + a2: 4f16 ldr r7, [pc, #88] ; (fc <main+0x5c>) + a4: 2400 movs r4, #0 + a6: eb09 0307 add.w r3, r9, r7 + aa: f813 2f01 ldrb.w r2, [r3, #1]! + ae: 3401 adds r4, #1 + b0: 2a00 cmp r2, #0 + b2: d1fa bne.n aa <main+0xa> + b4: 444f add r7, r9 + b6: 4638 mov r0, r7 + b8: f240 4102 movw r1, #1026 ; 0x402 + bc: f000 f822 bl 104 <open> + c0: f1b0 3fff cmp.w r0, #4294967295 ; 0xffffffff + c4: 4606 mov r6, r0 + c6: d011 beq.n ec <main+0x4c> + c8: f44f 757a mov.w r5, #1000 ; 0x3e8 + cc: e002 b.n d4 <main+0x34> + ce: f115 35ff adds.w r5, r5, #4294967295 ; 0xffffffff + d2: d00d beq.n f0 <main+0x50> + d4: 4630 mov r0, r6 + d6: 4639 mov r1, r7 + d8: 4622 mov r2, r4 + da: f000 f819 bl 110 <write> + de: 42a0 cmp r0, r4 + e0: d0f5 beq.n ce <main+0x2e> + e2: 4630 mov r0, r6 + e4: f000 f811 bl 10a <close> + e8: 2002 movs r0, #2 + ea: bdf8 pop {r3, r4, r5, r6, r7, pc} + ec: 2001 movs r0, #1 + ee: e7fc b.n ea <main+0x4a> + f0: 4630 mov r0, r6 + f2: f000 f80a bl 10a <close> + f6: 4628 mov r0, r5 + f8: e7f7 b.n ea <main+0x4a> + fa: bf00 nop + fc: 00000038 andeq r0, r0, r8, lsr r0 + +00000100 <_exit>: +_exit(): + 100: 2302 movs r3, #2 + 102: df00 svc 0 + +00000104 <open>: +open(): + 104: 2306 movs r3, #6 + 106: df00 svc 0 + 108: 4770 bx lr + +0000010a <close>: +close(): + 10a: 2307 movs r3, #7 + 10c: df00 svc 0 + 10e: 4770 bx lr + +00000110 <write>: +write(): + 110: 2303 movs r3, #3 + 112: df00 svc 0 + 114: 4770 bx lr + +Disassembly of section .got: + +10000000 <.got>: +10000000: 1000000c andne r0, r0, ip + ... + +Disassembly of section .dynamic: + +1000000c <.dynamic>: +1000000c: 00000015 andeq r0, r0, r5, lsl r0 + ... + +Disassembly of section .rodata: + +10000038 <.rodata>: +10000038: 656c6966 strbvs r6, [ip, #-2406]! ; 0x966 +1000003c: 69622e32 stmdbvs r2!, {r1, r4, r5, r9, sl, fp, sp}^ +10000040: 0000006e andeq r0, r0, lr, rrx diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_simple.h b/miosix/_tools/testsuite/syscall_testsuite/testsuite_simple.h new file mode 100644 index 0000000000000000000000000000000000000000..fd4cd50e8f54a68798894d655bb04cefa7a56827 --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_simple.h @@ -0,0 +1,22 @@ +const unsigned char __attribute__((aligned(8))) testsuite_simple_elf[] = { + 0x7f, 0x45, 0x4c, 0x46, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x28, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x99, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x05, 0x34, 0x00, 0x20, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, + 0x98, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x10, 0x34, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0xb4, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10, 0x0c, 0x00, 0x00, 0x10, + 0x28, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x02, 0xf8, + 0x00, 0xf0, 0x02, 0xf8, 0x2a, 0x20, 0x70, 0x47, 0x02, 0x23, 0x00, 0xdf, + 0x0c, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00, + 0x4d, 0x69, 0x6f, 0x73, 0x69, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 +}; +unsigned int testsuite_simple_elf_len = 220; diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_simple/Makefile b/miosix/_tools/testsuite/syscall_testsuite/testsuite_simple/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..4f84bfef8faef0da502b49682e72369cb498ee1a --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_simple/Makefile @@ -0,0 +1,45 @@ +## +## Makefile for writing PROGRAMS for the Miosix embedded OS +## TFT:Terraneo Federico Technlogies +## + +SRC := \ +main.c + +## Replaces both "foo.cpp"-->"foo.o" and "foo.c"-->"foo.o" +OBJ := $(addsuffix .o, $(basename $(SRC))) +ELF := $(addsuffix .elf, $(NAME)) + +AS := arm-miosix-eabi-as +CC := arm-miosix-eabi-gcc +CXX := arm-miosix-eabi-g++ +SZ := arm-miosix-eabi-size + +AFLAGS := -mcpu=cortex-m3 -mthumb +CFLAGS := -mcpu=cortex-m3 -mthumb -mfix-cortex-m3-ldrd -fpie -msingle-pic-base \ + -ffunction-sections -O2 -Wall -c -DRETURN_VALUE=$(RET) +CXXFLAGS := $(CFLAGS) +LFLAGS := -mcpu=cortex-m3 -mthumb -mfix-cortex-m3-ldrd -fpie -msingle-pic-base \ + -Wl,--gc-sections,-Map,test.map,-T./miosix.ld,-n,-pie,--spare-dynamic-tags,3 \ + -O2 -nostdlib + +LINK_LIBS := -Wl,--start-group -lstdc++ -lc -lm -lgcc -Wl,--end-group + +all: $(OBJ) crt0.o + $(CXX) $(LFLAGS) -o $(ELF) $(OBJ) crt0.o $(LINK_LIBS) + $(SZ) $(ELF) + @arm-miosix-eabi-objdump -Dslx $(ELF) > test.txt + @mx-postlinker $(ELF) --ramsize=16384 --stacksize=2048 --strip-sectheader + @xxd -i $(ELF) | sed 's/unsigned char/const unsigned char __attribute__((aligned(8)))/' > prog3.h + +clean: + -rm $(OBJ) crt0.o *.elf test.map test.txt + +%.o: %.s + $(AS) $(AFLAGS) $< -o $@ + +%.o : %.c + $(CC) $(CFLAGS) $< -o $@ + +%.o : %.cpp + $(CXX) $(CXXFLAGS) $< -o $@ diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_simple/crt0.s b/miosix/_tools/testsuite/syscall_testsuite/testsuite_simple/crt0.s new file mode 100644 index 0000000000000000000000000000000000000000..8dbb153d806028cd739d686a05eac59d6357eb74 --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_simple/crt0.s @@ -0,0 +1,130 @@ +/* + * Startup script for writing PROGRAMS for the Miosix embedded OS + * TFT:Terraneo Federico Technlogies + */ + +.syntax unified +.cpu cortex-m3 +.thumb + +.section .text + +/** + * _start, program entry point + */ +.global _start +.type _start, %function +_start: + /* TODO: .ctor */ + bl main + /* TODO: .dtor */ + bl _exit + +/** + * _exit, terminate process + * \param v exit value + */ +.section .text._exit +.global _exit +.type _exit, %function +_exit: + movs r3, #2 + svc 0 + +/** + * open, open a file + * \param fd file descriptor + * \param file access mode + * \param xxx access permisions + * \return file descriptor or -1 if errors + */ +.section .text.open +.global open +.type open, %function +open: + movs r3, #6 + svc 0 + bx lr + +/** + * close, close a file + * \param fd file descriptor + */ +.section .text.close +.global close +.type close, %function +close: + movs r3, #7 + svc 0 + bx lr + +/** + * lseek + * \param fd file descriptor + * \param pos moving offset + * \param start position, SEEK_SET, SEEK_CUR or SEEK_END +*/ +.section .text.seek +.global seek +.type seek, %function + + movs r3, #8 + svc 0 + bx lr + + +/** + * system, fork and execture a program, blocking + * \param program to execute + */ +.section .text.system +.global system +.type system, %function +system: + movs r3, #9 + svc 0 + bx lr +/** + * write, write to file + * \param fd file descriptor + * \param buf data to be written + * \param len buffer length + * \return number of written bytes or -1 if errors + */ +.section .text.write +.global write +.type write, %function +write: + movs r3, #3 + svc 0 + bx lr + +/** + * read, read from file + * \param fd file descriptor + * \param buf data to be read + * \param len buffer length + * \return number of read bytes or -1 if errors + */ +.section .text.read +.global read +.type read, %function +read: + movs r3, #4 + svc 0 + bx lr + +/** + * usleep, sleep a specified number of microseconds + * \param us number of microseconds to sleep + * \return 0 on success or -1 if errors + */ +.section .text.usleep +.global usleep +.type usleep, %function +usleep: + movs r3, #5 + svc 0 + bx lr + +.end diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_simple/main.c b/miosix/_tools/testsuite/syscall_testsuite/testsuite_simple/main.c new file mode 100644 index 0000000000000000000000000000000000000000..00ea56a6cfa7fab92fcea8a9440dc31088dc19aa --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_simple/main.c @@ -0,0 +1,12 @@ +#include <unistd.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <string.h> +#include <stdio.h> +#include <stdlib.h> + +int main(){ + return RETURN_VALUE; +} diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_simple/miosix.ld b/miosix/_tools/testsuite/syscall_testsuite/testsuite_simple/miosix.ld new file mode 100644 index 0000000000000000000000000000000000000000..c91c803e629040b14233a8f8251a7d9952f68910 --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_simple/miosix.ld @@ -0,0 +1,66 @@ +/* + * Linker script for writing PROGRAMS for the Miosix embedded OS + * TFT:Terraneo Federico Technlogies + */ + +OUTPUT_FORMAT("elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) + +SECTIONS +{ + /* Here starts the first elf segment, that stays in flash */ + . = 0 + SIZEOF_HEADERS; + + .text : ALIGN(8) + { + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + } + + .rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) } + .rel.got : { *(.rel.got) } + + /* Here starts the second segment, that is copied in RAM and relocated */ + . = 0x10000000; + + .got : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) } + + /* FIXME: If this is put in the other segment, it makes it writable */ + .dynamic : { *(.dynamic) } + + /* FIXME: The compiler insists in addressing rodata relative to r9 */ + .rodata : ALIGN(8) + { + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + } + + .data : ALIGN(8) + { + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + } + + .bss : ALIGN(8) + { + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + } + + /* These are removed since are unused and increase binary size */ + /DISCARD/ : + { + *(.interp) + *(.dynsym) + *(.dynstr) + *(.hash) + *(.comment) + *(.ARM.attributes) + } +} diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_simple/prog3.h b/miosix/_tools/testsuite/syscall_testsuite/testsuite_simple/prog3.h new file mode 100644 index 0000000000000000000000000000000000000000..fd4cd50e8f54a68798894d655bb04cefa7a56827 --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_simple/prog3.h @@ -0,0 +1,22 @@ +const unsigned char __attribute__((aligned(8))) testsuite_simple_elf[] = { + 0x7f, 0x45, 0x4c, 0x46, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x28, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x99, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x05, 0x34, 0x00, 0x20, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, + 0x98, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x10, 0x34, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0xb4, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10, 0x0c, 0x00, 0x00, 0x10, + 0x28, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x02, 0xf8, + 0x00, 0xf0, 0x02, 0xf8, 0x2a, 0x20, 0x70, 0x47, 0x02, 0x23, 0x00, 0xdf, + 0x0c, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00, + 0x4d, 0x69, 0x6f, 0x73, 0x69, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 +}; +unsigned int testsuite_simple_elf_len = 220; diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_simple/test.txt b/miosix/_tools/testsuite/syscall_testsuite/testsuite_simple/test.txt new file mode 100644 index 0000000000000000000000000000000000000000..8e8264dfccb9d5bcedc3af5fd8bebe179a7a3eda --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_simple/test.txt @@ -0,0 +1,77 @@ + +testsuite_simple.elf: file format elf32-littlearm +testsuite_simple.elf +architecture: arm, flags 0x00000050: +HAS_SYMS, DYNAMIC +start address 0x00000099 + +Program Header: + LOAD off 0x00000098 vaddr 0x00000098 paddr 0x00000098 align 2**3 + filesz 0x00000010 memsz 0x00000010 flags r-x + LOAD off 0x000000a8 vaddr 0x10000000 paddr 0x10000000 align 2**2 + filesz 0x00000034 memsz 0x00000034 flags rw- + DYNAMIC off 0x000000b4 vaddr 0x1000000c paddr 0x1000000c align 2**2 + filesz 0x00000028 memsz 0x00000028 flags rw- + +Dynamic Section: + DEBUG 0x00000000 +private flags = 5000002: [Version5 EABI] [has entry point] + +Sections: +Idx Name Size VMA LMA File off Algn + 0 .text 00000010 00000098 00000098 00000098 2**3 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 1 .got 0000000c 10000000 10000000 000000a8 2**2 + CONTENTS, ALLOC, LOAD, DATA + 2 .dynamic 00000028 1000000c 1000000c 000000b4 2**2 + CONTENTS, ALLOC, LOAD, DATA +SYMBOL TABLE: +00000098 l d .text 00000000 .text +10000000 l d .got 00000000 .got +1000000c l d .dynamic 00000000 .dynamic +00000000 l df *ABS* 00000000 main.c +1000000c l O *ABS* 00000000 _DYNAMIC +10000000 l O *ABS* 00000000 _GLOBAL_OFFSET_TABLE_ +00000098 g F .text 00000000 _start +000000a0 g F .text 00000004 main +00000000 F *UND* 00000000 seek +000000a4 g F .text 00000000 _exit + + +Contents of section .text: + 0098 00f002f8 00f002f8 2a207047 022300df ........* pG.#.. +Contents of section .got: + 10000000 0c000010 00000000 00000000 ............ +Contents of section .dynamic: + 1000000c 15000000 00000000 00000000 00000000 ................ + 1000001c 00000000 00000000 00000000 00000000 ................ + 1000002c 00000000 00000000 ........ + +Disassembly of section .text: + +00000098 <_start>: +_start(): + 98: f000 f802 bl a0 <main> + 9c: f000 f802 bl a4 <_exit> + +000000a0 <main>: +main(): + a0: 202a movs r0, #42 ; 0x2a + a2: 4770 bx lr + +000000a4 <_exit>: +_exit(): + a4: 2302 movs r3, #2 + a6: df00 svc 0 + +Disassembly of section .got: + +10000000 <.got>: +10000000: 1000000c andne r0, r0, ip + ... + +Disassembly of section .dynamic: + +1000000c <.dynamic>: +1000000c: 00000015 andeq r0, r0, r5, lsl r0 + ... diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_sleep.h b/miosix/_tools/testsuite/syscall_testsuite/testsuite_sleep.h new file mode 100644 index 0000000000000000000000000000000000000000..bfe5d3e1198241e1f346f8b3bd858e3a792b007f --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_sleep.h @@ -0,0 +1,23 @@ +const unsigned char __attribute__((aligned(8))) testsuite_sleep_elf[] = { + 0x7f, 0x45, 0x4c, 0x46, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x28, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x99, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x05, 0x34, 0x00, 0x20, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, + 0x98, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, + 0x22, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0xbc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x10, 0x34, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0xc8, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10, 0x0c, 0x00, 0x00, 0x10, + 0x28, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x02, 0xf8, + 0x00, 0xf0, 0x08, 0xf8, 0x44, 0xf6, 0x40, 0x30, 0x08, 0xb5, 0xc0, 0xf2, + 0x4c, 0x00, 0x00, 0xf0, 0x03, 0xf8, 0x08, 0xbd, 0x02, 0x23, 0x00, 0xdf, + 0x05, 0x23, 0x00, 0xdf, 0x70, 0x47, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00, 0x4d, 0x69, 0x6f, 0x73, + 0x69, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +unsigned int testsuite_sleep_elf_len = 240; diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_sleep/Makefile b/miosix/_tools/testsuite/syscall_testsuite/testsuite_sleep/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..34f92e723fa43f571d53cbaaddcc9329cd32cb2b --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_sleep/Makefile @@ -0,0 +1,45 @@ +## +## Makefile for writing PROGRAMS for the Miosix embedded OS +## TFT:Terraneo Federico Technlogies +## + +SRC := \ +main.c + +## Replaces both "foo.cpp"-->"foo.o" and "foo.c"-->"foo.o" +OBJ := $(addsuffix .o, $(basename $(SRC))) +ELF := $(addsuffix .elf, $(NAME)) + +AS := arm-miosix-eabi-as +CC := arm-miosix-eabi-gcc +CXX := arm-miosix-eabi-g++ +SZ := arm-miosix-eabi-size + +AFLAGS := -mcpu=cortex-m3 -mthumb +CFLAGS := -mcpu=cortex-m3 -mthumb -mfix-cortex-m3-ldrd -fpie -msingle-pic-base \ + -ffunction-sections -O2 -Wall -c +CXXFLAGS := $(CFLAGS) +LFLAGS := -mcpu=cortex-m3 -mthumb -mfix-cortex-m3-ldrd -fpie -msingle-pic-base \ + -Wl,--gc-sections,-Map,test.map,-T./miosix.ld,-n,-pie,--spare-dynamic-tags,3 \ + -O2 -nostdlib + +LINK_LIBS := -Wl,--start-group -lstdc++ -lc -lm -lgcc -Wl,--end-group + +all: $(OBJ) crt0.o + $(CXX) $(LFLAGS) -o $(ELF) $(OBJ) crt0.o $(LINK_LIBS) + $(SZ) $(ELF) + @arm-miosix-eabi-objdump -Dslx $(ELF) > test.txt + @mx-postlinker $(ELF) --ramsize=16384 --stacksize=2048 --strip-sectheader + @xxd -i $(ELF) | sed 's/unsigned char/const unsigned char __attribute__((aligned(8)))/' > prog3.h + +clean: + -rm $(OBJ) crt0.o *.elf test.map test.txt + +%.o: %.s + $(AS) $(AFLAGS) $< -o $@ + +%.o : %.c + $(CC) $(CFLAGS) $< -o $@ + +%.o : %.cpp + $(CXX) $(CXXFLAGS) $< -o $@ diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_sleep/crt0.s b/miosix/_tools/testsuite/syscall_testsuite/testsuite_sleep/crt0.s new file mode 100644 index 0000000000000000000000000000000000000000..9959b317dcafd42e8cb82c896b3eef2e0205f7cc --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_sleep/crt0.s @@ -0,0 +1,131 @@ +/* + * Startup script for writing PROGRAMS for the Miosix embedded OS + * TFT:Terraneo Federico Technlogies + */ + +.syntax unified +.cpu cortex-m3 +.thumb + +.section .text + +/** + * _start, program entry point + */ +.global _start +.type _start, %function +_start: + /* TODO: .ctor */ + bl main + /* TODO: .dtor */ + bl _exit + +/** + * _exit, terminate process + * \param v exit value + */ +.section .text._exit +.global _exit +.type _exit, %function +_exit: + movs r3, #2 + svc 0 + +/** + * open, open a file + * \param fd file descriptor + * \param file access mode + * \param xxx access permisions + * \return file descriptor or -1 if errors + */ +.section .text.open +.global open +.type open, %function +open: + movs r3, #6 + svc 0 + bx lr + +/** + * close, close a file + * \param fd file descriptor + */ +.section .text.close +.global close +.type close, %function +close: + movs r3, #7 + svc 0 + bx lr + +/** + * seek + * \param fd file descriptor + * \param pos moving offset + * \param start position, SEEK_SET, SEEK_CUR or SEEK_END +*/ +.section .text.seek +.global seek +.type seek, %function +seek: + movs r3, #8 + svc 0 + bx lr + + +/** + * system, fork and execture a program, blocking + * \param program to execute + */ +.section .text.system +.global system +.type system, %function +system: + movs r3, #9 + svc 0 + bx lr + +/** + * write, write to file + * \param fd file descriptor + * \param buf data to be written + * \param len buffer length + * \return number of written bytes or -1 if errors + */ +.section .text.write +.global write +.type write, %function +write: + movs r3, #3 + svc 0 + bx lr + +/** + * read, read from file + * \param fd file descriptor + * \param buf data to be read + * \param len buffer length + * \return number of read bytes or -1 if errors + */ +.section .text.read +.global read +.type read, %function +read: + movs r3, #4 + svc 0 + bx lr + +/** + * usleep, sleep a specified number of microseconds + * \param us number of microseconds to sleep + * \return 0 on success or -1 if errors + */ +.section .text.usleep +.global usleep +.type usleep, %function +usleep: + movs r3, #5 + svc 0 + bx lr + +.end diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_sleep/main.c b/miosix/_tools/testsuite/syscall_testsuite/testsuite_sleep/main.c new file mode 100644 index 0000000000000000000000000000000000000000..5a9879272656419fc23edc5598860250a348a9c1 --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_sleep/main.c @@ -0,0 +1,11 @@ +#include <unistd.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <string.h> +#include <stdio.h> + +int main(){ + usleep(5000000); +} \ No newline at end of file diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_sleep/miosix.ld b/miosix/_tools/testsuite/syscall_testsuite/testsuite_sleep/miosix.ld new file mode 100644 index 0000000000000000000000000000000000000000..c91c803e629040b14233a8f8251a7d9952f68910 --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_sleep/miosix.ld @@ -0,0 +1,66 @@ +/* + * Linker script for writing PROGRAMS for the Miosix embedded OS + * TFT:Terraneo Federico Technlogies + */ + +OUTPUT_FORMAT("elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) + +SECTIONS +{ + /* Here starts the first elf segment, that stays in flash */ + . = 0 + SIZEOF_HEADERS; + + .text : ALIGN(8) + { + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + } + + .rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) } + .rel.got : { *(.rel.got) } + + /* Here starts the second segment, that is copied in RAM and relocated */ + . = 0x10000000; + + .got : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) } + + /* FIXME: If this is put in the other segment, it makes it writable */ + .dynamic : { *(.dynamic) } + + /* FIXME: The compiler insists in addressing rodata relative to r9 */ + .rodata : ALIGN(8) + { + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + } + + .data : ALIGN(8) + { + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + } + + .bss : ALIGN(8) + { + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + } + + /* These are removed since are unused and increase binary size */ + /DISCARD/ : + { + *(.interp) + *(.dynsym) + *(.dynstr) + *(.hash) + *(.comment) + *(.ARM.attributes) + } +} diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_sleep/prog3.h b/miosix/_tools/testsuite/syscall_testsuite/testsuite_sleep/prog3.h new file mode 100644 index 0000000000000000000000000000000000000000..bfe5d3e1198241e1f346f8b3bd858e3a792b007f --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_sleep/prog3.h @@ -0,0 +1,23 @@ +const unsigned char __attribute__((aligned(8))) testsuite_sleep_elf[] = { + 0x7f, 0x45, 0x4c, 0x46, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x28, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x99, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x05, 0x34, 0x00, 0x20, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, + 0x98, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, + 0x22, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0xbc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x10, 0x34, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0xc8, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10, 0x0c, 0x00, 0x00, 0x10, + 0x28, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x02, 0xf8, + 0x00, 0xf0, 0x08, 0xf8, 0x44, 0xf6, 0x40, 0x30, 0x08, 0xb5, 0xc0, 0xf2, + 0x4c, 0x00, 0x00, 0xf0, 0x03, 0xf8, 0x08, 0xbd, 0x02, 0x23, 0x00, 0xdf, + 0x05, 0x23, 0x00, 0xdf, 0x70, 0x47, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00, 0x4d, 0x69, 0x6f, 0x73, + 0x69, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +unsigned int testsuite_sleep_elf_len = 240; diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_sleep/test.txt b/miosix/_tools/testsuite/syscall_testsuite/testsuite_sleep/test.txt new file mode 100644 index 0000000000000000000000000000000000000000..c860216c5de5f69f8ca14ca07ced9e20b29fb21b --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_sleep/test.txt @@ -0,0 +1,88 @@ + +testsuite_sleep.elf: file format elf32-littlearm +testsuite_sleep.elf +architecture: arm, flags 0x00000050: +HAS_SYMS, DYNAMIC +start address 0x00000099 + +Program Header: + LOAD off 0x00000098 vaddr 0x00000098 paddr 0x00000098 align 2**3 + filesz 0x00000022 memsz 0x00000022 flags r-x + LOAD off 0x000000bc vaddr 0x10000000 paddr 0x10000000 align 2**2 + filesz 0x00000034 memsz 0x00000034 flags rw- + DYNAMIC off 0x000000c8 vaddr 0x1000000c paddr 0x1000000c align 2**2 + filesz 0x00000028 memsz 0x00000028 flags rw- + +Dynamic Section: + DEBUG 0x00000000 +private flags = 5000002: [Version5 EABI] [has entry point] + +Sections: +Idx Name Size VMA LMA File off Algn + 0 .text 00000022 00000098 00000098 00000098 2**3 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 1 .got 0000000c 10000000 10000000 000000bc 2**2 + CONTENTS, ALLOC, LOAD, DATA + 2 .dynamic 00000028 1000000c 1000000c 000000c8 2**2 + CONTENTS, ALLOC, LOAD, DATA +SYMBOL TABLE: +00000098 l d .text 00000000 .text +10000000 l d .got 00000000 .got +1000000c l d .dynamic 00000000 .dynamic +00000000 l df *ABS* 00000000 main.c +1000000c l O *ABS* 00000000 _DYNAMIC +10000000 l O *ABS* 00000000 _GLOBAL_OFFSET_TABLE_ +000000b4 g F .text 00000000 usleep +00000098 g F .text 00000000 _start +000000a0 g F .text 00000010 main +000000b0 g F .text 00000000 _exit + + +Contents of section .text: + 0098 00f002f8 00f008f8 44f64030 08b5c0f2 ........D.@0.... + 00a8 4c0000f0 03f808bd 022300df 052300df L........#...#.. + 00b8 7047 pG +Contents of section .got: + 10000000 0c000010 00000000 00000000 ............ +Contents of section .dynamic: + 1000000c 15000000 00000000 00000000 00000000 ................ + 1000001c 00000000 00000000 00000000 00000000 ................ + 1000002c 00000000 00000000 ........ + +Disassembly of section .text: + +00000098 <_start>: +_start(): + 98: f000 f802 bl a0 <main> + 9c: f000 f808 bl b0 <_exit> + +000000a0 <main>: +main(): + a0: f644 3040 movw r0, #19264 ; 0x4b40 + a4: b508 push {r3, lr} + a6: f2c0 004c movt r0, #76 ; 0x4c + aa: f000 f803 bl b4 <usleep> + ae: bd08 pop {r3, pc} + +000000b0 <_exit>: +_exit(): + b0: 2302 movs r3, #2 + b2: df00 svc 0 + +000000b4 <usleep>: +usleep(): + b4: 2305 movs r3, #5 + b6: df00 svc 0 + b8: 4770 bx lr + +Disassembly of section .got: + +10000000 <.got>: +10000000: 1000000c andne r0, r0, ip + ... + +Disassembly of section .dynamic: + +1000000c <.dynamic>: +1000000c: 00000015 andeq r0, r0, r5, lsl r0 + ... diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall.h b/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall.h new file mode 100644 index 0000000000000000000000000000000000000000..9da3e20b11c45059b60ad04de99553c35c631c7b --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall.h @@ -0,0 +1,75 @@ +const unsigned char __attribute__((aligned(8))) testsuite_syscall_elf[] = { + 0x7f, 0x45, 0x4c, 0x46, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x28, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x99, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x05, 0x34, 0x00, 0x20, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, + 0x98, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0xbe, 0x01, 0x00, 0x00, + 0xbe, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x58, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x10, 0x04, 0x01, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x64, 0x02, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10, 0x0c, 0x00, 0x00, 0x10, + 0x28, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x10, 0xf8, + 0x00, 0xf0, 0xca, 0xf8, 0x08, 0xb5, 0x02, 0x78, 0x01, 0x46, 0x22, 0xb1, + 0x00, 0x22, 0x01, 0x32, 0x8b, 0x5c, 0x00, 0x2b, 0xfb, 0xd1, 0x01, 0x20, + 0x00, 0xf0, 0xc9, 0xf8, 0x08, 0xbd, 0x00, 0xbf, 0x2d, 0xe9, 0xf0, 0x45, + 0xad, 0xf5, 0x00, 0x6d, 0x81, 0xb0, 0x00, 0x24, 0x0d, 0xf5, 0x80, 0x65, + 0x2c, 0x55, 0x01, 0x34, 0xb4, 0xf5, 0x80, 0x6f, 0xfa, 0xd1, 0x4e, 0x4f, + 0x02, 0x21, 0x09, 0xeb, 0x07, 0x06, 0x00, 0x22, 0x30, 0x46, 0x00, 0xf0, + 0xa9, 0xf8, 0xb0, 0xf1, 0xff, 0x3f, 0x05, 0xd0, 0x01, 0x20, 0x01, 0xb0, + 0x0d, 0xf5, 0x00, 0x6d, 0xbd, 0xe8, 0xf0, 0x85, 0x00, 0xf0, 0xa1, 0xf8, + 0x45, 0x48, 0x48, 0x44, 0xff, 0xf7, 0xce, 0xff, 0x30, 0x46, 0x00, 0x22, + 0x40, 0xf2, 0x02, 0x41, 0x00, 0xf0, 0x94, 0xf8, 0xb0, 0xf1, 0xff, 0x3f, + 0x06, 0x46, 0x11, 0xd0, 0x02, 0x28, 0x01, 0xd8, 0x03, 0x20, 0xe6, 0xe7, + 0x3d, 0x48, 0x48, 0x44, 0xff, 0xf7, 0xbc, 0xff, 0x30, 0x46, 0x29, 0x46, + 0x22, 0x46, 0x00, 0xf0, 0x8c, 0xf8, 0xb0, 0xf5, 0x80, 0x6f, 0x03, 0xd0, + 0x04, 0x20, 0xd8, 0xe7, 0x02, 0x20, 0xd6, 0xe7, 0x36, 0x48, 0xe8, 0x46, + 0x48, 0x44, 0xff, 0xf7, 0xab, 0xff, 0x00, 0x21, 0x0a, 0x46, 0x30, 0x46, + 0x00, 0xf0, 0x78, 0xf8, 0x30, 0x46, 0x69, 0x46, 0x22, 0x46, 0x00, 0xf0, + 0x79, 0xf8, 0xb0, 0xf5, 0x80, 0x6f, 0x01, 0xd0, 0x05, 0x20, 0xc2, 0xe7, + 0x4f, 0xf0, 0x00, 0x0a, 0x02, 0xe0, 0xba, 0xf5, 0x80, 0x6f, 0x09, 0xd0, + 0x15, 0xf8, 0x0a, 0x20, 0x18, 0xf8, 0x0a, 0x30, 0x0a, 0xf1, 0x01, 0x0a, + 0x9a, 0x42, 0xf4, 0xd0, 0x06, 0x20, 0xb2, 0xe7, 0x25, 0x48, 0x48, 0x44, + 0xff, 0xf7, 0x88, 0xff, 0x30, 0x46, 0x00, 0xf0, 0x54, 0xf8, 0x06, 0x46, + 0x08, 0xb1, 0x07, 0x20, 0xa7, 0xe7, 0x21, 0x48, 0x48, 0x44, 0xff, 0xf7, + 0x7d, 0xff, 0x02, 0x21, 0x09, 0xeb, 0x07, 0x00, 0x00, 0xf0, 0x44, 0xf8, + 0x01, 0x28, 0x04, 0x46, 0x0d, 0xdd, 0x1c, 0x48, 0x48, 0x44, 0xff, 0xf7, + 0x71, 0xff, 0x20, 0x46, 0x69, 0x46, 0x52, 0x46, 0x00, 0xf0, 0x44, 0xf8, + 0xb0, 0xf5, 0x80, 0x6f, 0x03, 0xd0, 0x09, 0x20, 0x8d, 0xe7, 0x08, 0x20, + 0x8b, 0xe7, 0xaa, 0x5d, 0x18, 0xf8, 0x06, 0x30, 0x01, 0x36, 0x9a, 0x42, + 0x0d, 0xd1, 0xb6, 0xf5, 0x80, 0x6f, 0xf6, 0xd1, 0x10, 0x48, 0x48, 0x44, + 0xff, 0xf7, 0x58, 0xff, 0x20, 0x46, 0x00, 0xf0, 0x24, 0xf8, 0x04, 0x46, + 0x18, 0xb1, 0x0b, 0x20, 0x77, 0xe7, 0x0a, 0x20, 0x75, 0xe7, 0x0b, 0x48, + 0x48, 0x44, 0xff, 0xf7, 0x4b, 0xff, 0x20, 0x46, 0x6f, 0xe7, 0x00, 0xbf, + 0x38, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, + 0x7c, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, + 0xb0, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00, 0xf4, 0x00, 0x00, 0x00, + 0x02, 0x23, 0x00, 0xdf, 0x06, 0x23, 0x00, 0xdf, 0x70, 0x47, 0x07, 0x23, + 0x00, 0xdf, 0x70, 0x47, 0x08, 0x23, 0x00, 0xdf, 0x70, 0x47, 0x03, 0x23, + 0x00, 0xdf, 0x70, 0x47, 0x04, 0x23, 0x00, 0xdf, 0x70, 0x47, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00, + 0x4d, 0x69, 0x6f, 0x73, 0x69, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x6f, 0x6f, 0x2e, + 0x62, 0x69, 0x6e, 0x00, 0x27, 0x4f, 0x70, 0x65, 0x6e, 0x27, 0x20, 0x6f, + 0x66, 0x20, 0x6e, 0x6f, 0x6e, 0x20, 0x65, 0x78, 0x69, 0x73, 0x74, 0x69, + 0x6e, 0x67, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x3a, 0x20, 0x50, 0x61, 0x73, + 0x73, 0x65, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x70, 0x65, 0x6e, + 0x20, 0x66, 0x69, 0x6c, 0x65, 0x3a, 0x20, 0x50, 0x61, 0x73, 0x73, 0x65, + 0x64, 0x0a, 0x00, 0x00, 0x57, 0x72, 0x69, 0x74, 0x65, 0x20, 0x66, 0x69, + 0x6c, 0x65, 0x3a, 0x20, 0x50, 0x61, 0x73, 0x73, 0x65, 0x64, 0x0a, 0x00, + 0x52, 0x65, 0x61, 0x64, 0x3a, 0x20, 0x50, 0x61, 0x73, 0x73, 0x65, 0x64, + 0x0a, 0x00, 0x00, 0x00, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x3a, 0x20, 0x50, + 0x61, 0x73, 0x73, 0x65, 0x64, 0x0a, 0x00, 0x00, 0x4f, 0x70, 0x65, 0x6e, + 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x65, 0x78, 0x69, 0x73, 0x74, + 0x69, 0x6e, 0x67, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x3a, 0x20, 0x50, 0x61, + 0x73, 0x73, 0x65, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x52, 0x65, 0x61, 0x64, + 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x63, 0x6f, 0x72, 0x65, 0x63, 0x74, + 0x6e, 0x65, 0x73, 0x73, 0x3a, 0x20, 0x50, 0x61, 0x73, 0x73, 0x65, 0x64, + 0x0a, 0x00, 0x00, 0x00, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x3a, 0x20, 0x70, + 0x61, 0x73, 0x73, 0x65, 0x64, 0x0a, 0x00, 0x00 +}; +unsigned int testsuite_syscall_elf_len = 860; diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall/Makefile b/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..34f92e723fa43f571d53cbaaddcc9329cd32cb2b --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall/Makefile @@ -0,0 +1,45 @@ +## +## Makefile for writing PROGRAMS for the Miosix embedded OS +## TFT:Terraneo Federico Technlogies +## + +SRC := \ +main.c + +## Replaces both "foo.cpp"-->"foo.o" and "foo.c"-->"foo.o" +OBJ := $(addsuffix .o, $(basename $(SRC))) +ELF := $(addsuffix .elf, $(NAME)) + +AS := arm-miosix-eabi-as +CC := arm-miosix-eabi-gcc +CXX := arm-miosix-eabi-g++ +SZ := arm-miosix-eabi-size + +AFLAGS := -mcpu=cortex-m3 -mthumb +CFLAGS := -mcpu=cortex-m3 -mthumb -mfix-cortex-m3-ldrd -fpie -msingle-pic-base \ + -ffunction-sections -O2 -Wall -c +CXXFLAGS := $(CFLAGS) +LFLAGS := -mcpu=cortex-m3 -mthumb -mfix-cortex-m3-ldrd -fpie -msingle-pic-base \ + -Wl,--gc-sections,-Map,test.map,-T./miosix.ld,-n,-pie,--spare-dynamic-tags,3 \ + -O2 -nostdlib + +LINK_LIBS := -Wl,--start-group -lstdc++ -lc -lm -lgcc -Wl,--end-group + +all: $(OBJ) crt0.o + $(CXX) $(LFLAGS) -o $(ELF) $(OBJ) crt0.o $(LINK_LIBS) + $(SZ) $(ELF) + @arm-miosix-eabi-objdump -Dslx $(ELF) > test.txt + @mx-postlinker $(ELF) --ramsize=16384 --stacksize=2048 --strip-sectheader + @xxd -i $(ELF) | sed 's/unsigned char/const unsigned char __attribute__((aligned(8)))/' > prog3.h + +clean: + -rm $(OBJ) crt0.o *.elf test.map test.txt + +%.o: %.s + $(AS) $(AFLAGS) $< -o $@ + +%.o : %.c + $(CC) $(CFLAGS) $< -o $@ + +%.o : %.cpp + $(CXX) $(CXXFLAGS) $< -o $@ diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall/crt0.s b/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall/crt0.s new file mode 100644 index 0000000000000000000000000000000000000000..9959b317dcafd42e8cb82c896b3eef2e0205f7cc --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall/crt0.s @@ -0,0 +1,131 @@ +/* + * Startup script for writing PROGRAMS for the Miosix embedded OS + * TFT:Terraneo Federico Technlogies + */ + +.syntax unified +.cpu cortex-m3 +.thumb + +.section .text + +/** + * _start, program entry point + */ +.global _start +.type _start, %function +_start: + /* TODO: .ctor */ + bl main + /* TODO: .dtor */ + bl _exit + +/** + * _exit, terminate process + * \param v exit value + */ +.section .text._exit +.global _exit +.type _exit, %function +_exit: + movs r3, #2 + svc 0 + +/** + * open, open a file + * \param fd file descriptor + * \param file access mode + * \param xxx access permisions + * \return file descriptor or -1 if errors + */ +.section .text.open +.global open +.type open, %function +open: + movs r3, #6 + svc 0 + bx lr + +/** + * close, close a file + * \param fd file descriptor + */ +.section .text.close +.global close +.type close, %function +close: + movs r3, #7 + svc 0 + bx lr + +/** + * seek + * \param fd file descriptor + * \param pos moving offset + * \param start position, SEEK_SET, SEEK_CUR or SEEK_END +*/ +.section .text.seek +.global seek +.type seek, %function +seek: + movs r3, #8 + svc 0 + bx lr + + +/** + * system, fork and execture a program, blocking + * \param program to execute + */ +.section .text.system +.global system +.type system, %function +system: + movs r3, #9 + svc 0 + bx lr + +/** + * write, write to file + * \param fd file descriptor + * \param buf data to be written + * \param len buffer length + * \return number of written bytes or -1 if errors + */ +.section .text.write +.global write +.type write, %function +write: + movs r3, #3 + svc 0 + bx lr + +/** + * read, read from file + * \param fd file descriptor + * \param buf data to be read + * \param len buffer length + * \return number of read bytes or -1 if errors + */ +.section .text.read +.global read +.type read, %function +read: + movs r3, #4 + svc 0 + bx lr + +/** + * usleep, sleep a specified number of microseconds + * \param us number of microseconds to sleep + * \return 0 on success or -1 if errors + */ +.section .text.usleep +.global usleep +.type usleep, %function +usleep: + movs r3, #5 + svc 0 + bx lr + +.end diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall/main.c b/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall/main.c new file mode 100644 index 0000000000000000000000000000000000000000..042e8da868deaab072423be41a050c1193a299e2 --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall/main.c @@ -0,0 +1,100 @@ +#include <unistd.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <string.h> +#include <stdio.h> + + +#define error(x) (x) + +#define SIZE 1024 + +int mystrlen(const char *s){ + int result=0; + while(*s++) result++; + return result; +} + +void print(const char *s){ + write(1, s, mystrlen(s)); +} + +#define FILE_PATH "foo.bin" + +int main(){ + unsigned char buffer[SIZE], + buffer2[SIZE]; + + int i = 0; + int fd = 0; + + for(i = 0; i < SIZE; i++) + buffer[i] = i; + + fd = open(FILE_PATH, O_RDWR, 0); + + if(fd != -1) + return error(1); + + close(fd); + + print("'Open' of non existing file: Passed\n"); + + fd = open(FILE_PATH, O_RDWR|O_TRUNC, 0); + + if(fd == -1) + return error(2); + + if(fd >= 0 && fd <= 2) + return error(3); + + print("Open file: Passed\n"); + + if(write(fd, buffer, SIZE) != SIZE) + return error(4); + + print("Write file: Passed\n"); + + seek(fd, SEEK_SET, 0); + + if(read(fd, buffer2, SIZE) != SIZE) + return error(5); + + for(i = 0; i < SIZE; i++){ + if(buffer[i] != buffer2[i]) + return error(6); + } + + print("Read: Passed\n"); + + if(close(fd) != 0) + return error(7); + + print("close: Passed\n"); + + fd = open(FILE_PATH, O_RDWR); + + if(fd < 2) + return error(8); + + print("Open of an existing file: Passed\n"); + + if(read(fd, buffer2, SIZE) != SIZE) + return error(9); + + for(i = 0; i < SIZE; i++){ + if(buffer[i] != buffer2[i]) + return error(10); + } + + print("Read data corectness: Passed\n"); + + if(close(fd)) + return error(11); + + print("close: passed\n"); + + return 0; +} \ No newline at end of file diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall/miosix.ld b/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall/miosix.ld new file mode 100644 index 0000000000000000000000000000000000000000..c91c803e629040b14233a8f8251a7d9952f68910 --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall/miosix.ld @@ -0,0 +1,66 @@ +/* + * Linker script for writing PROGRAMS for the Miosix embedded OS + * TFT:Terraneo Federico Technlogies + */ + +OUTPUT_FORMAT("elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) + +SECTIONS +{ + /* Here starts the first elf segment, that stays in flash */ + . = 0 + SIZEOF_HEADERS; + + .text : ALIGN(8) + { + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + } + + .rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) } + .rel.got : { *(.rel.got) } + + /* Here starts the second segment, that is copied in RAM and relocated */ + . = 0x10000000; + + .got : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) } + + /* FIXME: If this is put in the other segment, it makes it writable */ + .dynamic : { *(.dynamic) } + + /* FIXME: The compiler insists in addressing rodata relative to r9 */ + .rodata : ALIGN(8) + { + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + } + + .data : ALIGN(8) + { + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + } + + .bss : ALIGN(8) + { + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + } + + /* These are removed since are unused and increase binary size */ + /DISCARD/ : + { + *(.interp) + *(.dynsym) + *(.dynstr) + *(.hash) + *(.comment) + *(.ARM.attributes) + } +} diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall/prog3.h b/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall/prog3.h new file mode 100644 index 0000000000000000000000000000000000000000..9da3e20b11c45059b60ad04de99553c35c631c7b --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall/prog3.h @@ -0,0 +1,75 @@ +const unsigned char __attribute__((aligned(8))) testsuite_syscall_elf[] = { + 0x7f, 0x45, 0x4c, 0x46, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x28, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x99, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x05, 0x34, 0x00, 0x20, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, + 0x98, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0xbe, 0x01, 0x00, 0x00, + 0xbe, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x58, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x10, 0x04, 0x01, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x64, 0x02, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10, 0x0c, 0x00, 0x00, 0x10, + 0x28, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x10, 0xf8, + 0x00, 0xf0, 0xca, 0xf8, 0x08, 0xb5, 0x02, 0x78, 0x01, 0x46, 0x22, 0xb1, + 0x00, 0x22, 0x01, 0x32, 0x8b, 0x5c, 0x00, 0x2b, 0xfb, 0xd1, 0x01, 0x20, + 0x00, 0xf0, 0xc9, 0xf8, 0x08, 0xbd, 0x00, 0xbf, 0x2d, 0xe9, 0xf0, 0x45, + 0xad, 0xf5, 0x00, 0x6d, 0x81, 0xb0, 0x00, 0x24, 0x0d, 0xf5, 0x80, 0x65, + 0x2c, 0x55, 0x01, 0x34, 0xb4, 0xf5, 0x80, 0x6f, 0xfa, 0xd1, 0x4e, 0x4f, + 0x02, 0x21, 0x09, 0xeb, 0x07, 0x06, 0x00, 0x22, 0x30, 0x46, 0x00, 0xf0, + 0xa9, 0xf8, 0xb0, 0xf1, 0xff, 0x3f, 0x05, 0xd0, 0x01, 0x20, 0x01, 0xb0, + 0x0d, 0xf5, 0x00, 0x6d, 0xbd, 0xe8, 0xf0, 0x85, 0x00, 0xf0, 0xa1, 0xf8, + 0x45, 0x48, 0x48, 0x44, 0xff, 0xf7, 0xce, 0xff, 0x30, 0x46, 0x00, 0x22, + 0x40, 0xf2, 0x02, 0x41, 0x00, 0xf0, 0x94, 0xf8, 0xb0, 0xf1, 0xff, 0x3f, + 0x06, 0x46, 0x11, 0xd0, 0x02, 0x28, 0x01, 0xd8, 0x03, 0x20, 0xe6, 0xe7, + 0x3d, 0x48, 0x48, 0x44, 0xff, 0xf7, 0xbc, 0xff, 0x30, 0x46, 0x29, 0x46, + 0x22, 0x46, 0x00, 0xf0, 0x8c, 0xf8, 0xb0, 0xf5, 0x80, 0x6f, 0x03, 0xd0, + 0x04, 0x20, 0xd8, 0xe7, 0x02, 0x20, 0xd6, 0xe7, 0x36, 0x48, 0xe8, 0x46, + 0x48, 0x44, 0xff, 0xf7, 0xab, 0xff, 0x00, 0x21, 0x0a, 0x46, 0x30, 0x46, + 0x00, 0xf0, 0x78, 0xf8, 0x30, 0x46, 0x69, 0x46, 0x22, 0x46, 0x00, 0xf0, + 0x79, 0xf8, 0xb0, 0xf5, 0x80, 0x6f, 0x01, 0xd0, 0x05, 0x20, 0xc2, 0xe7, + 0x4f, 0xf0, 0x00, 0x0a, 0x02, 0xe0, 0xba, 0xf5, 0x80, 0x6f, 0x09, 0xd0, + 0x15, 0xf8, 0x0a, 0x20, 0x18, 0xf8, 0x0a, 0x30, 0x0a, 0xf1, 0x01, 0x0a, + 0x9a, 0x42, 0xf4, 0xd0, 0x06, 0x20, 0xb2, 0xe7, 0x25, 0x48, 0x48, 0x44, + 0xff, 0xf7, 0x88, 0xff, 0x30, 0x46, 0x00, 0xf0, 0x54, 0xf8, 0x06, 0x46, + 0x08, 0xb1, 0x07, 0x20, 0xa7, 0xe7, 0x21, 0x48, 0x48, 0x44, 0xff, 0xf7, + 0x7d, 0xff, 0x02, 0x21, 0x09, 0xeb, 0x07, 0x00, 0x00, 0xf0, 0x44, 0xf8, + 0x01, 0x28, 0x04, 0x46, 0x0d, 0xdd, 0x1c, 0x48, 0x48, 0x44, 0xff, 0xf7, + 0x71, 0xff, 0x20, 0x46, 0x69, 0x46, 0x52, 0x46, 0x00, 0xf0, 0x44, 0xf8, + 0xb0, 0xf5, 0x80, 0x6f, 0x03, 0xd0, 0x09, 0x20, 0x8d, 0xe7, 0x08, 0x20, + 0x8b, 0xe7, 0xaa, 0x5d, 0x18, 0xf8, 0x06, 0x30, 0x01, 0x36, 0x9a, 0x42, + 0x0d, 0xd1, 0xb6, 0xf5, 0x80, 0x6f, 0xf6, 0xd1, 0x10, 0x48, 0x48, 0x44, + 0xff, 0xf7, 0x58, 0xff, 0x20, 0x46, 0x00, 0xf0, 0x24, 0xf8, 0x04, 0x46, + 0x18, 0xb1, 0x0b, 0x20, 0x77, 0xe7, 0x0a, 0x20, 0x75, 0xe7, 0x0b, 0x48, + 0x48, 0x44, 0xff, 0xf7, 0x4b, 0xff, 0x20, 0x46, 0x6f, 0xe7, 0x00, 0xbf, + 0x38, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, + 0x7c, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, + 0xb0, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00, 0xf4, 0x00, 0x00, 0x00, + 0x02, 0x23, 0x00, 0xdf, 0x06, 0x23, 0x00, 0xdf, 0x70, 0x47, 0x07, 0x23, + 0x00, 0xdf, 0x70, 0x47, 0x08, 0x23, 0x00, 0xdf, 0x70, 0x47, 0x03, 0x23, + 0x00, 0xdf, 0x70, 0x47, 0x04, 0x23, 0x00, 0xdf, 0x70, 0x47, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00, + 0x4d, 0x69, 0x6f, 0x73, 0x69, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x6f, 0x6f, 0x2e, + 0x62, 0x69, 0x6e, 0x00, 0x27, 0x4f, 0x70, 0x65, 0x6e, 0x27, 0x20, 0x6f, + 0x66, 0x20, 0x6e, 0x6f, 0x6e, 0x20, 0x65, 0x78, 0x69, 0x73, 0x74, 0x69, + 0x6e, 0x67, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x3a, 0x20, 0x50, 0x61, 0x73, + 0x73, 0x65, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x70, 0x65, 0x6e, + 0x20, 0x66, 0x69, 0x6c, 0x65, 0x3a, 0x20, 0x50, 0x61, 0x73, 0x73, 0x65, + 0x64, 0x0a, 0x00, 0x00, 0x57, 0x72, 0x69, 0x74, 0x65, 0x20, 0x66, 0x69, + 0x6c, 0x65, 0x3a, 0x20, 0x50, 0x61, 0x73, 0x73, 0x65, 0x64, 0x0a, 0x00, + 0x52, 0x65, 0x61, 0x64, 0x3a, 0x20, 0x50, 0x61, 0x73, 0x73, 0x65, 0x64, + 0x0a, 0x00, 0x00, 0x00, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x3a, 0x20, 0x50, + 0x61, 0x73, 0x73, 0x65, 0x64, 0x0a, 0x00, 0x00, 0x4f, 0x70, 0x65, 0x6e, + 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x65, 0x78, 0x69, 0x73, 0x74, + 0x69, 0x6e, 0x67, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x3a, 0x20, 0x50, 0x61, + 0x73, 0x73, 0x65, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x52, 0x65, 0x61, 0x64, + 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x63, 0x6f, 0x72, 0x65, 0x63, 0x74, + 0x6e, 0x65, 0x73, 0x73, 0x3a, 0x20, 0x50, 0x61, 0x73, 0x73, 0x65, 0x64, + 0x0a, 0x00, 0x00, 0x00, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x3a, 0x20, 0x70, + 0x61, 0x73, 0x73, 0x65, 0x64, 0x0a, 0x00, 0x00 +}; +unsigned int testsuite_syscall_elf_len = 860; diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall/test.txt b/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall/test.txt new file mode 100644 index 0000000000000000000000000000000000000000..eeef106f614c98c239a761e51d2c1d1efc3c55fc --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall/test.txt @@ -0,0 +1,365 @@ + +testsuite_syscall.elf: file format elf32-littlearm +testsuite_syscall.elf +architecture: arm, flags 0x00000050: +HAS_SYMS, DYNAMIC +start address 0x00000099 + +Program Header: + LOAD off 0x00000098 vaddr 0x00000098 paddr 0x00000098 align 2**3 + filesz 0x000001be memsz 0x000001be flags r-x + LOAD off 0x00000258 vaddr 0x10000000 paddr 0x10000000 align 2**3 + filesz 0x00000104 memsz 0x00000104 flags rw- + DYNAMIC off 0x00000264 vaddr 0x1000000c paddr 0x1000000c align 2**2 + filesz 0x00000028 memsz 0x00000028 flags rw- + +Dynamic Section: + DEBUG 0x00000000 +private flags = 5000002: [Version5 EABI] [has entry point] + +Sections: +Idx Name Size VMA LMA File off Algn + 0 .text 000001be 00000098 00000098 00000098 2**3 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 1 .got 0000000c 10000000 10000000 00000258 2**2 + CONTENTS, ALLOC, LOAD, DATA + 2 .dynamic 00000028 1000000c 1000000c 00000264 2**2 + CONTENTS, ALLOC, LOAD, DATA + 3 .rodata 000000cc 10000038 10000038 00000290 2**3 + CONTENTS, ALLOC, LOAD, READONLY, DATA +SYMBOL TABLE: +00000098 l d .text 00000000 .text +10000000 l d .got 00000000 .got +1000000c l d .dynamic 00000000 .dynamic +10000038 l d .rodata 00000000 .rodata +00000000 l df *ABS* 00000000 main.c +1000000c l O *ABS* 00000000 _DYNAMIC +10000000 l O *ABS* 00000000 _GLOBAL_OFFSET_TABLE_ +000000a0 g F .text 0000001a print +0000024a g F .text 00000000 write +00000098 g F .text 00000000 _start +00000250 g F .text 00000000 read +000000bc g F .text 00000178 main +00000244 g F .text 00000000 seek +00000234 g F .text 00000000 _exit +00000238 g F .text 00000000 open +0000023e g F .text 00000000 close + + +Contents of section .text: + 0098 00f010f8 00f0caf8 08b50278 014622b1 ...........x.F". + 00a8 00220132 8b5c002b fbd10120 00f0c9f8 .".2.\.+... .... + 00b8 08bd00bf 2de9f045 adf5006d 81b00024 ....-..E...m...$ + 00c8 0df58065 2c550134 b4f5806f fad14e4f ...e,U.4...o..NO + 00d8 022109eb 07060022 304600f0 a9f8b0f1 .!....."0F...... + 00e8 ff3f05d0 012001b0 0df5006d bde8f085 .?... .....m.... + 00f8 00f0a1f8 45484844 fff7ceff 30460022 ....EHHD....0F." + 0108 40f20241 00f094f8 b0f1ff3f 064611d0 @..A.......?.F.. + 0118 022801d8 0320e6e7 3d484844 fff7bcff .(... ..=HHD.... + 0128 30462946 224600f0 8cf8b0f5 806f03d0 0F)F"F.......o.. + 0138 0420d8e7 0220d6e7 3648e846 4844fff7 . ... ..6H.FHD.. + 0148 abff0021 0a463046 00f078f8 30466946 ...!.F0F..x.0FiF + 0158 224600f0 79f8b0f5 806f01d0 0520c2e7 "F..y....o... .. + 0168 4ff0000a 02e0baf5 806f09d0 15f80a20 O........o..... + 0178 18f80a30 0af1010a 9a42f4d0 0620b2e7 ...0.....B... .. + 0188 25484844 fff788ff 304600f0 54f80646 %HHD....0F..T..F + 0198 08b10720 a7e72148 4844fff7 7dff0221 ... ..!HHD..}..! + 01a8 09eb0700 00f044f8 01280446 0ddd1c48 ......D..(.F...H + 01b8 4844fff7 71ff2046 69465246 00f044f8 HD..q. FiFRF..D. + 01c8 b0f5806f 03d00920 8de70820 8be7aa5d ...o... ... ...] + 01d8 18f80630 01369a42 0dd1b6f5 806ff6d1 ...0.6.B.....o.. + 01e8 10484844 fff758ff 204600f0 24f80446 .HHD..X. F..$..F + 01f8 18b10b20 77e70a20 75e70b48 4844fff7 ... w.. u..HHD.. + 0208 4bff2046 6fe700bf 38000000 40000000 K. Fo...8...@... + 0218 68000000 7c000000 90000000 a0000000 h...|........... + 0228 b0000000 d4000000 f4000000 022300df .............#.. + 0238 062300df 70470723 00df7047 082300df .#..pG.#..pG.#.. + 0248 70470323 00df7047 042300df 7047 pG.#..pG.#..pG +Contents of section .got: + 10000000 0c000010 00000000 00000000 ............ +Contents of section .dynamic: + 1000000c 15000000 00000000 00000000 00000000 ................ + 1000001c 00000000 00000000 00000000 00000000 ................ + 1000002c 00000000 00000000 ........ +Contents of section .rodata: + 10000038 666f6f2e 62696e00 274f7065 6e27206f foo.bin.'Open' o + 10000048 66206e6f 6e206578 69737469 6e672066 f non existing f + 10000058 696c653a 20506173 7365640a 00000000 ile: Passed..... + 10000068 4f70656e 2066696c 653a2050 61737365 Open file: Passe + 10000078 640a0000 57726974 65206669 6c653a20 d...Write file: + 10000088 50617373 65640a00 52656164 3a205061 Passed..Read: Pa + 10000098 73736564 0a000000 636c6f73 653a2050 ssed....close: P + 100000a8 61737365 640a0000 4f70656e 206f6620 assed...Open of + 100000b8 616e2065 78697374 696e6720 66696c65 an existing file + 100000c8 3a205061 73736564 0a000000 52656164 : Passed....Read + 100000d8 20646174 6120636f 72656374 6e657373 data corectness + 100000e8 3a205061 73736564 0a000000 636c6f73 : Passed....clos + 100000f8 653a2070 61737365 640a0000 e: passed... + +Disassembly of section .text: + +00000098 <_start>: +_start(): + 98: f000 f810 bl bc <main> + 9c: f000 f8ca bl 234 <_exit> + +000000a0 <print>: +print(): + a0: b508 push {r3, lr} + a2: 7802 ldrb r2, [r0, #0] + a4: 4601 mov r1, r0 + a6: b122 cbz r2, b2 <print+0x12> + a8: 2200 movs r2, #0 + aa: 3201 adds r2, #1 + ac: 5c8b ldrb r3, [r1, r2] + ae: 2b00 cmp r3, #0 + b0: d1fb bne.n aa <print+0xa> + b2: 2001 movs r0, #1 + b4: f000 f8c9 bl 24a <write> + b8: bd08 pop {r3, pc} + ba: bf00 nop + +000000bc <main>: +main(): + bc: e92d 45f0 stmdb sp!, {r4, r5, r6, r7, r8, sl, lr} + c0: f5ad 6d00 sub.w sp, sp, #2048 ; 0x800 + c4: b081 sub sp, #4 + c6: 2400 movs r4, #0 + c8: f50d 6580 add.w r5, sp, #1024 ; 0x400 + cc: 552c strb r4, [r5, r4] + ce: 3401 adds r4, #1 + d0: f5b4 6f80 cmp.w r4, #1024 ; 0x400 + d4: d1fa bne.n cc <main+0x10> + d6: 4f4e ldr r7, [pc, #312] ; (210 <main+0x154>) + d8: 2102 movs r1, #2 + da: eb09 0607 add.w r6, r9, r7 + de: 2200 movs r2, #0 + e0: 4630 mov r0, r6 + e2: f000 f8a9 bl 238 <open> + e6: f1b0 3fff cmp.w r0, #4294967295 ; 0xffffffff + ea: d005 beq.n f8 <main+0x3c> + ec: 2001 movs r0, #1 + ee: b001 add sp, #4 + f0: f50d 6d00 add.w sp, sp, #2048 ; 0x800 + f4: e8bd 85f0 ldmia.w sp!, {r4, r5, r6, r7, r8, sl, pc} + f8: f000 f8a1 bl 23e <close> + fc: 4845 ldr r0, [pc, #276] ; (214 <main+0x158>) + fe: 4448 add r0, r9 + 100: f7ff ffce bl a0 <print> + 104: 4630 mov r0, r6 + 106: 2200 movs r2, #0 + 108: f240 4102 movw r1, #1026 ; 0x402 + 10c: f000 f894 bl 238 <open> + 110: f1b0 3fff cmp.w r0, #4294967295 ; 0xffffffff + 114: 4606 mov r6, r0 + 116: d011 beq.n 13c <main+0x80> + 118: 2802 cmp r0, #2 + 11a: d801 bhi.n 120 <main+0x64> + 11c: 2003 movs r0, #3 + 11e: e7e6 b.n ee <main+0x32> + 120: 483d ldr r0, [pc, #244] ; (218 <main+0x15c>) + 122: 4448 add r0, r9 + 124: f7ff ffbc bl a0 <print> + 128: 4630 mov r0, r6 + 12a: 4629 mov r1, r5 + 12c: 4622 mov r2, r4 + 12e: f000 f88c bl 24a <write> + 132: f5b0 6f80 cmp.w r0, #1024 ; 0x400 + 136: d003 beq.n 140 <main+0x84> + 138: 2004 movs r0, #4 + 13a: e7d8 b.n ee <main+0x32> + 13c: 2002 movs r0, #2 + 13e: e7d6 b.n ee <main+0x32> + 140: 4836 ldr r0, [pc, #216] ; (21c <main+0x160>) + 142: 46e8 mov r8, sp + 144: 4448 add r0, r9 + 146: f7ff ffab bl a0 <print> + 14a: 2100 movs r1, #0 + 14c: 460a mov r2, r1 + 14e: 4630 mov r0, r6 + 150: f000 f878 bl 244 <seek> + 154: 4630 mov r0, r6 + 156: 4669 mov r1, sp + 158: 4622 mov r2, r4 + 15a: f000 f879 bl 250 <read> + 15e: f5b0 6f80 cmp.w r0, #1024 ; 0x400 + 162: d001 beq.n 168 <main+0xac> + 164: 2005 movs r0, #5 + 166: e7c2 b.n ee <main+0x32> + 168: f04f 0a00 mov.w sl, #0 + 16c: e002 b.n 174 <main+0xb8> + 16e: f5ba 6f80 cmp.w sl, #1024 ; 0x400 + 172: d009 beq.n 188 <main+0xcc> + 174: f815 200a ldrb.w r2, [r5, sl] + 178: f818 300a ldrb.w r3, [r8, sl] + 17c: f10a 0a01 add.w sl, sl, #1 + 180: 429a cmp r2, r3 + 182: d0f4 beq.n 16e <main+0xb2> + 184: 2006 movs r0, #6 + 186: e7b2 b.n ee <main+0x32> + 188: 4825 ldr r0, [pc, #148] ; (220 <main+0x164>) + 18a: 4448 add r0, r9 + 18c: f7ff ff88 bl a0 <print> + 190: 4630 mov r0, r6 + 192: f000 f854 bl 23e <close> + 196: 4606 mov r6, r0 + 198: b108 cbz r0, 19e <main+0xe2> + 19a: 2007 movs r0, #7 + 19c: e7a7 b.n ee <main+0x32> + 19e: 4821 ldr r0, [pc, #132] ; (224 <main+0x168>) + 1a0: 4448 add r0, r9 + 1a2: f7ff ff7d bl a0 <print> + 1a6: 2102 movs r1, #2 + 1a8: eb09 0007 add.w r0, r9, r7 + 1ac: f000 f844 bl 238 <open> + 1b0: 2801 cmp r0, #1 + 1b2: 4604 mov r4, r0 + 1b4: dd0d ble.n 1d2 <main+0x116> + 1b6: 481c ldr r0, [pc, #112] ; (228 <main+0x16c>) + 1b8: 4448 add r0, r9 + 1ba: f7ff ff71 bl a0 <print> + 1be: 4620 mov r0, r4 + 1c0: 4669 mov r1, sp + 1c2: 4652 mov r2, sl + 1c4: f000 f844 bl 250 <read> + 1c8: f5b0 6f80 cmp.w r0, #1024 ; 0x400 + 1cc: d003 beq.n 1d6 <main+0x11a> + 1ce: 2009 movs r0, #9 + 1d0: e78d b.n ee <main+0x32> + 1d2: 2008 movs r0, #8 + 1d4: e78b b.n ee <main+0x32> + 1d6: 5daa ldrb r2, [r5, r6] + 1d8: f818 3006 ldrb.w r3, [r8, r6] + 1dc: 3601 adds r6, #1 + 1de: 429a cmp r2, r3 + 1e0: d10d bne.n 1fe <main+0x142> + 1e2: f5b6 6f80 cmp.w r6, #1024 ; 0x400 + 1e6: d1f6 bne.n 1d6 <main+0x11a> + 1e8: 4810 ldr r0, [pc, #64] ; (22c <main+0x170>) + 1ea: 4448 add r0, r9 + 1ec: f7ff ff58 bl a0 <print> + 1f0: 4620 mov r0, r4 + 1f2: f000 f824 bl 23e <close> + 1f6: 4604 mov r4, r0 + 1f8: b118 cbz r0, 202 <main+0x146> + 1fa: 200b movs r0, #11 + 1fc: e777 b.n ee <main+0x32> + 1fe: 200a movs r0, #10 + 200: e775 b.n ee <main+0x32> + 202: 480b ldr r0, [pc, #44] ; (230 <main+0x174>) + 204: 4448 add r0, r9 + 206: f7ff ff4b bl a0 <print> + 20a: 4620 mov r0, r4 + 20c: e76f b.n ee <main+0x32> + 20e: bf00 nop + 210: 00000038 andeq r0, r0, r8, lsr r0 + 214: 00000040 andeq r0, r0, r0, asr #32 + 218: 00000068 andeq r0, r0, r8, rrx + 21c: 0000007c andeq r0, r0, ip, ror r0 + 220: 00000090 muleq r0, r0, r0 + 224: 000000a0 andeq r0, r0, r0, lsr #1 + 228: 000000b0 strheq r0, [r0], -r0 ; <UNPREDICTABLE> + 22c: 000000d4 ldrdeq r0, [r0], -r4 + 230: 000000f4 strdeq r0, [r0], -r4 + +00000234 <_exit>: +_exit(): + 234: 2302 movs r3, #2 + 236: df00 svc 0 + +00000238 <open>: +open(): + 238: 2306 movs r3, #6 + 23a: df00 svc 0 + 23c: 4770 bx lr + +0000023e <close>: +close(): + 23e: 2307 movs r3, #7 + 240: df00 svc 0 + 242: 4770 bx lr + +00000244 <seek>: +seek(): + 244: 2308 movs r3, #8 + 246: df00 svc 0 + 248: 4770 bx lr + +0000024a <write>: +write(): + 24a: 2303 movs r3, #3 + 24c: df00 svc 0 + 24e: 4770 bx lr + +00000250 <read>: +read(): + 250: 2304 movs r3, #4 + 252: df00 svc 0 + 254: 4770 bx lr + +Disassembly of section .got: + +10000000 <.got>: +10000000: 1000000c andne r0, r0, ip + ... + +Disassembly of section .dynamic: + +1000000c <.dynamic>: +1000000c: 00000015 andeq r0, r0, r5, lsl r0 + ... + +Disassembly of section .rodata: + +10000038 <.rodata>: +10000038: 2e6f6f66 cdpcs 15, 6, cr6, cr15, cr6, {3} +1000003c: 006e6962 rsbeq r6, lr, r2, ror #18 +10000040: 65704f27 ldrbvs r4, [r0, #-3879]! ; 0xf27 +10000044: 6f20276e svcvs 0x0020276e +10000048: 6f6e2066 svcvs 0x006e2066 +1000004c: 7865206e stmdavc r5!, {r1, r2, r3, r5, r6, sp}^ +10000050: 69747369 ldmdbvs r4!, {r0, r3, r5, r6, r8, r9, ip, sp, lr}^ +10000054: 6620676e strtvs r6, [r0], -lr, ror #14 +10000058: 3a656c69 bcc 1195b204 <_DYNAMIC+0x195b1f8> +1000005c: 73615020 cmnvc r1, #32 +10000060: 0a646573 beq 11919634 <_DYNAMIC+0x1919628> +10000064: 00000000 andeq r0, r0, r0 +10000068: 6e65704f cdpvs 0, 6, cr7, cr5, cr15, {2} +1000006c: 6c696620 stclvs 6, cr6, [r9], #-128 ; 0xffffff80 +10000070: 50203a65 eorpl r3, r0, r5, ror #20 +10000074: 65737361 ldrbvs r7, [r3, #-865]! ; 0x361 +10000078: 00000a64 andeq r0, r0, r4, ror #20 +1000007c: 74697257 strbtvc r7, [r9], #-599 ; 0x257 +10000080: 69662065 stmdbvs r6!, {r0, r2, r5, r6, sp}^ +10000084: 203a656c eorscs r6, sl, ip, ror #10 +10000088: 73736150 cmnvc r3, #20 +1000008c: 000a6465 andeq r6, sl, r5, ror #8 +10000090: 64616552 strbtvs r6, [r1], #-1362 ; 0x552 +10000094: 6150203a cmpvs r0, sl, lsr r0 +10000098: 64657373 strbtvs r7, [r5], #-883 ; 0x373 +1000009c: 0000000a andeq r0, r0, sl +100000a0: 736f6c63 cmnvc pc, #25344 ; 0x6300 +100000a4: 50203a65 eorpl r3, r0, r5, ror #20 +100000a8: 65737361 ldrbvs r7, [r3, #-865]! ; 0x361 +100000ac: 00000a64 andeq r0, r0, r4, ror #20 +100000b0: 6e65704f cdpvs 0, 6, cr7, cr5, cr15, {2} +100000b4: 20666f20 rsbcs r6, r6, r0, lsr #30 +100000b8: 65206e61 strvs r6, [r0, #-3681]! ; 0xe61 +100000bc: 74736978 ldrbtvc r6, [r3], #-2424 ; 0x978 +100000c0: 20676e69 rsbcs r6, r7, r9, ror #28 +100000c4: 656c6966 strbvs r6, [ip, #-2406]! ; 0x966 +100000c8: 6150203a cmpvs r0, sl, lsr r0 +100000cc: 64657373 strbtvs r7, [r5], #-883 ; 0x373 +100000d0: 0000000a andeq r0, r0, sl +100000d4: 64616552 strbtvs r6, [r1], #-1362 ; 0x552 +100000d8: 74616420 strbtvc r6, [r1], #-1056 ; 0x420 +100000dc: 6f632061 svcvs 0x00632061 +100000e0: 74636572 strbtvc r6, [r3], #-1394 ; 0x572 +100000e4: 7373656e cmnvc r3, #461373440 ; 0x1b800000 +100000e8: 6150203a cmpvs r0, sl, lsr r0 +100000ec: 64657373 strbtvs r7, [r5], #-883 ; 0x373 +100000f0: 0000000a andeq r0, r0, sl +100000f4: 736f6c63 cmnvc pc, #25344 ; 0x6300 +100000f8: 70203a65 eorvc r3, r0, r5, ror #20 +100000fc: 65737361 ldrbvs r7, [r3, #-865]! ; 0x361 +10000100: 00000a64 andeq r0, r0, r4, ror #20 diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu.h b/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu.h new file mode 100644 index 0000000000000000000000000000000000000000..2d53a3c2674f0ed8b1dfa50a61f25dc6980e5ecd --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu.h @@ -0,0 +1,24 @@ +const unsigned char __attribute__((aligned(8))) testsuite_syscall_mpu_elf[] = { + 0x7f, 0x45, 0x4c, 0x46, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x28, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x99, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x05, 0x34, 0x00, 0x20, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, + 0x98, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, + 0x26, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x10, 0x34, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0xcc, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10, 0x0c, 0x00, 0x00, 0x10, + 0x28, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x02, 0xf8, + 0x00, 0xf0, 0x0a, 0xf8, 0x00, 0x20, 0x08, 0xb5, 0x40, 0xf2, 0x02, 0x41, + 0x02, 0x46, 0x00, 0xf0, 0x05, 0xf8, 0x00, 0x20, 0x08, 0xbd, 0x00, 0xbf, + 0x02, 0x23, 0x00, 0xdf, 0x06, 0x23, 0x00, 0xdf, 0x70, 0x47, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00, + 0x4d, 0x69, 0x6f, 0x73, 0x69, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 +}; +unsigned int testsuite_syscall_mpu_elf_len = 244; diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_open.h b/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_open.h new file mode 100644 index 0000000000000000000000000000000000000000..796bcc6141a3232cafa7ff58816afcda0247b6e6 --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_open.h @@ -0,0 +1,24 @@ +const unsigned char __attribute__((aligned(8))) testsuite_syscall_mpu_open_elf[] = { + 0x7f, 0x45, 0x4c, 0x46, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x28, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x99, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x05, 0x34, 0x00, 0x20, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, + 0x98, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, + 0x26, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x10, 0x34, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0xcc, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10, 0x0c, 0x00, 0x00, 0x10, + 0x28, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x02, 0xf8, + 0x00, 0xf0, 0x0a, 0xf8, 0x00, 0x20, 0x08, 0xb5, 0x40, 0xf2, 0x02, 0x41, + 0x02, 0x46, 0x00, 0xf0, 0x05, 0xf8, 0x00, 0x20, 0x08, 0xbd, 0x00, 0xbf, + 0x02, 0x23, 0x00, 0xdf, 0x06, 0x23, 0x00, 0xdf, 0x70, 0x47, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00, + 0x4d, 0x69, 0x6f, 0x73, 0x69, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 +}; +unsigned int testsuite_syscall_mpu_open_elf_len = 244; diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_open/Makefile b/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_open/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..34f92e723fa43f571d53cbaaddcc9329cd32cb2b --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_open/Makefile @@ -0,0 +1,45 @@ +## +## Makefile for writing PROGRAMS for the Miosix embedded OS +## TFT:Terraneo Federico Technlogies +## + +SRC := \ +main.c + +## Replaces both "foo.cpp"-->"foo.o" and "foo.c"-->"foo.o" +OBJ := $(addsuffix .o, $(basename $(SRC))) +ELF := $(addsuffix .elf, $(NAME)) + +AS := arm-miosix-eabi-as +CC := arm-miosix-eabi-gcc +CXX := arm-miosix-eabi-g++ +SZ := arm-miosix-eabi-size + +AFLAGS := -mcpu=cortex-m3 -mthumb +CFLAGS := -mcpu=cortex-m3 -mthumb -mfix-cortex-m3-ldrd -fpie -msingle-pic-base \ + -ffunction-sections -O2 -Wall -c +CXXFLAGS := $(CFLAGS) +LFLAGS := -mcpu=cortex-m3 -mthumb -mfix-cortex-m3-ldrd -fpie -msingle-pic-base \ + -Wl,--gc-sections,-Map,test.map,-T./miosix.ld,-n,-pie,--spare-dynamic-tags,3 \ + -O2 -nostdlib + +LINK_LIBS := -Wl,--start-group -lstdc++ -lc -lm -lgcc -Wl,--end-group + +all: $(OBJ) crt0.o + $(CXX) $(LFLAGS) -o $(ELF) $(OBJ) crt0.o $(LINK_LIBS) + $(SZ) $(ELF) + @arm-miosix-eabi-objdump -Dslx $(ELF) > test.txt + @mx-postlinker $(ELF) --ramsize=16384 --stacksize=2048 --strip-sectheader + @xxd -i $(ELF) | sed 's/unsigned char/const unsigned char __attribute__((aligned(8)))/' > prog3.h + +clean: + -rm $(OBJ) crt0.o *.elf test.map test.txt + +%.o: %.s + $(AS) $(AFLAGS) $< -o $@ + +%.o : %.c + $(CC) $(CFLAGS) $< -o $@ + +%.o : %.cpp + $(CXX) $(CXXFLAGS) $< -o $@ diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_open/crt0.s b/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_open/crt0.s new file mode 100644 index 0000000000000000000000000000000000000000..9959b317dcafd42e8cb82c896b3eef2e0205f7cc --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_open/crt0.s @@ -0,0 +1,131 @@ +/* + * Startup script for writing PROGRAMS for the Miosix embedded OS + * TFT:Terraneo Federico Technlogies + */ + +.syntax unified +.cpu cortex-m3 +.thumb + +.section .text + +/** + * _start, program entry point + */ +.global _start +.type _start, %function +_start: + /* TODO: .ctor */ + bl main + /* TODO: .dtor */ + bl _exit + +/** + * _exit, terminate process + * \param v exit value + */ +.section .text._exit +.global _exit +.type _exit, %function +_exit: + movs r3, #2 + svc 0 + +/** + * open, open a file + * \param fd file descriptor + * \param file access mode + * \param xxx access permisions + * \return file descriptor or -1 if errors + */ +.section .text.open +.global open +.type open, %function +open: + movs r3, #6 + svc 0 + bx lr + +/** + * close, close a file + * \param fd file descriptor + */ +.section .text.close +.global close +.type close, %function +close: + movs r3, #7 + svc 0 + bx lr + +/** + * seek + * \param fd file descriptor + * \param pos moving offset + * \param start position, SEEK_SET, SEEK_CUR or SEEK_END +*/ +.section .text.seek +.global seek +.type seek, %function +seek: + movs r3, #8 + svc 0 + bx lr + + +/** + * system, fork and execture a program, blocking + * \param program to execute + */ +.section .text.system +.global system +.type system, %function +system: + movs r3, #9 + svc 0 + bx lr + +/** + * write, write to file + * \param fd file descriptor + * \param buf data to be written + * \param len buffer length + * \return number of written bytes or -1 if errors + */ +.section .text.write +.global write +.type write, %function +write: + movs r3, #3 + svc 0 + bx lr + +/** + * read, read from file + * \param fd file descriptor + * \param buf data to be read + * \param len buffer length + * \return number of read bytes or -1 if errors + */ +.section .text.read +.global read +.type read, %function +read: + movs r3, #4 + svc 0 + bx lr + +/** + * usleep, sleep a specified number of microseconds + * \param us number of microseconds to sleep + * \return 0 on success or -1 if errors + */ +.section .text.usleep +.global usleep +.type usleep, %function +usleep: + movs r3, #5 + svc 0 + bx lr + +.end diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_open/main.c b/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_open/main.c new file mode 100644 index 0000000000000000000000000000000000000000..376be3d7764c2a6a6b2c7bc3e7cd4aa01de26df5 --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_open/main.c @@ -0,0 +1,13 @@ +#include <unistd.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <string.h> +#include <stdio.h> + +int main(){ + int fd = open(0x00000000, O_RDWR|O_TRUNC, 0); + return 0; +} + diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_open/miosix.ld b/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_open/miosix.ld new file mode 100644 index 0000000000000000000000000000000000000000..c91c803e629040b14233a8f8251a7d9952f68910 --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_open/miosix.ld @@ -0,0 +1,66 @@ +/* + * Linker script for writing PROGRAMS for the Miosix embedded OS + * TFT:Terraneo Federico Technlogies + */ + +OUTPUT_FORMAT("elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) + +SECTIONS +{ + /* Here starts the first elf segment, that stays in flash */ + . = 0 + SIZEOF_HEADERS; + + .text : ALIGN(8) + { + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + } + + .rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) } + .rel.got : { *(.rel.got) } + + /* Here starts the second segment, that is copied in RAM and relocated */ + . = 0x10000000; + + .got : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) } + + /* FIXME: If this is put in the other segment, it makes it writable */ + .dynamic : { *(.dynamic) } + + /* FIXME: The compiler insists in addressing rodata relative to r9 */ + .rodata : ALIGN(8) + { + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + } + + .data : ALIGN(8) + { + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + } + + .bss : ALIGN(8) + { + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + } + + /* These are removed since are unused and increase binary size */ + /DISCARD/ : + { + *(.interp) + *(.dynsym) + *(.dynstr) + *(.hash) + *(.comment) + *(.ARM.attributes) + } +} diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_open/prog3.h b/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_open/prog3.h new file mode 100644 index 0000000000000000000000000000000000000000..796bcc6141a3232cafa7ff58816afcda0247b6e6 --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_open/prog3.h @@ -0,0 +1,24 @@ +const unsigned char __attribute__((aligned(8))) testsuite_syscall_mpu_open_elf[] = { + 0x7f, 0x45, 0x4c, 0x46, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x28, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x99, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x05, 0x34, 0x00, 0x20, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, + 0x98, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, + 0x26, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x10, 0x34, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0xcc, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10, 0x0c, 0x00, 0x00, 0x10, + 0x28, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x02, 0xf8, + 0x00, 0xf0, 0x0a, 0xf8, 0x00, 0x20, 0x08, 0xb5, 0x40, 0xf2, 0x02, 0x41, + 0x02, 0x46, 0x00, 0xf0, 0x05, 0xf8, 0x00, 0x20, 0x08, 0xbd, 0x00, 0xbf, + 0x02, 0x23, 0x00, 0xdf, 0x06, 0x23, 0x00, 0xdf, 0x70, 0x47, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00, + 0x4d, 0x69, 0x6f, 0x73, 0x69, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 +}; +unsigned int testsuite_syscall_mpu_open_elf_len = 244; diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_open/test.txt b/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_open/test.txt new file mode 100644 index 0000000000000000000000000000000000000000..1171c3914a8e6585b7dabe399e52f08450f9b670 --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_open/test.txt @@ -0,0 +1,91 @@ + +testsuite_syscall_mpu_open.elf: file format elf32-littlearm +testsuite_syscall_mpu_open.elf +architecture: arm, flags 0x00000050: +HAS_SYMS, DYNAMIC +start address 0x00000099 + +Program Header: + LOAD off 0x00000098 vaddr 0x00000098 paddr 0x00000098 align 2**3 + filesz 0x00000026 memsz 0x00000026 flags r-x + LOAD off 0x000000c0 vaddr 0x10000000 paddr 0x10000000 align 2**2 + filesz 0x00000034 memsz 0x00000034 flags rw- + DYNAMIC off 0x000000cc vaddr 0x1000000c paddr 0x1000000c align 2**2 + filesz 0x00000028 memsz 0x00000028 flags rw- + +Dynamic Section: + DEBUG 0x00000000 +private flags = 5000002: [Version5 EABI] [has entry point] + +Sections: +Idx Name Size VMA LMA File off Algn + 0 .text 00000026 00000098 00000098 00000098 2**3 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 1 .got 0000000c 10000000 10000000 000000c0 2**2 + CONTENTS, ALLOC, LOAD, DATA + 2 .dynamic 00000028 1000000c 1000000c 000000cc 2**2 + CONTENTS, ALLOC, LOAD, DATA +SYMBOL TABLE: +00000098 l d .text 00000000 .text +10000000 l d .got 00000000 .got +1000000c l d .dynamic 00000000 .dynamic +00000000 l df *ABS* 00000000 main.c +1000000c l O *ABS* 00000000 _DYNAMIC +10000000 l O *ABS* 00000000 _GLOBAL_OFFSET_TABLE_ +00000098 g F .text 00000000 _start +000000a0 g F .text 00000012 main +000000b4 g F .text 00000000 _exit +000000b8 g F .text 00000000 open + + +Contents of section .text: + 0098 00f002f8 00f00af8 002008b5 40f20241 ......... ..@..A + 00a8 024600f0 05f80020 08bd00bf 022300df .F..... .....#.. + 00b8 062300df 7047 .#..pG +Contents of section .got: + 10000000 0c000010 00000000 00000000 ............ +Contents of section .dynamic: + 1000000c 15000000 00000000 00000000 00000000 ................ + 1000001c 00000000 00000000 00000000 00000000 ................ + 1000002c 00000000 00000000 ........ + +Disassembly of section .text: + +00000098 <_start>: +_start(): + 98: f000 f802 bl a0 <main> + 9c: f000 f80a bl b4 <_exit> + +000000a0 <main>: +main(): + a0: 2000 movs r0, #0 + a2: b508 push {r3, lr} + a4: f240 4102 movw r1, #1026 ; 0x402 + a8: 4602 mov r2, r0 + aa: f000 f805 bl b8 <open> + ae: 2000 movs r0, #0 + b0: bd08 pop {r3, pc} + b2: bf00 nop + +000000b4 <_exit>: +_exit(): + b4: 2302 movs r3, #2 + b6: df00 svc 0 + +000000b8 <open>: +open(): + b8: 2306 movs r3, #6 + ba: df00 svc 0 + bc: 4770 bx lr + +Disassembly of section .got: + +10000000 <.got>: +10000000: 1000000c andne r0, r0, ip + ... + +Disassembly of section .dynamic: + +1000000c <.dynamic>: +1000000c: 00000015 andeq r0, r0, r5, lsl r0 + ... diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_read.h b/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_read.h new file mode 100644 index 0000000000000000000000000000000000000000..ac0c259590b4ad83125d5b755bbd2582930fa5d5 --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_read.h @@ -0,0 +1,26 @@ +const unsigned char __attribute__((aligned(8))) testsuite_syscall_mpu_read_elf[] = { + 0x7f, 0x45, 0x4c, 0x46, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x28, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x99, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x05, 0x34, 0x00, 0x20, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, + 0x98, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, + 0x38, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x10, 0x44, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0xdc, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10, 0x0c, 0x00, 0x00, 0x10, + 0x28, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x02, 0xf8, + 0x00, 0xf0, 0x10, 0xf8, 0x06, 0x48, 0x08, 0xb5, 0x00, 0x22, 0x40, 0xf2, + 0x02, 0x41, 0x48, 0x44, 0x00, 0xf0, 0x0a, 0xf8, 0x00, 0x21, 0x0a, 0x22, + 0x00, 0xf0, 0x09, 0xf8, 0x00, 0x20, 0x08, 0xbd, 0x38, 0x00, 0x00, 0x00, + 0x02, 0x23, 0x00, 0xdf, 0x06, 0x23, 0x00, 0xdf, 0x70, 0x47, 0x04, 0x23, + 0x00, 0xdf, 0x70, 0x47, 0x0c, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, + 0x00, 0x08, 0x00, 0x00, 0x4d, 0x69, 0x6f, 0x73, 0x69, 0x78, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2f, 0x72, 0x64, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x74, 0x78, 0x74, 0x00 +}; +unsigned int testsuite_syscall_mpu_read_elf_len = 276; diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_read/Makefile b/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_read/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..34f92e723fa43f571d53cbaaddcc9329cd32cb2b --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_read/Makefile @@ -0,0 +1,45 @@ +## +## Makefile for writing PROGRAMS for the Miosix embedded OS +## TFT:Terraneo Federico Technlogies +## + +SRC := \ +main.c + +## Replaces both "foo.cpp"-->"foo.o" and "foo.c"-->"foo.o" +OBJ := $(addsuffix .o, $(basename $(SRC))) +ELF := $(addsuffix .elf, $(NAME)) + +AS := arm-miosix-eabi-as +CC := arm-miosix-eabi-gcc +CXX := arm-miosix-eabi-g++ +SZ := arm-miosix-eabi-size + +AFLAGS := -mcpu=cortex-m3 -mthumb +CFLAGS := -mcpu=cortex-m3 -mthumb -mfix-cortex-m3-ldrd -fpie -msingle-pic-base \ + -ffunction-sections -O2 -Wall -c +CXXFLAGS := $(CFLAGS) +LFLAGS := -mcpu=cortex-m3 -mthumb -mfix-cortex-m3-ldrd -fpie -msingle-pic-base \ + -Wl,--gc-sections,-Map,test.map,-T./miosix.ld,-n,-pie,--spare-dynamic-tags,3 \ + -O2 -nostdlib + +LINK_LIBS := -Wl,--start-group -lstdc++ -lc -lm -lgcc -Wl,--end-group + +all: $(OBJ) crt0.o + $(CXX) $(LFLAGS) -o $(ELF) $(OBJ) crt0.o $(LINK_LIBS) + $(SZ) $(ELF) + @arm-miosix-eabi-objdump -Dslx $(ELF) > test.txt + @mx-postlinker $(ELF) --ramsize=16384 --stacksize=2048 --strip-sectheader + @xxd -i $(ELF) | sed 's/unsigned char/const unsigned char __attribute__((aligned(8)))/' > prog3.h + +clean: + -rm $(OBJ) crt0.o *.elf test.map test.txt + +%.o: %.s + $(AS) $(AFLAGS) $< -o $@ + +%.o : %.c + $(CC) $(CFLAGS) $< -o $@ + +%.o : %.cpp + $(CXX) $(CXXFLAGS) $< -o $@ diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_read/crt0.s b/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_read/crt0.s new file mode 100644 index 0000000000000000000000000000000000000000..9959b317dcafd42e8cb82c896b3eef2e0205f7cc --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_read/crt0.s @@ -0,0 +1,131 @@ +/* + * Startup script for writing PROGRAMS for the Miosix embedded OS + * TFT:Terraneo Federico Technlogies + */ + +.syntax unified +.cpu cortex-m3 +.thumb + +.section .text + +/** + * _start, program entry point + */ +.global _start +.type _start, %function +_start: + /* TODO: .ctor */ + bl main + /* TODO: .dtor */ + bl _exit + +/** + * _exit, terminate process + * \param v exit value + */ +.section .text._exit +.global _exit +.type _exit, %function +_exit: + movs r3, #2 + svc 0 + +/** + * open, open a file + * \param fd file descriptor + * \param file access mode + * \param xxx access permisions + * \return file descriptor or -1 if errors + */ +.section .text.open +.global open +.type open, %function +open: + movs r3, #6 + svc 0 + bx lr + +/** + * close, close a file + * \param fd file descriptor + */ +.section .text.close +.global close +.type close, %function +close: + movs r3, #7 + svc 0 + bx lr + +/** + * seek + * \param fd file descriptor + * \param pos moving offset + * \param start position, SEEK_SET, SEEK_CUR or SEEK_END +*/ +.section .text.seek +.global seek +.type seek, %function +seek: + movs r3, #8 + svc 0 + bx lr + + +/** + * system, fork and execture a program, blocking + * \param program to execute + */ +.section .text.system +.global system +.type system, %function +system: + movs r3, #9 + svc 0 + bx lr + +/** + * write, write to file + * \param fd file descriptor + * \param buf data to be written + * \param len buffer length + * \return number of written bytes or -1 if errors + */ +.section .text.write +.global write +.type write, %function +write: + movs r3, #3 + svc 0 + bx lr + +/** + * read, read from file + * \param fd file descriptor + * \param buf data to be read + * \param len buffer length + * \return number of read bytes or -1 if errors + */ +.section .text.read +.global read +.type read, %function +read: + movs r3, #4 + svc 0 + bx lr + +/** + * usleep, sleep a specified number of microseconds + * \param us number of microseconds to sleep + * \return 0 on success or -1 if errors + */ +.section .text.usleep +.global usleep +.type usleep, %function +usleep: + movs r3, #5 + svc 0 + bx lr + +.end diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_read/main.c b/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_read/main.c new file mode 100644 index 0000000000000000000000000000000000000000..f442ac5449df51a65993feb47b9a2f8570d32797 --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_read/main.c @@ -0,0 +1,15 @@ +#include <unistd.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <string.h> +#include <stdio.h> + +int main(){ + int fd = open("/rdtest.txt", O_RDWR|O_TRUNC, 0); + + read(fd, 0x00, 10); + return 0; +} + diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_read/miosix.ld b/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_read/miosix.ld new file mode 100644 index 0000000000000000000000000000000000000000..c91c803e629040b14233a8f8251a7d9952f68910 --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_read/miosix.ld @@ -0,0 +1,66 @@ +/* + * Linker script for writing PROGRAMS for the Miosix embedded OS + * TFT:Terraneo Federico Technlogies + */ + +OUTPUT_FORMAT("elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) + +SECTIONS +{ + /* Here starts the first elf segment, that stays in flash */ + . = 0 + SIZEOF_HEADERS; + + .text : ALIGN(8) + { + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + } + + .rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) } + .rel.got : { *(.rel.got) } + + /* Here starts the second segment, that is copied in RAM and relocated */ + . = 0x10000000; + + .got : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) } + + /* FIXME: If this is put in the other segment, it makes it writable */ + .dynamic : { *(.dynamic) } + + /* FIXME: The compiler insists in addressing rodata relative to r9 */ + .rodata : ALIGN(8) + { + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + } + + .data : ALIGN(8) + { + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + } + + .bss : ALIGN(8) + { + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + } + + /* These are removed since are unused and increase binary size */ + /DISCARD/ : + { + *(.interp) + *(.dynsym) + *(.dynstr) + *(.hash) + *(.comment) + *(.ARM.attributes) + } +} diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_read/prog3.h b/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_read/prog3.h new file mode 100644 index 0000000000000000000000000000000000000000..ac0c259590b4ad83125d5b755bbd2582930fa5d5 --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_read/prog3.h @@ -0,0 +1,26 @@ +const unsigned char __attribute__((aligned(8))) testsuite_syscall_mpu_read_elf[] = { + 0x7f, 0x45, 0x4c, 0x46, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x28, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x99, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x05, 0x34, 0x00, 0x20, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, + 0x98, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, + 0x38, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x10, 0x44, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0xdc, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10, 0x0c, 0x00, 0x00, 0x10, + 0x28, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x02, 0xf8, + 0x00, 0xf0, 0x10, 0xf8, 0x06, 0x48, 0x08, 0xb5, 0x00, 0x22, 0x40, 0xf2, + 0x02, 0x41, 0x48, 0x44, 0x00, 0xf0, 0x0a, 0xf8, 0x00, 0x21, 0x0a, 0x22, + 0x00, 0xf0, 0x09, 0xf8, 0x00, 0x20, 0x08, 0xbd, 0x38, 0x00, 0x00, 0x00, + 0x02, 0x23, 0x00, 0xdf, 0x06, 0x23, 0x00, 0xdf, 0x70, 0x47, 0x04, 0x23, + 0x00, 0xdf, 0x70, 0x47, 0x0c, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, + 0x00, 0x08, 0x00, 0x00, 0x4d, 0x69, 0x6f, 0x73, 0x69, 0x78, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2f, 0x72, 0x64, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x74, 0x78, 0x74, 0x00 +}; +unsigned int testsuite_syscall_mpu_read_elf_len = 276; diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_read/test.txt b/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_read/test.txt new file mode 100644 index 0000000000000000000000000000000000000000..29fe458254a092dc3ed536111dd02b20df4f6bfc --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_read/test.txt @@ -0,0 +1,115 @@ + +testsuite_syscall_mpu_read.elf: file format elf32-littlearm +testsuite_syscall_mpu_read.elf +architecture: arm, flags 0x00000050: +HAS_SYMS, DYNAMIC +start address 0x00000099 + +Program Header: + LOAD off 0x00000098 vaddr 0x00000098 paddr 0x00000098 align 2**3 + filesz 0x00000038 memsz 0x00000038 flags r-x + LOAD off 0x000000d0 vaddr 0x10000000 paddr 0x10000000 align 2**3 + filesz 0x00000044 memsz 0x00000044 flags rw- + DYNAMIC off 0x000000dc vaddr 0x1000000c paddr 0x1000000c align 2**2 + filesz 0x00000028 memsz 0x00000028 flags rw- + +Dynamic Section: + DEBUG 0x00000000 +private flags = 5000002: [Version5 EABI] [has entry point] + +Sections: +Idx Name Size VMA LMA File off Algn + 0 .text 00000038 00000098 00000098 00000098 2**3 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 1 .got 0000000c 10000000 10000000 000000d0 2**2 + CONTENTS, ALLOC, LOAD, DATA + 2 .dynamic 00000028 1000000c 1000000c 000000dc 2**2 + CONTENTS, ALLOC, LOAD, DATA + 3 .rodata 0000000c 10000038 10000038 00000108 2**3 + CONTENTS, ALLOC, LOAD, READONLY, DATA +SYMBOL TABLE: +00000098 l d .text 00000000 .text +10000000 l d .got 00000000 .got +1000000c l d .dynamic 00000000 .dynamic +10000038 l d .rodata 00000000 .rodata +00000000 l df *ABS* 00000000 main.c +1000000c l O *ABS* 00000000 _DYNAMIC +10000000 l O *ABS* 00000000 _GLOBAL_OFFSET_TABLE_ +00000098 g F .text 00000000 _start +000000ca g F .text 00000000 read +000000a0 g F .text 00000020 main +000000c0 g F .text 00000000 _exit +000000c4 g F .text 00000000 open + + +Contents of section .text: + 0098 00f002f8 00f010f8 064808b5 002240f2 .........H..."@. + 00a8 02414844 00f00af8 00210a22 00f009f8 .AHD.....!.".... + 00b8 002008bd 38000000 022300df 062300df . ..8....#...#.. + 00c8 70470423 00df7047 pG.#..pG +Contents of section .got: + 10000000 0c000010 00000000 00000000 ............ +Contents of section .dynamic: + 1000000c 15000000 00000000 00000000 00000000 ................ + 1000001c 00000000 00000000 00000000 00000000 ................ + 1000002c 00000000 00000000 ........ +Contents of section .rodata: + 10000038 2f726474 6573742e 74787400 /rdtest.txt. + +Disassembly of section .text: + +00000098 <_start>: +_start(): + 98: f000 f802 bl a0 <main> + 9c: f000 f810 bl c0 <_exit> + +000000a0 <main>: +main(): + a0: 4806 ldr r0, [pc, #24] ; (bc <main+0x1c>) + a2: b508 push {r3, lr} + a4: 2200 movs r2, #0 + a6: f240 4102 movw r1, #1026 ; 0x402 + aa: 4448 add r0, r9 + ac: f000 f80a bl c4 <open> + b0: 2100 movs r1, #0 + b2: 220a movs r2, #10 + b4: f000 f809 bl ca <read> + b8: 2000 movs r0, #0 + ba: bd08 pop {r3, pc} + bc: 00000038 andeq r0, r0, r8, lsr r0 + +000000c0 <_exit>: +_exit(): + c0: 2302 movs r3, #2 + c2: df00 svc 0 + +000000c4 <open>: +open(): + c4: 2306 movs r3, #6 + c6: df00 svc 0 + c8: 4770 bx lr + +000000ca <read>: +read(): + ca: 2304 movs r3, #4 + cc: df00 svc 0 + ce: 4770 bx lr + +Disassembly of section .got: + +10000000 <.got>: +10000000: 1000000c andne r0, r0, ip + ... + +Disassembly of section .dynamic: + +1000000c <.dynamic>: +1000000c: 00000015 andeq r0, r0, r5, lsl r0 + ... + +Disassembly of section .rodata: + +10000038 <.rodata>: +10000038: 7464722f strbtvc r7, [r4], #-559 ; 0x22f +1000003c: 2e747365 cdpcs 3, 7, cr7, cr4, cr5, {3} +10000040: 00747874 rsbseq r7, r4, r4, ror r8 diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_write.h b/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_write.h new file mode 100644 index 0000000000000000000000000000000000000000..61bf80e6e882d1f6824ec89f61cf7df86ed350ac --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_write.h @@ -0,0 +1,26 @@ +const unsigned char __attribute__((aligned(8))) testsuite_syscall_mpu_write_elf[] = { + 0x7f, 0x45, 0x4c, 0x46, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x28, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x99, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x05, 0x34, 0x00, 0x20, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, + 0x98, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, + 0x38, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x10, 0x44, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0xdc, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10, 0x0c, 0x00, 0x00, 0x10, + 0x28, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x02, 0xf8, + 0x00, 0xf0, 0x10, 0xf8, 0x06, 0x48, 0x08, 0xb5, 0x00, 0x22, 0x40, 0xf2, + 0x02, 0x41, 0x48, 0x44, 0x00, 0xf0, 0x0a, 0xf8, 0x00, 0x21, 0x0a, 0x22, + 0x00, 0xf0, 0x09, 0xf8, 0x00, 0x20, 0x08, 0xbd, 0x38, 0x00, 0x00, 0x00, + 0x02, 0x23, 0x00, 0xdf, 0x06, 0x23, 0x00, 0xdf, 0x70, 0x47, 0x03, 0x23, + 0x00, 0xdf, 0x70, 0x47, 0x0c, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, + 0x00, 0x08, 0x00, 0x00, 0x4d, 0x69, 0x6f, 0x73, 0x69, 0x78, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2f, 0x72, 0x64, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x74, 0x78, 0x74, 0x00 +}; +unsigned int testsuite_syscall_mpu_write_elf_len = 276; diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_write/Makefile b/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_write/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..34f92e723fa43f571d53cbaaddcc9329cd32cb2b --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_write/Makefile @@ -0,0 +1,45 @@ +## +## Makefile for writing PROGRAMS for the Miosix embedded OS +## TFT:Terraneo Federico Technlogies +## + +SRC := \ +main.c + +## Replaces both "foo.cpp"-->"foo.o" and "foo.c"-->"foo.o" +OBJ := $(addsuffix .o, $(basename $(SRC))) +ELF := $(addsuffix .elf, $(NAME)) + +AS := arm-miosix-eabi-as +CC := arm-miosix-eabi-gcc +CXX := arm-miosix-eabi-g++ +SZ := arm-miosix-eabi-size + +AFLAGS := -mcpu=cortex-m3 -mthumb +CFLAGS := -mcpu=cortex-m3 -mthumb -mfix-cortex-m3-ldrd -fpie -msingle-pic-base \ + -ffunction-sections -O2 -Wall -c +CXXFLAGS := $(CFLAGS) +LFLAGS := -mcpu=cortex-m3 -mthumb -mfix-cortex-m3-ldrd -fpie -msingle-pic-base \ + -Wl,--gc-sections,-Map,test.map,-T./miosix.ld,-n,-pie,--spare-dynamic-tags,3 \ + -O2 -nostdlib + +LINK_LIBS := -Wl,--start-group -lstdc++ -lc -lm -lgcc -Wl,--end-group + +all: $(OBJ) crt0.o + $(CXX) $(LFLAGS) -o $(ELF) $(OBJ) crt0.o $(LINK_LIBS) + $(SZ) $(ELF) + @arm-miosix-eabi-objdump -Dslx $(ELF) > test.txt + @mx-postlinker $(ELF) --ramsize=16384 --stacksize=2048 --strip-sectheader + @xxd -i $(ELF) | sed 's/unsigned char/const unsigned char __attribute__((aligned(8)))/' > prog3.h + +clean: + -rm $(OBJ) crt0.o *.elf test.map test.txt + +%.o: %.s + $(AS) $(AFLAGS) $< -o $@ + +%.o : %.c + $(CC) $(CFLAGS) $< -o $@ + +%.o : %.cpp + $(CXX) $(CXXFLAGS) $< -o $@ diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_write/crt0.s b/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_write/crt0.s new file mode 100644 index 0000000000000000000000000000000000000000..9959b317dcafd42e8cb82c896b3eef2e0205f7cc --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_write/crt0.s @@ -0,0 +1,131 @@ +/* + * Startup script for writing PROGRAMS for the Miosix embedded OS + * TFT:Terraneo Federico Technlogies + */ + +.syntax unified +.cpu cortex-m3 +.thumb + +.section .text + +/** + * _start, program entry point + */ +.global _start +.type _start, %function +_start: + /* TODO: .ctor */ + bl main + /* TODO: .dtor */ + bl _exit + +/** + * _exit, terminate process + * \param v exit value + */ +.section .text._exit +.global _exit +.type _exit, %function +_exit: + movs r3, #2 + svc 0 + +/** + * open, open a file + * \param fd file descriptor + * \param file access mode + * \param xxx access permisions + * \return file descriptor or -1 if errors + */ +.section .text.open +.global open +.type open, %function +open: + movs r3, #6 + svc 0 + bx lr + +/** + * close, close a file + * \param fd file descriptor + */ +.section .text.close +.global close +.type close, %function +close: + movs r3, #7 + svc 0 + bx lr + +/** + * seek + * \param fd file descriptor + * \param pos moving offset + * \param start position, SEEK_SET, SEEK_CUR or SEEK_END +*/ +.section .text.seek +.global seek +.type seek, %function +seek: + movs r3, #8 + svc 0 + bx lr + + +/** + * system, fork and execture a program, blocking + * \param program to execute + */ +.section .text.system +.global system +.type system, %function +system: + movs r3, #9 + svc 0 + bx lr + +/** + * write, write to file + * \param fd file descriptor + * \param buf data to be written + * \param len buffer length + * \return number of written bytes or -1 if errors + */ +.section .text.write +.global write +.type write, %function +write: + movs r3, #3 + svc 0 + bx lr + +/** + * read, read from file + * \param fd file descriptor + * \param buf data to be read + * \param len buffer length + * \return number of read bytes or -1 if errors + */ +.section .text.read +.global read +.type read, %function +read: + movs r3, #4 + svc 0 + bx lr + +/** + * usleep, sleep a specified number of microseconds + * \param us number of microseconds to sleep + * \return 0 on success or -1 if errors + */ +.section .text.usleep +.global usleep +.type usleep, %function +usleep: + movs r3, #5 + svc 0 + bx lr + +.end diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_write/main.c b/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_write/main.c new file mode 100644 index 0000000000000000000000000000000000000000..0fd7b2c1a4a40b8511bf6956af916374994689bd --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_write/main.c @@ -0,0 +1,15 @@ +#include <unistd.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <string.h> +#include <stdio.h> + +int main(){ + int fd = open("/rdtest.txt", O_RDWR|O_TRUNC, 0); + + write(fd, 0x00, 10); + return 0; +} + diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_write/miosix.ld b/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_write/miosix.ld new file mode 100644 index 0000000000000000000000000000000000000000..c91c803e629040b14233a8f8251a7d9952f68910 --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_write/miosix.ld @@ -0,0 +1,66 @@ +/* + * Linker script for writing PROGRAMS for the Miosix embedded OS + * TFT:Terraneo Federico Technlogies + */ + +OUTPUT_FORMAT("elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) + +SECTIONS +{ + /* Here starts the first elf segment, that stays in flash */ + . = 0 + SIZEOF_HEADERS; + + .text : ALIGN(8) + { + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + } + + .rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) } + .rel.got : { *(.rel.got) } + + /* Here starts the second segment, that is copied in RAM and relocated */ + . = 0x10000000; + + .got : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) } + + /* FIXME: If this is put in the other segment, it makes it writable */ + .dynamic : { *(.dynamic) } + + /* FIXME: The compiler insists in addressing rodata relative to r9 */ + .rodata : ALIGN(8) + { + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + } + + .data : ALIGN(8) + { + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + } + + .bss : ALIGN(8) + { + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + } + + /* These are removed since are unused and increase binary size */ + /DISCARD/ : + { + *(.interp) + *(.dynsym) + *(.dynstr) + *(.hash) + *(.comment) + *(.ARM.attributes) + } +} diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_write/prog3.h b/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_write/prog3.h new file mode 100644 index 0000000000000000000000000000000000000000..61bf80e6e882d1f6824ec89f61cf7df86ed350ac --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_write/prog3.h @@ -0,0 +1,26 @@ +const unsigned char __attribute__((aligned(8))) testsuite_syscall_mpu_write_elf[] = { + 0x7f, 0x45, 0x4c, 0x46, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x28, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x99, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x05, 0x34, 0x00, 0x20, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, + 0x98, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, + 0x38, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x10, 0x44, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0xdc, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10, 0x0c, 0x00, 0x00, 0x10, + 0x28, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x02, 0xf8, + 0x00, 0xf0, 0x10, 0xf8, 0x06, 0x48, 0x08, 0xb5, 0x00, 0x22, 0x40, 0xf2, + 0x02, 0x41, 0x48, 0x44, 0x00, 0xf0, 0x0a, 0xf8, 0x00, 0x21, 0x0a, 0x22, + 0x00, 0xf0, 0x09, 0xf8, 0x00, 0x20, 0x08, 0xbd, 0x38, 0x00, 0x00, 0x00, + 0x02, 0x23, 0x00, 0xdf, 0x06, 0x23, 0x00, 0xdf, 0x70, 0x47, 0x03, 0x23, + 0x00, 0xdf, 0x70, 0x47, 0x0c, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, + 0x00, 0x08, 0x00, 0x00, 0x4d, 0x69, 0x6f, 0x73, 0x69, 0x78, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2f, 0x72, 0x64, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x74, 0x78, 0x74, 0x00 +}; +unsigned int testsuite_syscall_mpu_write_elf_len = 276; diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_write/test.txt b/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_write/test.txt new file mode 100644 index 0000000000000000000000000000000000000000..21e148eb168d529f32d617ffd97cc46308e9a61d --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_syscall_mpu_write/test.txt @@ -0,0 +1,115 @@ + +testsuite_syscall_mpu_write.elf: file format elf32-littlearm +testsuite_syscall_mpu_write.elf +architecture: arm, flags 0x00000050: +HAS_SYMS, DYNAMIC +start address 0x00000099 + +Program Header: + LOAD off 0x00000098 vaddr 0x00000098 paddr 0x00000098 align 2**3 + filesz 0x00000038 memsz 0x00000038 flags r-x + LOAD off 0x000000d0 vaddr 0x10000000 paddr 0x10000000 align 2**3 + filesz 0x00000044 memsz 0x00000044 flags rw- + DYNAMIC off 0x000000dc vaddr 0x1000000c paddr 0x1000000c align 2**2 + filesz 0x00000028 memsz 0x00000028 flags rw- + +Dynamic Section: + DEBUG 0x00000000 +private flags = 5000002: [Version5 EABI] [has entry point] + +Sections: +Idx Name Size VMA LMA File off Algn + 0 .text 00000038 00000098 00000098 00000098 2**3 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 1 .got 0000000c 10000000 10000000 000000d0 2**2 + CONTENTS, ALLOC, LOAD, DATA + 2 .dynamic 00000028 1000000c 1000000c 000000dc 2**2 + CONTENTS, ALLOC, LOAD, DATA + 3 .rodata 0000000c 10000038 10000038 00000108 2**3 + CONTENTS, ALLOC, LOAD, READONLY, DATA +SYMBOL TABLE: +00000098 l d .text 00000000 .text +10000000 l d .got 00000000 .got +1000000c l d .dynamic 00000000 .dynamic +10000038 l d .rodata 00000000 .rodata +00000000 l df *ABS* 00000000 main.c +1000000c l O *ABS* 00000000 _DYNAMIC +10000000 l O *ABS* 00000000 _GLOBAL_OFFSET_TABLE_ +000000ca g F .text 00000000 write +00000098 g F .text 00000000 _start +000000a0 g F .text 00000020 main +000000c0 g F .text 00000000 _exit +000000c4 g F .text 00000000 open + + +Contents of section .text: + 0098 00f002f8 00f010f8 064808b5 002240f2 .........H..."@. + 00a8 02414844 00f00af8 00210a22 00f009f8 .AHD.....!.".... + 00b8 002008bd 38000000 022300df 062300df . ..8....#...#.. + 00c8 70470323 00df7047 pG.#..pG +Contents of section .got: + 10000000 0c000010 00000000 00000000 ............ +Contents of section .dynamic: + 1000000c 15000000 00000000 00000000 00000000 ................ + 1000001c 00000000 00000000 00000000 00000000 ................ + 1000002c 00000000 00000000 ........ +Contents of section .rodata: + 10000038 2f726474 6573742e 74787400 /rdtest.txt. + +Disassembly of section .text: + +00000098 <_start>: +_start(): + 98: f000 f802 bl a0 <main> + 9c: f000 f810 bl c0 <_exit> + +000000a0 <main>: +main(): + a0: 4806 ldr r0, [pc, #24] ; (bc <main+0x1c>) + a2: b508 push {r3, lr} + a4: 2200 movs r2, #0 + a6: f240 4102 movw r1, #1026 ; 0x402 + aa: 4448 add r0, r9 + ac: f000 f80a bl c4 <open> + b0: 2100 movs r1, #0 + b2: 220a movs r2, #10 + b4: f000 f809 bl ca <write> + b8: 2000 movs r0, #0 + ba: bd08 pop {r3, pc} + bc: 00000038 andeq r0, r0, r8, lsr r0 + +000000c0 <_exit>: +_exit(): + c0: 2302 movs r3, #2 + c2: df00 svc 0 + +000000c4 <open>: +open(): + c4: 2306 movs r3, #6 + c6: df00 svc 0 + c8: 4770 bx lr + +000000ca <write>: +write(): + ca: 2303 movs r3, #3 + cc: df00 svc 0 + ce: 4770 bx lr + +Disassembly of section .got: + +10000000 <.got>: +10000000: 1000000c andne r0, r0, ip + ... + +Disassembly of section .dynamic: + +1000000c <.dynamic>: +1000000c: 00000015 andeq r0, r0, r5, lsl r0 + ... + +Disassembly of section .rodata: + +10000038 <.rodata>: +10000038: 7464722f strbtvc r7, [r4], #-559 ; 0x22f +1000003c: 2e747365 cdpcs 3, 7, cr7, cr4, cr5, {3} +10000040: 00747874 rsbseq r7, r4, r4, ror r8 diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_system.h b/miosix/_tools/testsuite/syscall_testsuite/testsuite_system.h new file mode 100644 index 0000000000000000000000000000000000000000..e263fad5b2841783c8b235aa6a87cb3ab712012d --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_system.h @@ -0,0 +1,25 @@ +const unsigned char __attribute__((aligned(8))) testsuite_system_elf[] = { + 0x7f, 0x45, 0x4c, 0x46, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x28, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x99, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x05, 0x34, 0x00, 0x20, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, + 0x98, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, + 0x22, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0xcc, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10, 0x0c, 0x00, 0x00, 0x10, + 0x28, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x02, 0xf8, + 0x00, 0xf0, 0x08, 0xf8, 0x02, 0x48, 0x08, 0xb5, 0x48, 0x44, 0x00, 0xf0, + 0x05, 0xf8, 0x08, 0xbd, 0x38, 0x00, 0x00, 0x00, 0x02, 0x23, 0x00, 0xdf, + 0x09, 0x23, 0x00, 0xdf, 0x70, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00, + 0x4d, 0x69, 0x6f, 0x73, 0x69, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x65, 0x73, 0x74, + 0x00, 0x00, 0x00, 0x00 +}; +unsigned int testsuite_system_elf_len = 256; diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_system/Makefile b/miosix/_tools/testsuite/syscall_testsuite/testsuite_system/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..34f92e723fa43f571d53cbaaddcc9329cd32cb2b --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_system/Makefile @@ -0,0 +1,45 @@ +## +## Makefile for writing PROGRAMS for the Miosix embedded OS +## TFT:Terraneo Federico Technlogies +## + +SRC := \ +main.c + +## Replaces both "foo.cpp"-->"foo.o" and "foo.c"-->"foo.o" +OBJ := $(addsuffix .o, $(basename $(SRC))) +ELF := $(addsuffix .elf, $(NAME)) + +AS := arm-miosix-eabi-as +CC := arm-miosix-eabi-gcc +CXX := arm-miosix-eabi-g++ +SZ := arm-miosix-eabi-size + +AFLAGS := -mcpu=cortex-m3 -mthumb +CFLAGS := -mcpu=cortex-m3 -mthumb -mfix-cortex-m3-ldrd -fpie -msingle-pic-base \ + -ffunction-sections -O2 -Wall -c +CXXFLAGS := $(CFLAGS) +LFLAGS := -mcpu=cortex-m3 -mthumb -mfix-cortex-m3-ldrd -fpie -msingle-pic-base \ + -Wl,--gc-sections,-Map,test.map,-T./miosix.ld,-n,-pie,--spare-dynamic-tags,3 \ + -O2 -nostdlib + +LINK_LIBS := -Wl,--start-group -lstdc++ -lc -lm -lgcc -Wl,--end-group + +all: $(OBJ) crt0.o + $(CXX) $(LFLAGS) -o $(ELF) $(OBJ) crt0.o $(LINK_LIBS) + $(SZ) $(ELF) + @arm-miosix-eabi-objdump -Dslx $(ELF) > test.txt + @mx-postlinker $(ELF) --ramsize=16384 --stacksize=2048 --strip-sectheader + @xxd -i $(ELF) | sed 's/unsigned char/const unsigned char __attribute__((aligned(8)))/' > prog3.h + +clean: + -rm $(OBJ) crt0.o *.elf test.map test.txt + +%.o: %.s + $(AS) $(AFLAGS) $< -o $@ + +%.o : %.c + $(CC) $(CFLAGS) $< -o $@ + +%.o : %.cpp + $(CXX) $(CXXFLAGS) $< -o $@ diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_system/crt0.s b/miosix/_tools/testsuite/syscall_testsuite/testsuite_system/crt0.s new file mode 100644 index 0000000000000000000000000000000000000000..8dbb153d806028cd739d686a05eac59d6357eb74 --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_system/crt0.s @@ -0,0 +1,130 @@ +/* + * Startup script for writing PROGRAMS for the Miosix embedded OS + * TFT:Terraneo Federico Technlogies + */ + +.syntax unified +.cpu cortex-m3 +.thumb + +.section .text + +/** + * _start, program entry point + */ +.global _start +.type _start, %function +_start: + /* TODO: .ctor */ + bl main + /* TODO: .dtor */ + bl _exit + +/** + * _exit, terminate process + * \param v exit value + */ +.section .text._exit +.global _exit +.type _exit, %function +_exit: + movs r3, #2 + svc 0 + +/** + * open, open a file + * \param fd file descriptor + * \param file access mode + * \param xxx access permisions + * \return file descriptor or -1 if errors + */ +.section .text.open +.global open +.type open, %function +open: + movs r3, #6 + svc 0 + bx lr + +/** + * close, close a file + * \param fd file descriptor + */ +.section .text.close +.global close +.type close, %function +close: + movs r3, #7 + svc 0 + bx lr + +/** + * lseek + * \param fd file descriptor + * \param pos moving offset + * \param start position, SEEK_SET, SEEK_CUR or SEEK_END +*/ +.section .text.seek +.global seek +.type seek, %function + + movs r3, #8 + svc 0 + bx lr + + +/** + * system, fork and execture a program, blocking + * \param program to execute + */ +.section .text.system +.global system +.type system, %function +system: + movs r3, #9 + svc 0 + bx lr +/** + * write, write to file + * \param fd file descriptor + * \param buf data to be written + * \param len buffer length + * \return number of written bytes or -1 if errors + */ +.section .text.write +.global write +.type write, %function +write: + movs r3, #3 + svc 0 + bx lr + +/** + * read, read from file + * \param fd file descriptor + * \param buf data to be read + * \param len buffer length + * \return number of read bytes or -1 if errors + */ +.section .text.read +.global read +.type read, %function +read: + movs r3, #4 + svc 0 + bx lr + +/** + * usleep, sleep a specified number of microseconds + * \param us number of microseconds to sleep + * \return 0 on success or -1 if errors + */ +.section .text.usleep +.global usleep +.type usleep, %function +usleep: + movs r3, #5 + svc 0 + bx lr + +.end diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_system/main.c b/miosix/_tools/testsuite/syscall_testsuite/testsuite_system/main.c new file mode 100644 index 0000000000000000000000000000000000000000..3cc4e59f29527db6947b1cae6260e76a75a53d5c --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_system/main.c @@ -0,0 +1,12 @@ +#include <unistd.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <string.h> +#include <stdio.h> +#include <stdlib.h> + +int main(){ + return system("test"); +} diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_system/miosix.ld b/miosix/_tools/testsuite/syscall_testsuite/testsuite_system/miosix.ld new file mode 100644 index 0000000000000000000000000000000000000000..c91c803e629040b14233a8f8251a7d9952f68910 --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_system/miosix.ld @@ -0,0 +1,66 @@ +/* + * Linker script for writing PROGRAMS for the Miosix embedded OS + * TFT:Terraneo Federico Technlogies + */ + +OUTPUT_FORMAT("elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) + +SECTIONS +{ + /* Here starts the first elf segment, that stays in flash */ + . = 0 + SIZEOF_HEADERS; + + .text : ALIGN(8) + { + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + } + + .rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) } + .rel.got : { *(.rel.got) } + + /* Here starts the second segment, that is copied in RAM and relocated */ + . = 0x10000000; + + .got : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) } + + /* FIXME: If this is put in the other segment, it makes it writable */ + .dynamic : { *(.dynamic) } + + /* FIXME: The compiler insists in addressing rodata relative to r9 */ + .rodata : ALIGN(8) + { + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + } + + .data : ALIGN(8) + { + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + } + + .bss : ALIGN(8) + { + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + } + + /* These are removed since are unused and increase binary size */ + /DISCARD/ : + { + *(.interp) + *(.dynsym) + *(.dynstr) + *(.hash) + *(.comment) + *(.ARM.attributes) + } +} diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_system/prog3.h b/miosix/_tools/testsuite/syscall_testsuite/testsuite_system/prog3.h new file mode 100644 index 0000000000000000000000000000000000000000..e263fad5b2841783c8b235aa6a87cb3ab712012d --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_system/prog3.h @@ -0,0 +1,25 @@ +const unsigned char __attribute__((aligned(8))) testsuite_system_elf[] = { + 0x7f, 0x45, 0x4c, 0x46, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x28, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x99, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x05, 0x34, 0x00, 0x20, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, + 0x98, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, + 0x22, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0xcc, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10, 0x0c, 0x00, 0x00, 0x10, + 0x28, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x02, 0xf8, + 0x00, 0xf0, 0x08, 0xf8, 0x02, 0x48, 0x08, 0xb5, 0x48, 0x44, 0x00, 0xf0, + 0x05, 0xf8, 0x08, 0xbd, 0x38, 0x00, 0x00, 0x00, 0x02, 0x23, 0x00, 0xdf, + 0x09, 0x23, 0x00, 0xdf, 0x70, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00, + 0x4d, 0x69, 0x6f, 0x73, 0x69, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x65, 0x73, 0x74, + 0x00, 0x00, 0x00, 0x00 +}; +unsigned int testsuite_system_elf_len = 256; diff --git a/miosix/_tools/testsuite/syscall_testsuite/testsuite_system/test.txt b/miosix/_tools/testsuite/syscall_testsuite/testsuite_system/test.txt new file mode 100644 index 0000000000000000000000000000000000000000..532c7ab9121d7059d831783b60bd4f3de110a607 --- /dev/null +++ b/miosix/_tools/testsuite/syscall_testsuite/testsuite_system/test.txt @@ -0,0 +1,101 @@ + +testsuite_system.elf: file format elf32-littlearm +testsuite_system.elf +architecture: arm, flags 0x00000050: +HAS_SYMS, DYNAMIC +start address 0x00000099 + +Program Header: + LOAD off 0x00000098 vaddr 0x00000098 paddr 0x00000098 align 2**3 + filesz 0x00000022 memsz 0x00000022 flags r-x + LOAD off 0x000000c0 vaddr 0x10000000 paddr 0x10000000 align 2**3 + filesz 0x00000040 memsz 0x00000040 flags rw- + DYNAMIC off 0x000000cc vaddr 0x1000000c paddr 0x1000000c align 2**2 + filesz 0x00000028 memsz 0x00000028 flags rw- + +Dynamic Section: + DEBUG 0x00000000 +private flags = 5000002: [Version5 EABI] [has entry point] + +Sections: +Idx Name Size VMA LMA File off Algn + 0 .text 00000022 00000098 00000098 00000098 2**3 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 1 .got 0000000c 10000000 10000000 000000c0 2**2 + CONTENTS, ALLOC, LOAD, DATA + 2 .dynamic 00000028 1000000c 1000000c 000000cc 2**2 + CONTENTS, ALLOC, LOAD, DATA + 3 .rodata 00000008 10000038 10000038 000000f8 2**3 + CONTENTS, ALLOC, LOAD, READONLY, DATA +SYMBOL TABLE: +00000098 l d .text 00000000 .text +10000000 l d .got 00000000 .got +1000000c l d .dynamic 00000000 .dynamic +10000038 l d .rodata 00000000 .rodata +00000000 l df *ABS* 00000000 main.c +1000000c l O *ABS* 00000000 _DYNAMIC +10000000 l O *ABS* 00000000 _GLOBAL_OFFSET_TABLE_ +000000b4 g F .text 00000000 system +00000098 g F .text 00000000 _start +000000a0 g F .text 00000010 main +00000000 F *UND* 00000000 seek +000000b0 g F .text 00000000 _exit + + +Contents of section .text: + 0098 00f002f8 00f008f8 024808b5 484400f0 .........H..HD.. + 00a8 05f808bd 38000000 022300df 092300df ....8....#...#.. + 00b8 7047 pG +Contents of section .got: + 10000000 0c000010 00000000 00000000 ............ +Contents of section .dynamic: + 1000000c 15000000 00000000 00000000 00000000 ................ + 1000001c 00000000 00000000 00000000 00000000 ................ + 1000002c 00000000 00000000 ........ +Contents of section .rodata: + 10000038 74657374 00000000 test.... + +Disassembly of section .text: + +00000098 <_start>: +_start(): + 98: f000 f802 bl a0 <main> + 9c: f000 f808 bl b0 <_exit> + +000000a0 <main>: +main(): + a0: 4802 ldr r0, [pc, #8] ; (ac <main+0xc>) + a2: b508 push {r3, lr} + a4: 4448 add r0, r9 + a6: f000 f805 bl b4 <system> + aa: bd08 pop {r3, pc} + ac: 00000038 andeq r0, r0, r8, lsr r0 + +000000b0 <_exit>: +_exit(): + b0: 2302 movs r3, #2 + b2: df00 svc 0 + +000000b4 <system>: +system(): + b4: 2309 movs r3, #9 + b6: df00 svc 0 + b8: 4770 bx lr + +Disassembly of section .got: + +10000000 <.got>: +10000000: 1000000c andne r0, r0, ip + ... + +Disassembly of section .dynamic: + +1000000c <.dynamic>: +1000000c: 00000015 andeq r0, r0, r5, lsl r0 + ... + +Disassembly of section .rodata: + +10000038 <.rodata>: +10000038: 74736574 ldrbtvc r6, [r3], #-1396 ; 0x574 +1000003c: 00000000 andeq r0, r0, r0 diff --git a/miosix/_tools/testsuite/testsuite.cpp b/miosix/_tools/testsuite/testsuite.cpp index bee0f8693748e37c61cab00273b9c365dc242988..1e996d4306501a6186766ec4d5b9dda6c4ccce03 100644 --- a/miosix/_tools/testsuite/testsuite.cpp +++ b/miosix/_tools/testsuite/testsuite.cpp @@ -41,6 +41,8 @@ #include <cassert> #include <fcntl.h> #include <sys/stat.h> +#include <sys/wait.h> +#include <signal.h> #include <pthread.h> #include <errno.h> #include <dirent.h> @@ -58,6 +60,17 @@ #include "filesystem/console/console_device.h" #include "util/crc16.h" +#ifdef WITH_PROCESSES +#include "miosix/kernel/elf_program.h" +#include "miosix/kernel/process.h" +#include "kernel/process_pool.h" +#include "kernel/SystemMap.h" + +#include "miosix/testsuite/syscall_testsuite/includes.h" +#include "miosix/testsuite/elf_testsuite/includes.h" +#include "miosix/testsuite/mpu_testsuite/includes.h" +#endif //WITH_PROCESSES + using namespace std::tr1; using namespace miosix; @@ -115,6 +128,37 @@ static void benchmark_4(); static void exception_test(); #endif //__NO_EXCEPTIONS +#ifdef WITH_PROCESSES +void syscall_test_sleep(); +void process_test_process_ret(); +void syscall_test_system(); +#ifdef WITH_FILESYSTEM +void syscall_test_files(); +void process_test_file_concurrency(); +void syscall_test_mpu_open(); +void syscall_test_mpu_read(); +void syscall_test_mpu_write(); +#endif //WITH_FILESYSTEM + +unsigned int* memAllocation(unsigned int size); +bool memCheck(unsigned int *base, unsigned int size); +void runElfTest(const char *name, const unsigned char *filename, unsigned int file_length); + +int runProgram(const unsigned char *filename, unsigned int file_length); +bool isSignaled(int exit_code); +void mpuTest1(); +void mpuTest2(); +void mpuTest3(); +void mpuTest4(); +void mpuTest5(); +void mpuTest6(); +void mpuTest7(); +void mpuTest8(); +void mpuTest9(); +void mpuTest10(); +#endif //WITH_PROCESSES + + //main(), calls all tests int main() { @@ -123,14 +167,17 @@ int main() Thread::setPriority(0); for(;;) { - iprintf("Type 't' for kernel test, 'f' for filesystem test, 'x' for " - "exception test, 'b' for benchmarks or 's' for shutdown\n"); + iprintf("Type:\n 't' for kernel test\n 'f' for filesystem test\n 'x' for " + "exception test\n 'b' for benchmarks\n 'p' for process tes\n 'y' for syscall test\n" + " 'm' for elf and mpu test\n 's' for shutdown\n"); char c; for(;;) { c=getchar(); if(c!='\n') break; } + //For testing mpu + unsigned int *m; switch(c) { case 't': @@ -202,6 +249,87 @@ int main() case 's': iprintf("Shutting down\n"); shutdown(); + case 'y': + ledOn(); + #ifdef WITH_PROCESSES + #ifdef WITH_FILESYSTEM + syscall_test_files(); + syscall_test_mpu_open(); + syscall_test_mpu_read(); + syscall_test_mpu_write(); + #else //WITH_FILESYSTEM + iprintf("Error, filesystem support is disabled\n"); + #endif //WITH_FILESYSTEM + + syscall_test_sleep(); + syscall_test_system(); + #else //WITH_PROCESSES + iprintf("Error, process support is disabled\n"); + #endif //WITH_PROCESSES + ledOff(); + break; + case 'p': + #ifdef WITH_PROCESSES + ledOn(); + process_test_process_ret(); + process_test_file_concurrency(); + ledOff(); + #endif //WITH_PROCESSES + break; + case 'm': + //The priority of the test thread must be 1 + Thread::setPriority(1); + ledOn(); + #ifdef WITH_PROCESSES + //Note by TFT: these addresses are only valid for the stm3220g-eval. + //FIXME: llok into it + // ProcessPool allocates 4096 bytes starting from address 0x64100000 + // Range : 0x64100000 - 0x64101000 + + // First process memory layout + // Code region : 0x64101000 - 0x64101400 + // Data region : 0x64104000 - 0x64108000 + + // Second process memory layout + // Code region : 0x64101400 - 0x64101800 + // Data region : 0x64108000 - 0x6410c000 + + // Third process memory layout + // Code region : 0x64101800 - 0x64101c00 + // Data region : 0x6410c000 - 0x64110000 + + //Altered elfs tests + iprintf("\nExecuting ELF tests.\n"); + iprintf("--------------------\n"); + runElfTest("Elf Test1", aelf1, aelf1_len); + runElfTest("Elf Test2", aelf2, aelf2_len); + runElfTest("Elf Test3", aelf3, aelf3_len); + runElfTest("Elf Test4", aelf4, aelf4_len); + runElfTest("Elf Test5", aelf5, aelf5_len); + runElfTest("Elf Test6", aelf6, aelf6_len); + runElfTest("Elf Test7", aelf7, aelf7_len); + + //Mpu tests + iprintf("\n\nExecuting MPU tests.\n"); + iprintf("---------------------\n"); + m = memAllocation(4096); + mpuTest1(); + mpuTest2(); + mpuTest3(); + mpuTest4(); + mpuTest5(); + mpuTest6(); + mpuTest7(); + mpuTest8(); + mpuTest9(); + mpuTest10(); + ProcessPool::instance().deallocate(m); + #else //#ifdef WITH_PROCESSES + iprintf("Error, process support is disabled\n"); + #endif //#ifdef WITH_PROCESSES + ledOff(); + Thread::setPriority(0); + break; default: iprintf("Unrecognized option\n"); } @@ -240,6 +368,212 @@ static void fail(const char *cause) reboot(); } +#ifdef WITH_PROCESSES + +void process_test_file_concurrency() +{ + test_name("Process file concurrency"); + + remove("/file1.bin"); + remove("/file2.bin"); + + ElfProgram prog1(reinterpret_cast<const unsigned int*>(testsuite_file1_elf), testsuite_file1_elf_len); + ElfProgram prog2(reinterpret_cast<const unsigned int*>(testsuite_file2_elf), testsuite_file2_elf_len); + + pid_t p1 = Process::create(prog1); + pid_t p2 = Process::create(prog2); + + int res1 = 0, res2 = 0; + + Process::waitpid(p1, &res1, 0); + Process::waitpid(p2, &res2, 0); + + FILE *f1 = fopen("/file1.bin", "rb"); + FILE *f2 = fopen("/file2.bin", "rb"); + + if(!f1) fail("Unable to open first file"); + if(!f2) fail("Unable to open second file"); + + char buffer[10]; + + for(int i = 0; i < 1000; i++) + { + fread(buffer, 1, 9, f1); + if(strncmp(buffer, "file1.bin", 9) != 0) fail("Wrong data from file 1"); + } + + for(int i = 0; i < 1000; i++) + { + fread(buffer, 1, 9, f2); + if(strncmp(buffer, "file2.bin", 9) != 0) fail("Wrong data from file 2"); + } + + fclose(f1); + fclose(f2); + + pass(); +} + +void process_test_process_ret() +{ + test_name("Process return value"); + ElfProgram prog(reinterpret_cast<const unsigned int*>(testsuite_simple_elf),testsuite_simple_elf_len); + int ret = 0; + pid_t p = Process::create(prog); + Process::waitpid(p, &ret, 0); + //iprintf("Returned value is %d\n", WEXITSTATUS(ret)); + if(WEXITSTATUS(ret) != 42) fail("Wrong returned value"); + pass(); +} + +void syscall_test_mpu_open() +{ + test_name("open and MPU"); + ElfProgram prog(reinterpret_cast<const unsigned int*>(testsuite_syscall_mpu_open_elf), testsuite_syscall_mpu_open_elf_len); + int ret = 0; + pid_t p = Process::create(prog); + Process::waitpid(p, &ret, 0); + //iprintf("Returned value is %d\n", ret); + if(WTERMSIG(ret) != SIGSYS) fail("0x00000000 is not a valid address!"); + pass(); +} + +void syscall_test_mpu_read() +{ + test_name("read calls and MPU"); + ElfProgram prog(reinterpret_cast<const unsigned int*>(testsuite_syscall_mpu_read_elf), testsuite_syscall_mpu_read_elf_len); + int ret = 0; + pid_t p = Process::create(prog); + Process::waitpid(p, &ret, 0); + //iprintf("Returned value is %d\n", ret); + if(WTERMSIG(ret) != SIGSYS) fail("0x00000000 is not a valid address!"); + pass(); +} + +void syscall_test_mpu_write() +{ + test_name("write and MPU"); + ElfProgram prog(reinterpret_cast<const unsigned int*>(testsuite_syscall_mpu_write_elf), testsuite_syscall_mpu_write_elf_len); + int ret = 0; + pid_t p = Process::create(prog); + Process::waitpid(p, &ret, 0); + iprintf("Returned value is %d\n", ret); + if(WTERMSIG(ret) != SIGSYS) fail("0x00000000 is not a valid address!"); + pass(); +} + +void syscall_test_system() +{ + test_name("system"); + if(SystemMap::instance().getElfCount() != 0) + fail("The system lookup table should be empty"); + else + iprintf("The system lookup table is empty. Correct.\n"); + + SystemMap::instance().addElfProgram("test", reinterpret_cast<const unsigned int*>(testsuite_simple_elf), testsuite_simple_elf_len); + + if(SystemMap::instance().getElfCount() != 1) + fail("Now the system lookup table should contain 1 program"); + else + iprintf("The system lookup table contain one program. Correct.\n"); + + std::pair<const unsigned int*, unsigned int> sysret = SystemMap::instance().getElfProgram("test"); + + if(sysret.first == 0 || sysret.second == 0) + fail("The system lookup table has returned an invalid process size or an invalid elf pointer for the process"); + + ElfProgram prog(reinterpret_cast<const unsigned int*>(testsuite_system_elf), testsuite_system_elf_len); + + int ret = 0; + pid_t p = Process::create(prog); + Process::waitpid(p, &ret, 0); + + if(WEXITSTATUS(ret) != 42){ + iprintf("Host process returned: %d\n", WEXITSTATUS(ret)); + fail("The system inside a process has failed"); + } + + SystemMap::instance().removeElfProgram("test"); + + if(SystemMap::instance().getElfCount() != 0) + fail("The system lookup table now should be empty.\n"); + + pass(); +} + +void syscall_test_sleep(){ + test_name("System Call: sleep"); + ElfProgram prog(reinterpret_cast<const unsigned int*>(testsuite_sleep_elf),testsuite_sleep_elf_len); + +// iprintf("diff was: %d\n", (unsigned int)getTick()); + + int ret = 0; + long long time = getTick(); + pid_t p = Process::create(prog); + Process::waitpid(p, &ret, 0); + + long long diff = llabs((getTick() - time)); + + if (llabs(diff - 5*TICK_FREQ) > static_cast<long long>(TICK_FREQ * 0.02)) + fail("The sleep should have only a little more than 5 seconds."); + + pass(); +} + +void syscall_test_files(){ + test_name("System Call: open, read, write, seek, close, system"); + + ElfProgram prog(reinterpret_cast<const unsigned int*>(testsuite_syscall_elf),testsuite_syscall_elf_len); + int ret = 0; + + remove("/foo.bin"); + + pid_t child = Process::create(prog); + Process::waitpid(child, &ret, 0); + + iprintf("Returned value %d\n", WEXITSTATUS(ret)); + switch(WEXITSTATUS(ret)){ + case 0: + pass(); + break; + case 1: + fail("Open with O_RDWR should have failed, the file doesn't exist"); + break; + case 2: + fail("Cannot craete new file"); + break; + case 3: + fail("file descriptor not valid"); + break; + case 4: + fail("write has written the wrong amount of data"); + break; + case 5: + fail("read has read the wrong amount of data"); + break; + case 6: + fail("readed data doesn't match the written one"); + break; + case 7: + fail("close hasn't returned 0"); + break; + case 8: + fail("open with O_RDWR failed, but the file exists"); + break; + case 9: + fail("read has return the wrogn amount of data"); + break; + case 10: + fail("readed data doesn't match the written one"); + break; + case 11: + fail("close hasn't returned 0"); + break; + } +} + +#endif //WITH_PROCESSES + // // Test 1 // @@ -4258,3 +4592,279 @@ static void benchmark_4() } iprintf("%d fast disable/enable interrupts pairs per second\n",i); } + +#ifdef WITH_PROCESSES + +unsigned int* memAllocation(unsigned int size) +{ + unsigned int *p = ProcessPool::instance().allocate(size); + memset(p, WATERMARK_FILL, size); + iprintf("Allocated %d bytes. Base: %p. Size: 0x%x.\n\n", size, p, size); + return p; +} + +// Returns true if a watermark filled memory zone is not corrupted. +// 'base' must be 4-byte aligned +bool memCheck(unsigned int *base, unsigned int size) +{ + for(unsigned int i = 0; i < size / 4; i++) + { + if(*(base + i) != WATERMARK_FILL) + return false; + } + return true; +} + +void runElfTest(const char *name, const unsigned char *filename, unsigned int file_length) +{ + iprintf("Executing %s...", name); + try + { + ElfProgram prog(reinterpret_cast<const unsigned int*>(filename),file_length); + iprintf("not passed.\n"); + } + catch (std::runtime_error &err) + { + iprintf("passed.\n"); + } +} + +//It runs the program, waits for its exit, and returns the exit code +int runProgram(const unsigned char *filename, unsigned int file_length) +{ + int ec; + ElfProgram prog(reinterpret_cast<const unsigned int*>(filename), file_length); + pid_t child=Process::create(prog); + Process::waitpid(child, &ec, 0); + return ec; +} + +//Returns true if the process has been signaled with SIGSEV +bool isSignaled(int exit_code) +{ + if(WIFSIGNALED(exit_code) && WTERMSIG(exit_code)==SIGSEGV) + { + return true; + } + return false; +} + +void mpuTest1() +{ + int ec; + unsigned int *addr = (unsigned int*) 0x64100000; + iprintf("Executing MPU Test 1...\n"); + ec = runProgram(test1_elf, test1_elf_len); + if(isSignaled(ec)) + { + if(*addr == 0xbbbbbbbb) + iprintf("...not passed! The process has written a forbidden memory location.\n\n"); + else if(*addr == WATERMARK_FILL) + iprintf("...passed!\n\n"); + else + iprintf("...not passed! Memory has been somehow corrupted.\n\n"); + } + else + { + iprintf("...not passed! Process exited normally.\n\n"); + } +} + +void mpuTest2() +{ + int ec; + unsigned int *addr = (unsigned int*) 0x64100200; + iprintf("Executing MPU Test 2...\n"); + ec = runProgram(test2_elf, test2_elf_len); + if(isSignaled(ec)) + { + if(*addr == WATERMARK_FILL) + iprintf("...passed!\n\n"); + else + iprintf("...not passed! Memory has been somehow corrupted.\n\n"); + } + else + { + iprintf("...not passed! Process exited normally.\n\n"); + } +} + +void mpuTest3() +{ + int ec; + unsigned int *addr = (unsigned int*) 0x64100200; + iprintf("Executing MPU Test 3...\n"); + ec = runProgram(test3_elf, test3_elf_len); + if(isSignaled(ec)) + { + if(*addr == 0xbbbbbbbb) + iprintf("...not passed! The process has written a forbidden memory location.\n\n"); + else + iprintf("...passed!\n\n"); + } + else + { + iprintf("...not passed! Process exited normally.\n\n"); + } +} + +void mpuTest4() +{ + int ec; + iprintf("Executing MPU Test 4...\n"); + ec = runProgram(test4_elf, test4_elf_len); + if(isSignaled(ec)) + { + iprintf("...passed!.\n\n"); + } + else + { + iprintf("...not passed! Process exited normally.\n\n"); + } +} + +void mpuTest5() +{ + int ec; + unsigned int *addr = (unsigned int*) 0x64101000; + iprintf("Executing MPU Test 5...\n"); + ec = runProgram(test5_elf, test5_elf_len); + if(isSignaled(ec)) + { + if(*addr == 0xbbbbbbbb) + iprintf("...not passed! The process has written a forbidden memory location.\n\n"); + else + iprintf("...passed!.\n\n"); + } + else + { + iprintf("...not passed! Process exited normally.\n\n"); + } +} + +void mpuTest6() +{ + int ec; + unsigned int *addr = (unsigned int*) 0x64101404; + iprintf("Executing MPU Test 6...\n"); + ec = runProgram(test6_elf, test6_elf_len); + if(isSignaled(ec)) + { + if(*addr == 0xbbbbbbbb) + iprintf("...not passed! The process has written a forbidden memory location.\n\n"); + else + iprintf("...passed!.\n\n"); + } + else + { + iprintf("...not passed! Process exited normally.\n\n"); + } +} + +void mpuTest7() +{ + int ec; + unsigned int memSize = 8192; + + iprintf("Executing MPU Test 7...\n"); + unsigned int *p = ProcessPool::instance().allocate(memSize); + memset(p, WATERMARK_FILL, memSize); + ElfProgram prog(reinterpret_cast<const unsigned int*>(test7_elf), test7_elf_len); + pid_t child=Process::create(prog); + delayMs(1000); + Process::waitpid(child, &ec, 0); + if(isSignaled(ec)) + { + if(memCheck(p, memSize) == true) + iprintf("...passed!.\n\n"); + else + iprintf("...not passed! Memory NOT sane!"); + ProcessPool::instance().deallocate(p); + } + else + { + iprintf("...not passed! Process exited normally.\n\n"); + ProcessPool::instance().deallocate(p); + } +} + +void mpuTest8() +{ + // We create two processes. The first goes to sleep for 2 seconds, + // while the second process tries to access the data region of the + // first. + unsigned int *addr = (unsigned int*) 0x64104004; + iprintf("Executing MPU Test 8...\n"); + ElfProgram prog1(reinterpret_cast<const unsigned int*>(test8_1_elf),test8_1_elf_len); + ElfProgram prog2(reinterpret_cast<const unsigned int*>(test8_2_elf),test8_2_elf_len); + pid_t child1=Process::create(prog1); + pid_t child2=Process::create(prog2); + int ec1, ec2; + Process::waitpid(child1,&ec1,0); + Process::waitpid(child2,&ec2,0); + if(WIFSIGNALED(ec2) && (WTERMSIG(ec2) == SIGSEGV) && WIFEXITED(ec1)) + { + if(*addr == 0xbbbbbbbb) + iprintf("...not passed! The process has written a forbidden memory location.\n\n"); + else + iprintf("...passed!.\n\n"); + } + else + { + iprintf("...not passed!\n\n"); + } +} + +void mpuTest9() +{ + iprintf("Executing MPU Test 9...\n"); + ElfProgram prog(reinterpret_cast<const unsigned int*>(test9_elf),test9_elf_len); + std::vector<pid_t> pids; + int ec; + for(unsigned int i = 0; i < 100; i++) + { + pid_t pid; + try { + pid = Process::create(prog); + pids.push_back(pid); + } + catch (std::bad_alloc &ex) + { + iprintf("Bad alloc raised: %s\nIteration is: %d\n", ex.what(), i); + break; + } + } + iprintf("Allocated %d processes before system ran out of memory.\n", pids.size()); + for(unsigned int i = 0; i < pids.size(); i++) + { + Process::waitpid(pids[i], &ec, 0); + //iprintf("Process %d has terminated with return code: %d\n", pids[i], ec); + } + iprintf("...passed!.\n\n"); +} + +void mpuTest10() +{ + // The first process is allocated and sent to sleep. The second process statically + // allocates a big array and calls a syscall, which will try to write in the memory + // chunk owned by the first process. + // The first process should end properly, the second process should fault. + int ec1, ec2; + iprintf("Executing MPU Test 10...\n"); + ElfProgram prog1(reinterpret_cast<const unsigned int*>(test10_1_elf), test10_1_elf_len); + ElfProgram prog2(reinterpret_cast<const unsigned int*>(test10_2_elf), test10_2_elf_len); + pid_t child1=Process::create(prog1); + pid_t child2=Process::create(prog2); + Process::waitpid(child1, &ec1, 0); + Process::waitpid(child2, &ec2, 0); + + if(!isSignaled(ec1) && isSignaled(ec2)) + { + iprintf("...passed!.\n\n"); + } + else + { + iprintf("...not passed!\n\n"); + } +} +#endif //WITH_PROCESSES diff --git a/miosix/arch/arm7_lpc2000/lpc2138_miosix_board/interfaces-impl/portability.cpp b/miosix/arch/arm7_lpc2000/lpc2138_miosix_board/interfaces-impl/portability.cpp index 23894c03b497d5df22b108d2b0bfce451737f4a2..dac606dfc76d34c788e8408338c27d2777e79352 100644 --- a/miosix/arch/arm7_lpc2000/lpc2138_miosix_board/interfaces-impl/portability.cpp +++ b/miosix/arch/arm7_lpc2000/lpc2138_miosix_board/interfaces-impl/portability.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2008, 2009, 2010 by Terraneo Federico * + * Copyright (C) 2008, 2009, 2010, 2011, 2012 by Terraneo Federico * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * @@ -189,6 +189,33 @@ void initCtxsave(unsigned int *ctxsave, void *(*pc)(void *), unsigned int *sp, ctxsave[16]=0x1f;//thread starts in system mode with irq and fiq enabled. } +#ifdef WITH_PROCESSES + +void initCtxsave(unsigned int *ctxsave, void *(*pc)(void *), unsigned int *sp, + void *argv, unsigned int *gotBase) +{ + ctxsave[0]=(unsigned int)argv; + ctxsave[1]=0; + ctxsave[2]=0; + ctxsave[3]=0; + ctxsave[4]=0; + ctxsave[5]=0; + ctxsave[6]=0; + ctxsave[7]=0; + ctxsave[8]=0; + ctxsave[9]=(unsigned int)gotBase; + ctxsave[10]=0; + ctxsave[11]=0; + ctxsave[12]=0; + ctxsave[13]=(unsigned int)sp;//Initialize the thread's stack pointer + ctxsave[14]=0xffffffff;//threadLauncher never returns, so lr is not important + //Initialize the thread's program counter to the beginning of the entry point + ctxsave[15]=(unsigned int)pc; + ctxsave[16]=0x1f;//thread starts in system mode with irq and fiq enabled. +} + +#endif //WITH_PROCESSES + void IRQportableStartKernel() { PCONP|=(1<<1);//Enable TIMER0 diff --git a/miosix/arch/arm7_lpc2000/lpc2138_miosix_board/interfaces-impl/portability_impl.h b/miosix/arch/arm7_lpc2000/lpc2138_miosix_board/interfaces-impl/portability_impl.h index 0cb8accadea242a76a3fb5c8a4cb0c2015f432b6..8da834c8e7f7cd2683a456e80b810fe7f2a060eb 100644 --- a/miosix/arch/arm7_lpc2000/lpc2138_miosix_board/interfaces-impl/portability_impl.h +++ b/miosix/arch/arm7_lpc2000/lpc2138_miosix_board/interfaces-impl/portability_impl.h @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2008, 2009, 2010 by Terraneo Federico * + * Copyright (C) 2008, 2009, 2010, 2011, 2012 by Terraneo Federico * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * @@ -181,7 +181,9 @@ namespace miosix_private { inline void doYield() { - asm volatile("swi 0"); + asm volatile("movs r3, #0\n\t" + "swi 0" + :::"r3"); } inline void doDisableInterrupts() diff --git a/miosix/arch/cortexM3_stm32/common/interfaces-impl/portability.cpp b/miosix/arch/cortexM3_stm32/common/interfaces-impl/portability.cpp index 93406ec7be268f319354ff00548622da5e7502c3..aad6f88cd81757f0ff750364e3f1aa66840e0724 100644 --- a/miosix/arch/cortexM3_stm32/common/interfaces-impl/portability.cpp +++ b/miosix/arch/cortexM3_stm32/common/interfaces-impl/portability.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2010 by Terraneo Federico * + * Copyright (C) 2010, 2011, 2012 by Terraneo Federico * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * @@ -168,6 +168,29 @@ void initCtxsave(unsigned int *ctxsave, void *(*pc)(void *), unsigned int *sp, //leaving the content of r4-r11 uninitialized } +#ifdef WITH_PROCESSES + +void initCtxsave(unsigned int *ctxsave, void *(*pc)(void *), unsigned int *sp, + void *argv, unsigned int *gotBase) +{ + unsigned int *stackPtr=sp; + stackPtr--; //Stack is full descending, so decrement first + *stackPtr=0x01000000; stackPtr--; //--> xPSR + *stackPtr=reinterpret_cast<unsigned long>(pc); stackPtr--; //--> pc + *stackPtr=0xffffffff; stackPtr--; //--> lr + *stackPtr=0; stackPtr--; //--> r12 + *stackPtr=0; stackPtr--; //--> r3 + *stackPtr=0; stackPtr--; //--> r2 + *stackPtr=0; stackPtr--; //--> r1 + *stackPtr=reinterpret_cast<unsigned long >(argv); //--> r0 + + ctxsave[0]=reinterpret_cast<unsigned long>(stackPtr); //--> psp + ctxsave[6]=reinterpret_cast<unsigned long>(gotBase); //--> r9 + //leaving the content of r4-r8,r10-r11 uninitialized +} + +#endif //WITH_PROCESSES + void IRQportableStartKernel() { //Enable fault handlers diff --git a/miosix/arch/cortexM3_stm32/common/interfaces-impl/portability_impl.h b/miosix/arch/cortexM3_stm32/common/interfaces-impl/portability_impl.h index c6686a632e24ecbad9eeab1f91bcf7a2b6216e23..e40061aa5df985f07b8f1e316cc554d79f25f1cb 100644 --- a/miosix/arch/cortexM3_stm32/common/interfaces-impl/portability_impl.h +++ b/miosix/arch/cortexM3_stm32/common/interfaces-impl/portability_impl.h @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2010 by Terraneo Federico * + * Copyright (C) 2010, 2011, 2012 by Terraneo Federico * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * @@ -102,7 +102,9 @@ namespace miosix_private { inline void doYield() { - asm volatile("svc 0"); + asm volatile("movs r3, #0\n\t" + "svc 0" + :::"r3"); } inline void doDisableInterrupts() diff --git a/miosix/arch/cortexM3_stm32f2/common/core/interrupts.cpp b/miosix/arch/cortexM3_stm32f2/common/core/interrupts.cpp index 411cbda4887cd546744aede791391c37e5e28403..40eb7a1b5192f4b8085c2e3d358c3d17abc32311 100644 --- a/miosix/arch/cortexM3_stm32f2/common/core/interrupts.cpp +++ b/miosix/arch/cortexM3_stm32f2/common/core/interrupts.cpp @@ -26,6 +26,7 @@ ***************************************************************************/ #include "kernel/logging.h" +#include "kernel/kernel.h" #include "config/miosix_settings.h" #include "interfaces/portability.h" #include "interfaces/arch_registers.h" @@ -54,34 +55,46 @@ static void printUnsignedInt(unsigned int x) IRQerrorLog(result); } +#endif //WITH_ERRLOG + /** * \internal - * Print the program counter of the thread that was running when the exception + * \return the program counter of the thread that was running when the exception * occurred. */ -static void printProgramCounter() +static unsigned int getProgramCounter() { - register unsigned int pc; + register unsigned int result; // Get program counter when the exception was thrown from stack frame asm volatile("mrs %0, psp \n\t" "add %0, %0, #24 \n\t" - "ldr %0, [%0] \n\t":"=r"(pc)); - printUnsignedInt(pc); + "ldr %0, [%0] \n\t":"=r"(result)); + return result; } -#endif //WITH_ERRLOG - void NMI_Handler() { IRQerrorLog("\r\n***Unexpected NMI\r\n"); miosix_private::IRQsystemReboot(); } -void HardFault_Handler() +void __attribute__((naked)) HardFault_Handler() { + saveContext(); + //Call HardFault_impl(). Name is a C++ mangled name. + asm volatile("bl _Z14HardFault_implv"); + restoreContext(); +} + +void __attribute__((noinline)) HardFault_impl() +{ + #ifdef WITH_PROCESSES + if(miosix::Thread::IRQreportFault(miosix_private::FaultData( + HARDFAULT,getProgramCounter()))) return; + #endif //WITH_PROCESSES #ifdef WITH_ERRLOG IRQerrorLog("\r\n***Unexpected HardFault @ "); - printProgramCounter(); + printUnsignedInt(getProgramCounter()); unsigned int hfsr=SCB->HFSR; if(hfsr & SCB_HFSR_FORCED_Msk) IRQerrorLog("Fault escalation occurred\r\n"); @@ -91,12 +104,32 @@ void HardFault_Handler() miosix_private::IRQsystemReboot(); } -void MemManage_Handler() +void __attribute__((naked)) MemManage_Handler() { + saveContext(); + //Call MemManage_impl(). Name is a C++ mangled name. + asm volatile("bl _Z14MemManage_implv"); + restoreContext(); +} + +void __attribute__((noinline)) MemManage_impl() +{ + unsigned int cfsr=SCB->CFSR; + #ifdef WITH_PROCESSES + int id, arg=0; + if(cfsr & 0x00000001) id=MP_XN; + else if(cfsr & 0x00000080) { id=MP; arg=SCB->MMFAR; } + else id=MP_NOADDR; + if(miosix::Thread::IRQreportFault(miosix_private::FaultData( + id,getProgramCounter(),arg))) + { + SCB->SHCSR &= ~(1<<13); //Clear MEMFAULTPENDED bit + return; + } + #endif //WITH_PROCESSES #ifdef WITH_ERRLOG IRQerrorLog("\r\n***Unexpected MemManage @ "); - printProgramCounter(); - unsigned int cfsr=SCB->CFSR; + printUnsignedInt(getProgramCounter()); if(cfsr & 0x00000080) { IRQerrorLog("Fault caused by attempted access to "); @@ -118,7 +151,7 @@ void BusFault_Handler() { #ifdef WITH_ERRLOG IRQerrorLog("\r\n***Unexpected BusFault @ "); - printProgramCounter(); + printUnsignedInt(getProgramCounter()); unsigned int cfsr=SCB->CFSR; if(cfsr & 0x00008000) { @@ -139,12 +172,36 @@ void BusFault_Handler() miosix_private::IRQsystemReboot(); } -void UsageFault_Handler() +void __attribute__((naked)) UsageFault_Handler() +{ + saveContext(); + //Call UsageFault_impl(). Name is a C++ mangled name. + asm volatile("bl _Z15UsageFault_implv"); + restoreContext(); +} + +void __attribute__((noinline)) UsageFault_impl() { + unsigned int cfsr=SCB->CFSR; + #ifdef WITH_PROCESSES + int id; + if(cfsr & 0x02000000) id=UF_DIVZERO; + else if(cfsr & 0x01000000) id=UF_UNALIGNED; + else if(cfsr & 0x00080000) id=UF_COPROC; + else if(cfsr & 0x00040000) id=UF_EXCRET; + else if(cfsr & 0x00020000) id=UF_EPSR; + else if(cfsr & 0x00010000) id=UF_UNDEF; + else id=UF_UNEXP; + if(miosix::Thread::IRQreportFault(miosix_private::FaultData( + id,getProgramCounter()))) + { + SCB->SHCSR &= ~(1<<12); //Clear USGFAULTPENDED bit + return; + } + #endif //WITH_PROCESSES #ifdef WITH_ERRLOG IRQerrorLog("\r\n***Unexpected UsageFault @ "); - printProgramCounter(); - unsigned int cfsr=SCB->CFSR; + printUnsignedInt(getProgramCounter()); if(cfsr & 0x02000000) IRQerrorLog("Divide by zero\r\n"); if(cfsr & 0x01000000) IRQerrorLog("Unaligned memory access\r\n"); if(cfsr & 0x00080000) IRQerrorLog("Attempted coprocessor access\r\n"); @@ -159,7 +216,7 @@ void DebugMon_Handler() { #ifdef WITH_ERRLOG IRQerrorLog("\r\n***Unexpected DebugMon @ "); - printProgramCounter(); + printUnsignedInt(getProgramCounter()); #endif //WITH_ERRLOG miosix_private::IRQsystemReboot(); } @@ -168,7 +225,7 @@ void PendSV_Handler() { #ifdef WITH_ERRLOG IRQerrorLog("\r\n***Unexpected PendSV @ "); - printProgramCounter(); + printUnsignedInt(getProgramCounter()); #endif //WITH_ERRLOG miosix_private::IRQsystemReboot(); } diff --git a/miosix/arch/cortexM3_stm32f2/common/core/interrupts.h b/miosix/arch/cortexM3_stm32f2/common/core/interrupts.h index 6b74a54ff907127a2719b87ddcae0e6b5a782fb7..cdb648f554046e8a59c519aa79826e1bf6f03620 100644 --- a/miosix/arch/cortexM3_stm32f2/common/core/interrupts.h +++ b/miosix/arch/cortexM3_stm32f2/common/core/interrupts.h @@ -34,4 +34,23 @@ */ void unexpectedInterrupt(); +/** + * Possible kind of faults that the Cortex-M3 can report. + * They are used to print debug information if a process causes a fault + */ +enum FaultType +{ + MP=1, //Process attempted data access outside its memory + MP_NOADDR=2, //Process attempted data access outside its memory (missing addr) + MP_XN=3, //Process attempted code access outside its memory + UF_DIVZERO=4, //Process attempted to divide by zero + UF_UNALIGNED=5,//Process attempted unaligned memory access + UF_COPROC=6, //Process attempted a coprocessor access + UF_EXCRET=7, //Process attempted an exception return + UF_EPSR=8, //Process attempted to access the EPSR + UF_UNDEF=9, //Process attempted to execute an invalid instruction + UF_UNEXP=10, //Unexpected usage fault + HARDFAULT=11 //Hardfault (for example process executed a BKPT instruction) +}; + #endif //INTERRUPTS_H diff --git a/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/disk.cpp b/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/disk.cpp index f1108d490bd9eea5a6859693db5af62a2ff4114d..a0f6e5f7329234b6648877aa36b49836d99b1ae8 100644 --- a/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/disk.cpp +++ b/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/disk.cpp @@ -140,9 +140,11 @@ static CardType cardType=Invalid; //SD card GPIOs typedef Gpio<GPIOC_BASE,8> sdD0; -typedef Gpio<GPIOC_BASE,9> sdD1; +#ifndef _BOARD_STM3220G_EVAL //QUIRK: serial port and SD have pins in common +typedef Gpio<GPIOC_BASE,9> sdD1; typedef Gpio<GPIOC_BASE,10> sdD2; typedef Gpio<GPIOC_BASE,11> sdD3; +#endif //_BOARD_STM3220G_EVAL typedef Gpio<GPIOC_BASE,12> sdCLK; typedef Gpio<GPIOD_BASE,2> sdCMD; diff --git a/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/portability.cpp b/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/portability.cpp index e5d69aeb4768b302804917e970d3e35903c8e486..f0f1d1f314ce14054c6534377124982e52c0d749 100644 --- a/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/portability.cpp +++ b/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/portability.cpp @@ -32,7 +32,11 @@ #include "interfaces/bsp.h" #include "kernel/scheduler/scheduler.h" #include "kernel/scheduler/tick_interrupt.h" +#include "core/interrupts.h" #include <algorithm> +#include <cstdio> +#include <cstring> +#include <cassert> /** * \internal @@ -98,7 +102,7 @@ void ISR_preempt() __attribute__((noinline)); void ISR_preempt() { IRQstackOverflowCheck(); - miosix::IRQtickInterrupt(); + miosix::IRQtickInterrupt(); } /** @@ -111,8 +115,48 @@ void ISR_preempt() void ISR_yield() __attribute__((noinline)); void ISR_yield() { + #ifdef WITH_PROCESSES + // WARNING: Temporary fix. Rationale: + // This fix is intended to avoid kernel or process faulting due to + // another process actions. Consider the case in which a process statically + // allocates a big array such that there is no space left for saving + // context data. If the process issues a system call, in the following + // interrupt the context is saved, but since there is no memory available + // for all the context data, a mem manage interrupt is set to 'pending'. Then, + // a fake syscall is issued, based on the value read on the stack (which + // the process hasn't set due to the memory fault and is likely to be 0); + // this syscall is usually a yield (due to the value of 0 above), + // which can cause the scheduling of the kernel thread. At this point, + // the pending mem fault is issued from the kernel thread, causing the + //kernel fault and reboot. This is caused by the mem fault interrupt + // having less priority of the other interrupts. + // This fix checks if there is a mem fault interrupt pending, and, if so, + // it clears it and returns before calling the previously mentioned fake + // syscall. + if(SCB->SHCSR & (1<<13)) + { + if(miosix::Thread::IRQreportFault(miosix_private::FaultData( + MP,0,0))) + { + SCB->SHCSR &= ~(1<<13); //Clear MEMFAULTPENDED bit + return; + } + } + #endif // WITH_PROCESSES IRQstackOverflowCheck(); + + #ifdef WITH_PROCESSES + //If processes are enabled, check the content of r3. If zero then it + //it is a simple yield, otherwise handle the syscall + //Note that it is required to use ctxsave and not cur->ctxsave because + //at this time we do not know if the active context is user or kernel + unsigned int threadSp=ctxsave[0]; + unsigned int *processStack=reinterpret_cast<unsigned int*>(threadSp); + if(processStack[3]!=0) miosix::Thread::IRQhandleSvc(processStack[3]); + else miosix::Scheduler::IRQfindNextThread(); + #else //WITH_PROCESSES miosix::Scheduler::IRQfindNextThread(); + #endif //WITH_PROCESSES } #ifdef SCHED_TYPE_CONTROL_BASED @@ -168,6 +212,150 @@ void initCtxsave(unsigned int *ctxsave, void *(*pc)(void *), unsigned int *sp, //leaving the content of r4-r11 uninitialized } +#ifdef WITH_PROCESSES + +// +// class FaultData +// + +void FaultData::print() const +{ + switch(id) + { + case MP: + iprintf("* Attempted data access @ 0x%x (PC was 0x%x)\n",arg,pc); + break; + case MP_NOADDR: + iprintf("* Invalid data access (PC was 0x%x)\n",pc); + break; + case MP_XN: + iprintf("* Attempted instruction fetch @ 0x%x\n",pc); + break; + case UF_DIVZERO: + iprintf("* Dvide by zero (PC was 0x%x)\n",pc); + break; + case UF_UNALIGNED: + iprintf("* Unaligned memory access (PC was 0x%x)\n",pc); + break; + case UF_COPROC: + iprintf("* Attempted coprocessor access (PC was 0x%x)\n",pc); + break; + case UF_EXCRET: + iprintf("* Invalid exception return sequence (PC was 0x%x)\n",pc); + break; + case UF_EPSR: + iprintf("* Attempted access to the EPSR (PC was 0x%x)\n",pc); + break; + case UF_UNDEF: + iprintf("* Undefined instruction (PC was 0x%x)\n",pc); + break; + case UF_UNEXP: + iprintf("* Unexpected usage fault (PC was 0x%x)\n",pc); + break; + case HARDFAULT: + iprintf("* Hardfault (PC was 0x%x)\n",pc); + break; + } +} + +void initCtxsave(unsigned int *ctxsave, void *(*pc)(void *), unsigned int *sp, + void *argv, unsigned int *gotBase) +{ + unsigned int *stackPtr=sp; + stackPtr--; //Stack is full descending, so decrement first + *stackPtr=0x01000000; stackPtr--; //--> xPSR + *stackPtr=reinterpret_cast<unsigned long>(pc); stackPtr--; //--> pc + *stackPtr=0xffffffff; stackPtr--; //--> lr + *stackPtr=0; stackPtr--; //--> r12 + *stackPtr=0; stackPtr--; //--> r3 + *stackPtr=0; stackPtr--; //--> r2 + *stackPtr=0; stackPtr--; //--> r1 + *stackPtr=reinterpret_cast<unsigned long >(argv); //--> r0 + + ctxsave[0]=reinterpret_cast<unsigned long>(stackPtr); //--> psp + ctxsave[6]=reinterpret_cast<unsigned long>(gotBase); //--> r9 //--> r9 + //leaving the content of r4-r8,r10-r11 uninitialized +} + +static unsigned int sizeToMpu(unsigned int size) +{ + assert(size>=32); + unsigned int result=30-__builtin_clz(size); + if(size & (size-1)) result++; + return result<<1; +} + +// +// class MPUConfiguration +// + +MPUConfiguration::MPUConfiguration(unsigned int *elfBase, unsigned int elfSize, + unsigned int *imageBase, unsigned int imageSize) +{ + regValues[0]=(reinterpret_cast<unsigned int>(elfBase) & (~0x1f)) + | MPU_RBAR_VALID_Msk | 0; //Region 0 + regValues[2]=(reinterpret_cast<unsigned int>(imageBase) & (~0x1f)) + | MPU_RBAR_VALID_Msk | 1; //Region 1 + #ifndef __CODE_IN_XRAM + regValues[1]=2<<MPU_RASR_AP_Pos + | MPU_RASR_C_Msk + | 1 //Enable bit + | sizeToMpu(elfSize); + regValues[3]=3<<MPU_RASR_AP_Pos + | MPU_RASR_XN_Msk + | MPU_RASR_C_Msk + | MPU_RASR_S_Msk + | 1 //Enable bit + | sizeToMpu(imageSize); + #else //__CODE_IN_XRAM + regValues[1]=2<<MPU_RASR_AP_Pos + | MPU_RASR_C_Msk + | MPU_RASR_B_Msk + | MPU_RASR_S_Msk + | 1 //Enable bit + | sizeToMpu(elfSize); + regValues[3]=3<<MPU_RASR_AP_Pos + | MPU_RASR_XN_Msk + | MPU_RASR_C_Msk + | MPU_RASR_B_Msk + | MPU_RASR_S_Msk + | 1 //Enable bit + | sizeToMpu(imageSize); + #endif //__CODE_IN_XRAM +} + +void MPUConfiguration::dumpConfiguration() +{ + for(int i=0;i<2;i++) + { + unsigned int base=regValues[2*i] & (~0x1f); + unsigned int end=base+(1<<(((regValues[2*i+1]>>1) & 31)+1)); + char w=regValues[2*i+1] & (1<<MPU_RASR_AP_Pos) ? 'w' : '-'; + char x=regValues[2*i+1] & MPU_RASR_XN_Msk ? '-' : 'x'; + iprintf("* MPU region %d 0x%x-0x%x r%c%c\n",i,base,end,w,x); + } +} + +bool MPUConfiguration::within(const unsigned int ptr) const +{ + unsigned int base = regValues[2] & (~0x1f); + unsigned int end = base + (1 << (((regValues[3] >> 1) & 31) + 1)); + + return ptr >= base && ptr < end; +} + +unsigned int MPUConfiguration::getBaseDataAddress() const +{ + return regValues[2] & (~0x1f); +} + +unsigned int MPUConfiguration::getDataSize() const +{ + return (1 << (((regValues[3] >> 1) & 31) + 1)); +} + +#endif //WITH_PROCESSES + void IRQportableStartKernel() { //Enable fault handlers @@ -180,11 +368,16 @@ void IRQportableStartKernel() NVIC_SetPriorityGrouping(7);//This should disable interrupt nesting NVIC_SetPriority(SVCall_IRQn,3);//High priority for SVC (Max=0, min=15) NVIC_SetPriority(SysTick_IRQn,3);//High priority for SysTick (Max=0, min=15) + NVIC_SetPriority(MemoryManagement_IRQn,2);//Higher priority for MemoryManagement (Max=0, min=15) SysTick->LOAD=SystemCoreClock/miosix::TICK_FREQ; //Start SysTick, set to generate interrupts SysTick->CTRL=SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_CLKSOURCE_Msk; + #ifdef WITH_PROCESSES + //Enable MPU + MPU->CTRL=MPU_CTRL_PRIVDEFENA_Msk | MPU_CTRL_ENABLE_Msk; + #endif //WITH_PROCESSES #ifdef SCHED_TYPE_CONTROL_BASED AuxiliaryTimer::IRQinit(); #endif //SCHED_TYPE_CONTROL_BASED diff --git a/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/portability_impl.h b/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/portability_impl.h index 5fcc019b48c22748b3466d29368a89a918708327..47c48a267dd94580e45bbbd90cbf1bc3e3c50b01 100644 --- a/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/portability_impl.h +++ b/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/portability_impl.h @@ -30,6 +30,7 @@ #define PORTABILITY_IMPL_H #include "interfaces/arch_registers.h" +#include "interfaces/portability.h" #include "config/miosix_settings.h" /** @@ -43,7 +44,7 @@ * context switch. It requires C linkage to be used inside asm statement. * Registers are saved in the following order: * *ctxsave+32 --> r11 - * *ctxsave+28 --> r10 + * *ctxsave+28 --> r10 * *ctxsave+24 --> r9 * *ctxsave+20 --> r8 * *ctxsave+16 --> r7 @@ -102,7 +103,9 @@ namespace miosix_private { inline void doYield() { - asm volatile("svc 0"); + asm volatile("movs r3, #0\n\t" + "svc 0" + :::"r3"); } inline void doDisableInterrupts() @@ -132,6 +135,68 @@ inline bool checkAreInterruptsEnabled() return true; } +#ifdef WITH_PROCESSES + +// +// class SyscallParameters +// + +inline SyscallParameters::SyscallParameters(unsigned int *context) : + registers(reinterpret_cast<unsigned int*>(context[0])) {} + +inline int SyscallParameters::getSyscallId() const +{ + return registers[3]; +} + +inline unsigned int SyscallParameters::getFirstParameter() const +{ + return registers[0]; +} + +inline unsigned int SyscallParameters::getSecondParameter() const +{ + return registers[1]; +} + +inline unsigned int SyscallParameters::getThirdParameter() const +{ + return registers[2]; +} + +inline void SyscallParameters::setReturnValue(unsigned int ret) +{ + registers[0]=ret; +} + +inline void portableSwitchToUserspace() +{ + asm volatile("movs r3, #1\n\t" + "svc 0" + :::"r3"); +} + +// +// class MPU +// + +inline void MPUConfiguration::IRQenable() +{ + MPU->RBAR=regValues[0]; + MPU->RASR=regValues[1]; + MPU->RBAR=regValues[2]; + MPU->RASR=regValues[3]; + __set_CONTROL(3); +} + +inline void MPUConfiguration::IRQdisable() +{ + __set_CONTROL(2); +} + + +#endif //WITH_PROCESSES + /** * \} */ diff --git a/miosix/arch/cortexM3_stm32f2/stm32f207ig_stm3220g-eval/stm32_1m+128k_all_in_xram.ld b/miosix/arch/cortexM3_stm32f2/stm32f207ig_stm3220g-eval/stm32_1m+128k_all_in_xram.ld index 78b66e0257f1f6a703f32ec04142ab9cb2c1e000..b0b9eedd4009218d0af49f780264f8f87181eeca 100644 --- a/miosix/arch/cortexM3_stm32f2/stm32f207ig_stm3220g-eval/stm32_1m+128k_all_in_xram.ld +++ b/miosix/arch/cortexM3_stm32f2/stm32f207ig_stm3220g-eval/stm32_1m+128k_all_in_xram.ld @@ -1,6 +1,7 @@ /* * C++ enabled linker script for stm32 (1M FLASH, 128K RAM) + 2MB xram * Developed by TFT: Terraneo Federico Technologies + * Optimized for use with the Miosix kernel */ /* diff --git a/miosix/arch/cortexM3_stm32f2/stm32f207ig_stm3220g-eval/stm32_1m+128k_all_in_xram_processes.ld b/miosix/arch/cortexM3_stm32f2/stm32f207ig_stm3220g-eval/stm32_1m+128k_all_in_xram_processes.ld new file mode 100644 index 0000000000000000000000000000000000000000..89104ab0034ddc1d20aadbdb816504b78a4e1809 --- /dev/null +++ b/miosix/arch/cortexM3_stm32f2/stm32f207ig_stm3220g-eval/stm32_1m+128k_all_in_xram_processes.ld @@ -0,0 +1,145 @@ +/* + * C++ enabled linker script for stm32 (1M FLASH, 128K RAM) + 2MB xram + * Developed by TFT: Terraneo Federico Technologies + * Optimized for use with the Miosix kernel + */ + +/* + * This linker script puts: + * - all (code, .data, .bss, stacks, heap) in the external ram, using only + * half of it (1MB). + * - the rest of the RAM (upper 1MB) is used as the process pool for allocating + * processes. + * It is most useful for debugging, since powercycling the board will erase code + */ + +/* + * The main stack is used for interrupt handling by the kernel. + * In this linker script the main stack is placed at the top of the ram since: + * - having 2MB of ram makes the "stack at bottom of ram" optimization useless + * - the interrupt vectors are forwarded at the bottom of the ram + */ +_main_stack_size = 0x00000200; /* main stack size = 512Bytes */ +ASSERT(_main_stack_size % 8 == 0, "MAIN stack size error"); + +/* end of the stack */ +_main_stack_top = 0x64100000; /* placed at the top of ram */ +_heap_end = _main_stack_top - _main_stack_size; +_process_pool_start = _main_stack_top; +_process_pool_end = 0x64200000; + +/* identify the Entry Point */ +ENTRY(_Z13Reset_Handlerv) + +/* specify the memory areas */ +MEMORY +{ + ram(wx) : ORIGIN = 0x64000000, LENGTH = 1M +} + +/* now define the output sections */ +SECTIONS +{ + . = 0; + + /* .text section: code goes to flash */ + .text : + { + /* Startup code must go at address 0 */ + KEEP(*(.isr_vector)) + + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + /* these sections for thumb interwork? */ + *(.glue_7) + *(.glue_7t) + /* these sections for C++? */ + *(.gcc_except_table) + *(.gcc_except_table.*) + *(.ARM.extab*) + *(.gnu.linkonce.armextab.*) + + . = ALIGN(4); + /* .rodata: constant data */ + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + + /* C++ Static constructors/destructors (eabi) */ + . = ALIGN(4); + KEEP(*(.init)) + + . = ALIGN(4); + __preinit_array_start = .; + KEEP (*(.preinit_array)) + __preinit_array_end = .; + + . = ALIGN(4); + __init_array_start = .; + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + __init_array_end = .; + + . = ALIGN(4); + KEEP(*(.fini)) + + . = ALIGN(4); + __fini_array_start = .; + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + __fini_array_end = .; + + /* C++ Static constructors/destructors (elf) */ + . = ALIGN(4); + _ctor_start = .; + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*crtend.o(.ctors)) + _ctor_end = .; + + . = ALIGN(4); + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*crtend.o(.dtors)) + } > ram + + /* .ARM.exidx is sorted, so has to go in its own output section. */ + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > ram + __exidx_end = .; + + . = ALIGN(8); + _etext = .; + + /* .data section: global variables go to ram, but also store a copy to + flash to initialize them */ + .data : ALIGN(8) + { + _data = .; + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + . = ALIGN(8); + _edata = .; + } > ram + + /* .bss section: uninitialized global variables go to ram */ + _bss_start = .; + .bss : + { + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + . = ALIGN(8); + } > ram + _bss_end = .; + + _end = .; + PROVIDE(end = .); +} diff --git a/miosix/arch/cortexM4_stm32f4/common/CMSIS/core_cm4.h b/miosix/arch/cortexM4_stm32f4/common/CMSIS/core_cm4.h index c7718bfa331cf081bab8eef8b42f13cb0d45edd1..98ec72ba5fd7edb8308cf4bdaad1395b5650c777 100644 --- a/miosix/arch/cortexM4_stm32f4/common/CMSIS/core_cm4.h +++ b/miosix/arch/cortexM4_stm32f4/common/CMSIS/core_cm4.h @@ -750,6 +750,26 @@ typedef struct #define MPU_RASR_ATTRS_Pos 16 /*!< MPU RASR: MPU Region Attribute field Position */ #define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ +//By TFT: copy-pasted those from core_cm3.h for compatibility -- begin +#define MPU_RASR_XN_Pos 28 /*!< MPU RASR: XN Position */ +#define MPU_RASR_XN_Msk (1ul << MPU_RASR_XN_Pos) /*!< MPU RASR: XN Mask */ + +#define MPU_RASR_AP_Pos 24 /*!< MPU RASR: AP Position */ +#define MPU_RASR_AP_Msk (7ul << MPU_RASR_AP_Pos) /*!< MPU RASR: AP Mask */ + +#define MPU_RASR_TEX_Pos 19 /*!< MPU RASR: TEX Position */ +#define MPU_RASR_TEX_Msk (7ul << MPU_RASR_TEX_Pos) /*!< MPU RASR: TEX Mask */ + +#define MPU_RASR_S_Pos 18 /*!< MPU RASR: Shareable bit Position */ +#define MPU_RASR_S_Msk (1ul << MPU_RASR_S_Pos) /*!< MPU RASR: Shareable bit Mask */ + +#define MPU_RASR_C_Pos 17 /*!< MPU RASR: Cacheable bit Position */ +#define MPU_RASR_C_Msk (1ul << MPU_RASR_C_Pos) /*!< MPU RASR: Cacheable bit Mask */ + +#define MPU_RASR_B_Pos 16 /*!< MPU RASR: Bufferable bit Position */ +#define MPU_RASR_B_Msk (1ul << MPU_RASR_B_Pos) /*!< MPU RASR: Bufferable bit Mask */ +//By TFT: copy-pasted those from core_cm3.h for compatibility -- end + #define MPU_RASR_SRD_Pos 8 /*!< MPU RASR: Sub-Region Disable Position */ #define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ diff --git a/miosix/arch/cortexM4_stm32f4/common/core/interrupts.cpp b/miosix/arch/cortexM4_stm32f4/common/core/interrupts.cpp index 411cbda4887cd546744aede791391c37e5e28403..40eb7a1b5192f4b8085c2e3d358c3d17abc32311 100644 --- a/miosix/arch/cortexM4_stm32f4/common/core/interrupts.cpp +++ b/miosix/arch/cortexM4_stm32f4/common/core/interrupts.cpp @@ -26,6 +26,7 @@ ***************************************************************************/ #include "kernel/logging.h" +#include "kernel/kernel.h" #include "config/miosix_settings.h" #include "interfaces/portability.h" #include "interfaces/arch_registers.h" @@ -54,34 +55,46 @@ static void printUnsignedInt(unsigned int x) IRQerrorLog(result); } +#endif //WITH_ERRLOG + /** * \internal - * Print the program counter of the thread that was running when the exception + * \return the program counter of the thread that was running when the exception * occurred. */ -static void printProgramCounter() +static unsigned int getProgramCounter() { - register unsigned int pc; + register unsigned int result; // Get program counter when the exception was thrown from stack frame asm volatile("mrs %0, psp \n\t" "add %0, %0, #24 \n\t" - "ldr %0, [%0] \n\t":"=r"(pc)); - printUnsignedInt(pc); + "ldr %0, [%0] \n\t":"=r"(result)); + return result; } -#endif //WITH_ERRLOG - void NMI_Handler() { IRQerrorLog("\r\n***Unexpected NMI\r\n"); miosix_private::IRQsystemReboot(); } -void HardFault_Handler() +void __attribute__((naked)) HardFault_Handler() { + saveContext(); + //Call HardFault_impl(). Name is a C++ mangled name. + asm volatile("bl _Z14HardFault_implv"); + restoreContext(); +} + +void __attribute__((noinline)) HardFault_impl() +{ + #ifdef WITH_PROCESSES + if(miosix::Thread::IRQreportFault(miosix_private::FaultData( + HARDFAULT,getProgramCounter()))) return; + #endif //WITH_PROCESSES #ifdef WITH_ERRLOG IRQerrorLog("\r\n***Unexpected HardFault @ "); - printProgramCounter(); + printUnsignedInt(getProgramCounter()); unsigned int hfsr=SCB->HFSR; if(hfsr & SCB_HFSR_FORCED_Msk) IRQerrorLog("Fault escalation occurred\r\n"); @@ -91,12 +104,32 @@ void HardFault_Handler() miosix_private::IRQsystemReboot(); } -void MemManage_Handler() +void __attribute__((naked)) MemManage_Handler() { + saveContext(); + //Call MemManage_impl(). Name is a C++ mangled name. + asm volatile("bl _Z14MemManage_implv"); + restoreContext(); +} + +void __attribute__((noinline)) MemManage_impl() +{ + unsigned int cfsr=SCB->CFSR; + #ifdef WITH_PROCESSES + int id, arg=0; + if(cfsr & 0x00000001) id=MP_XN; + else if(cfsr & 0x00000080) { id=MP; arg=SCB->MMFAR; } + else id=MP_NOADDR; + if(miosix::Thread::IRQreportFault(miosix_private::FaultData( + id,getProgramCounter(),arg))) + { + SCB->SHCSR &= ~(1<<13); //Clear MEMFAULTPENDED bit + return; + } + #endif //WITH_PROCESSES #ifdef WITH_ERRLOG IRQerrorLog("\r\n***Unexpected MemManage @ "); - printProgramCounter(); - unsigned int cfsr=SCB->CFSR; + printUnsignedInt(getProgramCounter()); if(cfsr & 0x00000080) { IRQerrorLog("Fault caused by attempted access to "); @@ -118,7 +151,7 @@ void BusFault_Handler() { #ifdef WITH_ERRLOG IRQerrorLog("\r\n***Unexpected BusFault @ "); - printProgramCounter(); + printUnsignedInt(getProgramCounter()); unsigned int cfsr=SCB->CFSR; if(cfsr & 0x00008000) { @@ -139,12 +172,36 @@ void BusFault_Handler() miosix_private::IRQsystemReboot(); } -void UsageFault_Handler() +void __attribute__((naked)) UsageFault_Handler() +{ + saveContext(); + //Call UsageFault_impl(). Name is a C++ mangled name. + asm volatile("bl _Z15UsageFault_implv"); + restoreContext(); +} + +void __attribute__((noinline)) UsageFault_impl() { + unsigned int cfsr=SCB->CFSR; + #ifdef WITH_PROCESSES + int id; + if(cfsr & 0x02000000) id=UF_DIVZERO; + else if(cfsr & 0x01000000) id=UF_UNALIGNED; + else if(cfsr & 0x00080000) id=UF_COPROC; + else if(cfsr & 0x00040000) id=UF_EXCRET; + else if(cfsr & 0x00020000) id=UF_EPSR; + else if(cfsr & 0x00010000) id=UF_UNDEF; + else id=UF_UNEXP; + if(miosix::Thread::IRQreportFault(miosix_private::FaultData( + id,getProgramCounter()))) + { + SCB->SHCSR &= ~(1<<12); //Clear USGFAULTPENDED bit + return; + } + #endif //WITH_PROCESSES #ifdef WITH_ERRLOG IRQerrorLog("\r\n***Unexpected UsageFault @ "); - printProgramCounter(); - unsigned int cfsr=SCB->CFSR; + printUnsignedInt(getProgramCounter()); if(cfsr & 0x02000000) IRQerrorLog("Divide by zero\r\n"); if(cfsr & 0x01000000) IRQerrorLog("Unaligned memory access\r\n"); if(cfsr & 0x00080000) IRQerrorLog("Attempted coprocessor access\r\n"); @@ -159,7 +216,7 @@ void DebugMon_Handler() { #ifdef WITH_ERRLOG IRQerrorLog("\r\n***Unexpected DebugMon @ "); - printProgramCounter(); + printUnsignedInt(getProgramCounter()); #endif //WITH_ERRLOG miosix_private::IRQsystemReboot(); } @@ -168,7 +225,7 @@ void PendSV_Handler() { #ifdef WITH_ERRLOG IRQerrorLog("\r\n***Unexpected PendSV @ "); - printProgramCounter(); + printUnsignedInt(getProgramCounter()); #endif //WITH_ERRLOG miosix_private::IRQsystemReboot(); } diff --git a/miosix/arch/cortexM4_stm32f4/common/core/interrupts.h b/miosix/arch/cortexM4_stm32f4/common/core/interrupts.h index 6b74a54ff907127a2719b87ddcae0e6b5a782fb7..cdb648f554046e8a59c519aa79826e1bf6f03620 100644 --- a/miosix/arch/cortexM4_stm32f4/common/core/interrupts.h +++ b/miosix/arch/cortexM4_stm32f4/common/core/interrupts.h @@ -34,4 +34,23 @@ */ void unexpectedInterrupt(); +/** + * Possible kind of faults that the Cortex-M3 can report. + * They are used to print debug information if a process causes a fault + */ +enum FaultType +{ + MP=1, //Process attempted data access outside its memory + MP_NOADDR=2, //Process attempted data access outside its memory (missing addr) + MP_XN=3, //Process attempted code access outside its memory + UF_DIVZERO=4, //Process attempted to divide by zero + UF_UNALIGNED=5,//Process attempted unaligned memory access + UF_COPROC=6, //Process attempted a coprocessor access + UF_EXCRET=7, //Process attempted an exception return + UF_EPSR=8, //Process attempted to access the EPSR + UF_UNDEF=9, //Process attempted to execute an invalid instruction + UF_UNEXP=10, //Unexpected usage fault + HARDFAULT=11 //Hardfault (for example process executed a BKPT instruction) +}; + #endif //INTERRUPTS_H diff --git a/miosix/arch/cortexM4_stm32f4/common/interfaces-impl/portability.cpp b/miosix/arch/cortexM4_stm32f4/common/interfaces-impl/portability.cpp index 9700002290dfd1129ca3bc0be80baa28527084e2..8e85fe65fdfa7306de0e0e64e33bb9d78fe65b09 100644 --- a/miosix/arch/cortexM4_stm32f4/common/interfaces-impl/portability.cpp +++ b/miosix/arch/cortexM4_stm32f4/common/interfaces-impl/portability.cpp @@ -32,7 +32,11 @@ #include "interfaces/bsp.h" #include "kernel/scheduler/scheduler.h" #include "kernel/scheduler/tick_interrupt.h" +#include "core/interrupts.h" #include <algorithm> +#include <cstdio> +#include <cstring> +#include <cassert> /** * \internal @@ -111,8 +115,48 @@ void ISR_preempt() void ISR_yield() __attribute__((noinline)); void ISR_yield() { + #ifdef WITH_PROCESSES + // WARNING: Temporary fix. Rationale: + // This fix is intended to avoid kernel or process faulting due to + // another process actions. Consider the case in which a process statically + // allocates a big array such that there is no space left for saving + // context data. If the process issues a system call, in the following + // interrupt the context is saved, but since there is no memory available + // for all the context data, a mem manage interrupt is set to 'pending'. Then, + // a fake syscall is issued, based on the value read on the stack (which + // the process hasn't set due to the memory fault and is likely to be 0); + // this syscall is usually a yield (due to the value of 0 above), + // which can cause the scheduling of the kernel thread. At this point, + // the pending mem fault is issued from the kernel thread, causing the + //kernel fault and reboot. This is caused by the mem fault interrupt + // having less priority of the other interrupts. + // This fix checks if there is a mem fault interrupt pending, and, if so, + // it clears it and returns before calling the previously mentioned fake + // syscall. + if(SCB->SHCSR & (1<<13)) + { + if(miosix::Thread::IRQreportFault(miosix_private::FaultData( + MP,0,0))) + { + SCB->SHCSR &= ~(1<<13); //Clear MEMFAULTPENDED bit + return; + } + } + #endif // WITH_PROCESSES IRQstackOverflowCheck(); + + #ifdef WITH_PROCESSES + //If processes are enabled, check the content of r3. If zero then it + //it is a simple yield, otherwise handle the syscall + //Note that it is required to use ctxsave and not cur->ctxsave because + //at this time we do not know if the active context is user or kernel + unsigned int threadSp=ctxsave[0]; + unsigned int *processStack=reinterpret_cast<unsigned int*>(threadSp); + if(processStack[3]!=0) miosix::Thread::IRQhandleSvc(processStack[3]); + else miosix::Scheduler::IRQfindNextThread(); + #else //WITH_PROCESSES miosix::Scheduler::IRQfindNextThread(); + #endif //WITH_PROCESSES } #ifdef SCHED_TYPE_CONTROL_BASED @@ -170,6 +214,150 @@ void initCtxsave(unsigned int *ctxsave, void *(*pc)(void *), unsigned int *sp, //leaving the content of s16-s31 uninitialized } +#ifdef WITH_PROCESSES + +// +// class FaultData +// + +void FaultData::print() const +{ + switch(id) + { + case MP: + iprintf("* Attempted data access @ 0x%x (PC was 0x%x)\n",arg,pc); + break; + case MP_NOADDR: + iprintf("* Invalid data access (PC was 0x%x)\n",pc); + break; + case MP_XN: + iprintf("* Attempted instruction fetch @ 0x%x\n",pc); + break; + case UF_DIVZERO: + iprintf("* Dvide by zero (PC was 0x%x)\n",pc); + break; + case UF_UNALIGNED: + iprintf("* Unaligned memory access (PC was 0x%x)\n",pc); + break; + case UF_COPROC: + iprintf("* Attempted coprocessor access (PC was 0x%x)\n",pc); + break; + case UF_EXCRET: + iprintf("* Invalid exception return sequence (PC was 0x%x)\n",pc); + break; + case UF_EPSR: + iprintf("* Attempted access to the EPSR (PC was 0x%x)\n",pc); + break; + case UF_UNDEF: + iprintf("* Undefined instruction (PC was 0x%x)\n",pc); + break; + case UF_UNEXP: + iprintf("* Unexpected usage fault (PC was 0x%x)\n",pc); + break; + case HARDFAULT: + iprintf("* Hardfault (PC was 0x%x)\n",pc); + break; + } +} + +void initCtxsave(unsigned int *ctxsave, void *(*pc)(void *), unsigned int *sp, + void *argv, unsigned int *gotBase) +{ + unsigned int *stackPtr=sp; + stackPtr--; //Stack is full descending, so decrement first + *stackPtr=0x01000000; stackPtr--; //--> xPSR + *stackPtr=reinterpret_cast<unsigned long>(pc); stackPtr--; //--> pc + *stackPtr=0xffffffff; stackPtr--; //--> lr + *stackPtr=0; stackPtr--; //--> r12 + *stackPtr=0; stackPtr--; //--> r3 + *stackPtr=0; stackPtr--; //--> r2 + *stackPtr=0; stackPtr--; //--> r1 + *stackPtr=reinterpret_cast<unsigned long >(argv); //--> r0 + + ctxsave[0]=reinterpret_cast<unsigned long>(stackPtr); //--> psp + ctxsave[6]=reinterpret_cast<unsigned long>(gotBase); //--> r9 + //leaving the content of r4-r8,r10-r11 uninitialized +} + +static unsigned int sizeToMpu(unsigned int size) +{ + assert(size>=32); + unsigned int result=30-__builtin_clz(size); + if(size & (size-1)) result++; + return result<<1; +} + +// +// class MPUConfiguration +// + +MPUConfiguration::MPUConfiguration(unsigned int *elfBase, unsigned int elfSize, + unsigned int *imageBase, unsigned int imageSize) +{ + regValues[0]=(reinterpret_cast<unsigned int>(elfBase) & (~0x1f)) + | MPU_RBAR_VALID_Msk | 0; //Region 0 + regValues[2]=(reinterpret_cast<unsigned int>(imageBase) & (~0x1f)) + | MPU_RBAR_VALID_Msk | 1; //Region 1 + #ifndef __CODE_IN_XRAM + regValues[1]=2<<MPU_RASR_AP_Pos + | MPU_RASR_C_Msk + | 1 //Enable bit + | sizeToMpu(elfSize); + regValues[3]=3<<MPU_RASR_AP_Pos + | MPU_RASR_XN_Msk + | MPU_RASR_C_Msk + | MPU_RASR_S_Msk + | 1 //Enable bit + | sizeToMpu(imageSize); + #else //__CODE_IN_XRAM + regValues[1]=2<<MPU_RASR_AP_Pos + | MPU_RASR_C_Msk + | MPU_RASR_B_Msk + | MPU_RASR_S_Msk + | 1 //Enable bit + | sizeToMpu(elfSize); + regValues[3]=3<<MPU_RASR_AP_Pos + | MPU_RASR_XN_Msk + | MPU_RASR_C_Msk + | MPU_RASR_B_Msk + | MPU_RASR_S_Msk + | 1 //Enable bit + | sizeToMpu(imageSize); + #endif //__CODE_IN_XRAM +} + +void MPUConfiguration::dumpConfiguration() +{ + for(int i=0;i<2;i++) + { + unsigned int base=regValues[2*i] & (~0x1f); + unsigned int end=base+(1<<(((regValues[2*i+1]>>1) & 31)+1)); + char w=regValues[2*i+1] & (1<<MPU_RASR_AP_Pos) ? 'w' : '-'; + char x=regValues[2*i+1] & MPU_RASR_XN_Msk ? '-' : 'x'; + iprintf("* MPU region %d 0x%x-0x%x r%c%c\n",i,base,end,w,x); + } +} + +bool MPUConfiguration::within(const unsigned int ptr) const +{ + unsigned int base = regValues[2] & (~0x1f); + unsigned int end = base + (1 << (((regValues[3] >> 1) & 31) + 1)); + + return ptr >= base && ptr < end; +} + +unsigned int MPUConfiguration::getBaseDataAddress() const +{ + return regValues[2] & (~0x1f); +} + +unsigned int MPUConfiguration::getDataSize() const +{ + return (1 << (((regValues[3] >> 1) & 31) + 1)); +} + +#endif //WITH_PROCESSES + void IRQportableStartKernel() { //Enable fault handlers @@ -182,11 +370,16 @@ void IRQportableStartKernel() NVIC_SetPriorityGrouping(7);//This should disable interrupt nesting NVIC_SetPriority(SVCall_IRQn,3);//High priority for SVC (Max=0, min=15) NVIC_SetPriority(SysTick_IRQn,3);//High priority for SysTick (Max=0, min=15) + NVIC_SetPriority(MemoryManagement_IRQn,2);//Higher priority for MemoryManagement (Max=0, min=15) SysTick->LOAD=SystemCoreClock/miosix::TICK_FREQ; //Start SysTick, set to generate interrupts SysTick->CTRL=SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_CLKSOURCE_Msk; + #ifdef WITH_PROCESSES + //Enable MPU + MPU->CTRL=MPU_CTRL_PRIVDEFENA_Msk | MPU_CTRL_ENABLE_Msk; + #endif //WITH_PROCESSES #ifdef SCHED_TYPE_CONTROL_BASED AuxiliaryTimer::IRQinit(); #endif //SCHED_TYPE_CONTROL_BASED diff --git a/miosix/arch/cortexM4_stm32f4/common/interfaces-impl/portability_impl.h b/miosix/arch/cortexM4_stm32f4/common/interfaces-impl/portability_impl.h index e37f87b00c503f1c5d243049a922fd4ed15889c6..e80a2a4d9fe6de4ff2dd0f9929c9959cafcf7f7b 100644 --- a/miosix/arch/cortexM4_stm32f4/common/interfaces-impl/portability_impl.h +++ b/miosix/arch/cortexM4_stm32f4/common/interfaces-impl/portability_impl.h @@ -30,6 +30,7 @@ #define PORTABILITY_IMPL_H #include "interfaces/arch_registers.h" +#include "interfaces/portability.h" #include "config/miosix_settings.h" /** @@ -112,7 +113,9 @@ namespace miosix_private { inline void doYield() { - asm volatile("svc 0"); + asm volatile("movs r3, #0\n\t" + "svc 0" + :::"r3"); } inline void doDisableInterrupts() @@ -142,6 +145,68 @@ inline bool checkAreInterruptsEnabled() return true; } +#ifdef WITH_PROCESSES + +// +// class SyscallParameters +// + +inline SyscallParameters::SyscallParameters(unsigned int *context) : + registers(reinterpret_cast<unsigned int*>(context[0])) {} + +inline int SyscallParameters::getSyscallId() const +{ + return registers[3]; +} + +inline unsigned int SyscallParameters::getFirstParameter() const +{ + return registers[0]; +} + +inline unsigned int SyscallParameters::getSecondParameter() const +{ + return registers[1]; +} + +inline unsigned int SyscallParameters::getThirdParameter() const +{ + return registers[2]; +} + +inline void SyscallParameters::setReturnValue(unsigned int ret) +{ + registers[0]=ret; +} + +inline void portableSwitchToUserspace() +{ + asm volatile("movs r3, #1\n\t" + "svc 0" + :::"r3"); +} + +// +// class MPU +// + +inline void MPUConfiguration::IRQenable() +{ + MPU->RBAR=regValues[0]; + MPU->RASR=regValues[1]; + MPU->RBAR=regValues[2]; + MPU->RASR=regValues[3]; + __set_CONTROL(3); +} + +inline void MPUConfiguration::IRQdisable() +{ + __set_CONTROL(2); +} + + +#endif //WITH_PROCESSES + /** * \} */ diff --git a/miosix/arch/cortexM4_stm32f4/stm32f407vg_stm32f4discovery/stm32_1m+192k_rom_processes.ld b/miosix/arch/cortexM4_stm32f4/stm32f407vg_stm32f4discovery/stm32_1m+192k_rom_processes.ld new file mode 100644 index 0000000000000000000000000000000000000000..df941de32e53989da0020dcfbeb36df5909ccf78 --- /dev/null +++ b/miosix/arch/cortexM4_stm32f4/stm32f407vg_stm32f4discovery/stm32_1m+192k_rom_processes.ld @@ -0,0 +1,179 @@ +/* + * C++ enabled linker script for stm32 (1M FLASH, 192K RAM) + * Developed by TFT: Terraneo Federico Technologies + * Optimized for use with the Miosix kernel + */ + +/* + * This chip has an unusual quirk that the RAM is divided in two block mapped + * at two non contiguous memory addresses. I don't know why they've done that, + * probably doing the obvious thing would have made writing code too easy... + * Anyway, since hardware can't be changed, we've got to live with that and + * try to make use of both RAMs. + * + * Given the constraints above, this linker script puts: + * - read only data and code (.text, .rodata, .eh_*) in FLASH + * - the 512Byte main (IRQ) stack, .data and .bss in the "small" 64KB RAM + * - stacks and heap in the "large" 128KB RAM. + * + * Unfortunately thread stacks can't be put in the small RAM as Miosix + * allocates them inside the heap. + */ + +/* + * The main stack is used for interrupt handling by the kernel. + * + * *** Readme *** + * This linker script places the main stack (used by the kernel for interrupts) + * at the bottom of the ram, instead of the top. This is done for two reasons: + * + * - as an optimization for microcontrollers with little ram memory. In fact + * the implementation of malloc from newlib requests memory to the OS in 4KB + * block (except the first block that can be smaller). This is probably done + * for compatibility with OSes with an MMU and paged memory. To see why this + * is bad, consider a microcontroller with 8KB of ram: when malloc finishes + * up the first 4KB it will call _sbrk_r asking for a 4KB block, but this will + * fail because the top part of the ram is used by the main stack. As a + * result, the top part of the memory will not be used by malloc, even if + * available (and it is nearly *half* the ram on an 8KB mcu). By placing the + * main stack at the bottom of the ram, the upper 4KB block will be entirely + * free and available as heap space. + * + * - In case of main stack overflow the cpu will fault because access to memory + * before the beginning of the ram faults. Instead with the default stack + * placement the main stack will silently collide with the heap. + * Note: if increasing the main stack size also increase the ORIGIN value in + * the MEMORY definitions below accordingly. + */ +_main_stack_size = 0x00000200; /* main stack = 512Bytes */ +_main_stack_top = 0x10000000 + _main_stack_size; +ASSERT(_main_stack_size % 8 == 0, "MAIN stack size error"); + +/* Mapping the heap into the bottom 32KB of the large 128KB RAM */ +_end = 0x20000000; +_heap_end = 0x20008000; +/* Mapping the process pool into the upper 96KB of the large 128KB RAM */ +_process_pool_start = _heap_end; +_process_pool_end = 0x20020000; /* end of available ram */ + +/* identify the Entry Point */ +ENTRY(_Z13Reset_Handlerv) + +/* specify the memory areas */ +MEMORY +{ + flash(rx) : ORIGIN = 0x08000000, LENGTH = 1M + /* + * Note, the small ram starts at 0x10000000 but it is necessary to add the + * size of the main stack, so it is 0x10000200. + */ + smallram(wx) : ORIGIN = 0x10000200, LENGTH = 64K-0x200 + largeram(wx) : ORIGIN = 0x20000000, LENGTH = 128K +} + +/* now define the output sections */ +SECTIONS +{ + . = 0; + + /* .text section: code goes to flash */ + .text : + { + /* Startup code must go at address 0 */ + KEEP(*(.isr_vector)) + + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + /* these sections for thumb interwork? */ + *(.glue_7) + *(.glue_7t) + /* these sections for C++? */ + *(.gcc_except_table) + *(.gcc_except_table.*) + *(.ARM.extab*) + *(.gnu.linkonce.armextab.*) + + . = ALIGN(4); + /* .rodata: constant data */ + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + + /* C++ Static constructors/destructors (eabi) */ + . = ALIGN(4); + KEEP(*(.init)) + + . = ALIGN(4); + __preinit_array_start = .; + KEEP (*(.preinit_array)) + __preinit_array_end = .; + + . = ALIGN(4); + __init_array_start = .; + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + __init_array_end = .; + + . = ALIGN(4); + KEEP(*(.fini)) + + . = ALIGN(4); + __fini_array_start = .; + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + __fini_array_end = .; + + /* C++ Static constructors/destructors (elf) */ + . = ALIGN(4); + _ctor_start = .; + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*crtend.o(.ctors)) + _ctor_end = .; + + . = ALIGN(4); + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*crtend.o(.dtors)) + } > flash + + /* .ARM.exidx is sorted, so has to go in its own output section. */ + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > flash + __exidx_end = .; + + . = ALIGN(8); + _etext = .; + + /* .data section: global variables go to ram, but also store a copy to + flash to initialize them */ + .data : ALIGN(8) + { + _data = .; + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + . = ALIGN(8); + _edata = .; + } > smallram AT > flash + + /* .bss section: uninitialized global variables go to ram */ + _bss_start = .; + .bss : + { + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + . = ALIGN(8); + } > smallram + _bss_end = .; + + /*_end = .;*/ + /*PROVIDE(end = .);*/ +} diff --git a/miosix/compiler/mx-postlinker/ELF.h b/miosix/compiler/mx-postlinker/ELF.h new file mode 100644 index 0000000000000000000000000000000000000000..8ec65f2013820c9ca6f3197b7997cf96fb0e6373 --- /dev/null +++ b/miosix/compiler/mx-postlinker/ELF.h @@ -0,0 +1,194 @@ +/*************************************************************************** + * Copyright (C) 2012 by Luigi Rucco and Terraneo Federico * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, see <http://www.gnu.org/licenses/> * + ***************************************************************************/ + +#ifndef ELF_TYPES_H +#define ELF_TYPES_H + +#include <inttypes.h> + +// elf-specific types +typedef uint32_t Elf32_Word; +typedef int32_t Elf32_Sword; +typedef uint16_t Elf32_Half; +typedef uint32_t Elf32_Off; +typedef uint32_t Elf32_Addr; + +// Size of e_ident in the elf header +const int EI_NIDENT=16; + +/* + * Elf header + */ +struct Elf32_Ehdr +{ + unsigned char e_ident[EI_NIDENT]; // Ident bytes + Elf32_Half e_type; // File type, any of the ET_* constants + Elf32_Half e_machine; // Target machine + Elf32_Word e_version; // File version + Elf32_Addr e_entry; // Start address + Elf32_Off e_phoff; // Phdr file offset + Elf32_Off e_shoff; // Shdr file offset + Elf32_Word e_flags; // File flags + Elf32_Half e_ehsize; // Sizeof ehdr + Elf32_Half e_phentsize; // Sizeof phdr + Elf32_Half e_phnum; // Number phdrs + Elf32_Half e_shentsize; // Sizeof shdr + Elf32_Half e_shnum; // Number shdrs + Elf32_Half e_shstrndx; // Shdr string index +} __attribute__((packed)); + +// Values for e_type +const Elf32_Half ET_NONE = 0; // Unknown type +const Elf32_Half ET_REL = 1; // Relocatable +const Elf32_Half ET_EXEC = 2; // Executable +const Elf32_Half ET_DYN = 3; // Shared object +const Elf32_Half ET_CORE = 4; // Core file + +// Values for e_version +const Elf32_Word EV_CURRENT = 1; + +// Values for e_machine +const Elf32_Half EM_ARM = 0x28; + +// Values for e_flags +const Elf32_Word EF_ARM_EABI_MASK = 0x05000000; +const Elf32_Word EF_HAS_ENTRY_POINT = 2; + +/* + * Elf program header + */ +struct Elf32_Phdr +{ + Elf32_Word p_type; // Program header type, any of the PH_* constants + Elf32_Off p_offset; // Segment start offset in file + Elf32_Addr p_vaddr; // Segment virtual address + Elf32_Addr p_paddr; // Segment physical address + Elf32_Word p_filesz; // Segment size in file + Elf32_Word p_memsz; // Segment size in memory + Elf32_Word p_flags; // Segment flasgs, any of the PF_* constants + Elf32_Word p_align; // Segment alignment requirements +} __attribute__((packed)); + +// Values for p_type +const Elf32_Word PT_NULL = 0; // Unused array entry +const Elf32_Word PT_LOAD = 1; // Loadable segment +const Elf32_Word PT_DYNAMIC = 2; // Segment is the dynamic section +const Elf32_Word PT_INTERP = 3; // Shared library interpreter +const Elf32_Word PT_NOTE = 4; // Auxiliary information + +// Values for p_flags +const Elf32_Word PF_X = 0x1; // Execute +const Elf32_Word PF_W = 0x2; // Write +const Elf32_Word PF_R = 0x4; // Read + +/* + * Entries of the DYNAMIC segment + */ +struct Elf32_Dyn +{ + Elf32_Sword d_tag; // Type of entry + union { + Elf32_Word d_val; // Value of entry, if number + Elf32_Addr d_ptr; // Value of entry, if offset into the file + } d_un; +} __attribute__((packed)); + +// Values for d_tag +const int DT_NULL = 0; +const int DT_NEEDED = 1; +const int DT_PLTRELSZ = 2; +const int DT_PLTGOT = 3; +const int DT_HASH = 4; +const int DT_STRTAB = 5; +const int DT_SYMTAB = 6; +const int DT_RELA = 7; +const int DT_RELASZ = 8; +const int DT_RELAENT = 9; +const int DT_STRSZ = 10; +const int DT_SYMENT = 11; +const int DT_INIT = 12; +const int DT_FINI = 13; +const int DT_SONAME = 14; +const int DT_RPATH = 15; +const int DT_SYMBOLIC = 16; +const int DT_REL = 17; +const int DT_RELSZ = 18; +const int DT_RELENT = 19; +const int DT_PLTREL = 20; +const int DT_DEBUG = 21; +const int DT_TEXTREL = 22; +const int DT_JMPREL = 23; +const int DT_BINDNOW = 24; +const int DT_MX_RAMSIZE = 0x10000000; //Miosix specific, RAM size +const int DT_MX_STACKSIZE = 0x10000001; //Miosix specific, STACK size +const int DT_MX_ABI = 0x736f694d; //Miosix specific, ABI version +const unsigned int DV_MX_ABI_V0 = 0x00007869; //Miosix specific, ABI version 0 + +/* + * Relocation entries + */ +struct Elf32_Rel +{ + Elf32_Addr r_offset; + Elf32_Word r_info; +} __attribute__((packed)); + +// To extract the two fields of r_info +#define ELF32_R_SYM(i) ((i)>>8) +#define ELF32_R_TYPE(i) ((unsigned char)(i)) + +// Possible values for ELF32_R_TYPE(r_info) +const unsigned char R_ARM_NONE = 0; +const unsigned char R_ARM_ABS32 = 2; +const unsigned char R_ARM_RELATIVE = 23; + +/* + * Elf Section header + */ +struct Elf32_Shdr +{ + Elf32_Word sh_name; + Elf32_Word sh_type; + Elf32_Word sh_flags; + Elf32_Addr sh_addr; + Elf32_Off sh_offset; + Elf32_Word sh_size; + Elf32_Word sh_link; + Elf32_Word sh_info; + Elf32_Word sh_addralign; + Elf32_Word sh_entsize; +}; + +// sh_type +const int SHT_NULL = 0; /* inactive */ +const int SHT_PROGBITS = 1; /* program defined information */ +const int SHT_SYMTAB = 2; /* symbol table section */ +const int SHT_STRTAB = 3; /* string table section */ +const int SHT_RELA = 4; /* relocation section with addends*/ +const int SHT_HASH = 5; /* symbol hash table section */ +const int SHT_DYNAMIC = 6; /* dynamic section */ +const int SHT_NOTE = 7; /* note section */ +const int SHT_NOBITS = 8; /* no space section */ +const int SHT_REL = 9; /* relation section without addends */ +const int SHT_SHLIB = 10; /* reserved - purpose unknown */ +const int SHT_DYNSYM = 11; /* dynamic symbol table section */ +const int SHT_LOPROC = 0x70000000; /* reserved range for processor */ +const int SHT_HIPROC = 0x7fffffff; /* specific section header types */ +const int SHT_LOUSER = 0x80000000; /* reserved range for application */ +const int SHT_HIUSER = 0xffffffff; /* specific indexes */ + +#endif //ELF_TYPES_H diff --git a/miosix/compiler/mx-postlinker/Makefile b/miosix/compiler/mx-postlinker/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..0252140b02eece7e5ef805c0677c6abf15cfcb5c --- /dev/null +++ b/miosix/compiler/mx-postlinker/Makefile @@ -0,0 +1,21 @@ +CXX:= g++ +CXXFLAGS:= -O2 -c +OBJS:= postlinker.o main.o +DFLAGS:= -MMD -MP + +#create program target + +mx-postlinker: $(OBJS) + $(CXX) -o $@ $? + +install: mx-postlinker + cp mx-postlinker $(INSTALL_DIR) + +clean: + -rm mx-postlinker *.o *.d + +%.o: %.cpp + $(CXX) $(DFLAGS) $(CXXFLAGS) $? -o $@ + +#pull in dependecy info for existing .o files +-include $(OBJ:.o=.d) diff --git a/miosix/compiler/mx-postlinker/main.cpp b/miosix/compiler/mx-postlinker/main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cbec798f53cb07c0f00e24137070c3f15cf1a260 --- /dev/null +++ b/miosix/compiler/mx-postlinker/main.cpp @@ -0,0 +1,52 @@ +/*************************************************************************** + * Copyright (C) 2012 by Luigi Rucco and Terraneo Federico * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, see <http://www.gnu.org/licenses/> * + ***************************************************************************/ + +#include <iostream> +#include "postlinker.h" + +using namespace std; + +int main(int argc, char *argv[]) +{ + int stackSize=-1; + int ramSize=-1; + string prog; + bool strip=false; + for(int i=1;i<argc;i++) + { + string opt(argv[i]); + if(opt=="--strip-sectheader") + strip=true; + else if(opt.substr(0,10)=="--ramsize=") + ramSize=atoi(opt.substr(10).c_str()); + else if(opt.substr(0,12)=="--stacksize=") + stackSize=atoi(opt.substr(12).c_str()); + else + prog=opt; + } + if(stackSize<=0 || ramSize<=0 || prog=="") + { + cerr<<"usage:"<<endl<<"mx-postlinker prog.elf --ramsize=<size>" + <<" --stacksize=<size> [--strip-sectheader]"<<endl; + return 1; + } + PostLinker pl(prog); + if(strip) pl.removeSectionHeaders(); + pl.setMxTags(stackSize,ramSize); + pl.writeFile(); + return 0; +} diff --git a/miosix/compiler/mx-postlinker/postlinker.cpp b/miosix/compiler/mx-postlinker/postlinker.cpp new file mode 100644 index 0000000000000000000000000000000000000000..83fa3b44a42aecc66aa48f431b6176a67c91cb5f --- /dev/null +++ b/miosix/compiler/mx-postlinker/postlinker.cpp @@ -0,0 +1,120 @@ +/*************************************************************************** + * Copyright (C) 2012 by Luigi Rucco and Terraneo Federico * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, see <http://www.gnu.org/licenses/> * + ***************************************************************************/ + +#include "postlinker.h" + +using namespace std; + +PostLinker::PostLinker(string s) +{ + elfFile=s; + ifstream f(s.c_str(),ios::binary); + if(!f.good()) throw runtime_error("File not found"); + f.seekg(0,ios::end); + size=f.tellg(); + newSize=size; + f.seekg(0,ios::beg); + int roundedSize=(size+sizeof(Elf32_Word)-1) & ~(sizeof(Elf32_Word)-1); + elf=new Elf32_Word[roundedSize/sizeof(Elf32_Word)]; + memset(elf,0,roundedSize); + f.read(reinterpret_cast<char*>(elf),size); + static const char magic[EI_NIDENT]={0x7f,'E','L','F',1,1,1}; + if(size<sizeof(Elf32_Ehdr) || memcmp(getElfHeader()->e_ident,magic,EI_NIDENT)) + throw runtime_error("Unrecognized format"); +} + +void PostLinker::removeSectionHeaders() +{ + newSize=getElfSection(getElfHeader()->e_shstrndx)->sh_offset; + getElfHeader()->e_shoff=0; + getElfHeader()->e_shnum=0; + getElfHeader()->e_shentsize=0; + getElfHeader()->e_shstrndx=0; +} + +void PostLinker::setMxTags(int stackSize, int ramSize) +{ + if(stackSize & 0x3) + throw runtime_error("stack size not four word aligned"); + if(ramSize & 0x3) + throw runtime_error("ram size not four word aligned"); + if(getSizeOfDataAndBss()+stackSize>ramSize) + throw runtime_error(".data + .bss + stack exceeds ramsize"); + getElfHeader()->e_type=ET_EXEC; //Force ET_EXEC + int ctr=0; + pair<Elf32_Dyn *,Elf32_Word> dyn=getDynamic(); + for(int i=0;i<dyn.second;i++,dyn.first++) + { + if(dyn.first->d_tag!=DT_NULL) continue; + switch(ctr) + { + case 0: + dyn.first->d_tag=DT_MX_RAMSIZE; + dyn.first->d_un.d_val=ramSize; + break; + case 1: + dyn.first->d_tag=DT_MX_STACKSIZE; + dyn.first->d_un.d_val=stackSize; + break; + case 2: + dyn.first->d_tag=DT_MX_ABI; + dyn.first->d_un.d_val=DV_MX_ABI_V0; + return; + } + ctr++; + } + throw runtime_error("Not enough null entries"); +} + +void PostLinker::writeFile() +{ + ofstream o(elfFile.c_str(),ios::binary); + o.write(reinterpret_cast<char*>(elf),newSize); +} + +pair<Elf32_Dyn *,Elf32_Word> PostLinker::getDynamic() +{ + for(int i=0;i<getElfHeader()->e_phnum;i++) + { + Elf32_Phdr* phdr=getElfSegment(i); + if(phdr->p_type!=PT_DYNAMIC) continue; + unsigned char *base=reinterpret_cast<unsigned char*>(elf); + unsigned int offset=phdr->p_offset; + if(offset+phdr->p_memsz>size) + throw std::runtime_error("Dynamic outside file bounds"); + return make_pair(reinterpret_cast<Elf32_Dyn*>(base+offset), + phdr->p_memsz/sizeof(Elf32_Dyn)); + } + throw runtime_error("Dynamic not found"); +} + +int PostLinker::getSizeOfDataAndBss() +{ + for(int i=0;i<getElfHeader()->e_phnum;i++) + { + Elf32_Phdr* phdr=getElfSegment(i); + if(phdr->p_type!=PT_LOAD) continue; + if(!(phdr->p_flags & PF_W) || (phdr->p_flags & PF_X)) continue; + return phdr->p_memsz; + } + throw runtime_error(".data/.bss not found"); +} + +PostLinker::~PostLinker() +{ + delete[] elf; +} diff --git a/miosix/compiler/mx-postlinker/postlinker.h b/miosix/compiler/mx-postlinker/postlinker.h new file mode 100644 index 0000000000000000000000000000000000000000..24b205706196f7bedab884c899cfd821e7f27b58 --- /dev/null +++ b/miosix/compiler/mx-postlinker/postlinker.h @@ -0,0 +1,127 @@ +/*************************************************************************** + * Copyright (C) 2012 by Luigi Rucco and Terraneo Federico * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, see <http://www.gnu.org/licenses/> * + ***************************************************************************/ + +#ifndef POSTLINKER_H +#define POSTLINKER_H + +#include "ELF.h" +#include <cstring> +#include <iostream> +#include <exception> +#include <stdexcept> +#include <utility> +#include <cstdlib> +#include <fstream> + +/** + * This class performs transformations on an elf file, + * including stripping the section header and associated + * string table, and setting some Miosix specific options + * in the dynamic segment + */ +class PostLinker +{ +public: + /** + * Constructor + * \param s elf file name + */ + PostLinker(std::string s); + + /** + * Remove the section header and string table from the elf file + */ + void removeSectionHeaders(); + + /** + * Set the Miosix specific options in the dynamic segment + * \param stackSize size that the runtime linker-loader will reserve for + * the stack of the process + * \param ramSize size of the process RAM image that the runtime + * linker-loader will allocate for the process + */ + void setMxTags(int stackSize, int ramSize); + + /** + * Write changes to disk + */ + void writeFile(); + + /** + * Destructor + */ + ~PostLinker(); + +private: + PostLinker(const PostLinker&); + PostLinker& operator= (const PostLinker&); + + /** + * \return the elf header + */ + Elf32_Ehdr* getElfHeader() + { + return reinterpret_cast<Elf32_Ehdr*>(elf); + } + + /** + * Allows to retrieve a section header given its index + * \param index a index from 0 to getElfHeader()->e_shnum + * \return the corresponding section header + */ + Elf32_Shdr* getElfSection(int index) + { + unsigned char *base=reinterpret_cast<unsigned char*>(elf); + unsigned int offset=getElfHeader()->e_shoff+index*sizeof(Elf32_Shdr); + if(offset+sizeof(Elf32_Shdr)>size) + throw std::runtime_error("Elf section outside file bounds"); + return reinterpret_cast<Elf32_Shdr*>(base+offset); + } + + /** + * Allows to retrieve a segment header given its index + * \param index a index from 0 to getElfHeader()->e_phnum + * \return the corresponding secgment header + */ + Elf32_Phdr *getElfSegment(int index) + { + unsigned char *base=reinterpret_cast<unsigned char*>(elf); + unsigned int offset=getElfHeader()->e_phoff+index*sizeof(Elf32_Phdr); + if(offset+sizeof(Elf32_Phdr)>size) + throw std::runtime_error("Elf segment outside file bounds"); + return reinterpret_cast<Elf32_Phdr*>(base+offset); + } + + /** + * \return the size of the segment that is loaded in RAM, with + * .data and .bss + */ + int getSizeOfDataAndBss(); + + /** + * \return a pair with a pointer to the first element in the dynamic + * segment and the number of entries in the dynamic segment + */ + std::pair<Elf32_Dyn *,Elf32_Word> getDynamic(); + + Elf32_Word* elf; + int size; + int newSize; + std::string elfFile; +}; + +#endif //POSTLINKER_H diff --git a/miosix/config/Makefile.inc b/miosix/config/Makefile.inc index 171181a41165252e7ab0549739b28fd3d1287190..7aaca4d797a1c0457fc5e6a8dfe84846429d3ec2 100644 --- a/miosix/config/Makefile.inc +++ b/miosix/config/Makefile.inc @@ -134,9 +134,12 @@ ifeq ($(OPT_BOARD),stm32f407vg_stm32f4discovery) ## Linker script type, there are two options ## 1) Code in FLASH, stack + heap in internal RAM (file *_rom.ld) ## 2) Code + stack + heap in internal RAM (file *_ram.ld) + ## 3) Same as 1) but space has been reserved for a process pool, allowing + ## to configure the kernel with "#define WITH_PROCESSES" LINKER_SCRIPT_PATH := arch/cortexM4_stm32f4/stm32f407vg_stm32f4discovery/ LINKER_SCRIPT := $(LINKER_SCRIPT_PATH)stm32_1m+192k_rom.ld #LINKER_SCRIPT := $(LINKER_SCRIPT_PATH)stm32_1m+192k_ram.ld + #LINKER_SCRIPT := $(LINKER_SCRIPT_PATH)stm32_1m+192k_rom_processes.ld ## This causes the interrupt vector table to be relocated in SRAM, must be ## uncommented when using the ram linker script @@ -165,12 +168,15 @@ ifeq ($(OPT_BOARD),stm32f207ig_stm3220g-eval) ## forwards interrrupts @ 0x64000000 (see miosix/_tools/bootloaders for ## one). ## The microcontroller must have an external memory interface. + ## 4) Same as 3) but space has been reserved for a process pool, allowing + ## to configure the kernel with "#define WITH_PROCESSES" ## Warning! enable external ram if you use a linker script that requires it ## (see the XRAM flag below) LINKER_SCRIPT_PATH := arch/cortexM3_stm32f2/stm32f207ig_stm3220g-eval/ #LINKER_SCRIPT := $(LINKER_SCRIPT_PATH)stm32_1m+128k_rom.ld #LINKER_SCRIPT := $(LINKER_SCRIPT_PATH)stm32_1m+128k_xram.ld LINKER_SCRIPT := $(LINKER_SCRIPT_PATH)stm32_1m+128k_all_in_xram.ld + #LINKER_SCRIPT := $(LINKER_SCRIPT_PATH)stm32_1m+128k_all_in_xram_processes.ld ## Enable/disable initialization of external RAM at boot. Three options: ## __ENABLE_XRAM : If you want the heap in xram (with an appropriate linker @@ -747,7 +753,7 @@ else ifeq ($(ARCH),cortexM3_stm32f2) PROGRAM_CMDLINE := miosix/_tools/bootloaders/stm32/pc_loader/pc_loader \ /dev/ttyUSB0 main.bin else - PROGRAM_CMDLINE := qstlink2 -cqewV ./main.bin + PROGRAM_CMDLINE := qstlink2 -cqewV ./main.bin endif ##------------------------------------------------------------------------- diff --git a/miosix/config/miosix_settings.h b/miosix/config/miosix_settings.h index 0c1cd482276c7dd59da6e3e0d6c22a6ed4dca4c3..475b1a7342cd59e5cf9658839223f0215e3648d6 100644 --- a/miosix/config/miosix_settings.h +++ b/miosix/config/miosix_settings.h @@ -61,6 +61,17 @@ namespace miosix { #define SCHED_TYPE_PRIORITY //#define SCHED_TYPE_CONTROL_BASED //#define SCHED_TYPE_EDF + +/// \def WITH_PROCESSES +/// If uncommented enables support for processes as well as threads. +/// This enables the dynamic loader to load elf programs, the extended system +/// call service and, if the hardware supports it, the MPU to provide memory +/// isolation of processes +//#define WITH_PROCESSES + +#if defined(WITH_PROCESSES) && defined(__NO_EXCEPTIONS) +#error Processes require C++ exception support +#endif //defined(WITH_PROCESSES) && defined(__NO_EXCEPTIONS) // // Filesystem options @@ -128,6 +139,20 @@ const unsigned int STACK_IDLE=256; /// such as printf/fopen which are stack-heavy const unsigned int STACK_DEFAULT_FOR_PTHREAD=2048; +/// Maximum size of the RAM image of a process. If a program requires more +/// the kernel will not run it (MUST be divisible by 4) +const unsigned int MAX_PROCESS_IMAGE_SIZE=64*1024; + +/// Minimum size of the stack for a process. If a program specifies a lower +/// size the kernel will not run it (MUST be divisible by 4) +const unsigned int MIN_PROCESS_STACK_SIZE=STACK_MIN; + +/// Every userspace thread has two stacks, one for when it is running in +/// userspace and one for when it is running in kernelspace (that is, while it +/// is executing system calls). This is the size of the stack for when the +/// thread is running in kernelspace (MUST be divisible by 4) +const unsigned int SYSTEM_MODE_PROCESS_STACK_SIZE=2*1024; + /// Number of priorities (MUST be >1) /// PRIORITY_MAX-1 is the highest priority, 0 is the lowest. -1 is reserved as /// the priority of the idle thread. diff --git a/miosix/interfaces/portability.h b/miosix/interfaces/portability.h index b1c7a807b41ff8f63e37dede2805df712f1cf9ab..0cf3e500c4c52564861c35568b1e47beacb146cd 100644 --- a/miosix/interfaces/portability.h +++ b/miosix/interfaces/portability.h @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2010 by Terraneo Federico * + * Copyright (C) 2010, 2011, 2012 by Terraneo Federico * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * @@ -49,6 +49,16 @@ * This file should contain the implementation of those inline functions. */ +#ifdef WITH_PROCESSES + +namespace miosix { + +class Process; //Forward decl + +} //namespace miosix + +#endif //WITH_PROCESSES + /** * \} */ @@ -99,6 +109,185 @@ inline void doYield(); void initCtxsave(unsigned int *ctxsave, void *(*pc)(void *), unsigned int *sp, void *argv); +#ifdef WITH_PROCESSES + +/** + * This class allows to access the parameters that a process passed to + * the operating system as part of a system call + */ +class SyscallParameters +{ +public: + /** + * Constructor, initialize the class starting from the thread's userspace + * context + */ + SyscallParameters(unsigned int *context); + + /** + * \return the syscall id, used to identify individual system calls + */ + int getSyscallId() const; + + /** + * \return the first syscall parameter. The returned result is meaningful + * only if the syscall (identified through its id) has one or more parameters + */ + unsigned int getFirstParameter() const; + + /** + * \return the second syscall parameter. The returned result is meaningful + * only if the syscall (identified through its id) has two or more parameters + */ + unsigned int getSecondParameter() const; + + /** + * \return the third syscall parameter. The returned result is meaningful + * only if the syscall (identified through its id) has three parameters + */ + unsigned int getThirdParameter() const; + + /** + * Set the value that will be returned by the syscall. + * Invalidates parameters so must be called only after the syscall + * parameteres have been read. + * \param ret value that will be returned by the syscall. + */ + void setReturnValue(unsigned int ret); + +private: + unsigned int *registers; +}; + +/** + * This class contains information about whether a fault occurred in a process. + * It is used to terminate processes that fault. + */ +class FaultData +{ +public: + /** + * Constructor, initializes the object + */ + FaultData() : id(0) {} + + /** + * Constructor, initializes a FaultData object + * \param id id of the fault + * \param pc program counter at the moment of the fault + * \param arg eventual additional argument, depending on the fault id + */ + FaultData(int id, unsigned int pc, unsigned int arg=0) + : id(id), pc(pc), arg(arg) {} + + /** + * \return true if a fault happened within a process + */ + bool faultHappened() const { return id!=0; } + + /** + * Print information about the occurred fault + */ + void print() const; + +private: + int id; ///< Id of the fault or zero if no faults + unsigned int pc; ///< Program counter value at the time of the fault + unsigned int arg;///< Eventual argument, valid only for some id values +}; + +/** + * \internal + * Initializes a ctxsave array when a thread is created. + * This version is to initialize the userspace context of processes. + * It is used by the kernel, and should not be used by end users. + * \param ctxsave a pointer to a field ctxsave inside a Thread class that need + * to be filled + * \param pc starting program counter of newly created thread, used to + * initialize ctxsave + * \param sp starting stack pointer of newly created thread, used to initialize + * ctxsave + * \param argv starting data passed to newly created thread, used to initialize + * ctxsave + * \param gotBase base address of the global offset table, for userspace + * processes + */ +void initCtxsave(unsigned int *ctxsave, void *(*pc)(void *), unsigned int *sp, + void *argv, unsigned int *gotBase); + +/** + * \internal + * Cause a supervisor call that will switch the thread back to kernelspace + * It is used by the kernel, and should not be used by end users. + */ +inline void portableSwitchToUserspace(); + +/** + * \internal + * This class is used to manage the MemoryProtectionUnit + */ + +class MPUConfiguration +{ + public: + /** + * Default constructor, leaves the MPU regions unconfigured + */ + MPUConfiguration() {} + + /** + * \internal + * \param elfBase base address of the ELF file + * \param elfSize size of the ELF file + * \param imageBase base address of the Process RAM image + * \param imageSize size of the Process RAM image + */ + MPUConfiguration(unsigned int *elfBase, unsigned int elfSize, + unsigned int *imageBase, unsigned int imageSize); + + /** + * \internal + * This method is used to configure the Memoy Protection region for a + * Process during a context-switch to a userspace thread. + * Can only be called inside an IRQ, not even with interrupts disabled + */ + void IRQenable(); + + /** + * \internal + * This method is used to disable the MPU during a context-switch to a + * kernelspace thread. + * Can only be called inside an IRQ, not even with interrupts disabled + */ + static void IRQdisable(); + + /** + * Print the MPU configuration for debugging purposes + */ + void dumpConfiguration(); + + /** + * Check if the address is within the data segment + * \param ptr the address of the pointer + * \return true if the pointer points within the data segment, + * false otherwise. + */ + bool within(const unsigned int ptr) const; + + /** + * \internal + */ + unsigned int getBaseDataAddress() const; + unsigned int getDataSize() const; + + //Uses default copy constructor and operator= +private: + ///These value are copied into the MPU registers to configure them + unsigned int regValues[4]; +}; + +#endif //WITH_PROCESSES + /** * \internal * Used before every context switch to check if the stack of the thread has diff --git a/miosix/kernel/SystemMap.cpp b/miosix/kernel/SystemMap.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e45eb34cf7c425097222c66f55dd8faa0913ba13 --- /dev/null +++ b/miosix/kernel/SystemMap.cpp @@ -0,0 +1,49 @@ + +#include "SystemMap.h" + +using namespace std; + +#ifdef WITH_PROCESSES + +namespace miosix { + +SystemMap& SystemMap::instance() +{ + static SystemMap singleton; + return singleton; +} + +void SystemMap::addElfProgram(const char* name, const unsigned int *elf, unsigned int size) +{ + string sName(name); + if(mPrograms.find(sName) == mPrograms.end()) + mPrograms.insert(make_pair(sName, make_pair(elf, size))); +} + +void SystemMap::removeElfProgram(const char* name) +{ + string sName(name); + ProgramsMap::iterator it = mPrograms.find(sName); + + if(it != mPrograms.end()) + mPrograms.erase(it); +} + +pair<const unsigned int*, unsigned int> SystemMap::getElfProgram(const char* name) const +{ + ProgramsMap::const_iterator it = mPrograms.find(string(name)); + + if(it == mPrograms.end()) + return make_pair<const unsigned int*, unsigned int>(0, 0); + + return it->second; +} + +unsigned int SystemMap::getElfCount() const +{ + return mPrograms.size(); +} + +} //namespace miosix + +#endif //WITH_PROCESSES diff --git a/miosix/kernel/SystemMap.h b/miosix/kernel/SystemMap.h new file mode 100644 index 0000000000000000000000000000000000000000..7094420d0113e434ea1f901ccb5ef62fffa04768 --- /dev/null +++ b/miosix/kernel/SystemMap.h @@ -0,0 +1,38 @@ +#ifndef SYSTEMMAP_H +#define SYSTEMMAP_H + +#include "kernel/sync.h" +#include "config/miosix_settings.h" + +#include <map> +#include <string> + +#ifdef WITH_PROCESSES + +namespace miosix { + +class SystemMap +{ +public: + static SystemMap &instance(); + + void addElfProgram(const char *name, const unsigned int *elf, unsigned int size); + void removeElfProgram(const char *name); + std::pair<const unsigned int*, unsigned int> getElfProgram(const char *name) const; + + unsigned int getElfCount() const; + +private: + SystemMap() {} + SystemMap(const SystemMap&); + SystemMap& operator= (const SystemMap&); + + typedef std::map<std::string, std::pair<const unsigned int*, unsigned int> > ProgramsMap; + ProgramsMap mPrograms; +}; + +} //namespace miosix + +#endif //WITH_PROCESSES + +#endif /* SYSTEMMAP_H */ diff --git a/miosix/kernel/elf_program.cpp b/miosix/kernel/elf_program.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bab4deae6655461392d5eccc93a0bdba44a2c547 --- /dev/null +++ b/miosix/kernel/elf_program.cpp @@ -0,0 +1,321 @@ +/*************************************************************************** + * Copyright (C) 2012 by Terraneo Federico * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * As a special exception, if other files instantiate templates or use * + * macros or inline functions from this file, or you compile this file * + * and link it with other works to produce a work based on this file, * + * this file does not by itself cause the resulting work to be covered * + * by the GNU General Public License. However the source code for this * + * file must still be made available in accordance with the GNU General * + * Public License. This exception does not invalidate any other reasons * + * why a work based on this file might be covered by the GNU General * + * Public License. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, see <http://www.gnu.org/licenses/> * + ***************************************************************************/ + +#include "elf_program.h" +#include "process_pool.h" +#include <stdexcept> +#include <cstring> +#include <cstdio> + +using namespace std; + +#ifdef WITH_PROCESSES + +namespace miosix { + +///\internal Enable/disable debugging of program loading +//#define DBG iprintf +#define DBG(x,...) ; + +///By convention, in an elf file for Miosix, the data segment starts @ this addr +static const unsigned int DATA_START=0x10000000; + +// +// class ElfProgram +// + +ElfProgram::ElfProgram(const unsigned int *elf, unsigned int size) + : elf(elf), size(size) +{ + //Trying to follow the "full recognition before processing" approach, + //(http://www.cs.dartmouth.edu/~sergey/langsec/occupy/FullRecognition.jpg) + //all of the elf fields that will later be used are checked in advance. + //Unused fields are unchecked, so when using new fields, add new checks + if(validateHeader()==false) throw runtime_error("Bad file"); +} + +bool ElfProgram::validateHeader() +{ + //Validate ELF header + //Note: this code assumes a little endian elf and a little endian ARM CPU + if(size<sizeof(Elf32_Ehdr)) return false; + const Elf32_Ehdr *ehdr=getElfHeader(); + static const char magic[EI_NIDENT]={0x7f,'E','L','F',1,1,1}; + if(memcmp(ehdr->e_ident,magic,EI_NIDENT)) + throw runtime_error("Unrecognized format"); + if(ehdr->e_type!=ET_EXEC) throw runtime_error("Not an executable"); + if(ehdr->e_machine!=EM_ARM) throw runtime_error("Wrong CPU arch"); + if(ehdr->e_version!=EV_CURRENT) return false; + if(ehdr->e_entry>=size) return false; + if(ehdr->e_phoff>=size-sizeof(Elf32_Phdr)) return false; + if(ehdr->e_flags!=(EF_ARM_EABI_MASK | EF_HAS_ENTRY_POINT)) return false; + if(ehdr->e_ehsize!=sizeof(Elf32_Ehdr)) return false; + if(ehdr->e_phentsize!=sizeof(Elf32_Phdr)) return false; + //This to avoid that the next condition could pass due to 32bit wraparound + //20 is an arbitrary number, could be increased if required + if(ehdr->e_phnum>20) throw runtime_error("Too many segments"); + if(ehdr->e_phoff+(ehdr->e_phnum*sizeof(Elf32_Phdr))>size) return false; + + //Validate program header table + bool codeSegmentPresent=false; + bool dataSegmentPresent=false; + bool dynamicSegmentPresent=false; + int dataSegmentSize=0; + const Elf32_Phdr *phdr=getProgramHeaderTable(); + for(int i=0;i<getNumOfProgramHeaderEntries();i++,phdr++) + { + //The third condition does not imply the other due to 32bit wraparound + if(phdr->p_offset>=size) return false; + if(phdr->p_filesz>=size) return false; + if(phdr->p_offset+phdr->p_filesz>size) return false; + + if(phdr->p_align>8) throw runtime_error("Segment alignment too strict"); + + switch(phdr->p_type) + { + case PT_LOAD: + if(phdr->p_flags & ~(PF_R | PF_W | PF_X)) return false; + if(!(phdr->p_flags & PF_R)) return false; + if((phdr->p_flags & PF_W) && (phdr->p_flags & PF_X)) + throw runtime_error("File violates W^X"); + if(phdr->p_flags & PF_X) + { + if(codeSegmentPresent) return false; //Can't apper twice + codeSegmentPresent=true; + if(ehdr->e_entry<phdr->p_offset || + ehdr->e_entry>phdr->p_offset+phdr->p_filesz || + phdr->p_filesz!=phdr->p_memsz) return false; + } + if((phdr->p_flags & PF_W) && !(phdr->p_flags & PF_X)) + { + if(dataSegmentPresent) return false; //Two data segments? + dataSegmentPresent=true; + if(phdr->p_memsz<phdr->p_filesz) return false; + unsigned int maxSize=MAX_PROCESS_IMAGE_SIZE- + MIN_PROCESS_STACK_SIZE; + if(phdr->p_memsz>=maxSize) + throw runtime_error("Data segment too big"); + dataSegmentSize=phdr->p_memsz; + } + break; + case PT_DYNAMIC: + if(dynamicSegmentPresent) return false; //Two dynamic segments? + dynamicSegmentPresent=true; + //DYNAMIC segment *must* come after data segment + if(dataSegmentPresent==false) return false; + if(validateDynamicSegment(phdr,dataSegmentSize)==false) + return false; + break; + default: + //Ignoring other segments + break; + } + } + if(codeSegmentPresent==false) return false; //Can't not have code segment + return true; +} + +bool ElfProgram::validateDynamicSegment(const Elf32_Phdr *dynamic, + unsigned int dataSegmentSize) +{ + unsigned int base=getElfBase(); + const Elf32_Dyn *dyn= + reinterpret_cast<const Elf32_Dyn*>(getElfBase()+dynamic->p_offset); + const int dynSize=dynamic->p_memsz/sizeof(Elf32_Dyn); + Elf32_Addr dtRel=0; + Elf32_Word dtRelsz=0; + unsigned int hasRelocs=0; + bool miosixTagFound=false; + unsigned int ramSize=0; + unsigned int stackSize=0; + for(int i=0;i<dynSize;i++,dyn++) + { + switch(dyn->d_tag) + { + case DT_REL: + hasRelocs |= 0x1; + dtRel=dyn->d_un.d_ptr; + break; + case DT_RELSZ: + hasRelocs |= 0x2; + dtRelsz=dyn->d_un.d_val; + break; + case DT_RELENT: + hasRelocs |= 0x4; + if(dyn->d_un.d_val!=sizeof(Elf32_Rel)) return false; + break; + case DT_MX_ABI: + if(dyn->d_un.d_val==DV_MX_ABI_V0) miosixTagFound=true; + break; + case DT_MX_RAMSIZE: + ramSize=dyn->d_un.d_val; + break; + case DT_MX_STACKSIZE: + stackSize=dyn->d_un.d_val; + break; + case DT_RELA: + case DT_RELASZ: + case DT_RELAENT: + throw runtime_error("RELA relocations unsupported"); + default: + //Ignore other entries + break; + } + } + if(miosixTagFound==false) throw runtime_error("Not a Miosix executable"); + if(stackSize<MIN_PROCESS_STACK_SIZE) + throw runtime_error("Requested stack is too small"); + if(ramSize>MAX_PROCESS_IMAGE_SIZE) + throw runtime_error("Requested image size is too large"); + if((stackSize & 0x3) || + (ramSize & 0x3) || + (ramSize < ProcessPool::blockSize) || + (stackSize>MAX_PROCESS_IMAGE_SIZE) || + (dataSegmentSize>MAX_PROCESS_IMAGE_SIZE) || + (dataSegmentSize+stackSize>ramSize)) + throw runtime_error("Invalid stack or RAM size"); + + if(hasRelocs!=0 && hasRelocs!=0x7) return false; + if(hasRelocs) + { + //The third condition does not imply the other due to 32bit wraparound + if(dtRel>=size) return false; + if(dtRelsz>=size) return false; + if(dtRel+dtRelsz>size) return false; + + const Elf32_Rel *rel=reinterpret_cast<const Elf32_Rel*>(base+dtRel); + const int relSize=dtRelsz/sizeof(Elf32_Rel); + for(int i=0;i<relSize;i++,rel++) + { + switch(ELF32_R_TYPE(rel->r_info)) + { + case R_ARM_NONE: + break; + case R_ARM_RELATIVE: + if(rel->r_offset<DATA_START) return false; + if(rel->r_offset>DATA_START+dataSegmentSize-4) return false; + if(rel->r_offset & 0x3) return false; + break; + default: + throw runtime_error("Unexpected relocation type"); + } + } + } + return true; +} + +// +// class ProcessImage +// + +void ProcessImage::load(const ElfProgram& program) +{ + if(image) ProcessPool::instance().deallocate(image); + const unsigned int base=program.getElfBase(); + const Elf32_Phdr *phdr=program.getProgramHeaderTable(); + const Elf32_Phdr *dataSegment=0; + Elf32_Addr dtRel=0; + Elf32_Word dtRelsz=0; + bool hasRelocs=false; + for(int i=0;i<program.getNumOfProgramHeaderEntries();i++,phdr++) + { + switch(phdr->p_type) + { + case PT_LOAD: + if((phdr->p_flags & PF_W) && !(phdr->p_flags & PF_X)) + dataSegment=phdr; + break; + case PT_DYNAMIC: + { + const Elf32_Dyn *dyn=reinterpret_cast<const Elf32_Dyn*> + (base+phdr->p_offset); + const int dynSize=phdr->p_memsz/sizeof(Elf32_Dyn); + for(int i=0;i<dynSize;i++,dyn++) + { + switch(dyn->d_tag) + { + case DT_REL: + hasRelocs=true; + dtRel=dyn->d_un.d_ptr; + break; + case DT_RELSZ: + hasRelocs=true; + dtRelsz=dyn->d_un.d_val; + break; + case DT_MX_RAMSIZE: + size=dyn->d_un.d_val; + image=ProcessPool::instance() + .allocate(dyn->d_un.d_val); + default: + break; + } + } + break; + } + default: + //Ignoring other segments + break; + } + } + const char *dataSegmentInFile= + reinterpret_cast<const char*>(base+dataSegment->p_offset); + char *dataSegmentInMem=reinterpret_cast<char*>(image); + memcpy(dataSegmentInMem,dataSegmentInFile,dataSegment->p_filesz); + dataSegmentInMem+=dataSegment->p_filesz; + memset(dataSegmentInMem,0,dataSegment->p_memsz-dataSegment->p_filesz); + if(hasRelocs) + { + const Elf32_Rel *rel=reinterpret_cast<const Elf32_Rel*>(base+dtRel); + const int relSize=dtRelsz/sizeof(Elf32_Rel); + const unsigned int base=reinterpret_cast<unsigned int>(image); + DBG("Relocations -- start (process RAM image @ 0x%x)\n",base); + for(int i=0;i<relSize;i++,rel++) + { + unsigned int offset=(rel->r_offset-DATA_START)/4; + switch(ELF32_R_TYPE(rel->r_info)) + { + case R_ARM_RELATIVE: + DBG("R_ARM_RELATIVE offset 0x%x from 0x%x to 0x%x\n", + offset*4,image[offset],image[offset]+base-DATA_START); + image[offset]+=base-DATA_START; + break; + default: + break; + } + } + DBG("Relocations -- end\n"); + } +} + +ProcessImage::~ProcessImage() +{ + if(image) ProcessPool::instance().deallocate(image); +} + +} //namespace miosix + +#endif //WITH_PROCESSES diff --git a/miosix/kernel/elf_program.h b/miosix/kernel/elf_program.h new file mode 100644 index 0000000000000000000000000000000000000000..5d5abed383da6451768805da6a2394bba02726f7 --- /dev/null +++ b/miosix/kernel/elf_program.h @@ -0,0 +1,178 @@ +/*************************************************************************** + * Copyright (C) 2012 by Terraneo Federico * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * As a special exception, if other files instantiate templates or use * + * macros or inline functions from this file, or you compile this file * + * and link it with other works to produce a work based on this file, * + * this file does not by itself cause the resulting work to be covered * + * by the GNU General Public License. However the source code for this * + * file must still be made available in accordance with the GNU General * + * Public License. This exception does not invalidate any other reasons * + * why a work based on this file might be covered by the GNU General * + * Public License. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, see <http://www.gnu.org/licenses/> * + ***************************************************************************/ + +#ifndef ELF_PROGRAM_H +#define ELF_PROGRAM_H + +#include <utility> +#include "elf_types.h" +#include "config/miosix_settings.h" + +#ifdef WITH_PROCESSES + +namespace miosix { + +/** + * This class represents an elf file. + */ +class ElfProgram +{ +public: + /** + * Constructor + * \param elf pointer to the elf file's content. Ownership of the data + * remains of the caller, that is, the pointer is not deleted by this + * class. This is done to allow passing a pointer directly to a location + * in the microcontroller's FLASH memory, in order to avoid copying the + * elf in RAM + * \param size size of the content of the elf file + */ + ElfProgram(const unsigned int *elf, unsigned int size); + + /** + * \return the a pointer to the elf header + */ + const Elf32_Ehdr *getElfHeader() const + { + return reinterpret_cast<const Elf32_Ehdr*>(elf); + } + + /** + * \return the already relocated value of the entry point + */ + unsigned int getEntryPoint() const + { + unsigned int base=reinterpret_cast<unsigned int>(elf); + return base+getElfHeader()->e_entry; + } + + /** + * \return an array of struct Elf32_Phdr + */ + const Elf32_Phdr *getProgramHeaderTable() const + { + unsigned int base=reinterpret_cast<unsigned int>(elf); + return reinterpret_cast<const Elf32_Phdr*>(base+getElfHeader()->e_phoff); + } + + /** + * \return the number of entries in the program header table + */ + int getNumOfProgramHeaderEntries() const + { + return getElfHeader()->e_phnum; + } + + /** + * \return a number representing the elf base address in memory + */ + unsigned int getElfBase() const + { + return reinterpret_cast<unsigned int>(elf); + } + + /** + * \return the size of the elf file, as passed in the class' constructor + */ + unsigned int getElfSize() const + { + return size; + } + +private: + /** + * \param size elf file size + * \return false if the file is not valid + * \throws runtime_error for selected specific types of errors + */ + bool validateHeader(); + + /** + * \param dynamic pointer to dynamic segment + * \param size elf file size + * \param dataSegmentSize size of data segment in memory + * \return false if the dynamic segment is not valid + * \throws runtime_error for selected specific types of errors + */ + bool validateDynamicSegment(const Elf32_Phdr *dynamic, + unsigned int dataSegmentSize); + + const unsigned int * const elf; ///<Pointer to the content of the elf file + unsigned int size; ///< Size of the elf file +}; + +/** + * This class represent the RAM image of a process. + */ +class ProcessImage +{ +public: + /** + * Constructor, creates an empty process image. + */ + ProcessImage() : image(0), size(0) {} + + /** + * Starting from the content of the elf program, create an image in RAM of + * the process, including copying .data, zeroing .bss and performing + * relocations + */ + void load(const ElfProgram& program); + + /** + * \return a pointer to the base of the program image + */ + unsigned int *getProcessBasePointer() const { return image; } + + /** + * \return the size of the process image, or zero if it is not valid + */ + unsigned int getProcessImageSize() const { return size; } + + /** + * \return true if this is a valid process image + */ + bool isValid() const { return image!=0; } + + /** + * Destructor. Deletes the process image memory. + */ + ~ProcessImage(); + +private: + ProcessImage(const ProcessImage&); + ProcessImage& operator= (const ProcessImage&); + + unsigned int *image; //Pointer to the process image in RAM + unsigned int size; //Size of the process image +}; + +} //namespace miosix + +#endif //WITH_PROCESSES + +#endif //ELF_PROGRAM_H diff --git a/miosix/kernel/elf_types.h b/miosix/kernel/elf_types.h new file mode 100644 index 0000000000000000000000000000000000000000..a4ef6e2d8868f70e8cc1e09be5fae600e7d907f3 --- /dev/null +++ b/miosix/kernel/elf_types.h @@ -0,0 +1,179 @@ +/*************************************************************************** + * Copyright (C) 2012 by Luigi Rucco and Terraneo Federico * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * As a special exception, if other files instantiate templates or use * + * macros or inline functions from this file, or you compile this file * + * and link it with other works to produce a work based on this file, * + * this file does not by itself cause the resulting work to be covered * + * by the GNU General Public License. However the source code for this * + * file must still be made available in accordance with the GNU General * + * Public License. This exception does not invalidate any other reasons * + * why a work based on this file might be covered by the GNU General * + * Public License. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, see <http://www.gnu.org/licenses/> * + ***************************************************************************/ + +#ifndef ELF_TYPES_H +#define ELF_TYPES_H + +#include <inttypes.h> +#include "config/miosix_settings.h" + +#ifdef WITH_PROCESSES + +namespace miosix { + +// elf-specific types +typedef uint32_t Elf32_Word; +typedef int32_t Elf32_Sword; +typedef uint16_t Elf32_Half; +typedef uint32_t Elf32_Off; +typedef uint32_t Elf32_Addr; + +// Size of e_ident in the elf header +const int EI_NIDENT=16; + +/* + * Elf header + */ +struct Elf32_Ehdr +{ + unsigned char e_ident[EI_NIDENT]; // Ident bytes + Elf32_Half e_type; // File type, any of the ET_* constants + Elf32_Half e_machine; // Target machine + Elf32_Word e_version; // File version + Elf32_Addr e_entry; // Start address + Elf32_Off e_phoff; // Phdr file offset + Elf32_Off e_shoff; // Shdr file offset + Elf32_Word e_flags; // File flags + Elf32_Half e_ehsize; // Sizeof ehdr + Elf32_Half e_phentsize; // Sizeof phdr + Elf32_Half e_phnum; // Number phdrs + Elf32_Half e_shentsize; // Sizeof shdr + Elf32_Half e_shnum; // Number shdrs + Elf32_Half e_shstrndx; // Shdr string index +} __attribute__((packed)); + +// Values for e_type +const Elf32_Half ET_NONE = 0; // Unknown type +const Elf32_Half ET_REL = 1; // Relocatable +const Elf32_Half ET_EXEC = 2; // Executable +const Elf32_Half ET_DYN = 3; // Shared object +const Elf32_Half ET_CORE = 4; // Core file + +// Values for e_version +const Elf32_Word EV_CURRENT = 1; + +// Values for e_machine +const Elf32_Half EM_ARM = 0x28; + +// Values for e_flags +const Elf32_Word EF_ARM_EABI_MASK = 0x05000000; +const Elf32_Word EF_HAS_ENTRY_POINT = 2; + +/* + * Elf program header + */ +struct Elf32_Phdr +{ + Elf32_Word p_type; // Program header type, any of the PH_* constants + Elf32_Off p_offset; // Segment start offset in file + Elf32_Addr p_vaddr; // Segment virtual address + Elf32_Addr p_paddr; // Segment physical address + Elf32_Word p_filesz; // Segment size in file + Elf32_Word p_memsz; // Segment size in memory + Elf32_Word p_flags; // Segment flasgs, any of the PF_* constants + Elf32_Word p_align; // Segment alignment requirements +} __attribute__((packed)); + +// Values for p_type +const Elf32_Word PT_NULL = 0; // Unused array entry +const Elf32_Word PT_LOAD = 1; // Loadable segment +const Elf32_Word PT_DYNAMIC = 2; // Segment is the dynamic section +const Elf32_Word PT_INTERP = 3; // Shared library interpreter +const Elf32_Word PT_NOTE = 4; // Auxiliary information + +// Values for p_flags +const Elf32_Word PF_X = 0x1; // Execute +const Elf32_Word PF_W = 0x2; // Write +const Elf32_Word PF_R = 0x4; // Read + +/* + * Entries of the DYNAMIC segment + */ +struct Elf32_Dyn +{ + Elf32_Sword d_tag; // Type of entry + union { + Elf32_Word d_val; // Value of entry, if number + Elf32_Addr d_ptr; // Value of entry, if offset into the file + } d_un; +} __attribute__((packed)); + +// Values for d_tag +const int DT_NULL = 0; +const int DT_NEEDED = 1; +const int DT_PLTRELSZ = 2; +const int DT_PLTGOT = 3; +const int DT_HASH = 4; +const int DT_STRTAB = 5; +const int DT_SYMTAB = 6; +const int DT_RELA = 7; +const int DT_RELASZ = 8; +const int DT_RELAENT = 9; +const int DT_STRSZ = 10; +const int DT_SYMENT = 11; +const int DT_INIT = 12; +const int DT_FINI = 13; +const int DT_SONAME = 14; +const int DT_RPATH = 15; +const int DT_SYMBOLIC = 16; +const int DT_REL = 17; +const int DT_RELSZ = 18; +const int DT_RELENT = 19; +const int DT_PLTREL = 20; +const int DT_DEBUG = 21; +const int DT_TEXTREL = 22; +const int DT_JMPREL = 23; +const int DT_BINDNOW = 24; +const int DT_MX_RAMSIZE = 0x10000000; //Miosix specific, RAM size +const int DT_MX_STACKSIZE = 0x10000001; //Miosix specific, STACK size +const int DT_MX_ABI = 0x736f694d; //Miosix specific, ABI version +const unsigned int DV_MX_ABI_V0 = 0x00007869; //Miosix specific, ABI version 0 + +/* + * Relocation entries + */ +struct Elf32_Rel +{ + Elf32_Addr r_offset; + Elf32_Word r_info; +} __attribute__((packed)); + +// To extract the two fields of r_info +#define ELF32_R_SYM(i) ((i)>>8) +#define ELF32_R_TYPE(i) ((unsigned char)(i)) + + +// Possible values for ELF32_R_TYPE(r_info) +const unsigned char R_ARM_NONE = 0; +const unsigned char R_ARM_ABS32 = 2; +const unsigned char R_ARM_RELATIVE = 23; + +} //namespace miosix + +#endif //WITH_PROCESSES + +#endif //ELF_TYPES_H diff --git a/miosix/kernel/kernel.cpp b/miosix/kernel/kernel.cpp index 85363d08f1df5db8ee6ed15fe961487893e84ecd..eb041051d34966e8cce8e6e3fe6c60b0fb7f9bdb 100644 --- a/miosix/kernel/kernel.cpp +++ b/miosix/kernel/kernel.cpp @@ -34,6 +34,7 @@ #include "arch_settings.h" #include "sync.h" #include "stage_2_boot.h" +#include "process.h" #include "kernel/scheduler/scheduler.h" #include <stdexcept> #include <algorithm> @@ -594,6 +595,36 @@ Thread *Thread::doCreate(void*(*startfunc)(void*) , unsigned int stacksize, return thread; } +#ifdef WITH_PROCESSES + +void Thread::IRQhandleSvc(unsigned int svcNumber) +{ + if(cur->proc==0) errorHandler(UNEXPECTED); + if(svcNumber==1) + { + const_cast<Thread*>(cur)->flags.IRQsetUserspace(true); + ::ctxsave=cur->userCtxsave; + cur->proc->mpu.IRQenable(); + } else { + const_cast<Thread*>(cur)->flags.IRQsetUserspace(false); + ::ctxsave=cur->ctxsave; + miosix_private::MPUConfiguration::IRQdisable(); + } +} + +bool Thread::IRQreportFault(const miosix_private::FaultData& fault) +{ + if(cur->proc==0 || const_cast<Thread*>(cur)->flags.isInUserspace()==false) + return false; + cur->proc->fault=fault; + const_cast<Thread*>(cur)->flags.IRQsetUserspace(false); + ::ctxsave=cur->ctxsave; + miosix_private::MPUConfiguration::IRQdisable(); + return true; +} + +#endif //WITH_PROCESSES + void Thread::threadLauncher(void *(*threadfunc)(void*), void *argv) { void *result=0; @@ -639,7 +670,88 @@ void Thread::threadLauncher(void *(*threadfunc)(void*), void *argv) Thread::yield();//Since the thread is now deleted, yield immediately. //Will never reach here errorHandler(UNEXPECTED); +} + +#ifdef WITH_PROCESSES + +miosix_private::SyscallParameters Thread::switchToUserspace() +{ + miosix_private::portableSwitchToUserspace(); + miosix_private::SyscallParameters result(cur->userCtxsave); + return result; +} + +Thread *Thread::createUserspace(void *(*startfunc)(void *), void *argv, + unsigned short options, Process *proc) +{ + //Allocate memory for the thread, return if fail + unsigned int *base=static_cast<unsigned int*>(malloc(sizeof(Thread)+ + SYSTEM_MODE_PROCESS_STACK_SIZE+WATERMARK_LEN+CTXSAVE_ON_STACK)); + if(base==NULL) + { + errorHandler(OUT_OF_MEMORY); + return NULL;//Error + } + //At the top of thread memory allocate the Thread class with placement new + void *threadClass=base+((SYSTEM_MODE_PROCESS_STACK_SIZE+WATERMARK_LEN+ + CTXSAVE_ON_STACK)/sizeof(unsigned int)); + Thread *thread=new (threadClass) Thread(base,SYSTEM_MODE_PROCESS_STACK_SIZE,false); + try { + thread->userCtxsave=new unsigned int[CTXSAVE_SIZE]; + } catch(std::bad_alloc&) + { + thread->~Thread(); + free(base); //Delete ALL thread memory + errorHandler(OUT_OF_MEMORY); + return NULL;//Error + } + + //Fill watermark and stack + memset(base, WATERMARK_FILL, WATERMARK_LEN); + base+=WATERMARK_LEN/sizeof(unsigned int); + memset(base, STACK_FILL, SYSTEM_MODE_PROCESS_STACK_SIZE); + + //On some architectures some registers are saved on the stack, therefore + //initCtxsave *must* be called after filling the stack. + miosix_private::initCtxsave(thread->ctxsave,startfunc, + reinterpret_cast<unsigned int*>(thread),argv); + thread->proc=proc; + if((options & JOINABLE)==0) thread->flags.IRQsetDetached(); + thread->flags.IRQsetWait(true); //Thread is not yet ready + + //Add thread to thread list + { + //Handling the list of threads, critical section is required + PauseKernelLock lock; + if(Scheduler::PKaddThread(thread,MAIN_PRIORITY)==false) + { + //Reached limit on number of threads + base=thread->watermark; + thread->~Thread(); + free(base); //Delete ALL thread memory + return NULL; + } + } + + return thread; +} + +void Thread::setupUserspaceContext(unsigned int entry, unsigned int *gotBase, + unsigned int ramImageSize) +{ + void *(*startfunc)(void*)=reinterpret_cast<void *(*)(void*)>(entry); + unsigned int *ep=gotBase+ramImageSize/4; + miosix_private::initCtxsave(cur->userCtxsave,startfunc,ep,0,gotBase); +} + +#endif //WITH_PROCESSES + +Thread::~Thread() +{ + #ifdef WITH_PROCESSES + if(userCtxsave) delete[] userCtxsave; + #endif //WITH_PROCESSES } // diff --git a/miosix/kernel/kernel.h b/miosix/kernel/kernel.h index 51045123e5c3fb15416fbe55c4ec5734c5eb03df..561cc7d4064f54457edd1a6a5e956409d7b27ba9 100644 --- a/miosix/kernel/kernel.h +++ b/miosix/kernel/kernel.h @@ -260,7 +260,7 @@ private: * kernel is paused will cause deadlock. Therefore, if possible, it is better to * use a Mutex instead of pausing the kernel<br>This function is safe to be * called even before the kernel is started. In this case it has no effect. -*/ + */ void pauseKernel(); /** @@ -393,6 +393,9 @@ struct SleepData; class MemoryProfiling; class Mutex; class ConditionVariable; +#ifdef WITH_PROCESSES +class Process; +#endif //WITH_PROCESSES /** * This class represents a thread. It has methods for creating, deleting and @@ -687,6 +690,27 @@ public: * \return the size of the stack of the current thread. */ static const int getStackSize(); + + #ifdef WITH_PROCESSES + + /** + * \internal + * Can only be called inside an IRQ, its use is to switch a thread between + * userspace/kernelspace and back to perform context switches + */ + static void IRQhandleSvc(unsigned int svcNumber); + + /** + * \internal + * Can only be called inside an IRQ, its use is to report a fault so that + * in case the fault has occurred within a process while it was executing + * in userspace, the process can be terminated. + * \param fault data about the occurred fault + * \return true if the fault was caused by a process, false otherwise. + */ + static bool IRQreportFault(const miosix_private::FaultData& fault); + + #endif //WITH_PROCESSES private: //Unwanted methods @@ -699,45 +723,45 @@ private: /** * Constructor, sets flags to default. */ - ThreadFlags(): flags(0) {} + ThreadFlags() : flags(0) {} /** * Set the wait flag of the thread. - * Can only be called with interrupts enabled or within an interrupt. + * Can only be called with interrupts disabled or within an interrupt. * \param waiting if true the flag will be set, otherwise cleared */ void IRQsetWait(bool waiting); /** * Set the wait_join flag of the thread. - * Can only be called with interrupts enabled or within an interrupt. + * Can only be called with interrupts disabled or within an interrupt. * \param waiting if true the flag will be set, otherwise cleared */ void IRQsetJoinWait(bool waiting); /** * Set wait_cond flag of the thread. - * Can only be called with interrupts enabled or within an interrupt. + * Can only be called with interrupts disabled or within an interrupt. * \param waiting if true the flag will be set, otherwise cleared */ void IRQsetCondWait(bool waiting); /** * Set the sleep flag of the thread. - * Can only be called with interrupts enabled or within an interrupt. + * Can only be called with interrupts disabled or within an interrupt. * \param sleeping if true the flag will be set, otherwise cleared */ void IRQsetSleep(bool sleeping); /** * Set the deleted flag of the thread. This flag can't be cleared. - * Can only be called with interrupts enabled or within an interrupt. + * Can only be called with interrupts disabled or within an interrupt. */ void IRQsetDeleted(); /** * Set the sleep flag of the thread. This flag can't be cleared. - * Can only be called with interrupts enabled or within an interrupt. + * Can only be called with interrupts disabled or within an interrupt. */ void IRQsetDeleting() { @@ -746,12 +770,22 @@ private: /** * Set the detached flag. This flag can't be cleared. - * Can only be called with interrupts enabled or within an interrupt. + * Can only be called with interrupts disabled or within an interrupt. */ void IRQsetDetached() { flags |= DETACHED; } + + /** + * Set the userspace flag of the thread. + * Can only be called with interrupts disabled or within an interrupt. + * \param sleeping if true the flag will be set, otherwise cleared + */ + void IRQsetUserspace(bool userspace) + { + if(userspace) flags |= USERSPACE; else flags &= ~USERSPACE; + } /** * \return true if the wait flag is set @@ -798,6 +832,12 @@ private: * \return true if the thread is waiting on a condition variable */ bool isWaitingCond() const { return flags & WAIT_COND; } + + /** + * \return true if the thread is running unprivileged inside a process. + * Only threads with proc!=null can run in userspace + */ + bool isInUserspace() const { return flags & USERSPACE; } private: ///\internal Thread is in the wait status. A call to wakeup will change @@ -823,9 +863,47 @@ private: ///\internal Thread is waiting on a condition variable static const unsigned int WAIT_COND=1<<6; + + ///\internal Thread is running in userspace + static const unsigned int USERSPACE=1<<7; unsigned short flags;///<\internal flags are stored here }; + + #ifdef WITH_PROCESSES + + /** + * \internal + * Causes a thread belonging to a process to switch to userspace, and + * execute userspace code. This function returns when the process performs + * a syscall or faults. + * \return the syscall parameters used to serve the system call. + */ + static miosix_private::SyscallParameters switchToUserspace(); + + /** + * Create a thread to be used inside a process. The thread is created in + * WAIT status, a wakeup() on it is required to actually start it. + * \param startfunc entry point + * \param argv parameter to be passed to the entry point + * \param options thread options + * \param proc process to which this thread belongs + */ + static Thread *createUserspace(void *(*startfunc)(void *), + void *argv, unsigned short options, Process *proc); + + /** + * Setup the userspace context of the thread, so that it can be later + * switched to userspace. Must be called only once for each thread instance + * \param entry userspace entry point + * \param gotBase base address of the GOT, also corresponding to the start + * of the RAM image of the process + * \param ramImageSize size of the process ram image + */ + static void setupUserspaceContext(unsigned int entry, unsigned int *gotBase, + unsigned int ramImageSize); + + #endif //WITH_PROCESSES /** * Constructor, initializes thread data. @@ -839,12 +917,16 @@ private: cReent(defaultReent), cppReent() { joinData.waitingForJoin=NULL; + #ifdef WITH_PROCESSES + proc=0; + userCtxsave=0; + #endif //WITH_PROCESSES } /** - * Destructor, does nothing. + * Destructor */ - ~Thread() {} + ~Thread(); /** * Helper function to initialize a Thread @@ -897,6 +979,14 @@ private: /// Per-thread instance of data to make the C and C++ libraries thread safe. CReentrancyData cReent; CppReentrancyData cppReent; + #ifdef WITH_PROCESSES + ///Process to which this thread belongs. Null if it is a kernel thread. + Process *proc; + ///Pointer to the set of saved registers for when the thread is running in + ///user mode. For kernel threads (i.e, threads where proc==null) this + ///pointer is null + unsigned int *userCtxsave; + #endif //WITH_PROCESSES //friend functions //Needs access to watermark, ctxsave @@ -932,6 +1022,10 @@ private: friend class CReentrancyAccessor; //Needs access to cppReent friend class CppReentrancyAccessor; + #ifdef WITH_PROCESSES + //Needs PKcreateUserspace(), setupUserspaceContext(), switchToUserspace() + friend class Process; + #endif //WITH_PROCESSES }; /** diff --git a/miosix/kernel/process.cpp b/miosix/kernel/process.cpp new file mode 100644 index 0000000000000000000000000000000000000000..edbaef3ff7c1945389d2691cc07b72416a429a7b --- /dev/null +++ b/miosix/kernel/process.cpp @@ -0,0 +1,488 @@ +/*************************************************************************** + * Copyright (C) 2012 by Terraneo Federico * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * As a special exception, if other files instantiate templates or use * + * macros or inline functions from this file, or you compile this file * + * and link it with other works to produce a work based on this file, * + * this file does not by itself cause the resulting work to be covered * + * by the GNU General Public License. However the source code for this * + * file must still be made available in accordance with the GNU General * + * Public License. This exception does not invalidate any other reasons * + * why a work based on this file might be covered by the GNU General * + * Public License. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, see <http://www.gnu.org/licenses/> * + ***************************************************************************/ + +#include <stdexcept> +#include <memory> +#include <cstdio> +#include <cstring> +#include <algorithm> +#include <sys/wait.h> +#include <signal.h> +#include <limits.h> + +#include "sync.h" +#include "process_pool.h" +#include "process.h" +#include "SystemMap.h" + +using namespace std; + +#ifdef WITH_PROCESSES + +/* + * List of implemented supervisor calls + * ------------------------------------ + * + * 0 : Yield. Can be called both by kernel threads and process threads both in + * userspace and kernelspace mode. It causes the scheduler to switch to + * another thread. It is the only SVC that is available also when processes + * are disabled in miosix_config.h. No parameters, no return value. + * 1 : Back to userspace. It is used by process threads running in kernelspace + * mode to return to userspace mode after completing a supervisor call. + * If called by a process thread already in userspace mode it does nothing. + * Use of this SVC is by kernel threads is forbidden. No parameters, no + * return value. + * 2 : Exit. Terminates the current process. One parameter, the exit code. + * Never returns. Use of this SVC is by kernel threads is forbidden. + * 3 : Write. Writes to stdout or a file. Three parameters, file descriptor, + * pointer to data to be written, size of data. Returns the number of + * written data or -1 on error. Use of this SVC is by kernel threads is + * forbidden. + * 4 : Read. Reads from stdin or a file. Three parameters, file descriptor, + * pointer to data buffer, size of buffer. Returns the number of + * read data or -1 on error. Use of this SVC is by kernel threads is + * forbidden. + * 5 : Usleep. One parameter, number of microseconds to sleep. Returns 0 on + * success, -1 on failure. Use of this SVC is by kernel threads isforbidden. + */ + +namespace miosix { + +// +// class Process +// + +pid_t Process::create(const ElfProgram& program) +{ + auto_ptr<Process> proc(new Process(program)); + { + Lock<Mutex> l(procMutex); + proc->pid=getNewPid(); + if(Thread::getCurrentThread()->proc!=0) + { + proc->ppid=Thread::getCurrentThread()->proc->pid; + Thread::getCurrentThread()->proc->childs.push_back(proc.get()); + } else { + proc->ppid=0; + kernelChilds.push_back(proc.get()); + } + processes[proc->pid]=proc.get(); + } + Thread *thr=Thread::createUserspace(Process::start,0,Thread::DEFAULT, + proc.get()); + if(thr==0) + { + Lock<Mutex> l(procMutex); + processes.erase(proc->pid); + if(Thread::getCurrentThread()->proc!=0) + { + Thread::getCurrentThread()->proc->childs.remove(proc.get()); + } else kernelChilds.remove(proc.get()); + throw runtime_error("Thread creation failed"); + } + //Cannot throw bad_alloc due to the reserve in Process's constructor. + //This ensures we will never be in the uncomfortable situation where a + //thread has already been created but there's no memory to list it + //among the threads of a process + proc->threads.push_back(thr); + thr->wakeup(); //Actually start the thread, now that everything is set up + pid_t result=proc->pid; + proc.release(); //Do not delete the pointer + return result; +} + +pid_t Process::getppid(pid_t proc) +{ + Lock<Mutex> l(procMutex); + map<pid_t,Process *>::iterator it=processes.find(proc); + if(it==processes.end()) return -1; + return it->second->ppid; +} + +pid_t Process::waitpid(pid_t pid, int* exit, int options) +{ + Lock<Mutex> l(procMutex); + Process *self=Thread::getCurrentThread()->proc; + if(self==0) + { + //The wait is performed by the kernel + if(pid<=0) + { + //Wait for a generic child process + if(kernelZombies.empty() && (options & WNOHANG)) return 0; + while(kernelZombies.empty()) + { + if(kernelChilds.empty()) return -1; + genericWaiting.wait(l); + } + Process *joined=kernelZombies.front(); + kernelZombies.pop_front(); + processes.erase(joined->pid); + if(joined->waitCount!=0) errorHandler(UNEXPECTED); + if(exit!=0) *exit=joined->exitCode; + pid_t result=joined->pid; + delete joined; + return result; + } else { + //Wait on a specific child process + map<pid_t,Process *>::iterator it=processes.find(pid); + if(it==processes.end() || it->second->ppid!=0) return -1; + Process *joined=it->second; + if(joined->zombie==false) + { + //Process hasn't terminated yet + if(options & WNOHANG) return 0; + joined->waitCount++; + joined->waiting.wait(l); + joined->waitCount--; + if(joined->waitCount<0 || joined->zombie==false) + errorHandler(UNEXPECTED); + } + //If multiple threads call waitpid on the same child, the last + //gets the return value, the other -1 + pid_t result=-1; + if(joined->waitCount==0) + { + if(exit!=0) *exit=joined->exitCode; + result=joined->pid; + kernelZombies.remove(joined); + processes.erase(joined->pid); + delete joined; + } + return result; + } + } else { + //The wait is performed by a process + if(pid<=0) + { + //Wait for a generic child process + if(self->zombies.empty() && (options & WNOHANG)) return 0; + while(self->zombies.empty()) + { + if(self->childs.empty()) return -1; + genericWaiting.wait(l); + } + Process *joined=self->zombies.front(); + self->zombies.pop_front(); + processes.erase(joined->pid); + if(joined->waitCount!=0) errorHandler(UNEXPECTED); + if(exit!=0) *exit=joined->exitCode; + pid_t result=joined->pid; + delete joined; + return result; + } else { + //Wait on a specific child process + map<pid_t,Process *>::iterator it=processes.find(pid); + if(it==processes.end() || it->second->ppid!=self->pid + || pid==self->pid) return -1; + Process *joined=it->second; + if(joined->zombie==false) + { + //Process hasn't terminated yet + if(options & WNOHANG) return 0; + joined->waitCount++; + joined->waiting.wait(l); + joined->waitCount--; + if(joined->waitCount<0 || joined->zombie==false) + errorHandler(UNEXPECTED); + } + pid_t result=-1; + if(joined->waitCount==0) + { + result=joined->pid; + if(exit!=0) *exit=joined->exitCode; + self->zombies.remove(joined); + processes.erase(joined->pid); + delete joined; + } + return result; + } + } +} + +Process::~Process() +{ + #ifdef __CODE_IN_XRAM + ProcessPool::instance().deallocate(loadedProgram); + #endif //__CODE_IN_XRAM + + //close alla opened files + for(set<int>::iterator it = mFiles.begin(); it != mFiles.end(); ++it) + close(*it); +} + +Process::Process(const ElfProgram& program) : program(program), waitCount(0), + zombie(false) +{ + //This is required so that bad_alloc can never be thrown when the first + //thread of the process will be stored in this vector + threads.reserve(1); + //Done here so if not enough memory the new process is not even created + image.load(program); + unsigned int elfSize=program.getElfSize(); + unsigned int roundedSize=elfSize; + //Allocatable blocks must be greater than ProcessPool::blockSize, and must + //be a power of two due to MPU limitations + if(elfSize<ProcessPool::blockSize) roundedSize=ProcessPool::blockSize; + else if(elfSize & (elfSize-1)) roundedSize=1<<ffs(elfSize); + #ifndef __CODE_IN_XRAM + //FIXME -- begin + //Till a flash file system that ensures proper alignment of the programs + //loaded in flash is implemented, make the whole flash visible as a big MPU + //region + extern unsigned char _end asm("_end"); + unsigned int flashEnd=reinterpret_cast<unsigned int>(&_end); + if(flashEnd & (flashEnd-1)) flashEnd=1<<ffs(flashEnd); + mpu=miosix_private::MPUConfiguration(0,flashEnd, + image.getProcessBasePointer(),image.getProcessImageSize()); +// mpu=miosix_private::MPUConfiguration(program.getElfBase(),roundedSize, +// image.getProcessBasePointer(),image.getProcessImageSize()); + //FIXME -- end + #else //__CODE_IN_XRAM + loadedProgram=ProcessPool::instance().allocate(roundedSize); + memcpy(loadedProgram,reinterpret_cast<char*>(program.getElfBase()),elfSize); + mpu=miosix_private::MPUConfiguration(loadedProgram,roundedSize, + image.getProcessBasePointer(),image.getProcessImageSize()); + #endif //__CODE_IN_XRAM +} + +void *Process::start(void *argv) +{ + Process *proc=Thread::getCurrentThread()->proc; + if(proc==0) errorHandler(UNEXPECTED); + unsigned int entry=proc->program.getEntryPoint(); + #ifdef __CODE_IN_XRAM + entry=entry-proc->program.getElfBase()+ + reinterpret_cast<unsigned int>(proc->loadedProgram); + #endif //__CODE_IN_XRAM + Thread::setupUserspaceContext(entry,proc->image.getProcessBasePointer(), + proc->image.getProcessImageSize()); + bool running=true; + do { + miosix_private::SyscallParameters sp=Thread::switchToUserspace(); + if(proc->fault.faultHappened()) + { + running=false; + proc->exitCode=SIGSEGV; //Segfault + #ifdef WITH_ERRLOG + iprintf("Process %d terminated due to a fault\n" + "* Code base address was 0x%x\n" + "* Data base address was %p\n",proc->pid, + #ifndef __CODE_IN_XRAM + proc->program.getElfBase(), + #else //__CODE_IN_XRAM + reinterpret_cast<unsigned int>(proc->loadedProgram), + #endif //__CODE_IN_XRAM + proc->image.getProcessBasePointer()); + proc->mpu.dumpConfiguration(); + proc->fault.print(); + #endif //WITH_ERRLOG + } else { + switch(sp.getSyscallId()) + { + case 2: + running=false; + proc->exitCode=(sp.getFirstParameter() & 0xff)<<8; + break; + case 3: + //FIXME: check that the pointer belongs to the process + + if((sp.getFirstParameter() >= 0 && sp.getFirstParameter() < 3) || //stdio + proc->mFiles.find(sp.getFirstParameter()) != proc->mFiles.end()){ //only on my files + + //check if pointer and pointer + size is within the mpu data region + if(!proc->mpu.within(sp.getSecondParameter()) || + !proc->mpu.within(sp.getSecondParameter() + sp.getThirdParameter())){ + running = false; + proc->exitCode = SIGSYS; + break; + } + + sp.setReturnValue(write(sp.getFirstParameter(), + reinterpret_cast<const char*>(sp.getSecondParameter()), + sp.getThirdParameter())); + } else + sp.setReturnValue(-1); + + break; + case 4: + if((sp.getFirstParameter() >= 0 && sp.getFirstParameter() < 3) || //stdio + proc->mFiles.find(sp.getFirstParameter())!= proc->mFiles.end()){ //only on my files + + //check if pointer and pointer + size is within the mpu data region + if(!proc->mpu.within(sp.getSecondParameter()) || + !proc->mpu.within(sp.getSecondParameter() + sp.getThirdParameter())){ + running = false; + proc->exitCode = SIGSYS; + break; + } + + sp.setReturnValue(read(sp.getFirstParameter(), + reinterpret_cast<char*>(sp.getSecondParameter()), + sp.getThirdParameter())); + } else + sp.setReturnValue(-1); + + break; + case 5: + sp.setReturnValue(usleep(sp.getFirstParameter())); + break; + #ifdef WITH_FILESYSTEM + case 6: + //open + { + unsigned int base = proc->mpu.getBaseDataAddress(); + unsigned int size = proc->mpu.getDataSize(); + + unsigned int maxLen = min(base + size - sp.getFirstParameter(), (unsigned int)PATH_MAX); + size_t filenameLen = strnlen(reinterpret_cast<const char*>(sp.getFirstParameter()), maxLen); + + if(!proc->mpu.within(sp.getFirstParameter()) || + !proc->mpu.within(sp.getFirstParameter() + filenameLen)){ + + proc->mpu.dumpConfiguration(); + + running = false; + proc->exitCode = SIGSYS; + break; + } + + int fd = open(reinterpret_cast<const char*>(sp.getFirstParameter()), //filename + sp.getSecondParameter(), //flags + sp.getThirdParameter()); //permission, used? + if (fd != -1) + proc->mFiles.insert(fd); + + sp.setReturnValue(fd); + } + break; + case 7: + //close + if(proc->mFiles.find(sp.getFirstParameter()) != proc->mFiles.end()){ + int ret = close(sp.getFirstParameter()); + + if(ret == 0) + proc->mFiles.erase(sp.getFirstParameter()); + + sp.setReturnValue(ret); + } else + sp.setReturnValue(-1); + break; + case 8: + //seek + if(proc->mFiles.find(sp.getFirstParameter()) != proc->mFiles.end()) + sp.setReturnValue(Filesystem::instance().lseekFile(sp.getFirstParameter(), + sp.getSecondParameter(), + sp.getThirdParameter())); + else + sp.setReturnValue(-1); + + break; + #endif //WITH_FILESYSTEM + case 9: + //system + { + std::pair<const unsigned int*, unsigned int> res = SystemMap::instance().getElfProgram(reinterpret_cast<const char*>(sp.getFirstParameter())); + + if(res.first == 0 || res.second == 0){ + iprintf("Program not found.\n"); + sp.setReturnValue(-1); + break; + } + + ElfProgram program(res.first, res.second); + int ret = 0; + + pid_t child = Process::create(program); + Process::waitpid(child, &ret, 0); + + sp.setReturnValue(WEXITSTATUS(ret)); + } + break; + default: + running=false; + proc->exitCode=SIGSYS; //Bad syscall + #ifdef WITH_ERRLOG + iprintf("Unexpected syscall number %d\n",sp.getSyscallId()); + #endif //WITH_ERRLOG + break; + } + } + if(Thread::testTerminate()) running=false; + } while(running); + { + Lock<Mutex> l(procMutex); + proc->zombie=true; + list<Process*>::iterator it; + for(it=proc->childs.begin();it!=proc->childs.end();++it) (*it)->ppid=0; + for(it=proc->zombies.begin();it!=proc->zombies.end();++it) (*it)->ppid=0; + kernelChilds.splice(kernelChilds.begin(),proc->childs); + kernelZombies.splice(kernelZombies.begin(),proc->zombies); + if(proc->ppid!=0) + { + map<pid_t,Process *>::iterator it=processes.find(proc->ppid); + if(it==processes.end()) errorHandler(UNEXPECTED); + it->second->childs.remove(proc); + if(proc->waitCount>0) proc->waiting.broadcast(); + else { + it->second->zombies.push_back(proc); + genericWaiting.broadcast(); + } + } else { + kernelChilds.remove(proc); + if(proc->waitCount>0) proc->waiting.broadcast(); + else { + kernelZombies.push_back(proc); + genericWaiting.broadcast(); + } + } + } + return 0; +} + +pid_t Process::getNewPid() +{ + for(;;pidCounter++) + { + if(pidCounter<0) pidCounter=1; + if(pidCounter==0) continue; //Zero is not a valid pid + map<pid_t,Process*>::iterator it=processes.find(pidCounter); + if(it!=processes.end()) continue; //Pid number already used + return pidCounter++; + } +} + +map<pid_t,Process*> Process::processes; +std::list<Process *> Process::kernelChilds; +std::list<Process *> Process::kernelZombies; +pid_t Process::pidCounter=1; +Mutex Process::procMutex; +ConditionVariable Process::genericWaiting; + +} //namespace miosix + +#endif //WITH_PROCESSES diff --git a/miosix/kernel/process.h b/miosix/kernel/process.h new file mode 100644 index 0000000000000000000000000000000000000000..466f0be9b1c99bb672078ba64d85f748e9f6c517 --- /dev/null +++ b/miosix/kernel/process.h @@ -0,0 +1,166 @@ +/*************************************************************************** + * Copyright (C) 2012 by Terraneo Federico * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * As a special exception, if other files instantiate templates or use * + * macros or inline functions from this file, or you compile this file * + * and link it with other works to produce a work based on this file, * + * this file does not by itself cause the resulting work to be covered * + * by the GNU General Public License. However the source code for this * + * file must still be made available in accordance with the GNU General * + * Public License. This exception does not invalidate any other reasons * + * why a work based on this file might be covered by the GNU General * + * Public License. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, see <http://www.gnu.org/licenses/> * + ***************************************************************************/ + +#ifndef PROCESS_H +#define PROCESS_H + +#include <vector> +#include <map> +#include <list> +#include <set> +#include <sys/types.h> +#include "kernel.h" +#include "sync.h" +#include "elf_program.h" +#include "config/miosix_settings.h" + +#ifdef WITH_PROCESSES + +namespace miosix { + +/** + * Process class, allows to create and handle processes + */ +class Process +{ +public: + /** + * Create a new process + * \param program Program that the process will execute + * \return the pid of the newly created process + * \throws std::exception or a subclass in case of errors, including + * not emough memory to spawn the process + */ + static pid_t create(const ElfProgram& program); + + /** + * Given a process, returns the pid of its parent. + * \param proc the pid of a process + * \return the pid of the parent process, or zero if the process was created + * by the kernel directly, or -1 if proc is not a valid process + */ + static pid_t getppid(pid_t proc); + + /** + * Wait for child process termination + * \param exit the process exit code will be returned here, if the pointer + * is not null + * \return the pid of the terminated process, or -1 in case of errors + */ + static pid_t wait(int *exit) { return waitpid(-1,exit,0); } + + /** + * Wait for a specific child process to terminate + * \param pid pid of the process, or -1 to wait for any child process + * \param exit the process exit code will be returned here, if the pointer + * is not null + * \param options only 0 and WNOHANG are supported + * \return the pid of the terminated process, or -1 in case of errors. In + * case WNOHANG is specified and the specified process has not terminated, + * 0 is returned + */ + static pid_t waitpid(pid_t pid, int *exit, int options); + + /** + * Destructor + */ + ~Process(); + +private: + Process(const Process&); + Process& operator= (const Process&); + + /** + * Constructor + * \param program program that will be executed by the process + */ + Process(const ElfProgram& program); + + /** + * Contains the process' main loop. + * \param argv ignored parameter + * \return null + */ + static void *start(void *argv); + + /** + * \return an unique pid that is not zero and is not already in use in the + * system, used to assign a pid to a new process.<br> + */ + static pid_t getNewPid(); + + ElfProgram program; ///<The program that is running inside the process + #ifdef __CODE_IN_XRAM + /// When __CODE_IN_XRAM is defined, the programs are loaded in the process + /// pool so the memory is aligned and the MPU works + unsigned int *loadedProgram; + #endif //__CODE_IN_XRAM + ProcessImage image; ///<The RAM image of a process + miosix_private::FaultData fault; ///< Contains information about faults + miosix_private::MPUConfiguration mpu; ///<Memory protection data + + std::vector<Thread *> threads; ///<Threads that belong to the process + std::list<Process *> childs; ///<Living child processes are stored here + std::list<Process *> zombies; ///<Dead child processes are stored here + std::set<int> mFiles; ///<Files openend by this process + pid_t pid; ///<The pid of this process + pid_t ppid; ///<The parent pid of this process + ///Contains the count of active wait calls which specifically requested + ///to wait on this process + int waitCount; + ///Active wait calls which specifically requested to wait on this process + ///wait on this condition variable + ConditionVariable waiting; + bool zombie; ///< True for terminated not yet joined processes + short int exitCode; ///< Contains the exit code + + ///Maps the pid to the Process instance. Includes zombie processes + static std::map<pid_t,Process *> processes; + static std::list<Process *> kernelChilds; + static std::list<Process *> kernelZombies; + ///Used to assign a new pid to a process + static pid_t pidCounter; + ///Uset to guard access to processes and pidCounter + static Mutex procMutex; + ///Used to wait on process termination + static ConditionVariable genericWaiting; + + //Needs access to fault,mpu + friend class Thread; + //Needs access to mpu + friend class PriorityScheduler; + //Needs access to mpu + friend class ControlScheduler; + //Needs access to mpu + friend class EDFScheduler; +}; + +} //namespace miosix + +#endif //WITH_PROCESSES + +#endif //PROCESS_H diff --git a/miosix/kernel/process_pool.cpp b/miosix/kernel/process_pool.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a3401f43f9e5d4cbb7ad86fb5fb6cad315b53de3 --- /dev/null +++ b/miosix/kernel/process_pool.cpp @@ -0,0 +1,158 @@ +/*************************************************************************** + * Copyright (C) 2012 by Terraneo Federico and Luigi Rucco * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * As a special exception, if other files instantiate templates or use * + * macros or inline functions from this file, or you compile this file * + * and link it with other works to produce a work based on this file, * + * this file does not by itself cause the resulting work to be covered * + * by the GNU General Public License. However the source code for this * + * file must still be made available in accordance with the GNU General * + * Public License. This exception does not invalidate any other reasons * + * why a work based on this file might be covered by the GNU General * + * Public License. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, see <http://www.gnu.org/licenses/> * + ***************************************************************************/ + +#include "process_pool.h" +#include <stdexcept> +#include <cstring> + +using namespace std; + +#ifdef WITH_PROCESSES + +namespace miosix { + +ProcessPool& ProcessPool::instance() +{ + #ifndef TEST_ALLOC + //These are defined in the linker script + extern unsigned int _process_pool_start asm("_process_pool_start"); + extern unsigned int _process_pool_end asm("_process_pool_end"); + static ProcessPool pool(&_process_pool_start, + reinterpret_cast<unsigned int>(&_process_pool_end)- + reinterpret_cast<unsigned int>(&_process_pool_start)); + return pool; + #else //TEST_ALLOC + static ProcessPool pool(reinterpret_cast<unsigned int*>(0x20008000),96*1024); + return pool; + #endif //TEST_ALLOC +} + +unsigned int *ProcessPool::allocate(unsigned int size) +{ + #ifndef TEST_ALLOC + miosix::Lock<miosix::FastMutex> l(mutex); + #endif //TEST_ALLOC + //If size is not a power of two, or too big or small + if((size & (size - 1)) || size>poolSize || size<blockSize) + throw runtime_error(""); + + unsigned int offset=0; + if(reinterpret_cast<unsigned int>(poolBase) % size) + offset=size-(reinterpret_cast<unsigned int>(poolBase) % size); + unsigned int startBit=offset/blockSize; + unsigned int sizeBit=size/blockSize; + + for(unsigned int i=startBit;i<=poolSize/blockSize;i+=sizeBit) + { + bool notEmpty=false; + for(unsigned int j=0;j<sizeBit;j++) + { + if(testBit(i+j)==0) continue; + notEmpty=true; + break; + } + if(notEmpty) continue; + + for(unsigned int j=0;j<sizeBit;j++) setBit(i+j); + unsigned int *result=poolBase+i*blockSize/sizeof(unsigned int); + allocatedBlocks[result]=size; + return result; + } + throw bad_alloc(); +} + +void ProcessPool::deallocate(unsigned int *ptr) +{ + #ifndef TEST_ALLOC + miosix::Lock<miosix::FastMutex> l(mutex); + #endif //TEST_ALLOC + map<unsigned int*, unsigned int>::iterator it= allocatedBlocks.find(ptr); + if(it==allocatedBlocks.end())throw runtime_error(""); + unsigned int size =(it->second)/blockSize; + unsigned int firstBit=(reinterpret_cast<unsigned int>(ptr)- + reinterpret_cast<unsigned int>(poolBase))/blockSize; + for(unsigned int i=firstBit;i<firstBit+size;i++) clearBit(i); + allocatedBlocks.erase(it); +} + +ProcessPool::ProcessPool(unsigned int *poolBase, unsigned int poolSize) + : poolBase(poolBase), poolSize(poolSize) +{ + int numBytes=poolSize/blockSize/8; + bitmap=new unsigned int[numBytes/sizeof(unsigned int)]; + memset(bitmap,0,numBytes); +} + +ProcessPool::~ProcessPool() +{ + delete[] bitmap; +} + +#ifdef TEST_ALLOC +int main() +{ + ProcessPool& pool=ProcessPool::instance(); + while(1) + { + cout<<"a<size(exponent)>|d<addr>"<<endl; + unsigned int param; + char op; + string line; + getline(cin,line); + stringstream ss(line); + ss>>op; + switch(op) + { + case 'a': + ss>>dec>>param; + try { + pool.allocate(1<<param); + } catch(exception& e) { + cout<<typeid(e).name(); + } + pool.printAllocatedBlocks(); + break; + case 'd': + ss>>hex>>param; + try { + pool.deallocate(reinterpret_cast<unsigned int*>(param)); + } catch(exception& e) { + cout<<typeid(e).name(); + } + pool.printAllocatedBlocks(); + break; + default: + cout<<"Incorrect option"<<endl; + break; + } + } +} +#endif //TEST_ALLOC + +} //namespace miosix + +#endif //WITH_PROCESSES diff --git a/miosix/kernel/process_pool.h b/miosix/kernel/process_pool.h new file mode 100644 index 0000000000000000000000000000000000000000..26f5d1561d303d3a5c5f568e14e81b426cfeaf37 --- /dev/null +++ b/miosix/kernel/process_pool.h @@ -0,0 +1,173 @@ +/*************************************************************************** + * Copyright (C) 2012 by Terraneo Federico and Luigi Rucco * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * As a special exception, if other files instantiate templates or use * + * macros or inline functions from this file, or you compile this file * + * and link it with other works to produce a work based on this file, * + * this file does not by itself cause the resulting work to be covered * + * by the GNU General Public License. However the source code for this * + * file must still be made available in accordance with the GNU General * + * Public License. This exception does not invalidate any other reasons * + * why a work based on this file might be covered by the GNU General * + * Public License. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, see <http://www.gnu.org/licenses/> * + ***************************************************************************/ + +#ifndef PROCESS_POOL +#define PROCESS_POOL + +#include <map> + +#ifndef TEST_ALLOC +#include <miosix.h> +#else //TEST_ALLOC +#include <iostream> +#include <typeinfo> +#include <sstream> +#endif //TEST_ALLOC + +#ifdef WITH_PROCESSES + +namespace miosix { + +/** + * This class allows to handle a memory area reserved for the allocation of + * processes' images. This memory area is called process pool. + */ +class ProcessPool +{ +public: + /** + * \return an instance of the process pool (singleton) + */ + static ProcessPool& instance(); + + /** + * Allocate memory inside the process pool. + * \param size size of the requested memory, must be a power of two, + * and be grater or equal to blockSize. + * \return a pointer to the allocated memory. Note that the pointer is + * size-aligned, so that for example if a 16KByte block is requested, + * the returned pointer is aligned on a 16KB boundary. This is so to + * allow using the MPU of the Cortex-M3. + * \throws runtime_error in case the requested allocation is invalid, + * or bad_alloc if out of memory + */ + unsigned int *allocate(unsigned int size); + + /** + * Deallocate a memory block. + * \param ptr pointer to deallocate. + * \throws runtime_error if the pointer is invalid + */ + void deallocate(unsigned int *ptr); + + #ifdef TEST_ALLOC + /** + * Print the state of the allocator, used for debugging + */ + void printAllocatedBlocks() + { + using namespace std; + map<unsigned int*, unsigned int>::iterator it; + cout<<endl; + for(it=allocatedBlocks.begin();it!=allocatedBlocks.end();it++) + cout <<"block of size " << it->second + << " allocated @ " << it->first<<endl; + + cout<<"Bitmap:"<<endl; + const int SHIFT = 8 * sizeof(unsigned int); + const unsigned int MASK = 1 << (SHIFT-1); + int bitarray[32]; + for(int i=0; i<(poolSize/blockSize)/(sizeof(unsigned int)*8);i++) + { + int value=bitmap[i]; + for ( int j = 0; j < SHIFT; j++ ) + { + bitarray[31-j]= ( value & MASK ? 1 : 0 ); + value <<= 1; + } + for(int j=0;j<32;j++) + cout<<bitarray[j]; + cout << endl; + } + } + #endif //TEST_ALLOC + + ///This constant specifies the size of the minimum allocatable block, + ///in bits. So for example 10 is 1KB. + static const unsigned int blockBits=10; + ///This constant is the the size of the minimum allocatable block, in bytes. + static const unsigned int blockSize=1<<blockBits; + +private: + ProcessPool(const ProcessPool&); + ProcessPool& operator= (const ProcessPool&); + + /** + * Constructor. + * \param poolBase address of the start of the process pool. + * \param poolSize size of the process pool. Must be a multiple of blockSize + */ + ProcessPool(unsigned int *poolBase, unsigned int poolSize); + + /** + * Destructor + */ + ~ProcessPool(); + + /** + * \param bit bit to test, from 0 to poolSize/blockSize + * \return true if the bit is set + */ + bool testBit(unsigned int bit) + { + return (bitmap[bit/(sizeof(unsigned int)*8)] & + 1<<(bit % (sizeof(unsigned int)*8))) ? true : false; + } + + /** + * \param bit bit to set, from 0 to poolSize/blockSize + */ + void setBit(unsigned int bit) + { + bitmap[(bit/(sizeof(unsigned int)*8))] |= + 1<<(bit % (sizeof(unsigned int)*8)); + } + + /** + * \param bit bit to clear, from 0 to poolSize/blockSize + */ + void clearBit(unsigned int bit) + { + bitmap[bit/(sizeof(unsigned int)*8)] &= + ~(1<<(bit % (sizeof(unsigned int)*8))); + } + + unsigned int *bitmap; ///< Pointer to the status of the allocator + unsigned int *poolBase; ///< Base address of the entire pool + unsigned int poolSize; ///< Size of the pool, in bytes + ///Lists all allocated blocks, allows to retrieve their sizes + std::map<unsigned int*,unsigned int> allocatedBlocks; + #ifndef TEST_ALLOC + miosix::FastMutex mutex; ///< Mutex to guard concurrent access + #endif //TEST_ALLOC +}; + +} //namespace miosix + +#endif //WITH_PROCESSES + +#endif //PROCESS_POOL diff --git a/miosix/kernel/scheduler/control/control_scheduler.cpp b/miosix/kernel/scheduler/control/control_scheduler.cpp index 659c2dec791507ffa8da99e9a3715f1d0576b95b..3be4cd723afbe27ce96d7b2fafb1a57688aaf092 100644 --- a/miosix/kernel/scheduler/control/control_scheduler.cpp +++ b/miosix/kernel/scheduler/control/control_scheduler.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2010, 2011 by Terraneo Federico * + * Copyright (C) 2010, 2011, 2012 by Terraneo Federico * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * @@ -27,6 +27,7 @@ #include "control_scheduler.h" #include "kernel/error.h" +#include "kernel/process.h" #include <limits> using namespace std; @@ -200,6 +201,9 @@ void ControlScheduler::IRQfindNextThread() curInRound=0; cur=idle; ctxsave=cur->ctxsave; + #ifdef WITH_PROCESSES + miosix_private::MPUConfiguration::IRQdisable(); + #endif miosix_private::AuxiliaryTimer::IRQsetValue(bIdle); return; } @@ -213,7 +217,18 @@ void ControlScheduler::IRQfindNextThread() { //Found a READY thread, so run this one cur=curInRound; + #ifdef WITH_PROCESSES + if(const_cast<Thread*>(cur)->flags.isInUserspace()==false) + { + ctxsave=cur->ctxsave; + miosix_private::MPUConfiguration::IRQdisable(); + } else { + ctxsave=cur->userCtxsave; + cur->proc->mpu.IRQenable(); + } + #else //WITH_PROCESSES ctxsave=cur->ctxsave; + #endif //WITH_PROCESSES miosix_private::AuxiliaryTimer::IRQsetValue( curInRound->schedData.bo/multFactor); return; diff --git a/miosix/kernel/scheduler/edf/edf_scheduler.cpp b/miosix/kernel/scheduler/edf/edf_scheduler.cpp index fa7ca01584d6dd095a9c716a612da5ae4dc77840..5eac0a0b159ab7527435b46ed421a7092979d833 100644 --- a/miosix/kernel/scheduler/edf/edf_scheduler.cpp +++ b/miosix/kernel/scheduler/edf/edf_scheduler.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2010, 2011 by Terraneo Federico * + * Copyright (C) 2010, 2011, 2012 by Terraneo Federico * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * @@ -27,6 +27,7 @@ #include "edf_scheduler.h" #include "kernel/error.h" +#include "kernel/process.h" #include <algorithm> using namespace std; @@ -115,7 +116,18 @@ void EDFScheduler::IRQfindNextThread() if(walk->flags.isReady()) { cur=walk; + #ifdef WITH_PROCESSES + if(const_cast<Thread*>(cur)->flags.isInUserspace()==false) + { + ctxsave=cur->ctxsave; + miosix_private::MPUConfiguration::IRQdisable(); + } else { + ctxsave=cur->userCtxsave; + cur->proc->mpu.IRQenable(); + } + #else //WITH_PROCESSES ctxsave=cur->ctxsave; + #endif //WITH_PROCESSES return; } walk=walk->schedData.next; diff --git a/miosix/kernel/scheduler/priority/priority_scheduler.cpp b/miosix/kernel/scheduler/priority/priority_scheduler.cpp index fe8845504a7cfee9e7e8959ee0fe79d873a4ee65..90c96295d107b68dcb16ad7283a459d66bc6b9e8 100644 --- a/miosix/kernel/scheduler/priority/priority_scheduler.cpp +++ b/miosix/kernel/scheduler/priority/priority_scheduler.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2010 by Terraneo Federico * + * Copyright (C) 2010, 2011, 2012 by Terraneo Federico * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * @@ -27,6 +27,7 @@ #include "priority_scheduler.h" #include "kernel/error.h" +#include "kernel/process.h" #ifdef SCHED_TYPE_PRIORITY @@ -209,7 +210,18 @@ void PriorityScheduler::IRQfindNextThread() { //Found a READY thread, so run this one cur=temp; + #ifdef WITH_PROCESSES + if(const_cast<Thread*>(cur)->flags.isInUserspace()==false) + { + ctxsave=cur->ctxsave; + miosix_private::MPUConfiguration::IRQdisable(); + } else { + ctxsave=cur->userCtxsave; + cur->proc->mpu.IRQenable(); + } + #else //WITH_PROCESSES ctxsave=temp->ctxsave; + #endif //WITH_PROCESSES //Rotate to next thread so that next time the list is walked //a different thread, if available, will be chosen first thread_list[i]=temp; @@ -221,6 +233,9 @@ void PriorityScheduler::IRQfindNextThread() //No thread found, run the idle thread cur=idle; ctxsave=idle->ctxsave; + #ifdef WITH_PROCESSES + miosix_private::MPUConfiguration::IRQdisable(); + #endif //WITH_PROCESSES } Thread *PriorityScheduler::thread_list[PRIORITY_MAX]={0}; diff --git a/miosix/util/util.cpp b/miosix/util/util.cpp index a67b6dd5c910e92bf261cc85e958fc4a3d24e6eb..dbf4f9cafc91348db4d0d8274eb0b950d79b21b4 100644 --- a/miosix/util/util.cpp +++ b/miosix/util/util.cpp @@ -75,23 +75,21 @@ unsigned int MemoryProfiling::getStackSize() unsigned int MemoryProfiling::getAbsoluteFreeStack() { - unsigned int count=0; const unsigned int *walk=miosix::Thread::getStackBottom(); - for(;;) + const unsigned int stackSize=miosix::Thread::getStackSize(); + unsigned int count=0; + while(count<stackSize && *walk==miosix::STACK_FILL) { //Count unused stack - if(*walk!=miosix::STACK_FILL) - { - //This takes in account CTXSAVE_ON_STACK. It might underestimate - //the absolute free stack (by a maximum of CTXSAVE_ON_STACK) but - //it will never overestimate it, which is important since this - //member function can be used to select stack sizes. - if(count<=CTXSAVE_ON_STACK) return 0; - return count-CTXSAVE_ON_STACK; - } walk++; count+=4; } + //This takes in account CTXSAVE_ON_STACK. It might underestimate + //the absolute free stack (by a maximum of CTXSAVE_ON_STACK) but + //it will never overestimate it, which is important since this + //member function can be used to select stack sizes. + if(count<=CTXSAVE_ON_STACK) return 0; + return count-CTXSAVE_ON_STACK; } unsigned int MemoryProfiling::getCurrentFreeStack()