diff --git a/ELF.h b/ELF.h new file mode 100644 index 0000000000000000000000000000000000000000..74eed133ada926e475911ab6ebb3ea14de279885 --- /dev/null +++ b/ELF.h @@ -0,0 +1,98 @@ +/* + * File: ELF.h + * Author: lr + * + * Created on March 3, 2012, 3:31 PM + */ + +#ifndef ELF_H +#define ELF_H + +#define EI_NIDENT 16 + +typedef unsigned long elf32_word; +typedef signed long elf32_sword; +typedef unsigned short elf32_half; +typedef unsigned long elf32_off; +typedef unsigned long elf32_addr; + +struct elf32_ehdr { + unsigned char e_ident[EI_NIDENT]; /* ident bytes */ + elf32_half e_type; /* file type */ + 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 */ +}; + +// Values for e_type +#define ET_NONE 0 /* Unknown type. */ +#define ET_REL 1 /* Relocatable. */ +#define ET_EXEC 2 /* Executable. */ +#define ET_DYN 3 /* Shared object. */ +#define ET_CORE 4 /* Core file. */ + +//values for e_machine + +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 +#define SHT_NULL 0 /* inactive */ +#define SHT_PROGBITS 1 /* program defined information */ +#define SHT_SYMTAB 2 /* symbol table section */ +#define SHT_STRTAB 3 /* string table section */ +#define SHT_RELA 4 /* relocation section with addends*/ +#define SHT_HASH 5 /* symbol hash table section */ +#define SHT_DYNAMIC 6 /* dynamic section */ +#define SHT_NOTE 7 /* note section */ +#define SHT_NOBITS 8 /* no space section */ +#define SHT_REL 9 /* relation section without addends */ +#define SHT_SHLIB 10 /* reserved - purpose unknown */ +#define SHT_DYNSYM 11 /* dynamic symbol table section */ +#define SHT_LOPROC 0x70000000 /* reserved range for processor */ +#define SHT_HIPROC 0x7fffffff /* specific section header types */ +#define SHT_LOUSER 0x80000000 /* reserved range for application */ +#define SHT_HIUSER 0xffffffff /* specific indexes */ + +struct elf32_rel { + elf32_addr r_offset; + elf32_word r_info; +}; + +struct elf32_rela { + elf32_addr r_offset; + elf32_word r_info; + elf32_sword r_addend; +}; + +struct elf32_sym { + elf32_word st_name; + elf32_addr st_value; + elf32_word st_size; + unsigned char st_info; + unsigned char st_other; + elf32_half st_shndx; +}; + + +#endif /* ELF_H */ + diff --git a/Makefile b/Makefile index 6c8092c395ce60ea16c806f71d2a1011ae067d4a..ff704950e17d5d22aa54f7338ad8df0698c43625 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,7 @@ SUBDIRS := miosix ## List here your source files (both .s, .c and .cpp) ## SRC := \ -main.cpp +main.cpp svc.s ## ## List here additional static libraries with relative path diff --git a/main.cpp b/main.cpp index 8764b9fabb7ead786e8a9eae3d8bd03873dc6ec4..c820fbadcd82b1485b118cdc54a1936c04151e30 100644 --- a/main.cpp +++ b/main.cpp @@ -1,11 +1,85 @@ #include <cstdio> #include "miosix.h" +#include "ELF.h" +#include "prog1.h" using namespace std; using namespace miosix; +extern "C" void syscallSupercazzola(int a, int b, int c); + +Thread *svcHandler=0; +Thread *blocked=0; + +void svcHandlerThread(void *) +{ + for(;;) + { + { + FastInterruptDisableLock dLock; + blocked=0; + for(;;) + { + if(blocked!=0) break; + Thread::getCurrentThread()->IRQwait(); + { + FastInterruptEnableLock eLock(dLock); + Thread::yield(); + } + } + } + + miosix_private::SyscallParameters sp=blocked->getSyscallParameters(); + if(sp.isValid()) + { + switch(sp.getSyscallId()) + { + case 1: + iprintf("Exit %d\n",sp.getFirstParameter()); + break; + case 2: + iprintf("Write called %d %x %d\n", + sp.getFirstParameter(), + sp.getSecondParameter(), + sp.getThirdParameter()); + write(sp.getFirstParameter(), + (const char*)sp.getSecondParameter(), + sp.getThirdParameter()); + blocked->wakeup(); + break; + } + } else { + iprintf("Unexpected invalid syscall\n"); + } + sp.invalidate(); + } +} + +void ledThread(void *) +{ + for(;;) + { + ledOn(); + Thread::sleep(200); + ledOff(); + Thread::sleep(200); + } +} + int main() { - //iprintf("Hello world, write your application here\n"); + Thread::create(ledThread,STACK_MIN); + svcHandler=Thread::create(svcHandlerThread,2048); + + const elf32_ehdr *elf=reinterpret_cast<const elf32_ehdr*>(main_elf); + unsigned int base=reinterpret_cast<unsigned int>(main_elf); + base+=+elf->e_entry; + void (*elfentry)(void*)=reinterpret_cast<void (*)(void*)>(base); + iprintf("elf base address = %p\n",main_elf); + iprintf("elf entry is = %p\n",elf->e_entry); + iprintf("elf entry (absolute) is = %p\n",elfentry); + + Thread::create(elfentry,2048); + for(;;) Thread::sleep(1000); } diff --git a/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/portability.cpp b/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/portability.cpp index c82fa7f5b11a057816feec6da4c981a71926944b..721fe8b8ac6d81ee926702c829a9acecfadd861e 100644 --- a/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/portability.cpp +++ b/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/portability.cpp @@ -85,6 +85,9 @@ void TIM3_IRQHandler() } #endif //SCHED_TYPE_CONTROL_BASED +extern miosix::Thread *svcHandler; +extern miosix::Thread *blocked; + namespace miosix_private { /** @@ -98,7 +101,7 @@ void ISR_preempt() __attribute__((noinline)); void ISR_preempt() { IRQstackOverflowCheck(); - miosix::IRQtickInterrupt(); + miosix::IRQtickInterrupt(); } /** @@ -112,6 +115,25 @@ void ISR_yield() __attribute__((noinline)); void ISR_yield() { IRQstackOverflowCheck(); + + #ifdef WITH_PROCESSES + //If processes are enabled, check the content of r3. If zero then it + //it is a simple yield, otherwise pause the thread and wake the svcHandler + unsigned int threadSp=miosix::cur->ctxsave[0]; + unsigned int *processStack=reinterpret_cast<unsigned int*>(threadSp); + if(processStack[3]!=0) + { + blocked=const_cast<miosix::Thread*>(miosix::cur); + blocked->IRQwait(); + blocked->syscallParameters.registers=processStack; + blocked->syscallParameters.valid=true; + if(svcHandler==0) miosix::errorHandler(miosix::UNEXPECTED); + svcHandler->IRQwakeup(); + } + #endif //WITH_PROCESSES + + //Note: this still has to be called even when r3!=0, since without this + //call the blocked->IRQwait() would not become effective miosix::Scheduler::IRQfindNextThread(); } 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..d01c03f1e9e973fc2e29dda53d915221f040da45 100644 --- a/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/portability_impl.h +++ b/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/portability_impl.h @@ -102,7 +102,9 @@ namespace miosix_private { inline void doYield() { - asm volatile("svc 0"); + asm volatile("movs r3, #0\n\t" + "svc 0" + :::"r1"); } inline void doDisableInterrupts() @@ -132,6 +134,68 @@ inline bool checkAreInterruptsEnabled() return true; } +#ifdef WITH_PROCESSES + +void ISR_yield(); //FIXME: make private again + +/** + * This class allows to access the parameters that a process passed to + * the operating system as part of a system call + */ +class SyscallParameters +{ +public: + /** + * Default constructor, generates an invalid syscall + */ + SyscallParameters() : valid(false) {} + + /** + * \return true if this object represent an actual pending syscall, + * false if it represent a special state in which no syscall is pending + * and therefore the value returned by all the other member functions of + * this class are invalid + */ + bool isValid() const { return valid; } + + /** + * \return the syscall id, used to identify individual system calls + */ + int getSyscallId() const { return registers[3]; } + + /** + * \return the first syscall parameter. The returned result is meaningful + * only if the syscall (identified throug its id) has one or more parameters + */ + unsigned int getFirstParameter() const { return registers[0]; } + + /** + * \return the first syscall parameter. The returned result is meaningful + * only if the syscall (identified throug its id) has two or more parameters + */ + unsigned int getSecondParameter() const { return registers[1]; } + + /** + * \return the first syscall parameter. The returned result is meaningful + * only if the syscall (identified throug its id) has three parameters + */ + unsigned int getThirdParameter() const { return registers[2]; } + + /** + * Invalidate the object. Meant to be called after the syscall has been + * serviced + */ + void invalidate() { valid=false; } + +private: + unsigned int *registers; + bool valid; + + friend void ISR_yield(); +}; + +#endif //WITH_PROCESSES + /** * \} */ diff --git a/miosix/config/miosix_settings.h b/miosix/config/miosix_settings.h index 879e4424ba23ff24ee989c90f4a4da29d74a0f90..766971c833df84e327f9f527bda691b8f0cac101 100644 --- a/miosix/config/miosix_settings.h +++ b/miosix/config/miosix_settings.h @@ -61,6 +61,13 @@ 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 // // Filesystem options diff --git a/miosix/kernel/kernel.h b/miosix/kernel/kernel.h index 9f3849422390938629cdcc76dc0f1666d8f6cc06..63c4d96cf69b2797ddc5eab76954beb193250d3f 100644 --- a/miosix/kernel/kernel.h +++ b/miosix/kernel/kernel.h @@ -689,6 +689,16 @@ public: * \return the size of the stack of the current thread. */ static const int getStackSize(); + + #ifdef WITH_PROCESSES + /** + * \return the syscall parameters + */ + miosix_private::SyscallParameters& getSyscallParameters() + { + return syscallParameters; + } + #endif //WITH_PROCESSES private: //Unwanted methods @@ -894,6 +904,9 @@ private: } joinData; /// Per-thread instance of data to make C++ exception handling thread safe. ExceptionHandlingData exData; + #ifdef WITH_PROCESSES + miosix_private::SyscallParameters syscallParameters; + #endif //WITH_PROCESSES //friend functions //Needs access to watermark, ctxsave @@ -906,6 +919,8 @@ private: friend void *idleThread(void *argv); //Needs to create the idle thread friend void startKernel(); + //Needs ctxsave, syscallParameters + friend void miosix_private::ISR_yield(); //Needs threadLauncher friend void miosix_private::initCtxsave(unsigned int *ctxsave, void *(*pc)(void *), unsigned int *sp, void *argv); diff --git a/miosix_np_2/nbproject/configurations.xml b/miosix_np_2/nbproject/configurations.xml index 6d64703629e4cd82ebafa6c3f39c976abfa372c7..4d098f315fdce5dbca50234b93e9190d3623bbab 100644 --- a/miosix_np_2/nbproject/configurations.xml +++ b/miosix_np_2/nbproject/configurations.xml @@ -307,6 +307,7 @@ <df name="miosix_np_2"> </df> <in>main.cpp</in> + <in>svc.s</in> </df> <logicalFolder name="ExternalFiles" displayName="Important Files" diff --git a/prog1.h b/prog1.h new file mode 100644 index 0000000000000000000000000000000000000000..000891f6c699364514bd43eee23040a80f1c6f56 --- /dev/null +++ b/prog1.h @@ -0,0 +1,29 @@ +const unsigned char 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, 0x90, 0x00, 0x00, 0x00, + 0x90, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x10, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0xf0, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, + 0x38, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x0c, 0xf8, + 0x00, 0xf0, 0x1a, 0xf8, 0x03, 0x78, 0x23, 0xb1, 0x00, 0x23, 0x01, 0x33, + 0xc2, 0x5c, 0x00, 0x2a, 0xfb, 0xd1, 0x18, 0x46, 0x70, 0x47, 0x00, 0xbf, + 0x10, 0xb5, 0x06, 0x4c, 0x4c, 0x44, 0x20, 0x46, 0xff, 0xf7, 0xf0, 0xff, + 0x21, 0x46, 0x02, 0x46, 0x01, 0x20, 0x00, 0xf0, 0x07, 0xf8, 0x00, 0x20, + 0x10, 0xbd, 0x00, 0xbf, 0xe0, 0x00, 0x00, 0xf0, 0x01, 0x23, 0x00, 0xdf, + 0x02, 0x23, 0x00, 0xdf, 0x70, 0x47, 0x00, 0x00, 0x48, 0x65, 0x6c, 0x6c, + 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +unsigned int main_elf_len = 308; diff --git a/svc.s b/svc.s new file mode 100644 index 0000000000000000000000000000000000000000..056d89eabf9d5ecafa1c393f1c4144d573e6153e --- /dev/null +++ b/svc.s @@ -0,0 +1,16 @@ + +.syntax unified +.cpu cortex-m3 +.thumb + +.section .text + +/** + * syscallSupercazzola + */ +.global syscallSupercazzola +.type syscallSupercazzola, %function +syscallSupercazzola: + movs r3, #1 + svc 0 + bx lr