From eed1c74b1a4198f0125090abd844acaa9c2af83d Mon Sep 17 00:00:00 2001
From: Andrea <andrea.ponte1987@gmail.com>
Date: Mon, 17 Dec 2012 17:30:00 +0100
Subject: [PATCH] New system calls: open, close, seek, system added.

---
 .directory                                    |    3 +
 .gitignore                                    |   10 +
 app_template/crt0.s                           |   53 +
 app_template/log.txt                          |    5 +
 app_template/main.c                           |   71 +-
 app_template/main.map                         |  139 +
 app_template/main.txt                         |  405 ++
 app_template/prog3.h                          |   91 +-
 app_template_withlibs/main.map                |    6 +
 chg.patch                                     | 3313 +++++++++++++++++
 log.txt                                       |    5 +
 main.cpp                                      |   10 +
 miosix/Makefile                               |    1 +
 .../common/interfaces-impl/disk.cpp           |   27 +-
 .../common/interfaces-impl/portability.cpp    |    9 +-
 miosix/compiler/cleanup.sh                    |    0
 miosix/compiler/download.sh                   |    0
 miosix/compiler/install-script.sh             |    0
 miosix/compiler/mx-postlinker/Makefile        |    4 +-
 miosix/compiler/uninstall.sh                  |    0
 miosix/kernel/SystemMap.cpp                   |   66 +
 miosix/kernel/SystemMap.h                     |   34 +
 miosix/kernel/filesystem/ff.c                 |    3 +-
 miosix/kernel/filesystem/filesystem.cpp       |   17 +-
 miosix/kernel/process.cpp                     |   63 +-
 miosix/kernel/process.h                       |    2 +
 miosix/kernel/syscalls.cpp                    |    4 +-
 miosix/util/util.cpp                          |    7 +
 miosix/util/util.h                            |    9 +
 .../nbproject/configurations.xml              |  569 ++-
 .../nbproject/private/configurations.xml      |    2 +-
 .../nbproject/private/private.xml             |    7 +
 .../stm32f207ig_stm3220g-eval.properties      |    0
 sd.patch                                      |   59 +
 system_app_test/Makefile                      |   44 +
 system_app_test/crt0.o                        |  Bin 0 -> 1464 bytes
 system_app_test/crt0.s                        |  130 +
 system_app_test/log.txt                       |    5 +
 system_app_test/main.c                        |   20 +
 system_app_test/main.c~                       |   51 +
 system_app_test/main.elf                      |  Bin 0 -> 220 bytes
 system_app_test/main.map                      |  128 +
 system_app_test/miosix.ld                     |   66 +
 system_app_test/prog3.h                       |   22 +
 system_app_test/test.txt                      |   76 +
 45 files changed, 5472 insertions(+), 64 deletions(-)
 create mode 100644 .directory
 create mode 100644 .gitignore
 create mode 100644 app_template/log.txt
 create mode 100644 app_template/main.map
 create mode 100644 app_template/main.txt
 create mode 100644 app_template_withlibs/main.map
 create mode 100644 chg.patch
 create mode 100644 log.txt
 mode change 100644 => 100755 miosix/compiler/cleanup.sh
 mode change 100644 => 100755 miosix/compiler/download.sh
 mode change 100644 => 100755 miosix/compiler/install-script.sh
 mode change 100644 => 100755 miosix/compiler/uninstall.sh
 create mode 100644 miosix/kernel/SystemMap.cpp
 create mode 100644 miosix/kernel/SystemMap.h
 create mode 100644 miosix_np_processes/nbproject/private/stm32f207ig_stm3220g-eval.properties
 create mode 100644 sd.patch
 create mode 100644 system_app_test/Makefile
 create mode 100644 system_app_test/crt0.o
 create mode 100644 system_app_test/crt0.s
 create mode 100644 system_app_test/log.txt
 create mode 100644 system_app_test/main.c
 create mode 100644 system_app_test/main.c~
 create mode 100755 system_app_test/main.elf
 create mode 100644 system_app_test/main.map
 create mode 100644 system_app_test/miosix.ld
 create mode 100644 system_app_test/prog3.h
 create mode 100644 system_app_test/test.txt

diff --git a/.directory b/.directory
new file mode 100644
index 00000000..3c542a57
--- /dev/null
+++ b/.directory
@@ -0,0 +1,3 @@
+[Dolphin]
+Timestamp=2012,12,17,17,4,38
+Version=3
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000..d08a834f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,10 @@
+*/nbproject/
+*.bz2
+*.gz
+*.o
+*.a
+*.elf
+*.map
+*.hex
+*.bin
+*~
diff --git a/app_template/crt0.s b/app_template/crt0.s
index 2eba4bfa..d02fabab 100644
--- a/app_template/crt0.s
+++ b/app_template/crt0.s
@@ -31,6 +31,59 @@ _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
diff --git a/app_template/log.txt b/app_template/log.txt
new file mode 100644
index 00000000..947e1fa9
--- /dev/null
+++ b/app_template/log.txt
@@ -0,0 +1,5 @@
+arm-miosix-eabi-g++ -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 -fPIC -o main.elf main.o crt0.o -Wl,--start-group -lstdc++ -lc -lm -lgcc -Wl,--end-group
+/opt/arm-miosix-eabi/lib/gcc/arm-eabi/4.5.2/../../../../arm-eabi/bin/ld: /opt/arm-miosix-eabi/lib/gcc/arm-eabi/4.5.2/../../../../arm-eabi/lib/thumb/thumb2/libc.a(lib_a-syslseek.o): relocation R_ARM_THM_MOVW_ABS_NC against `_impure_ptr' can not be used when making a shared object; recompile with -fPIC
+/opt/arm-miosix-eabi/lib/gcc/arm-eabi/4.5.2/../../../../arm-eabi/lib/thumb/thumb2/libc.a: could not read symbols: Bad value
+collect2: ld returned 1 exit status
+make: *** [all] Error 1
diff --git a/app_template/main.c b/app_template/main.c
index 109e99de..2e3bcb22 100644
--- a/app_template/main.c
+++ b/app_template/main.c
@@ -1,6 +1,11 @@
-
 #include <unistd.h>
 
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdio.h>
+
 int mystrlen(const char *s)
 {
 	int result=0;
@@ -10,8 +15,25 @@ int mystrlen(const char *s)
 
 int main()
 {
-	static const char str[]="0=divzero 1=sleep 5s, 2=exit 3=bkpt 4=dangling\n";
+	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";
+	
+	/*
+	char strTest[500] = {'a'};
+	
+	strTest[0] = 0;
+	
+	int c = (int)strTest[0];
+	
+	unsigned int *p = &i;
+	
+	p -= 567;
+	
+	*p = 0x00;
+	*/
+	
 	for(;;)
 	{
 		char result[100];
@@ -20,6 +42,9 @@ int main()
 		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':
@@ -36,6 +61,48 @@ int main()
 			case '4':
 				usleep(*p);
 				break;
+			case '5':
+				fp = open("/test.txt", O_RDWR|O_TRUNC, 0);
+				
+				if(fp != 0){
+					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/main.map b/app_template/main.map
new file mode 100644
index 00000000..333d4b33
--- /dev/null
+++ b/app_template/main.map
@@ -0,0 +1,139 @@
+
+Discarded input sections
+
+ .text          0x0000000000000000        0x0 main.o
+ .data          0x0000000000000000        0x0 main.o
+ .bss           0x0000000000000000        0x0 main.o
+ .text.mystrlen
+                0x0000000000000000       0x14 main.o
+ .comment       0x0000000000000000       0x12 main.o
+ .ARM.attributes
+                0x0000000000000000       0x31 main.o
+ .data          0x0000000000000000        0x0 crt0.o
+ .bss           0x0000000000000000        0x0 crt0.o
+ .ARM.attributes
+                0x0000000000000000       0x21 crt0.o
+
+Memory Configuration
+
+Name             Origin             Length             Attributes
+*default*        0x0000000000000000 0xffffffffffffffff
+
+Linker script and memory map
+
+                0x0000000000000094                . = (0x0 + SIZEOF_HEADERS)
+
+.text           0x0000000000000098      0x1f2
+ *(.text)
+ .text          0x0000000000000098        0x8 crt0.o
+                0x0000000000000098                _start
+ *(.text.*)
+ .text.main     0x00000000000000a0      0x1bc main.o
+                0x00000000000000a0                main
+ .text._exit    0x000000000000025c        0x4 crt0.o
+                0x000000000000025c                _exit
+ .text.open     0x0000000000000260        0x6 crt0.o
+                0x0000000000000260                open
+ .text.close    0x0000000000000266        0x6 crt0.o
+                0x0000000000000266                close
+ .text.seek     0x000000000000026c        0x6 crt0.o
+                0x000000000000026c                seek
+ .text.system   0x0000000000000272        0x6 crt0.o
+                0x0000000000000272                system
+ .text.write    0x0000000000000278        0x6 crt0.o
+                0x0000000000000278                write
+ .text.read     0x000000000000027e        0x6 crt0.o
+                0x000000000000027e                read
+ .text.usleep   0x0000000000000284        0x6 crt0.o
+                0x0000000000000284                usleep
+ *(.gnu.linkonce.t.*)
+
+.glue_7         0x000000000000028c        0x0
+ .glue_7        0x0000000000000000        0x0 linker stubs
+
+.glue_7t        0x000000000000028c        0x0
+ .glue_7t       0x0000000000000000        0x0 linker stubs
+
+.vfp11_veneer   0x000000000000028c        0x0
+ .vfp11_veneer  0x0000000000000000        0x0 linker stubs
+
+.v4_bx          0x000000000000028c        0x0
+ .v4_bx         0x0000000000000000        0x0 linker stubs
+
+.plt            0x000000000000028c        0x0
+ .plt           0x0000000000000000        0x0 main.o
+
+.rel.dyn        0x000000000000028c        0x0
+ .rel.plt       0x0000000000000000        0x0 main.o
+
+.rel.data
+ *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*)
+
+.rel.got        0x000000000000028c        0x0
+ *(.rel.got)
+ .rel.got       0x0000000000000000        0x0 main.o
+                0x0000000010000000                . = 0x10000000
+
+.got            0x0000000010000000        0xc
+ *(.got.plt)
+ .got.plt       0x0000000010000000        0xc main.o
+                0x0000000010000000                _GLOBAL_OFFSET_TABLE_
+ *(.igot.plt)
+ *(.got)
+ .got           0x0000000000000000        0x0 main.o
+ *(.igot)
+
+.dynamic        0x000000001000000c       0x28
+ *(.dynamic)
+ .dynamic       0x000000001000000c       0x28 main.o
+                0x000000001000000c                _DYNAMIC
+
+.rodata         0x0000000010000038       0xd8
+ *(.rodata)
+ .rodata        0x0000000010000038       0x84 main.o
+ *(.rodata.*)
+ .rodata.str1.4
+                0x00000000100000bc       0x54 main.o
+ *(.gnu.linkonce.r.*)
+
+.gnu.version_d  0x0000000010000110        0x0
+ .gnu.version_d
+                0x0000000000000000        0x0 main.o
+
+.gnu.version    0x0000000010000110        0x0
+ .gnu.version   0x0000000000000000        0x0 main.o
+
+.gnu.version_r  0x0000000010000110        0x0
+ .gnu.version_r
+                0x0000000000000000        0x0 main.o
+
+.data
+ *(.data)
+ *(.data.*)
+ *(.gnu.linkonce.d.*)
+
+.bss
+ *(.bss)
+ *(.bss.*)
+ *(.gnu.linkonce.b.*)
+ *(COMMON)
+
+.dynbss         0x0000000010000110        0x0
+ .dynbss        0x0000000000000000        0x0 main.o
+
+/DISCARD/
+ *(.interp)
+ *(.dynsym)
+ *(.dynstr)
+ *(.hash)
+ *(.comment)
+ *(.ARM.attributes)
+LOAD main.o
+LOAD crt0.o
+START GROUP
+LOAD /opt/arm-miosix-eabi/lib/gcc/arm-eabi/4.5.2/../../../../arm-eabi/lib/thumb/thumb2/libstdc++.a
+LOAD /opt/arm-miosix-eabi/lib/gcc/arm-eabi/4.5.2/../../../../arm-eabi/lib/thumb/thumb2/libc.a
+LOAD /opt/arm-miosix-eabi/lib/gcc/arm-eabi/4.5.2/../../../../arm-eabi/lib/thumb/thumb2/libm.a
+LOAD /opt/arm-miosix-eabi/lib/gcc/arm-eabi/4.5.2/thumb/thumb2/libgcc.a
+END GROUP
+OUTPUT(main.elf elf32-littlearm)
diff --git a/app_template/main.txt b/app_template/main.txt
new file mode 100644
index 00000000..f6aa0391
--- /dev/null
+++ b/app_template/main.txt
@@ -0,0 +1,405 @@
+
+main.elf:     file format elf32-littlearm
+main.elf
+architecture: arm, flags 0x00000050:
+HAS_SYMS, DYNAMIC
+start address 0x00000099
+
+Program Header:
+    LOAD off    0x00000098 vaddr 0x00000098 paddr 0x00000098 align 2**3
+         filesz 0x000001f2 memsz 0x000001f2 flags r-x
+    LOAD off    0x00000290 vaddr 0x10000000 paddr 0x10000000 align 2**3
+         filesz 0x00000110 memsz 0x00000110 flags rw-
+ DYNAMIC off    0x0000029c 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         000001f2  00000098  00000098  00000098  2**3
+                  CONTENTS, ALLOC, LOAD, READONLY, CODE
+  1 .got          0000000c  10000000  10000000  00000290  2**2
+                  CONTENTS, ALLOC, LOAD, DATA
+  2 .dynamic      00000028  1000000c  1000000c  0000029c  2**2
+                  CONTENTS, ALLOC, LOAD, DATA
+  3 .rodata       000000d8  10000038  10000038  000002c8  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
+10000038 l     O .rodata	00000051 str.2690
+1000008c l     O .rodata	0000001b okMsg.2692
+100000a8 l     O .rodata	00000014 str2.2691
+1000000c l     O *ABS*	00000000 _DYNAMIC
+10000000 l     O *ABS*	00000000 _GLOBAL_OFFSET_TABLE_
+00000284 g     F .text	00000000 usleep
+00000272 g     F .text	00000000 system
+00000278 g     F .text	00000000 write
+00000098 g     F .text	00000000 _start
+0000027e g     F .text	00000000 read
+000000a0 g     F .text	000001bc main
+0000026c g     F .text	00000000 seek
+0000025c g     F .text	00000000 _exit
+00000260 g     F .text	00000000 open
+00000266 g     F .text	00000000 close
+
+
+Contents of section .text:
+ 0098 00f002f8 00f0def8 2de9f04d dff89081  ........-..M....
+ 00a8 644fdff8 94a1dff8 94b19cb0 644d03ae  dO..........dM..
+ 00b8 c8444f44 ca44cb44 09eb0503 002213f8  .DOD.D.D....."..
+ 00c8 014f0132 002cfad1 09eb0501 012000f0  .O.2.,....... ..
+ 00d8 cff86422 20463146 00f0cdf8 0028ebdd  ..d" F1F.....(..
+ 00e8 9df80c30 303b062b 74d8dfe8 03f06c65  ...00;.+t.....le
+ 00f8 615f5908 04004046 00f0b7f8 dce73846  a_Y...@F......8F
+ 0108 40f20241 002200f0 a7f80446 0028d3d0  @..A.".....F.(..
+ 0118 0c220120 514600f0 abf80422 20465946  .". QF....." FYF
+ 0128 00f0a6f8 042870d0 00210191 00210a46  .....(p..!...!.F
+ 0138 204600f0 97f84349 03222046 494400f0   F....CI." FID..
+ 0148 97f80328 6ad00022 11462046 00f08af8  ...(j..".F F....
+ 0158 64222046 314600f0 8ef80428 4ad02046  d" F1F.....(J. F
+ 0168 00f07df8 04460028 a6d13749 01204944  ..}..F.(..7I. ID
+ 0178 092200f0 7df80199 41f00403 072b9bd1  ."..}...A....+..
+ 0188 09eb0503 54332246 13f8011f 01320029  ....T3"F.....2.)
+ 0198 fad109eb 05015431 012000f0 69f88be7  ......T1. ..i...
+ 01a8 4ff04043 186800f0 69f885e7 00be83e7  O.@C.h..i.......
+ 01b8 00201cb0 bde8f08d 44f64030 c0f24c00  . ......D.@0..L.
+ 01c8 00f05cf8 78e70023 0a2090fb f3f000f0  ..\.x..#. ......
+ 01d8 55f871e7 09eb0503 70330022 13f8011f  U.q.....p3."....
+ 01e8 01320029 fad109eb 05017031 012000f0  .2.)......p1. ..
+ 01f8 3ff861e7 15490120 49440822 00f038f8  ?.a..I. ID."..8.
+ 0208 019b43f0 02030193 a9e71149 01204944  ..C........I. ID
+ 0218 092200f0 2df80123 019387e7 0c490922  ."..-..#.....I."
+ 0228 01204944 00f024f8 01220192 8be700bf  . ID..$.."......
+ 0238 08010000 bc000000 c8000000 d8000000  ................
+ 0248 38000000 ec000000 fc000000 f0000000  8...............
+ 0258 e0000000 022300df 062300df 70470723  .....#...#..pG.#
+ 0268 00df7047 082300df 70470923 00df7047  ..pG.#..pG.#..pG
+ 0278 032300df 70470423 00df7047 052300df  .#..pG.#..pG.#..
+ 0288 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 54657374 20617070 6c696361 74696f6e  Test application
+ 10000048 3a0a303d 6469767a 65726f0a 313d736c  :.0=divzero.1=sl
+ 10000058 65657020 35730a32 3d657869 740a333d  eep 5s.2=exit.3=
+ 10000068 626b7074 0a343d64 616e676c 696e670a  bkpt.4=dangling.
+ 10000078 353d6f70 656e0a36 3d737973 74656d0a  5=open.6=system.
+ 10000088 00000000 45766572 79746869 6e672773  ....Everything's
+ 10000098 20736869 6e792c20 43617027 6e0a0000   shiny, Cap'n...
+ 100000a8 556e6578 70656374 65642063 6f6d6d61  Unexpected comma
+ 100000b8 6e640a00 2f746573 742e7478 74000000  nd../test.txt...
+ 100000c8 46696c65 206f7065 6e65640a 00000000  File opened.....
+ 100000d8 6369616f 00000000 57726974 65206f6b  ciao....Write ok
+ 100000e8 0a000000 31323300 52656164 206f6b0a  ....123.Read ok.
+ 100000f8 00000000 436c6f73 65206f6b 0a000000  ....Close ok....
+ 10000108 74657374 00000000                    test....        
+
+Disassembly of section .text:
+
+00000098 <_start>:
+_start():
+  98:	f000 f802 	bl	a0 <main>
+  9c:	f000 f8de 	bl	25c <_exit>
+
+000000a0 <main>:
+main():
+  a0:	e92d 4df0 	stmdb	sp!, {r4, r5, r6, r7, r8, sl, fp, lr}
+  a4:	f8df 8190 	ldr.w	r8, [pc, #400]	; 238 <main+0x198>
+  a8:	4f64      	ldr	r7, [pc, #400]	; (23c <main+0x19c>)
+  aa:	f8df a194 	ldr.w	sl, [pc, #404]	; 240 <main+0x1a0>
+  ae:	f8df b194 	ldr.w	fp, [pc, #404]	; 244 <main+0x1a4>
+  b2:	b09c      	sub	sp, #112	; 0x70
+  b4:	4d64      	ldr	r5, [pc, #400]	; (248 <main+0x1a8>)
+  b6:	ae03      	add	r6, sp, #12
+  b8:	44c8      	add	r8, r9
+  ba:	444f      	add	r7, r9
+  bc:	44ca      	add	sl, r9
+  be:	44cb      	add	fp, r9
+  c0:	eb09 0305 	add.w	r3, r9, r5
+  c4:	2200      	movs	r2, #0
+  c6:	f813 4f01 	ldrb.w	r4, [r3, #1]!
+  ca:	3201      	adds	r2, #1
+  cc:	2c00      	cmp	r4, #0
+  ce:	d1fa      	bne.n	c6 <main+0x26>
+  d0:	eb09 0105 	add.w	r1, r9, r5
+  d4:	2001      	movs	r0, #1
+  d6:	f000 f8cf 	bl	278 <write>
+  da:	2264      	movs	r2, #100	; 0x64
+  dc:	4620      	mov	r0, r4
+  de:	4631      	mov	r1, r6
+  e0:	f000 f8cd 	bl	27e <read>
+  e4:	2800      	cmp	r0, #0
+  e6:	ddeb      	ble.n	c0 <main+0x20>
+  e8:	f89d 300c 	ldrb.w	r3, [sp, #12]
+  ec:	3b30      	subs	r3, #48	; 0x30
+  ee:	2b06      	cmp	r3, #6
+  f0:	d874      	bhi.n	1dc <main+0x13c>
+  f2:	e8df f003 	tbb	[pc, r3]
+  f6:	5f61656c 	svcpl	0x0061656c
+  fa:	00040859 	andeq	r0, r4, r9, asr r8
+  fe:	4640      	mov	r0, r8
+ 100:	f000 f8b7 	bl	272 <system>
+ 104:	e7dc      	b.n	c0 <main+0x20>
+ 106:	4638      	mov	r0, r7
+ 108:	f240 4102 	movw	r1, #1026	; 0x402
+ 10c:	2200      	movs	r2, #0
+ 10e:	f000 f8a7 	bl	260 <open>
+ 112:	4604      	mov	r4, r0
+ 114:	2800      	cmp	r0, #0
+ 116:	d0d3      	beq.n	c0 <main+0x20>
+ 118:	220c      	movs	r2, #12
+ 11a:	2001      	movs	r0, #1
+ 11c:	4651      	mov	r1, sl
+ 11e:	f000 f8ab 	bl	278 <write>
+ 122:	2204      	movs	r2, #4
+ 124:	4620      	mov	r0, r4
+ 126:	4659      	mov	r1, fp
+ 128:	f000 f8a6 	bl	278 <write>
+ 12c:	2804      	cmp	r0, #4
+ 12e:	d070      	beq.n	212 <main+0x172>
+ 130:	2100      	movs	r1, #0
+ 132:	9101      	str	r1, [sp, #4]
+ 134:	2100      	movs	r1, #0
+ 136:	460a      	mov	r2, r1
+ 138:	4620      	mov	r0, r4
+ 13a:	f000 f897 	bl	26c <seek>
+ 13e:	4943      	ldr	r1, [pc, #268]	; (24c <main+0x1ac>)
+ 140:	2203      	movs	r2, #3
+ 142:	4620      	mov	r0, r4
+ 144:	4449      	add	r1, r9
+ 146:	f000 f897 	bl	278 <write>
+ 14a:	2803      	cmp	r0, #3
+ 14c:	d06a      	beq.n	224 <main+0x184>
+ 14e:	2200      	movs	r2, #0
+ 150:	4611      	mov	r1, r2
+ 152:	4620      	mov	r0, r4
+ 154:	f000 f88a 	bl	26c <seek>
+ 158:	2264      	movs	r2, #100	; 0x64
+ 15a:	4620      	mov	r0, r4
+ 15c:	4631      	mov	r1, r6
+ 15e:	f000 f88e 	bl	27e <read>
+ 162:	2804      	cmp	r0, #4
+ 164:	d04a      	beq.n	1fc <main+0x15c>
+ 166:	4620      	mov	r0, r4
+ 168:	f000 f87d 	bl	266 <close>
+ 16c:	4604      	mov	r4, r0
+ 16e:	2800      	cmp	r0, #0
+ 170:	d1a6      	bne.n	c0 <main+0x20>
+ 172:	4937      	ldr	r1, [pc, #220]	; (250 <main+0x1b0>)
+ 174:	2001      	movs	r0, #1
+ 176:	4449      	add	r1, r9
+ 178:	2209      	movs	r2, #9
+ 17a:	f000 f87d 	bl	278 <write>
+ 17e:	9901      	ldr	r1, [sp, #4]
+ 180:	f041 0304 	orr.w	r3, r1, #4
+ 184:	2b07      	cmp	r3, #7
+ 186:	d19b      	bne.n	c0 <main+0x20>
+ 188:	eb09 0305 	add.w	r3, r9, r5
+ 18c:	3354      	adds	r3, #84	; 0x54
+ 18e:	4622      	mov	r2, r4
+ 190:	f813 1f01 	ldrb.w	r1, [r3, #1]!
+ 194:	3201      	adds	r2, #1
+ 196:	2900      	cmp	r1, #0
+ 198:	d1fa      	bne.n	190 <main+0xf0>
+ 19a:	eb09 0105 	add.w	r1, r9, r5
+ 19e:	3154      	adds	r1, #84	; 0x54
+ 1a0:	2001      	movs	r0, #1
+ 1a2:	f000 f869 	bl	278 <write>
+ 1a6:	e78b      	b.n	c0 <main+0x20>
+ 1a8:	f04f 4340 	mov.w	r3, #3221225472	; 0xc0000000
+ 1ac:	6818      	ldr	r0, [r3, #0]
+ 1ae:	f000 f869 	bl	284 <usleep>
+ 1b2:	e785      	b.n	c0 <main+0x20>
+ 1b4:	be00      	bkpt	0x0000
+ 1b6:	e783      	b.n	c0 <main+0x20>
+ 1b8:	2000      	movs	r0, #0
+ 1ba:	b01c      	add	sp, #112	; 0x70
+ 1bc:	e8bd 8df0 	ldmia.w	sp!, {r4, r5, r6, r7, r8, sl, fp, pc}
+ 1c0:	f644 3040 	movw	r0, #19264	; 0x4b40
+ 1c4:	f2c0 004c 	movt	r0, #76	; 0x4c
+ 1c8:	f000 f85c 	bl	284 <usleep>
+ 1cc:	e778      	b.n	c0 <main+0x20>
+ 1ce:	2300      	movs	r3, #0
+ 1d0:	200a      	movs	r0, #10
+ 1d2:	fb90 f0f3 	sdiv	r0, r0, r3
+ 1d6:	f000 f855 	bl	284 <usleep>
+ 1da:	e771      	b.n	c0 <main+0x20>
+ 1dc:	eb09 0305 	add.w	r3, r9, r5
+ 1e0:	3370      	adds	r3, #112	; 0x70
+ 1e2:	2200      	movs	r2, #0
+ 1e4:	f813 1f01 	ldrb.w	r1, [r3, #1]!
+ 1e8:	3201      	adds	r2, #1
+ 1ea:	2900      	cmp	r1, #0
+ 1ec:	d1fa      	bne.n	1e4 <main+0x144>
+ 1ee:	eb09 0105 	add.w	r1, r9, r5
+ 1f2:	3170      	adds	r1, #112	; 0x70
+ 1f4:	2001      	movs	r0, #1
+ 1f6:	f000 f83f 	bl	278 <write>
+ 1fa:	e761      	b.n	c0 <main+0x20>
+ 1fc:	4915      	ldr	r1, [pc, #84]	; (254 <main+0x1b4>)
+ 1fe:	2001      	movs	r0, #1
+ 200:	4449      	add	r1, r9
+ 202:	2208      	movs	r2, #8
+ 204:	f000 f838 	bl	278 <write>
+ 208:	9b01      	ldr	r3, [sp, #4]
+ 20a:	f043 0302 	orr.w	r3, r3, #2
+ 20e:	9301      	str	r3, [sp, #4]
+ 210:	e7a9      	b.n	166 <main+0xc6>
+ 212:	4911      	ldr	r1, [pc, #68]	; (258 <main+0x1b8>)
+ 214:	2001      	movs	r0, #1
+ 216:	4449      	add	r1, r9
+ 218:	2209      	movs	r2, #9
+ 21a:	f000 f82d 	bl	278 <write>
+ 21e:	2301      	movs	r3, #1
+ 220:	9301      	str	r3, [sp, #4]
+ 222:	e787      	b.n	134 <main+0x94>
+ 224:	490c      	ldr	r1, [pc, #48]	; (258 <main+0x1b8>)
+ 226:	2209      	movs	r2, #9
+ 228:	2001      	movs	r0, #1
+ 22a:	4449      	add	r1, r9
+ 22c:	f000 f824 	bl	278 <write>
+ 230:	2201      	movs	r2, #1
+ 232:	9201      	str	r2, [sp, #4]
+ 234:	e78b      	b.n	14e <main+0xae>
+ 236:	bf00      	nop
+ 238:	00000108 	andeq	r0, r0, r8, lsl #2
+ 23c:	000000bc 	strheq	r0, [r0], -ip
+ 240:	000000c8 	andeq	r0, r0, r8, asr #1
+ 244:	000000d8 	ldrdeq	r0, [r0], -r8
+ 248:	00000038 	andeq	r0, r0, r8, lsr r0
+ 24c:	000000ec 	andeq	r0, r0, ip, ror #1
+ 250:	000000fc 	strdeq	r0, [r0], -ip
+ 254:	000000f0 	strdeq	r0, [r0], -r0	; <UNPREDICTABLE>
+ 258:	000000e0 	andeq	r0, r0, r0, ror #1
+
+0000025c <_exit>:
+_exit():
+ 25c:	2302      	movs	r3, #2
+ 25e:	df00      	svc	0
+
+00000260 <open>:
+open():
+ 260:	2306      	movs	r3, #6
+ 262:	df00      	svc	0
+ 264:	4770      	bx	lr
+
+00000266 <close>:
+close():
+ 266:	2307      	movs	r3, #7
+ 268:	df00      	svc	0
+ 26a:	4770      	bx	lr
+
+0000026c <seek>:
+seek():
+ 26c:	2308      	movs	r3, #8
+ 26e:	df00      	svc	0
+ 270:	4770      	bx	lr
+
+00000272 <system>:
+system():
+ 272:	2309      	movs	r3, #9
+ 274:	df00      	svc	0
+ 276:	4770      	bx	lr
+
+00000278 <write>:
+write():
+ 278:	2303      	movs	r3, #3
+ 27a:	df00      	svc	0
+ 27c:	4770      	bx	lr
+
+0000027e <read>:
+read():
+ 27e:	2304      	movs	r3, #4
+ 280:	df00      	svc	0
+ 282:	4770      	bx	lr
+
+00000284 <usleep>:
+usleep():
+ 284:	2305      	movs	r3, #5
+ 286:	df00      	svc	0
+ 288:	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 <str.2690>:
+10000038:	74736554 	ldrbtvc	r6, [r3], #-1364	; 0x554
+1000003c:	70706120 	rsbsvc	r6, r0, r0, lsr #2
+10000040:	6163696c 	cmnvs	r3, ip, ror #18
+10000044:	6e6f6974 	mcrvs	9, 3, r6, cr15, cr4, {3}
+10000048:	3d300a3a 	vldmdbcc	r0!, {s0-s57}
+1000004c:	7a766964 	bvc	11d9a5e4 <str2.2691+0x1d9a53c>
+10000050:	0a6f7265 	beq	11bdc9ec <str2.2691+0x1bdc944>
+10000054:	6c733d31 	ldclvs	13, cr3, [r3], #-196	; 0xffffff3c
+10000058:	20706565 	rsbscs	r6, r0, r5, ror #10
+1000005c:	320a7335 	andcc	r7, sl, #-738197504	; 0xd4000000
+10000060:	6978653d 	ldmdbvs	r8!, {r0, r2, r3, r4, r5, r8, sl, sp, lr}^
+10000064:	3d330a74 	vldmdbcc	r3!, {s0-s115}
+10000068:	74706b62 	ldrbtvc	r6, [r0], #-2914	; 0xb62
+1000006c:	643d340a 	ldrtvs	r3, [sp], #-1034	; 0x40a
+10000070:	6c676e61 	stclvs	14, cr6, [r7], #-388	; 0xfffffe7c
+10000074:	0a676e69 	beq	119dba20 <str2.2691+0x19db978>
+10000078:	706f3d35 	rsbvc	r3, pc, r5, lsr sp	; <UNPREDICTABLE>
+1000007c:	360a6e65 	strcc	r6, [sl], -r5, ror #28
+10000080:	7379733d 	cmnvc	r9, #-201326592	; 0xf4000000
+10000084:	0a6d6574 	beq	11b5965c <str2.2691+0x1b595b4>
+10000088:	00000000 	andeq	r0, r0, r0
+
+1000008c <okMsg.2692>:
+1000008c:	72657645 	rsbvc	r7, r5, #72351744	; 0x4500000
+10000090:	69687479 	stmdbvs	r8!, {r0, r3, r4, r5, r6, sl, ip, sp, lr}^
+10000094:	7327676e 	teqvc	r7, #28835840	; 0x1b80000
+10000098:	69687320 	stmdbvs	r8!, {r5, r8, r9, ip, sp, lr}^
+1000009c:	202c796e 	eorcs	r7, ip, lr, ror #18
+100000a0:	27706143 	ldrbcs	r6, [r0, -r3, asr #2]!
+100000a4:	00000a6e 	andeq	r0, r0, lr, ror #20
+
+100000a8 <str2.2691>:
+100000a8:	78656e55 	stmdavc	r5!, {r0, r2, r4, r6, r9, sl, fp, sp, lr}^
+100000ac:	74636570 	strbtvc	r6, [r3], #-1392	; 0x570
+100000b0:	63206465 	teqvs	r0, #1694498816	; 0x65000000
+100000b4:	616d6d6f 	cmnvs	sp, pc, ror #26
+100000b8:	000a646e 	andeq	r6, sl, lr, ror #8
+100000bc:	7365742f 	cmnvc	r5, #788529152	; 0x2f000000
+100000c0:	78742e74 	ldmdavc	r4!, {r2, r4, r5, r6, r9, sl, fp, sp}^
+100000c4:	00000074 	andeq	r0, r0, r4, ror r0
+100000c8:	656c6946 	strbvs	r6, [ip, #-2374]!	; 0x946
+100000cc:	65706f20 	ldrbvs	r6, [r0, #-3872]!	; 0xf20
+100000d0:	0a64656e 	beq	11919690 <str2.2691+0x19195e8>
+100000d4:	00000000 	andeq	r0, r0, r0
+100000d8:	6f616963 	svcvs	0x00616963
+100000dc:	00000000 	andeq	r0, r0, r0
+100000e0:	74697257 	strbtvc	r7, [r9], #-599	; 0x257
+100000e4:	6b6f2065 	blvs	11bc8280 <str2.2691+0x1bc81d8>
+100000e8:	0000000a 	andeq	r0, r0, sl
+100000ec:	00333231 	eorseq	r3, r3, r1, lsr r2
+100000f0:	64616552 	strbtvs	r6, [r1], #-1362	; 0x552
+100000f4:	0a6b6f20 	beq	11adbd7c <str2.2691+0x1adbcd4>
+100000f8:	00000000 	andeq	r0, r0, r0
+100000fc:	736f6c43 	cmnvc	pc, #17152	; 0x4300
+10000100:	6b6f2065 	blvs	11bc829c <str2.2691+0x1bc81f4>
+10000104:	0000000a 	andeq	r0, r0, sl
+10000108:	74736574 	ldrbtvc	r6, [r3], #-1396	; 0x574
+1000010c:	00000000 	andeq	r0, r0, r0
diff --git a/app_template/prog3.h b/app_template/prog3.h
index a7a34f4a..968bdcdb 100644
--- a/app_template/prog3.h
+++ b/app_template/prog3.h
@@ -4,39 +4,78 @@ const unsigned char __attribute__((aligned(8))) main_elf[] = {
   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, 0xba, 0x00, 0x00, 0x00,
-  0xba, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
-  0x01, 0x00, 0x00, 0x00, 0x58, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
-  0x00, 0x00, 0x00, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x7c, 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,
-  0x64, 0x01, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10, 0x0c, 0x00, 0x00, 0x10,
+  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, 0x4e, 0xf8, 0x2d, 0xe9, 0xf0, 0x45, 0x24, 0x4d, 0x9b, 0xb0,
-  0x01, 0xae, 0x4d, 0x44, 0x4f, 0xf0, 0x00, 0x08, 0x4f, 0xf0, 0x40, 0x47,
-  0x4f, 0xf0, 0x0a, 0x0a, 0x2b, 0x46, 0x00, 0x22, 0x13, 0xf8, 0x01, 0x4f,
-  0x01, 0x32, 0x00, 0x2c, 0xfa, 0xd1, 0x01, 0x20, 0x29, 0x46, 0x00, 0xf0,
-  0x39, 0xf8, 0x64, 0x22, 0x20, 0x46, 0x31, 0x46, 0x00, 0xf0, 0x37, 0xf8,
-  0x00, 0x28, 0xed, 0xdd, 0x9d, 0xf8, 0x04, 0x30, 0x30, 0x3b, 0x04, 0x2b,
-  0x1a, 0xd8, 0xdf, 0xe8, 0x03, 0xf0, 0x14, 0x0d, 0x09, 0x07, 0x03, 0x00,
-  0x38, 0x68, 0x00, 0xf0, 0x2b, 0xf8, 0xdf, 0xe7, 0x00, 0xbe, 0xdd, 0xe7,
-  0x00, 0x20, 0x1b, 0xb0, 0xbd, 0xe8, 0xf0, 0x85, 0x44, 0xf6, 0x40, 0x30,
-  0xc0, 0xf2, 0x4c, 0x00, 0x00, 0xf0, 0x1e, 0xf8, 0xd2, 0xe7, 0x9a, 0xfb,
-  0xf8, 0xf0, 0x00, 0xf0, 0x19, 0xf8, 0xcd, 0xe7, 0x05, 0xf1, 0x30, 0x03,
-  0x00, 0x22, 0x13, 0xf8, 0x01, 0x1f, 0x01, 0x32, 0x00, 0x29, 0xfa, 0xd1,
-  0x05, 0xf1, 0x30, 0x01, 0x01, 0x20, 0x00, 0xf0, 0x05, 0xf8, 0xbf, 0xe7,
-  0x38, 0x00, 0x00, 0x00, 0x02, 0x23, 0x00, 0xdf, 0x03, 0x23, 0x00, 0xdf,
+  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,
+  0x74, 0xd8, 0xdf, 0xe8, 0x03, 0xf0, 0x6c, 0x65, 0x61, 0x5f, 0x59, 0x08,
+  0x04, 0x00, 0x40, 0x46, 0x00, 0xf0, 0xb7, 0xf8, 0xdc, 0xe7, 0x38, 0x46,
+  0x40, 0xf2, 0x02, 0x41, 0x00, 0x22, 0x00, 0xf0, 0xa7, 0xf8, 0x04, 0x46,
+  0x00, 0x28, 0xd3, 0xd0, 0x0c, 0x22, 0x01, 0x20, 0x51, 0x46, 0x00, 0xf0,
+  0xab, 0xf8, 0x04, 0x22, 0x20, 0x46, 0x59, 0x46, 0x00, 0xf0, 0xa6, 0xf8,
+  0x04, 0x28, 0x70, 0xd0, 0x00, 0x21, 0x01, 0x91, 0x00, 0x21, 0x0a, 0x46,
+  0x20, 0x46, 0x00, 0xf0, 0x97, 0xf8, 0x43, 0x49, 0x03, 0x22, 0x20, 0x46,
+  0x49, 0x44, 0x00, 0xf0, 0x97, 0xf8, 0x03, 0x28, 0x6a, 0xd0, 0x00, 0x22,
+  0x11, 0x46, 0x20, 0x46, 0x00, 0xf0, 0x8a, 0xf8, 0x64, 0x22, 0x20, 0x46,
+  0x31, 0x46, 0x00, 0xf0, 0x8e, 0xf8, 0x04, 0x28, 0x4a, 0xd0, 0x20, 0x46,
+  0x00, 0xf0, 0x7d, 0xf8, 0x04, 0x46, 0x00, 0x28, 0xa6, 0xd1, 0x37, 0x49,
+  0x01, 0x20, 0x49, 0x44, 0x09, 0x22, 0x00, 0xf0, 0x7d, 0xf8, 0x01, 0x99,
+  0x41, 0xf0, 0x04, 0x03, 0x07, 0x2b, 0x9b, 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,
+  0x69, 0xf8, 0x8b, 0xe7, 0x4f, 0xf0, 0x40, 0x43, 0x18, 0x68, 0x00, 0xf0,
+  0x69, 0xf8, 0x85, 0xe7, 0x00, 0xbe, 0x83, 0xe7, 0x00, 0x20, 0x1c, 0xb0,
+  0xbd, 0xe8, 0xf0, 0x8d, 0x44, 0xf6, 0x40, 0x30, 0xc0, 0xf2, 0x4c, 0x00,
+  0x00, 0xf0, 0x5c, 0xf8, 0x78, 0xe7, 0x00, 0x23, 0x0a, 0x20, 0x90, 0xfb,
+  0xf3, 0xf0, 0x00, 0xf0, 0x55, 0xf8, 0x71, 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,
+  0x3f, 0xf8, 0x61, 0xe7, 0x15, 0x49, 0x01, 0x20, 0x49, 0x44, 0x08, 0x22,
+  0x00, 0xf0, 0x38, 0xf8, 0x01, 0x9b, 0x43, 0xf0, 0x02, 0x03, 0x01, 0x93,
+  0xa9, 0xe7, 0x11, 0x49, 0x01, 0x20, 0x49, 0x44, 0x09, 0x22, 0x00, 0xf0,
+  0x2d, 0xf8, 0x01, 0x23, 0x01, 0x93, 0x87, 0xe7, 0x0c, 0x49, 0x09, 0x22,
+  0x01, 0x20, 0x49, 0x44, 0x00, 0xf0, 0x24, 0xf8, 0x01, 0x22, 0x01, 0x92,
+  0x8b, 0xe7, 0x00, 0xbf, 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, 0xf0, 0x00, 0x00, 0x00,
+  0xe0, 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, 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
+  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 = 468;
+unsigned int main_elf_len = 928;
diff --git a/app_template_withlibs/main.map b/app_template_withlibs/main.map
new file mode 100644
index 00000000..08ed19c2
--- /dev/null
+++ b/app_template_withlibs/main.map
@@ -0,0 +1,6 @@
+Archive member included because of file (symbol)
+
+/opt/arm-miosix-eabi/lib/gcc/arm-eabi/4.5.2/../../../../arm-eabi/lib/thumb/thumb2/libc.a(lib_a-printf.o)
+                              main.o (printf)
+/opt/arm-miosix-eabi/lib/gcc/arm-eabi/4.5.2/../../../../arm-eabi/lib/thumb/thumb2/libc.a(lib_a-vfprintf.o)
+                              /opt/arm-miosix-eabi/lib/gcc/arm-eabi/4.5.2/../../../../arm-eabi/lib/thumb/thumb2/libc.a(lib_a-printf.o) (_vfprintf_r)
diff --git a/chg.patch b/chg.patch
new file mode 100644
index 00000000..d2a6d30b
--- /dev/null
+++ b/chg.patch
@@ -0,0 +1,3313 @@
+diff --git a/Time results.txt b/Time results.txt
+new file mode 100644
+index 0000000..e0d36a9
+--- /dev/null
++++ b/Time results.txt	
+@@ -0,0 +1,21 @@
++OS cold boot 450us
++
++Process with 32K of RAM
++swapout= 18.2ms (+/-0.5ms)
++swapin=  18.9ms
++
++Process with 16K of RAM
++swapout=  9.5ms (+/-0.5ms)
++swapin=  10.2ms
++
++Process with  8K of RAM
++swapout=  4.7ms (+/-0.5ms)
++swapin=   5.8ms
++
++Process with  4K of RAM
++swapout=  2.5ms (+/-0.5ms)
++swapin=   3.6ms
++
++Process with  2K of RAM
++swapout=  1.7ms (+/-0.5ms)
++swapin=   2.5ms 
+diff --git a/app_template_withlibs/Makefile b/app_template_withlibs/Makefile
+deleted file mode 100644
+index 81a35d4..0000000
+--- a/app_template_withlibs/Makefile
++++ /dev/null
+@@ -1,47 +0,0 @@
+-##
+-## 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
+-# 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
+-
+-%.o: %.s
+-	$(AS) $(AFLAGS) $< -o $@
+-
+-%.o : %.c
+-	$(CC) $(CFLAGS) $< -o $@
+-
+-%.o : %.cpp
+-	$(CXX) $(CXXFLAGS) $< -o $@
+diff --git a/app_template_withlibs/crt0.s b/app_template_withlibs/crt0.s
+deleted file mode 100644
+index 2eba4bf..0000000
+--- a/app_template_withlibs/crt0.s
++++ /dev/null
+@@ -1,77 +0,0 @@
+-/*
+- * 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
+deleted file mode 100644
+index 57197b7..0000000
+--- a/app_template_withlibs/main.c
++++ /dev/null
+@@ -1,39 +0,0 @@
+-
+-#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
+deleted file mode 100644
+index 0b86aaf..0000000
+--- a/app_template_withlibs/miosix.ld
++++ /dev/null
+@@ -1,77 +0,0 @@
+-/*
+- * 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
+deleted file mode 100644
+index 8855c4f..0000000
+--- a/app_template_withlibs/prog3.h
++++ /dev/null
+@@ -1,40 +0,0 @@
+-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
+deleted file mode 100644
+index 3c12251..0000000
+--- a/app_template_withlibs/syscallfuffa.c
++++ /dev/null
+@@ -1,62 +0,0 @@
+-
+-#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/fail.txt b/fail.txt
+new file mode 100644
+index 0000000..d9887fa
+--- /dev/null
++++ b/fail.txt
+@@ -0,0 +1,37 @@
++Miosix v1.60 (stm32f207ig_stm3220g-eval, Jul 12 2012 17:34:40, gcc 4.5.2)
++Starting Kernel... Ok
++Starting Filesystem... No disk
++Available heap 24576 out of 29868 Bytes
++tick=40
++First boot
++
++0=divzero 1=sleep 5s, 2=exit 3=bkpt 4=dangling
++1
++0x200039b0 | 58 bf 00 20 00 00 00 00 38 80 00 20 7c bf 00 20 | X.......8...|...
++0x200039c0 | 00 00 00 c0 00 00 00 00 00 80 00 20 0a 00 00 00 | ................
++0x200039d0 | bb bb bb bb                                     | ....
++Swapping 1 processes
++save base=0x1c578 size=468
++0x00000000 | 00 02 00 20 79 56 00 00 01 66 01 00 19 66 01 00 | ....yV...f...f..
++0x00000010 | cd 66 01 00 31 68 01 00 09 69 01 00 00 00 00 00 | .f..1h...i......
++0x00000020 | 00 00 00 00                                     | ....
++about to suspend, tick=2724
++Miosix v1.60 (stm32f207ig_stm3220g-eval, Jul 12 2012 17:34:40, gcc 4.5.2)
++Starting Kernel... Ok
++Starting Filesystem... No disk
++Available heap 24576 out of 29868 Bytes
++tick=7764
++RTC boot
++Reloading 1 processes
++reload base=0x1c578 size=468
++0x4002407e | 00 02 00 20 79 56 00 00 01 66 01 00 19 66 01 00 | ....yV...f...f..
++0x4002408e | cd 66 01 00 31 68 01 00 09 69 01 00 00 00 00 00 | .f..1h...i......
++0x4002409e | 00 00 00 00                                     | ....
++Process 1 terminated due to a fault
++* Code base address was 0x1c578
++* Data base address was 0x20008000
++* MPU region 0 0x0-0x20000 r-x
++* MPU region 1 0x20008000-0x2000c000 rw-
++* Invalid data access (PC was 0x4030201)
++Process terminated
++Process segfaulted
+diff --git a/main.cpp b/main.cpp
+index 75f70ce..b991f7f 100644
+--- a/main.cpp
++++ b/main.cpp
+@@ -2,8 +2,10 @@
+ #include <cstdio>
+ #include <sys/wait.h>
+ #include <signal.h>
++#include <string.h>
+ #include "miosix.h"
+ #include "kernel/process.h"
++#include "interfaces/suspend_support.h"
+ #include "app_template/prog3.h"
+ 
+ using namespace std;
+@@ -23,6 +25,35 @@ void ledThread(void *)
+ int main()
+ {
+     Thread::create(ledThread,STACK_MIN);
++    SuspendManager::startHibernationDaemon();
++    iprintf("tick=%llu\n",getTick());
++    if(firstBoot())
++    {
++        puts("First boot");
++//        //Watermarking
++//        memset(getBackupSramBase(),0xff,getBackupSramSize());
++//        char *buf=new char[1024];
++//        memset(buf,0xff,1024);
++//        Mram& mram=Mram::instance();
++//        mram.exitSleepMode();
++//        for(int i=0,j=0;i<mram.size()/1024;i++,j+=1024)
++//            mram.write(j,buf,1024);
++//        mram.enterSleepMode();
++//        delete[] buf;
++    } else {
++        puts("RTC boot");
++        SuspendManager::resume();
++        
++        int ec;
++        Process::wait(&ec);
++        iprintf("Process terminated\n");
++        if(WIFEXITED(ec))
++        {
++            iprintf("Exit code is %d\n",WEXITSTATUS(ec));
++        } else if(WIFSIGNALED(ec)) {
++            if(WTERMSIG(ec)==SIGSEGV) iprintf("Process segfaulted\n");
++        }
++    }
+     
+     ElfProgram prog(reinterpret_cast<const unsigned int*>(main_elf),main_elf_len);
+     for(int i=0;;i++)
+diff --git a/miosix/Makefile b/miosix/Makefile
+index e601cfc..483c893 100644
+--- a/miosix/Makefile
++++ b/miosix/Makefile
+@@ -20,6 +20,7 @@ kernel/syscalls.cpp                                                        \
+ kernel/elf_program.cpp                                                     \
+ kernel/process.cpp                                                         \
+ kernel/process_pool.cpp                                                    \
++kernel/suspend_manager.cpp                                                 \
+ kernel/scheduler/priority/priority_scheduler.cpp                           \
+ kernel/scheduler/control/control_scheduler.cpp                             \
+ kernel/scheduler/edf/edf_scheduler.cpp                                     \
+diff --git a/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/portability.cpp b/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/portability.cpp
+index 47fe617..c309f92 100644
+--- a/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/portability.cpp
++++ b/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/portability.cpp
+@@ -29,6 +29,7 @@
+ #include "interfaces/portability.h"
+ #include "kernel/kernel.h"
+ #include "kernel/error.h"
++#include "util/util.h"
+ #include "interfaces/bsp.h"
+ #include "kernel/scheduler/scheduler.h"
+ #include "kernel/scheduler/tick_interrupt.h"
+@@ -263,27 +264,27 @@ MPUConfiguration::MPUConfiguration(unsigned int *elfBase, unsigned int elfSize,
+     regValues[1]=2<<MPU_RASR_AP_Pos
+                | MPU_RASR_C_Msk
+                | 1 //Enable bit
+-               | ((ffs(elfSize)-2)<<1);
++               | ((miosix::fhbs(elfSize)-2)<<1);
+     regValues[3]=3<<MPU_RASR_AP_Pos
+                | MPU_RASR_XN_Msk
+                | MPU_RASR_C_Msk
+                | MPU_RASR_S_Msk
+                | 1 //Enable bit
+-               | ((ffs(imageSize)-2)<<1);
++               | ((miosix::fhbs(imageSize)-2)<<1);
+     #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
+-               | ((ffs(elfSize)-2)<<1);
++               | ((miosix::fhbs(elfSize)-2)<<1);
+     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
+-               | ((ffs(imageSize)-2)<<1);
++               | ((miosix::fhbs(imageSize)-2)<<1);
+     #endif //__CODE_IN_XRAM
+ }
+ 
+diff --git a/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/suspend_support_impl.cpp b/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/suspend_support_impl.cpp
+new file mode 100644
+index 0000000..dda8f03
+--- /dev/null
++++ b/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/suspend_support_impl.cpp
+@@ -0,0 +1,115 @@
++/***************************************************************************
++ *   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 <stdio.h>
++#include "interfaces/suspend_support.h"
++#include "kernel/process_pool.h"
++#include "miosix.h"
++#include "interfaces/arch_registers.h"
++
++#ifdef WITH_HIBERNATION
++
++namespace miosix {
++    
++void IRQinitializeSuspendSupport()
++{
++    RCC->APB1ENR |= RCC_APB1ENR_PWREN;
++    PWR->CR |= PWR_CR_DBP;
++    PWR->CSR |= PWR_CSR_BRE;
++    while((PWR->CSR & PWR_CSR_BRR)==0) ;
++    RCC->AHB1ENR |= RCC_AHB1ENR_BKPSRAMEN;
++
++    RCC->BDCR |= RCC_BDCR_LSEON;
++    while((RCC->BDCR & RCC_BDCR_LSERDY)==0) ; //wait
++    RCC->BDCR |= RCC_BDCR_RTCSEL_0 | RCC_BDCR_RTCEN;
++    RTC->WPR=0xca;
++    RTC->WPR=0x53;
++    
++    //FIXME: hack
++    if(firstBoot()==false)
++    {
++        long long tick=static_cast<long long>(getBackupSramBase()[1022])<<32
++                     | static_cast<long long>(getBackupSramBase()[1021]);
++        tick+=getBackupSramBase()[1023]*1000;
++        IRQsetTick(tick);
++    }
++}
++
++void doSuspend(unsigned int seconds)
++{
++    if(seconds==0) return;
++    if(seconds>31) seconds=31;
++  
++    while(Console::txComplete()==false) ;
++
++    {
++        FastInterruptDisableLock dLock;
++ 
++        RCC->CSR |= RCC_CSR_RMVF; //This makes firstBoot() return false next time
++        RTC->CR &= ~RTC_CR_WUTE;
++        while((RTC->ISR & RTC_ISR_WUTWF)==0) ; //Wait
++        RTC->WUTR=seconds*2048; //10s
++        RTC->CR |= RTC_CR_WUTE | RTC_CR_WUTIE;
++    
++        RTC->ISR= ~RTC_ISR_WUTF;
++        EXTI->EMR |= 1<<22;
++        EXTI->RTSR |= 1<<22;
++
++        PWR->CR |= PWR_CR_PDDS | PWR_CR_CWUF;
++        SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
++        //Using WFE instead of WFI because if while we are with interrupts
++        //disabled an interrupt (such as the tick interrupt) occurs, it
++        //remains pending and the WFI becomes a nop, and the device never goes
++        //in sleep mode. WFE events are latched in a separate pending register
++        //so interrupts do not interfere with them
++        __WFE();
++        //Should never reach here
++        NVIC_SystemReset();
++    }
++}
++
++bool firstBoot()
++{
++    static const unsigned int firstBootMask=
++        RCC_CSR_LPWRRSTF
++      | RCC_CSR_WWDGRSTF
++      | RCC_CSR_WDGRSTF
++      | RCC_CSR_SFTRSTF
++      | RCC_CSR_PORRSTF
++      | RCC_CSR_PADRSTF
++      | RCC_CSR_BORRSTF;
++    return (RCC->CSR & firstBootMask) ? true : false;
++}
++
++int getAllocatorSramAreaSize()
++{
++    return ProcessPool::instance().getSerializableSize();
++}
++
++} //namespace miosix
++
++#endif //WITH_HIBERNATION
+\ No newline at end of file
+diff --git a/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/suspend_support_impl.h b/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/suspend_support_impl.h
+new file mode 100644
+index 0000000..2783f1e
+--- /dev/null
++++ b/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/suspend_support_impl.h
+@@ -0,0 +1,73 @@
++/***************************************************************************
++ *   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 SUSPEND_SUPPORT_IMPL_H
++#define	SUSPEND_SUPPORT_IMPL_H
++
++#ifdef WITH_HIBERNATION
++
++#include "drivers/mram.h"
++
++namespace miosix {
++
++inline unsigned int *getBackupSramBase()
++{
++    return reinterpret_cast<unsigned int*>(0x40024000);
++}
++
++inline int getBackupSramSize()
++{
++    return 4096;
++}
++
++inline int getBackupAllocatorSramAreaSize()
++{
++    return sizeof(unsigned int*)*4;
++}
++
++inline int getProcessesSramAreaSize()
++{
++    return 1024;
++}
++
++inline int getRoutingTableSramAreaSize()
++{
++    return 1024;
++}
++
++inline int getSmartDriversQueueSramAreaSize()
++{
++    return getBackupSramSize()-
++           getAllocatorSramAreaSize() -
++           getProcessesSramAreaSize() -
++           getSmartDriversQueueSramAreaSize();
++}
++
++} //namespace miosix
++
++#endif  //WITH_HIBERNATION
++#endif	//SUSPEND_SUPPORT_IMPL_H
+diff --git a/miosix/arch/cortexM3_stm32f2/stm32f207ig_stm3220g-eval/drivers/mram.cpp b/miosix/arch/cortexM3_stm32f2/stm32f207ig_stm3220g-eval/drivers/mram.cpp
+new file mode 100644
+index 0000000..ff7fa91
+--- /dev/null
++++ b/miosix/arch/cortexM3_stm32f2/stm32f207ig_stm3220g-eval/drivers/mram.cpp
+@@ -0,0 +1,340 @@
++/***************************************************************************
++ *   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 "mram.h"
++#include <miosix.h>
++#include <kernel/scheduler/scheduler.h>
++#include <interfaces/delays.h>
++
++using namespace miosix;
++
++//Gpio mapping
++typedef Gpio<GPIOI_BASE,2> miso;
++typedef Gpio<GPIOI_BASE,3> mosi;
++typedef Gpio<GPIOI_BASE,1> sck;
++typedef Gpio<GPIOI_BASE,0> cs;
++
++/**
++ * DMA RX end of transfer
++ */
++void __attribute__((naked)) DMA1_Stream3_IRQHandler()
++{
++    saveContext();
++    asm volatile("bl _Z20SPI2rxDmaHandlerImplv");
++    restoreContext();
++}
++
++/**
++ * DMA TX end of transfer
++ */
++void __attribute__((naked)) DMA1_Stream4_IRQHandler()
++{
++    saveContext();
++    asm volatile("bl _Z20SPI2txDmaHandlerImplv");
++    restoreContext();
++}
++
++static Thread *waiting;
++static bool error;
++
++/**
++ * DMA RX end of transfer actual implementation
++ */
++void __attribute__((used)) SPI2rxDmaHandlerImpl()
++{
++    if(DMA1->LISR & (DMA_LISR_TEIF3 | DMA_LISR_DMEIF3)) error=true;
++    DMA1->LIFCR=DMA_LIFCR_CTCIF3
++              | DMA_LIFCR_CTEIF3
++              | DMA_LIFCR_CDMEIF3;
++    waiting->IRQwakeup();
++    if(waiting->IRQgetPriority()>Thread::IRQgetCurrentThread()->IRQgetPriority())
++        Scheduler::IRQfindNextThread();
++    waiting=0;
++}
++
++/**
++ * DMA TX end of transfer actual implementation
++ */
++void __attribute__((used)) SPI2txDmaHandlerImpl()
++{
++    if(DMA1->HISR & (DMA_HISR_TEIF4 | DMA_HISR_DMEIF4)) error=true;
++    DMA1->HIFCR=DMA_HIFCR_CTCIF4
++              | DMA_HIFCR_CTEIF4
++              | DMA_HIFCR_CDMEIF4;
++    waiting->IRQwakeup();
++    if(waiting->IRQgetPriority()>Thread::IRQgetCurrentThread()->IRQgetPriority())
++        Scheduler::IRQfindNextThread();
++    waiting=0;
++}
++
++/**
++ * Transfer a byte through SPI2 where the mram is connected
++ * \param data byte to send
++ * \return byte received
++ */
++static unsigned char spi2sendRecv(unsigned char data=0)
++{
++    SPI2->DR=data;
++    while((SPI2->SR & SPI_SR_RXNE)==0) ;
++    return SPI2->DR;
++}
++
++//
++// class Mram
++//
++
++Mram& Mram::instance()
++{
++    static Mram singleton;
++    return singleton;
++}
++    
++unsigned int Mram::size() const { return 128*1024; }
++
++bool Mram::write(unsigned int addr, const void *data, int size)
++{
++    // Write time, with CPU @ 120MHz and SPI2 @ 15MHz, is
++    // 2    us fixed time (mutex locking)
++    // 3.5  us fixed time (sending the address an peripheral register setup)
++    // 0.533us per byte transferred in DMA mode
++    // 4.5  us fixed time (context switch and peripheral register cleanup)
++    // 2    us fixed time (mutex unlock)
++    
++    if(addr>=this->size() || addr+size>this->size()) return false;
++    pthread_mutex_lock(&mutex);
++    if(sleepMode) { pthread_mutex_unlock(&mutex); return false; }
++    cs::low();
++    spi2sendRecv(0x02); //Write command
++    spi2sendRecv((addr>>16) & 0xff);
++    spi2sendRecv((addr>>8) & 0xff);
++    spi2sendRecv(addr & 0xff);
++    
++    //DMA1 stream 4 channel 0 = SPI2_TX
++    
++    error=false;
++
++    //Wait until the SPI is busy, required otherwise the last byte is not
++    //fully sent
++    while((SPI2->SR & SPI_SR_TXE)==0) ;
++    while(SPI2->SR & SPI_SR_BSY) ;
++    SPI2->CR1=0;
++    SPI2->CR2=SPI_CR2_TXDMAEN;
++    SPI2->CR1=SPI_CR1_SSM
++            | SPI_CR1_SSI
++            | SPI_CR1_MSTR
++            | SPI_CR1_SPE;
++
++    waiting=Thread::getCurrentThread();
++    NVIC_ClearPendingIRQ(DMA1_Stream4_IRQn);
++    NVIC_SetPriority(DMA1_Stream4_IRQn,10);//Low priority for DMA
++    NVIC_EnableIRQ(DMA1_Stream4_IRQn);
++
++    DMA1_Stream4->CR=0;
++    DMA1_Stream4->PAR=reinterpret_cast<unsigned int>(&SPI2->DR);
++    DMA1_Stream4->M0AR=reinterpret_cast<unsigned int>(data);
++    DMA1_Stream4->NDTR=size;
++    DMA1_Stream4->CR=DMA_SxCR_PL_1 //High priority because fifo disabled
++                | DMA_SxCR_MINC    //Increment memory pointer
++                | DMA_SxCR_DIR_0   //Memory to peripheral
++                | DMA_SxCR_TCIE    //Interrupt on transfer complete
++                | DMA_SxCR_TEIE    //Interrupt on transfer error
++                | DMA_SxCR_DMEIE   //Interrupt on direct mode error
++                | DMA_SxCR_EN;     //Start DMA
++    
++    {
++        FastInterruptDisableLock dLock;
++        while(waiting!=0)
++        {
++            waiting->IRQwait();
++            {
++                FastInterruptEnableLock eLock(dLock);
++                Thread::yield();
++            }
++        }
++    }
++                
++    NVIC_DisableIRQ(DMA1_Stream4_IRQn);
++
++    //Wait for last byte to be sent
++    while((SPI2->SR & SPI_SR_TXE)==0) ;
++    while(SPI2->SR & SPI_SR_BSY) ;
++    SPI2->CR1=0;
++    SPI2->CR2=0;
++    SPI2->CR1=SPI_CR1_SSM
++            | SPI_CR1_SSI
++            | SPI_CR1_MSTR
++            | SPI_CR1_SPE;
++    
++    //Quirk: reset RXNE by reading DR, or a byte remains in the input buffer
++    volatile short temp=SPI1->DR;
++    (void)temp;
++    
++    cs::high();
++    bool result=!error;
++    pthread_mutex_unlock(&mutex);
++    return result;
++}
++
++bool Mram::read(unsigned int addr, void *data, int size)
++{
++    // Read time, with CPU @ 120MHz and SPI2 @ 15MHz, is
++    // 2    us fixed time (mutex locking)
++    // 3.5  us fixed time (sending the address an peripheral register setup)
++    // 0.533us per byte transferred in DMA mode
++    // 4.5  us fixed time (context switch and peripheral register cleanup)
++    // 2    us fixed time (mutex unlock)
++    if(addr>=this->size() || addr+size>this->size()) return false;
++    pthread_mutex_lock(&mutex);
++    if(sleepMode) { pthread_mutex_unlock(&mutex); return false; }
++    cs::low();
++    spi2sendRecv(0x03); //Read command
++    spi2sendRecv((addr>>16) & 0xff);
++    spi2sendRecv((addr>>8) & 0xff);
++    spi2sendRecv(addr & 0xff);
++    
++    //DMA1 stream 3 channel 0 = SPI2_RX
++
++    error=false;
++
++    //Wait until the SPI is busy, required otherwise the last byte is not
++    //fully sent
++    while((SPI2->SR & SPI_SR_TXE)==0) ;
++    while(SPI2->SR & SPI_SR_BSY) ;
++    //Quirk: reset RXNE by reading DR before starting the DMA, or the first
++    //byte in the DMA buffer is garbage
++    volatile short temp=SPI2->DR;
++    (void)temp;
++    SPI2->CR1=0;
++    SPI2->CR2=SPI_CR2_RXDMAEN;
++
++    waiting=Thread::getCurrentThread();
++    NVIC_ClearPendingIRQ(DMA1_Stream3_IRQn);
++    NVIC_SetPriority(DMA1_Stream3_IRQn,10);//Low priority for DMA
++    NVIC_EnableIRQ(DMA1_Stream3_IRQn);
++
++    DMA1_Stream3->CR=0;
++    DMA1_Stream3->PAR=reinterpret_cast<unsigned int>(&SPI2->DR);
++    DMA1_Stream3->M0AR=reinterpret_cast<unsigned int>(data);
++    DMA1_Stream3->NDTR=size;
++    DMA1_Stream3->CR=DMA_SxCR_PL_1 //High priority because fifo disabled
++                | DMA_SxCR_MINC    //Increment memory pointer
++                | DMA_SxCR_TCIE    //Interrupt on transfer complete
++                | DMA_SxCR_TEIE    //Interrupt on transfer error
++                | DMA_SxCR_DMEIE   //Interrupt on direct mode error
++                | DMA_SxCR_EN;     //Start DMA
++
++    //Quirk: start the SPI in RXONLY mode only *after* the DMA has been
++    //setup or the SPI doesn't wait for the DMA and the first bytes are lost
++    SPI2->CR1=SPI_CR1_RXONLY
++            | SPI_CR1_SSM
++            | SPI_CR1_SSI
++            | SPI_CR1_MSTR
++            | SPI_CR1_SPE;
++        
++    {
++        FastInterruptDisableLock dLock;
++        while(waiting!=0)
++        {
++            waiting->IRQwait();
++            {
++                FastInterruptEnableLock eLock(dLock);
++                Thread::yield();
++            }
++        }
++    }
++
++    NVIC_DisableIRQ(DMA1_Stream3_IRQn);
++    SPI2->CR1=0;
++    
++    //Quirk, disabling the SPI in RXONLY mode is difficult
++    while(SPI2->SR & SPI_SR_RXNE) temp=SPI2->DR;
++    delayUs(1); //The last transfer may still be in progress
++    while(SPI2->SR & SPI_SR_RXNE) temp=SPI2->DR;
++    
++    SPI2->CR2=0;
++    SPI2->CR1=SPI_CR1_SSM
++            | SPI_CR1_SSI
++            | SPI_CR1_MSTR
++            | SPI_CR1_SPE;
++
++    cs::high();
++    bool result=!error;
++    pthread_mutex_unlock(&mutex);
++    return result;
++}
++
++void Mram::exitSleepMode()
++{
++    pthread_mutex_lock(&mutex);
++    cs::low();
++    spi2sendRecv(0xab); //Exit sleep mode command
++    cs::high();
++    Thread::sleep(1);   //It needs at least 400us to go out of sleep mode
++    cs::low();
++    spi2sendRecv(0x06); //Write enable command
++    cs::high();
++    sleepMode=false;
++    pthread_mutex_unlock(&mutex);
++}
++
++void Mram::enterSleepMode()
++{
++    pthread_mutex_lock(&mutex);
++    cs::low();
++    spi2sendRecv(0x04); //Write disable command
++    cs::high();
++    for(int i=0;i<5;i++) __NOP(); //To meet 40ns CS high time between commands
++    cs::low();
++    spi2sendRecv(0xb9); //Entr sleep mode command
++    cs::high();
++    delayUs(3);         //It needs at least 3us to enter sleep mode
++    sleepMode=true;
++    pthread_mutex_unlock(&mutex);
++}
++
++Mram::Mram() : sleepMode(true)
++{
++    pthread_mutex_init(&mutex,0);
++    {
++        FastInterruptDisableLock dLock;
++        mosi::mode(Mode::ALTERNATE);
++        mosi::alternateFunction(5);
++        miso::mode(Mode::ALTERNATE);
++        miso::alternateFunction(5);
++        sck::mode(Mode::ALTERNATE);
++        sck::alternateFunction(5);
++        cs::mode(Mode::OUTPUT);
++        cs::high();
++        RCC->AHB1ENR |= RCC_AHB1ENR_DMA1EN;
++        RCC->APB1ENR |= RCC_APB1ENR_SPI2EN;
++        SPI2->CR2=0;
++        SPI2->CR1=SPI_CR1_SSM  //Software cs
++                | SPI_CR1_SSI  //Hardware cs internally tied high
++                | SPI_CR1_MSTR //Master mode
++                | SPI_CR1_SPE; //SPI enabled
++    }
++}
+diff --git a/miosix/arch/cortexM3_stm32f2/stm32f207ig_stm3220g-eval/drivers/mram.h b/miosix/arch/cortexM3_stm32f2/stm32f207ig_stm3220g-eval/drivers/mram.h
+new file mode 100644
+index 0000000..34f2c95
+--- /dev/null
++++ b/miosix/arch/cortexM3_stm32f2/stm32f207ig_stm3220g-eval/drivers/mram.h
+@@ -0,0 +1,95 @@
++/***************************************************************************
++ *   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 <pthread.h>
++
++#ifndef MRAM_H
++#define	MRAM_H
++
++/**
++ * Class to access the mram memory
++ */
++class Mram
++{
++public:
++    /**
++     * Singleton
++     * \return an instance of the Mram class 
++     */
++    static Mram& instance();
++    
++    /**
++     * \return the MRAM's size in bytes 
++     */
++    unsigned int size() const;
++    
++    /**
++     * Write a block of data into the mram
++     * \param addr start address into the mram where the data block will be
++     * written
++     * \param data data block
++     * \param size data block size
++     * \return true on success, false on failure
++     */
++    bool write(unsigned int addr, const void *data, int size);
++    
++    /**
++     * Read a block of data from the mram
++     * \param addr start address into the mram where the data block will be read
++     * \param data data block
++     * \param size data block size
++     * \return true on success, false on failure
++     */
++    bool read(unsigned int addr, void *data, int size);
++    
++    /**
++     * This member function needs to be called before accessing the mram
++     */
++    void exitSleepMode();
++    
++    /**
++     * This member function can be called after performing operations on the
++     * mram to put it back in sleep mode
++     */
++    void enterSleepMode();
++    
++    /**
++     * \return true if the mram is in sleep mode 
++     */
++    bool isSleeping() const { return sleepMode; }
++    
++private:
++    Mram();
++    
++    Mram(const Mram&);
++    Mram& operator= (const Mram&);
++    
++    pthread_mutex_t mutex; ///Mutex to protect concurrent access to the hardware
++    bool sleepMode;
++};
++
++#endif //MRAM_H
+diff --git a/miosix/arch/cortexM3_stm32f2/stm32f207ig_stm3220g-eval/interfaces-impl/bsp.cpp b/miosix/arch/cortexM3_stm32f2/stm32f207ig_stm3220g-eval/interfaces-impl/bsp.cpp
+index 0950086..cd41faa 100644
+--- a/miosix/arch/cortexM3_stm32f2/stm32f207ig_stm3220g-eval/interfaces-impl/bsp.cpp
++++ b/miosix/arch/cortexM3_stm32f2/stm32f207ig_stm3220g-eval/interfaces-impl/bsp.cpp
+@@ -45,6 +45,7 @@
+ #include "config/miosix_settings.h"
+ #include "kernel/logging.h"
+ #include "console-impl.h"
++#include "interfaces/suspend_support.h"
+ 
+ namespace miosix {
+ 
+@@ -77,6 +78,10 @@ void IRQbspInit()
+     #ifndef STDOUT_REDIRECTED_TO_DCC
+     IRQstm32f2serialPortInit();
+     #endif //STDOUT_REDIRECTED_TO_DCC
++    
++    #ifdef WITH_HIBERNATION    
++    IRQinitializeSuspendSupport();
++    #endif //WITH_HIBERNATION
+ }
+ 
+ void bspInit2()
+diff --git a/miosix/arch/cortexM3_stm32f2/stm32f207ig_stm3220g-eval/stm32_1m+128k_rom_processes.ld b/miosix/arch/cortexM3_stm32f2/stm32f207ig_stm3220g-eval/stm32_1m+128k_rom_processes.ld
+new file mode 100644
+index 0000000..6dc5b31
+--- /dev/null
++++ b/miosix/arch/cortexM3_stm32f2/stm32f207ig_stm3220g-eval/stm32_1m+128k_rom_processes.ld
+@@ -0,0 +1,170 @@
++/*
++ * C++ enabled linker script for stm32 (1M FLASH, 128K RAM)
++ * Developed by TFT: Terraneo Federico Technologies
++ * Optimized for use with the Miosix kernel
++ */
++
++/*
++ * This linker script puts:
++ * - read only data and code (.text, .rodata, .eh_*) in flash
++ * - stacks, heap and sections .data and .bss in the first 32KB of the internal ram
++ * - leaves the rest of the RAM (upper 96KB) is used as the process pool for
++ *   allocating processes.
++ * - the external ram (if available) is not used.
++ */
++
++/*
++ * 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  = 0x20000000 + _main_stack_size;
++ASSERT(_main_stack_size   % 8 == 0, "MAIN stack size error");
++
++/* end of the heap (32KB) */
++_heap_end = 0x20008000;                            /* end of available ram  */
++_process_pool_start = _heap_end;                   /* from 32KB to 128KB    */
++_process_pool_end = 0x20020000;
++
++/* identify the Entry Point  */
++ENTRY(_Z13Reset_Handlerv)
++
++/* specify the memory areas  */
++MEMORY
++{
++    flash(rx)   : ORIGIN = 0,          LENGTH = 1M
++
++    /*
++     * Note, the ram starts at 0x20000000 but it is necessary to add the size
++     * of the main stack, so it is 0x20000200.
++     */
++    ram(wx)     : ORIGIN = 0x20000200, LENGTH =  32K-0x200
++}
++
++/* 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 = .;
++    } > ram AT > flash
++
++    /* .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/config/Makefile.inc b/miosix/config/Makefile.inc
+index 940be46..5e8a726 100644
+--- a/miosix/config/Makefile.inc
++++ b/miosix/config/Makefile.inc
+@@ -28,8 +28,8 @@ OPT_BOARD := stm32f207ig_stm3220g-eval
+ ## -O2 is recomended otherwise, as it provides a good balance between code
+ ## size and speed
+ ##
+-OPT_OPTIMIZATION := -O0
+-#OPT_OPTIMIZATION := -O2
++#OPT_OPTIMIZATION := -O0
++OPT_OPTIMIZATION := -O2
+ #OPT_OPTIMIZATION := -O3
+ #OPT_OPTIMIZATION := -Os
+ 
+@@ -167,7 +167,8 @@ ifeq ($(OPT_BOARD),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
++    LINKER_SCRIPT := $(LINKER_SCRIPT_PATH)stm32_1m+128k_rom_processes.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
+@@ -177,7 +178,7 @@ ifeq ($(OPT_BOARD),stm32f207ig_stm3220g-eval)
+     ## none selected : don't use xram (with an appropriate linker script
+     ## selected above)
+     #XRAM := -D__ENABLE_XRAM
+-    XRAM := -D__ENABLE_XRAM -D__CODE_IN_XRAM
++    #XRAM := -D__ENABLE_XRAM -D__CODE_IN_XRAM
+ 
+ endif
+ 
+@@ -665,11 +666,13 @@ else ifeq ($(ARCH),cortexM3_stm32f2)
+ 
+         ## Select architecture specific files
+         ## These are the files in arch/<arch name>/<board name>
+-        ARCH_SRC :=                                  \
+-        $(ARCH_INC)/interfaces-impl/disk.cpp         \
+-        $(BOARD_INC)/interfaces-impl/console.cpp     \
+-        $(BOARD_INC)/interfaces-impl/delays.cpp      \
+-        $(BOARD_INC)/interfaces-impl/bsp.cpp
++        ARCH_SRC :=                                          \
++        $(ARCH_INC)/interfaces-impl/disk.cpp                 \
++        $(BOARD_INC)/interfaces-impl/console.cpp             \
++        $(BOARD_INC)/interfaces-impl/delays.cpp              \
++        $(ARCH_INC)/interfaces-impl/suspend_support_impl.cpp \
++        $(BOARD_INC)/interfaces-impl/bsp.cpp                 \
++        $(BOARD_INC)/drivers/mram.cpp
+ 
+         ## Add a #define to allow querying board name
+         CFLAGS_BASE   += -D_BOARD_STM3220G_EVAL
+diff --git a/miosix/config/miosix_settings.h b/miosix/config/miosix_settings.h
+index e0952f6..648c3c4 100644
+--- a/miosix/config/miosix_settings.h
++++ b/miosix/config/miosix_settings.h
+@@ -68,10 +68,19 @@ namespace miosix {
+ /// call service and, if the hardware supports it, the MPU to provide memory
+ /// isolation of processes
+ #define WITH_PROCESSES
++    
++/// \def WITH_HIBERNATION
++/// Enable process hibernation, allowing to save the state of processes and
++/// put the system in low power mode
++#define WITH_HIBERNATION
+ 
+ #if defined(WITH_PROCESSES) && defined(__NO_EXCEPTIONS)
+ #error Processes require C++ exception support
+ #endif //defined(WITH_PROCESSES) && defined(__NO_EXCEPTIONS)
++    
++#if defined(WITH_HIBERNATION) && !defined(WITH_PROCESSES)
++#error Hibernation requires processes
++#endif //defined(WITH_HIBERNATION) && !defined(WITH_PROCESSES)
+ 
+ //
+ // Filesystem options
+@@ -93,6 +102,9 @@ namespace miosix {
+ /// Maximum number of open files. Trying to open more will fail.
+ const unsigned char MAX_OPEN_FILES=8;
+ 
++/// Maximum number of threads a process can spawn
++const unsigned char MAX_THREADS_PER_PROCESS=2;
++
+ //
+ // C/C++ standard library I/O (stdin, stdout and stderr related)
+ //
+diff --git a/miosix/doc/textdoc/Changelog.txt b/miosix/doc/textdoc/Changelog.txt
+index 0965bd7..e04e3ab 100644
+--- a/miosix/doc/textdoc/Changelog.txt
++++ b/miosix/doc/textdoc/Changelog.txt
+@@ -1,7 +1,6 @@
+ Changelog for Miosix np embedded OS
+ 
+ v1.60
+-- Fixed a bug in FastMutex::get(): the member function was unimplemented.
+ - Fixed a bug in ST code for the stm3220g-eval board: despite having a 2MB RAM,
+   A18, A19 and A20 were left as GPIOs, resulting in issues when accessing the
+   upper part of the RAM.
+diff --git a/miosix/interfaces/portability.h b/miosix/interfaces/portability.h
+index 6d30928..89feb7b 100644
+--- a/miosix/interfaces/portability.h
++++ b/miosix/interfaces/portability.h
+@@ -261,11 +261,29 @@ class MPUConfiguration
+       * Print the MPU configuration for debugging purposes
+       */
+      void dumpConfiguration();
+- 
++     
++     /**
++      * \return the number of registers
++      */
++     int getNumRegisters()
++     {
++         return numRegisters;
++     }
++     
++     /**
++      * \return the pointer to the register array, used to configure the MPU
++      */
++     unsigned int* getRegValuesPtr()
++     {
++         return regValues;
++     }
++     
++     static const int numRegisters=4;
++     
+      //Uses default copy constructor and operator=
+ private:
+      ///These value are copied into the MPU registers to configure them
+-     unsigned int regValues[4]; 
++     unsigned int regValues[numRegisters]; 
+ };
+ 
+ #endif //WITH_PROCESSES
+diff --git a/miosix/interfaces/suspend_support.h b/miosix/interfaces/suspend_support.h
+new file mode 100644
+index 0000000..96d69cd
+--- /dev/null
++++ b/miosix/interfaces/suspend_support.h
+@@ -0,0 +1,101 @@
++/***************************************************************************
++ *   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 SUSPEND_SUPPORT_H
++#define	SUSPEND_SUPPORT_H
++
++#include "config/miosix_settings.h"
++
++#ifdef WITH_HIBERNATION
++
++namespace miosix {
++
++/**
++ * \return a pointer to the beginning of the backup SRAM area, that preserves
++ * its content through hibernation
++ */
++inline unsigned int *getBackupSramBase();
++
++/**
++ * \return the size of the backup SRAM
++ */
++inline int getBackupSramSize();
++
++/**
++ * Needs to be called from IRQbspInit() if hibernation support is enabled.
++ * None of the functions in this haeder can be called prior to this, as they
++ * might access uninitialized resources
++ */
++void IRQinitializeSuspendSupport();
++
++/**
++ * Enter hibernation mode for the specified number of seconds
++ * \param seconds after how much time the system will reboot
++ */
++void doSuspend(unsigned int seconds);
++
++/**
++ * \return true if this is the first boot, i.e. a boot caused by a reset
++ * assertion or power on. If returns false, this is a boot caused by an RTC
++ * wakeup, and in this case swapped processes need to be reloaded.
++ */
++bool firstBoot();
++
++/**
++ * \return size of the backup SRAM for the allocator status
++ *  
++ */
++int getAllocatorSramAreaSize();
++
++/**
++ * \return size of the backup SRAM for the backup allocator status
++ *  this includes four pointers, i.e. the base pointers to the four 
++ * region of the backup memory
++ */
++inline int getBackupAllocatorSramAreaSize();
++
++/**
++ * \return size of the backup SRAM for the Processes status serialization 
++ */
++inline int getProcessesSramAreaSize();
++
++/**
++ * \return size of the backup SRAM for network topology information 
++ */
++inline int getRoutingTableSramAreaSize();
++
++/**
++ * \return size of the backup SRAM for the queue of the smart drivers
++ */
++inline int getSmartDriversQueueSramAreaSize();
++
++} //namespace miosix
++
++// This contains the macros and the implementation of inline functions
++#include "interfaces-impl/suspend_support_impl.h"
++
++#endif  //WITH_HIBERNATION
++#endif	//SUSPEND_SUPPORT_H
+diff --git a/miosix/kernel/elf_program.cpp b/miosix/kernel/elf_program.cpp
+index bab4dea..98edc3f 100644
+--- a/miosix/kernel/elf_program.cpp
++++ b/miosix/kernel/elf_program.cpp
+@@ -30,6 +30,9 @@
+ #include <stdexcept>
+ #include <cstring>
+ #include <cstdio>
++#ifdef WITH_HIBERNATION
++#include "interfaces/suspend_support.h"
++#endif
+ 
+ using namespace std;
+ 
+@@ -142,9 +145,9 @@ bool ElfProgram::validateHeader()
+ bool ElfProgram::validateDynamicSegment(const Elf32_Phdr *dynamic,
+         unsigned int dataSegmentSize)
+ {
+-    unsigned int base=getElfBase();
++    const unsigned int base=reinterpret_cast<unsigned int>(getElfBase());
+     const Elf32_Dyn *dyn=
+-        reinterpret_cast<const Elf32_Dyn*>(getElfBase()+dynamic->p_offset);
++        reinterpret_cast<const Elf32_Dyn*>(base+dynamic->p_offset);
+     const int dynSize=dynamic->p_memsz/sizeof(Elf32_Dyn);
+     Elf32_Addr dtRel=0;
+     Elf32_Word dtRelsz=0;
+@@ -235,7 +238,7 @@ bool ElfProgram::validateDynamicSegment(const Elf32_Phdr *dynamic,
+ void ProcessImage::load(const ElfProgram& program)
+ {
+     if(image) ProcessPool::instance().deallocate(image);
+-    const unsigned int base=program.getElfBase();
++    const unsigned int base=reinterpret_cast<unsigned int>(program.getElfBase());
+     const Elf32_Phdr *phdr=program.getProgramHeaderTable();
+     const Elf32_Phdr *dataSegment=0;
+     Elf32_Addr dtRel=0;
+@@ -311,6 +314,22 @@ void ProcessImage::load(const ElfProgram& program)
+     }
+ }
+ 
++#ifdef WITH_HIBERNATION
++void ProcessImage::resume(ProcessStatus* status)
++{
++    image=status->processImageBase;
++    size=status->processImageSize;
++    //TODO: optimize
++    Mram& mram=Mram::instance();
++    mram.exitSleepMode();
++    //reload the image from MRAM to the main RAM
++    mram.read(reinterpret_cast<unsigned int>(image)-
++            ProcessPool::instance().getBaseAddress(),
++            image,size);
++    mram.enterSleepMode();
++}
++#endif //WITH_HIBERNATION
++
+ ProcessImage::~ProcessImage()
+ {
+     if(image) ProcessPool::instance().deallocate(image);
+diff --git a/miosix/kernel/elf_program.h b/miosix/kernel/elf_program.h
+index 5d5abed..08b09f3 100644
+--- a/miosix/kernel/elf_program.h
++++ b/miosix/kernel/elf_program.h
+@@ -31,6 +31,7 @@
+ #include <utility>
+ #include "elf_types.h"
+ #include "config/miosix_settings.h"
++#include "suspend_manager.h"
+ 
+ #ifdef WITH_PROCESSES
+ 
+@@ -88,11 +89,11 @@ public:
+     }
+     
+     /**
+-     * \return a number representing the elf base address in memory
++     * \return the elf base address in memory
+      */
+-    unsigned int getElfBase() const
++    const unsigned int *getElfBase() const
+     {
+-        return reinterpret_cast<unsigned int>(elf);
++        return elf;
+     }
+     
+     /**
+@@ -143,6 +144,15 @@ public:
+      */
+     void load(const ElfProgram& program);
+     
++    #ifdef WITH_HIBERNATION
++    /**
++     * Resume the image of a process in RAM after and hibernation
++     * including copying .data, zeroing .bss and performing
++     * relocations
++     */
++    void resume(ProcessStatus* status);
++    #endif //WITH_HIBERNATION
++    
+     /**
+      * \return a pointer to the base of the program image
+      */
+diff --git a/miosix/kernel/kernel.cpp b/miosix/kernel/kernel.cpp
+index 8bae046..0d7f8d5 100644
+--- a/miosix/kernel/kernel.cpp
++++ b/miosix/kernel/kernel.cpp
+@@ -34,6 +34,7 @@
+ #include "sync.h"
+ #include "process.h"
+ #include "kernel/scheduler/scheduler.h"
++#include "arch/cortexM4_stm32f4/common/arch_settings.h"
+ #include <stdexcept>
+ #include <algorithm>
+ #include <string.h>
+@@ -215,6 +216,13 @@ long long getTick()
+     }
+ }
+ 
++#ifdef WITH_HIBERNATION
++void IRQsetTick(long long newTick)
++{
++    tick=newTick;
++}
++#endif //WITH_HIBERNATION
++
+ /**
+  * \internal
+  * Used by Thread::sleep() to add a thread to sleeping list. The list is sorted
+@@ -738,6 +746,18 @@ void Thread::setupUserspaceContext(unsigned int entry, unsigned int *gotBase,
+     miosix_private::initCtxsave(cur->userCtxsave,startfunc,ep,0,gotBase);
+ }
+ 
++#ifdef WITH_HIBERNATION
++void Thread::serializeUserspaceContext(unsigned int registers[CTXSAVE_SIZE])
++{
++    memcpy(registers,this->userCtxsave,CTXSAVE_SIZE*sizeof(unsigned int));
++}
++
++void Thread::resumeUserspaceContext(unsigned int registers[CTXSAVE_SIZE])
++{
++    memcpy(cur->userCtxsave,registers,CTXSAVE_SIZE*sizeof(unsigned int));
++}
++#endif //WITH_HIBERNATION
++
+ #endif //WITH_PROCESSES
+ 
+ Thread::~Thread()
+diff --git a/miosix/kernel/kernel.h b/miosix/kernel/kernel.h
+index c2abb0d..3128a37 100644
+--- a/miosix/kernel/kernel.h
++++ b/miosix/kernel/kernel.h
+@@ -386,6 +386,16 @@ bool isKernelRunning();
+  */
+ long long getTick();
+ 
++#ifdef WITH_HIBERNATION
++/**
++ * \internal
++ * Used when resuming from hibernation to make sure the absolute time does not
++ * restart from zero. Note that calling this function everywhere but in
++ * IRQbspInit will result in undefined behaviour
++ */
++void IRQsetTick(long long newTick);
++#endif //WITH_HIBERNATION
++
+ //Declaration of the struct, definition follows below
+ struct SleepData;
+ 
+@@ -871,7 +881,7 @@ private:
+     };
+     
+     #ifdef WITH_PROCESSES
+-
++    
+     /**
+      * \internal
+      * Causes a thread belonging to a process to switch to userspace, and
+@@ -903,6 +913,24 @@ private:
+     static void setupUserspaceContext(unsigned int entry, unsigned int *gotBase,
+         unsigned int ramImageSize);
+     
++    #ifdef WITH_HIBERNATION
++    
++    /**
++     * Serialize the userspace registers of a thread.Can only be called on
++     * a thread that is not running in userpsace
++     * \param registers are the saved registers during hibernation
++     */
++    void serializeUserspaceContext(unsigned int registers[CTXSAVE_SIZE]);
++    
++    /**
++     * Resume 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 registers are the saved registers during hibernation
++     */
++    static void resumeUserspaceContext(unsigned int registers[CTXSAVE_SIZE]);
++    
++    #endif //WITH_HIBERNATION
++    
+     #endif //WITH_PROCESSES
+ 
+     /**
+diff --git a/miosix/kernel/process.cpp b/miosix/kernel/process.cpp
+index 9ac56c2..06d7e55 100644
+--- a/miosix/kernel/process.cpp
++++ b/miosix/kernel/process.cpp
+@@ -31,6 +31,7 @@
+ #include <cstring>
+ #include <sys/wait.h>
+ #include <signal.h>
++#include "suspend_manager.h"
+ #include "sync.h"
+ #include "process_pool.h"
+ #include "process.h"
+@@ -74,6 +75,7 @@ namespace miosix {
+ 
+ pid_t Process::create(const ElfProgram& program)
+ {
++    Lock<Mutex> l(SuspendManager::suspMutex);
+     auto_ptr<Process> proc(new Process(program));
+     {   
+         Lock<Mutex> l(procMutex);
+@@ -105,12 +107,134 @@ pid_t Process::create(const ElfProgram& program)
+     //thread has already been created but there's no memory to list it
+     //among the threads of a process
+     proc->threads.push_back(thr);
++    proc->numActiveThreads++;    
+     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::create(ProcessStatus* status, int threadId)
++{
++    Lock<Mutex> l(SuspendManager::suspMutex);
++    map<pid_t,Process*>::iterator findProc;
++    findProc=processes.find(status->pid);
++    
++    if(findProc==processes.end())
++        throw runtime_error("Unable to recreate the process after hibernation");
++    Process* proc=findProc->second;
++    
++    proc->image.resume(status);
++    
++    //TODO: look at it -- begin
++    #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 int _etext asm("_etext");
++    unsigned int flashEnd=reinterpret_cast<unsigned int>(&_etext);
++    if(flashEnd & (flashEnd-1)) flashEnd=1<<fhbs(flashEnd);
++    proc->mpu=miosix_private::MPUConfiguration(0,flashEnd,
++            proc->image.getProcessBasePointer(),proc->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,program.getElfBase(),elfSize);
++    mpu=miosix_private::MPUConfiguration(loadedProgram,roundedSize,
++            image.getProcessBasePointer(),image.getProcessImageSize());
++    #endif //__CODE_IN_XRAM
++    //TODO: look at it -- end
++    
++    
++    Thread *thr=Thread::createUserspace(Process::start,
++            status->interruptionPoints[threadId].registers,
++            Thread::DEFAULT,proc);
++    proc->toBeSwappedOut=true;
++    
++    if(thr==0)
++    {
++        Lock<Mutex> l(procMutex);
++        processes.erase(proc->pid);
++        if(Thread::getCurrentThread()->proc!=0)
++        {
++            Thread::getCurrentThread()->proc->childs.remove(proc);
++        } else kernelChilds.remove(proc);
++        delete proc;
++        throw runtime_error("Thread recreation 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);
++    proc->numActiveThreads++;
++    thr->wakeup(); //Actually start the thread, now that everything is set up
++    pid_t result=proc->pid;
++    return result;
++}
++
++pid_t Process::resume(const ElfProgram& program, ProcessStatus* status)
++{
++    auto_ptr<Process> proc(new Process(program,true));
++    //in this block we set the number of 
++    {
++        Lock<Mutex> l(SuspendManager::suspMutex);
++        proc->suspended=true;
++        SuspendManager::suspendedProcesses.push_back(proc.get());
++    }
++    proc->pid=status->pid;
++    proc->ppid=status->ppid;
++    if(status->status & 1) proc->zombie=true;
++    else proc->zombie=false;
++    proc->exitCode=status->exitCode;
++    proc->toBeSwappedOut=false;
++    
++    map<pid_t,Process*>::iterator findProc;
++    {   
++        Lock<Mutex> l(procMutex);
++        if(proc->ppid!=0)
++        {   
++            findProc=processes.find(proc->ppid);
++            //now we check if the parent is resumed and eventually become part
++            //of its childs list
++            if(findProc!=processes.end())
++            {
++                if(proc->zombie==false)
++                {
++                    findProc->second->childs.push_back(proc.get());
++                } else {
++                    findProc->second->zombies.push_back(proc.get());
++                }
++            }
++        } else {
++            kernelChilds.push_back(proc.get());
++        }
++        
++        //since there is not a sequential resume schedule, we need to check if
++        //we are parent of children already resumed and eventually add them to
++        //the parent childs list. The following "for" cycle pursues this goal
++        for(findProc=processes.begin(); findProc!=processes.end(); findProc++)
++        {
++            if(findProc->second->ppid==proc->pid)
++            {
++                if(findProc->second->zombie==false)
++                    proc->childs.push_back(findProc->second);
++                else
++                    proc->zombies.push_back(findProc->second);
++                        
++            }
++        }
++        
++        processes[proc->pid]=proc.get();
++    }
++    
++    proc.release(); //Do not delete the pointer
++    return proc->pid;
++}
++
+ pid_t Process::getppid(pid_t proc)
+ {
+     Lock<Mutex> l(procMutex);
+@@ -220,35 +344,97 @@ pid_t Process::waitpid(pid_t pid, int* exit, int options)
+     }
+ }
+ 
++void Process::serialize(ProcessStatus* ptr)
++{
++    ptr->pid=this->pid;
++    ptr->ppid=this->ppid;
++    ptr->processImageBase = this->image.getProcessBasePointer();
++    ptr->processImageSize = this->image.getProcessImageSize();
++    memcpy(ptr->fileDescriptors,this->fileTable,MAX_OPEN_FILES*sizeof(int));
++    #ifndef __CODE_IN_XRAM
++    ptr->programBase=this->program->getElfBase();
++    ptr->programSize=this->program->getElfSize();
++    iprintf("save base=%p size=%d\n",ptr->programBase,ptr->programSize);
++    #else //__CODE_IN_XRAM
++    ptr->programBase=this->loadedProgram;
++    ptr->programBase=reinterpret_cast<unsigned int*>(this->roundedSize);
++    #endif //__CODE_IN_XRAM
++
++    ptr->exitCode=this->exitCode;
++    ptr->numThreads=this->threads.size();
++            
++    if(this->zombie)
++        ptr->status=1;
++    else
++        ptr->status=0;
++    
++    //in this cycle the interruptionPoint structure is serialized
++    for(unsigned int i=0;i<this->threads.size();i++)
++    {
++        list<SyscallResumeTime>::iterator it;
++        for(it=SuspendManager::syscallReturnTime.begin();
++                it!=SuspendManager::syscallReturnTime.end();
++                it++)
++        {
++            if(this->pid==it->pid && i==it->threadNum)
++            {
++                ptr->interruptionPoints[i].absSyscallTime=it->resumeTime;
++                ptr->interruptionPoints[i].intPointID=it->intPointID;
++                ptr->interruptionPoints[i].fileID=it->fileID;
++                ptr->interruptionPoints[i].wakeNow=0;
++                //FIXME: the following two will become similar to those commented
++                ptr->interruptionPoints[i].backupQueue=NULL;
++                ptr->interruptionPoints[i].queueSize=0;
++                //ptr->interruptionPoints[i].backupQueue=getBackupQueueBase(this->pid, i);
++                //ptr->interruptionPoints[i].queueSize=getBackupQueueSize(this->pid, i);
++                ptr->interruptionPoints[i].targetSampleMem=
++                        reinterpret_cast<unsigned int*>(this->sampleBuf);
++                ptr->interruptionPoints[i].sizeOfSample=this->sizeOfSample;
++                ptr->interruptionPoints[i].sampNum=0; //must be filled by smart driver
++                this->threads[i]->serializeUserspaceContext(
++                        ptr->interruptionPoints[i].registers);
++            }
++        }
++    }
++    
++}
++
++
+ Process::~Process()
+ {
++    if(program)
++        delete program;
+     #ifdef __CODE_IN_XRAM
+     ProcessPool::instance().deallocate(loadedProgram);
+     #endif //__CODE_IN_XRAM
+ }
+ 
+-Process::Process(const ElfProgram& program) : program(program), waitCount(0),
+-        zombie(false)
++
++Process::Process(const ElfProgram& program, bool resuming)
++        : numActiveThreads(0), waitCount(0), zombie(false), suspended(false),
++          toBeSwappedOut(true)
+ {
++    this->program=new ElfProgram(program);
+     //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;
++    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);
++    else if(elfSize & (elfSize-1)) roundedSize=1<<fhbs(elfSize);
++    if(resuming) return;
++    //Done here so if not enough memory the new process is not even created
++    image.load(program);
+     #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);
++    extern unsigned int _etext asm("_etext");
++    unsigned int flashEnd=reinterpret_cast<unsigned int>(&_etext);
++    if(flashEnd & (flashEnd-1)) flashEnd=1<<fhbs(flashEnd);
+     mpu=miosix_private::MPUConfiguration(0,flashEnd,
+             image.getProcessBasePointer(),image.getProcessImageSize());
+ //    mpu=miosix_private::MPUConfiguration(program.getElfBase(),roundedSize,
+@@ -256,23 +442,40 @@ Process::Process(const ElfProgram& program) : program(program), waitCount(0),
+     //FIXME -- end
+     #else //__CODE_IN_XRAM
+     loadedProgram=ProcessPool::instance().allocate(roundedSize);
+-    memcpy(loadedProgram,reinterpret_cast<char*>(program.getElfBase()),elfSize);
++    memcpy(loadedProgram,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();
++    unsigned int entry=proc->program->getEntryPoint();
+     #ifdef __CODE_IN_XRAM
+-    entry=entry-proc->program.getElfBase()+
++    entry=entry-reinterpret_cast<unsigned int>(proc->program->getElfBase())+
+         reinterpret_cast<unsigned int>(proc->loadedProgram);
+     #endif //__CODE_IN_XRAM
+-    Thread::setupUserspaceContext(entry,proc->image.getProcessBasePointer(),
+-        proc->image.getProcessImageSize());
++    if(proc->suspended==false)
++        Thread::setupUserspaceContext(entry,proc->image.getProcessBasePointer(),
++            proc->image.getProcessImageSize());
++    else
++    {
++        if(argv)
++            Thread::resumeUserspaceContext(reinterpret_cast<unsigned int*>(argv));
++        else
++            errorHandler(UNEXPECTED);
++        //in the following block the process is removed from the list of the
++        //suspended processes, after hibernation
++        {
++            Lock<Mutex> l(SuspendManager::suspMutex);
++            proc->suspended=false;
++            SuspendManager::suspendedProcesses.remove(proc);    
++        }
++    }
+     bool running=true;
+     do {
+         miosix_private::SyscallParameters sp=Thread::switchToUserspace();
+@@ -282,18 +485,28 @@ void *Process::start(void *argv)
+             proc->exitCode=SIGSEGV; //Segfault
+             #ifdef WITH_ERRLOG
+             iprintf("Process %d terminated due to a fault\n"
+-                    "* Code base address was 0x%x\n"
++                    "* Code base address was %p\n"
+                     "* Data base address was %p\n",proc->pid,
+                     #ifndef __CODE_IN_XRAM
+-                    proc->program.getElfBase(),
++                    proc->program->getElfBase(),
+                     #else //__CODE_IN_XRAM
+-                    reinterpret_cast<unsigned int>(proc->loadedProgram),
++                    proc->loadedProgram,
+                     #endif //__CODE_IN_XRAM
+                     proc->image.getProcessBasePointer());
+             proc->mpu.dumpConfiguration();
+             proc->fault.print();
+             #endif //WITH_ERRLOG
+         } else {
++            int threadID=-1;
++         
++            for(unsigned int i=0;i<proc->threads.size();i++)
++            {
++                if(proc->threads[i]==Thread::getCurrentThread())
++                    threadID=i;
++            }
++            if(threadID==-1)
++                errorHandler(UNEXPECTED);
++            
+             switch(sp.getSyscallId())
+             {
+                 case 2:
+@@ -302,17 +515,22 @@ void *Process::start(void *argv)
+                     break;
+                 case 3:
+                     //FIXME: check that the pointer belongs to the process
++                    
+                     sp.setReturnValue(write(sp.getFirstParameter(),
+                         reinterpret_cast<const char*>(sp.getSecondParameter()),
+                         sp.getThirdParameter()));
+                     break;
+                 case 4:
+                     //FIXME: check that the pointer belongs to the process
++             
+                     sp.setReturnValue(read(sp.getFirstParameter(),
+                         reinterpret_cast<char*>(sp.getSecondParameter()),
+                         sp.getThirdParameter()));
+                     break;
+-                case 5: 
++                case 5:
++                    if(sp.getFirstParameter()>=1000000)
++                        SuspendManager::enterInterruptionPoint(proc,threadID,
++                            sp.getFirstParameter()/1000000,5,-1);
+                     sp.setReturnValue(usleep(sp.getFirstParameter()));
+                     break;
+                 default:
+@@ -368,13 +586,14 @@ pid_t Process::getNewPid()
+     }
+ }
+ 
++
+ 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
+index dc54e1a..cf83b5f 100644
+--- a/miosix/kernel/process.h
++++ b/miosix/kernel/process.h
+@@ -36,6 +36,7 @@
+ #include "sync.h"
+ #include "elf_program.h"
+ #include "config/miosix_settings.h"
++#include "suspend_manager.h"
+ 
+ #ifdef WITH_PROCESSES
+ 
+@@ -57,6 +58,27 @@ public:
+     static pid_t create(const ElfProgram& program);
+     
+     /**
++     * Overloaded version that recreate a process after hibernation
++     * \param status is the serialized status of the process
++     * \param threadID is the number of the thread to be resumed
++     * \return the same pid of the original process
++     * \throws std::exception or a subclass in case of errors, including
++     * not emough memory to spawn the process
++     */
++    static pid_t create(ProcessStatus* status, int threadId);
++    
++    
++    /**
++     * Recreate a process after the hibernation, exactly as it was before
++     * \param program Program that the process will execute 
++     * \param ptr to the serialized status of the process in the backup RAM
++     * \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 resume(const ElfProgram& program, ProcessStatus* status);
++    
++    /**
+      * 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
+@@ -85,6 +107,20 @@ public:
+     static pid_t waitpid(pid_t pid, int *exit, int options);
+     
+     /**
++     * Save the state of the allocator 
++     * \param ptr pointer to a memory area of type ProcessStatus
++     * \param interruptionId id of the syscal that caused the interruption
++     * \param fileID file opened by the syscall
++     * \param sleepTime time to sleep for the syscall, actual or estimed,
++     * the latter case accounts for all the syscalls that are not sleep()
++     * \param sampleBuf pointer to the area of memore where the results of
++     * the syscall will be copied. Usefuls in case of smart drivers 
++     */
++    void serialize(ProcessStatus* ptr);
++    
++    
++    
++    /**
+      * Destructor
+      */
+     ~Process();
+@@ -96,8 +132,11 @@ private:
+     /**
+      * Constructor
+      * \param program program that will be executed by the process
++     * \param resuming true if resuming from hibernation
+      */
+-    Process(const ElfProgram& program);
++    Process(const ElfProgram& program, bool resuming=false);
++    
++
+     
+     /**
+      * Contains the process' main loop. 
+@@ -106,13 +145,14 @@ private:
+      */
+     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
++    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
+@@ -121,12 +161,13 @@ private:
+     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
+     pid_t pid;  ///<The pid of this process
+     pid_t ppid; ///<The parent pid of this process
++    ///number of the threads active, i.e. not suspended, in the process
++    int numActiveThreads; 
+     ///Contains the count of active wait calls which specifically requested
+     ///to wait on this process
+     int waitCount;
+@@ -134,7 +175,11 @@ private:
+     ///wait on this condition variable
+     ConditionVariable waiting;
+     bool zombie; ///< True for terminated not yet joined processes
++    bool suspended;
++    bool toBeSwappedOut;///This is set true only if a processs need to be
++                        ///swapped out when hibernating
+     short int exitCode; ///< Contains the exit code
++    int fileTable[MAX_OPEN_FILES];///table of files opened by the process
+     
+     ///Maps the pid to the Process instance. Includes zombie processes
+     static std::map<pid_t,Process *> processes;
+@@ -146,6 +191,16 @@ private:
+     static Mutex procMutex;
+     ///Used to wait on process termination
+     static ConditionVariable genericWaiting;
++    //Used to take account of the ELF size opportunely rounded to suit for MPU 
++    unsigned int roundedSize;
++    //FIXME: the following two must be implemented in future (smart drivers)
++    ///The following buffer has to be initialized in the constructor to store samples
++    void* sampleBuf;
++    ///the following will store the size of a sample to be retrieved from sensors
++    ///it should be initialized in the constructor too
++    int sizeOfSample;
++    
++    
+     
+     //Needs access to fault,mpu
+     friend class Thread;
+@@ -155,6 +210,8 @@ private:
+     friend class ControlScheduler;
+     //Needs access to mpu
+     friend class EDFScheduler;
++    //Nedds access interruption point and resume methods, to handle hibernation
++    friend class SuspendManager;
+ };
+ 
+ } //namespace miosix
+diff --git a/miosix/kernel/process_pool.cpp b/miosix/kernel/process_pool.cpp
+index a3401f4..8d53fbe 100644
+--- a/miosix/kernel/process_pool.cpp
++++ b/miosix/kernel/process_pool.cpp
+@@ -90,7 +90,7 @@ 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);
++    map<const 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)-
+diff --git a/miosix/kernel/process_pool.h b/miosix/kernel/process_pool.h
+index 26f5d15..c9b6064 100644
+--- a/miosix/kernel/process_pool.h
++++ b/miosix/kernel/process_pool.h
+@@ -25,20 +25,30 @@
+  *   along with this program; if not, see <http://www.gnu.org/licenses/>   *
+  ***************************************************************************/ 
+ 
+-#ifndef PROCESS_POOL
+-#define PROCESS_POOL
++#ifndef PROCESS_POOL_H
++#define PROCESS_POOL_H
++
++#include "config/miosix_settings.h"
++
++#ifdef WITH_PROCESSES
+ 
+ #include <map>
+ 
+ #ifndef TEST_ALLOC
++
+ #include <miosix.h>
++#include <cstring>
++#ifdef WITH_HIBERNATION
++#include "suspend_manager.h"
++#endif //WITH_HIBERNATION
++
+ #else //TEST_ALLOC
++
+ #include <iostream>
+ #include <typeinfo>
+ #include <sstream>
+-#endif //TEST_ALLOC
+ 
+-#ifdef WITH_PROCESSES
++#endif //TEST_ALLOC
+ 
+ namespace miosix {
+ 
+@@ -105,13 +115,53 @@ public:
+         }  
+     }
+     #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;
++
++    #ifdef WITH_HIBERNATION
++    /**
++     * \return a pointer to the base address of the memory pool
++     */
++    const unsigned int getBaseAddress() const
++    {
++        return reinterpret_cast<unsigned int>(poolBase);
++    }
++    /**
++     * \return the dimension of the data to be serialized at the
++     * moment of the hibernation 
++     */
++    int getSerializableSize()
++    {
++        return (sizeof(unsigned int)+poolSize/blockSize/8);
++    }
+     
++    void serialize(unsigned int* ptr)
++    {
++        *ptr=poolSize; //TODO: this does not need to be serialized
++        ptr++;
++        memcpy(ptr, bitmap,poolSize/blockSize/8);
++    }
++
++    void resume(unsigned int* ptrAlloc, ProcessStatus* backupPtr, int numProc)
++    {
++        poolSize=*ptrAlloc;
++        ptrAlloc++;
++        memcpy(bitmap,ptrAlloc,poolSize/blockSize/8);
++        for(int i=0;i<numProc;i++)
++        {
++            allocatedBlocks[backupPtr->processImageBase]=backupPtr->processImageSize;
++            #ifdef __CODE_IN_XRAM
++            allocatedBlocks[backupPtr->programBase]=backupPtr->programSize;
++            #endif //__CODE_IN_XRAM
++            backupPtr++;
++        }
++    }
++    #endif //WITH_HIBERNATION
++   
+ private:
+     ProcessPool(const ProcessPool&);
+     ProcessPool& operator= (const ProcessPool&);
+@@ -160,7 +210,7 @@ private:
+     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;
++    std::map<const unsigned int*,unsigned int> allocatedBlocks;
+     #ifndef TEST_ALLOC
+     miosix::FastMutex mutex; ///< Mutex to guard concurrent access
+     #endif //TEST_ALLOC
+@@ -170,4 +220,4 @@ private:
+ 
+ #endif //WITH_PROCESSES
+ 
+-#endif //PROCESS_POOL
++#endif //PROCESS_POOL_H
+diff --git a/miosix/kernel/suspend_manager.cpp b/miosix/kernel/suspend_manager.cpp
+new file mode 100644
+index 0000000..fb11ee3
+--- /dev/null
++++ b/miosix/kernel/suspend_manager.cpp
+@@ -0,0 +1,248 @@
++/***************************************************************************
++ *   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/>   *
++ ***************************************************************************/
++
++#include "suspend_manager.h"
++#include "interfaces/suspend_support.h"
++#include "elf_program.h"
++#include "process.h"
++#include "interfaces/suspend_support.h"
++#include "process_pool.h"
++#include <cstring>
++#include <cstdio>
++#include <stdexcept>
++
++#ifdef WITH_HIBERNATION
++
++using namespace std;
++
++namespace miosix {
++
++ProcessStatus* SuspendManager::getProcessesBackupAreaBase()
++{
++    return reinterpret_cast<struct ProcessStatus*>(
++                            reinterpret_cast<unsigned int>(getBackupSramBase())+
++                            getAllocatorSramAreaSize()+ 
++                            getBackupAllocatorSramAreaSize());
++}
++
++/*
++ *The following functions is used to sort the list of resuming time
++ */
++bool compareResumeTime(SyscallResumeTime first, SyscallResumeTime second )
++{
++    return first.resumeTime<second.resumeTime;
++}
++
++/*
++ *The following function is called each time a thread enter in a system call
++ * in order to update the status of the thread, and eventually of the process, 
++ * from 'suspended=false' to 'suspended=true', possibly. Moreover, if all the
++ * processes are suspended, this function signal the hibernation thread (through
++ * the condition variable), which will decide whether to hibernate or not the
++ * system.
++ */
++void SuspendManager::enterInterruptionPoint(Process* proc, int threadID,
++        long long resumeTime, int intPointID, int fileID)
++{
++    SyscallResumeTime newSuspThread;
++    newSuspThread.status=NULL;
++    newSuspThread.pid=proc->pid;
++    newSuspThread.resumeTime=resumeTime+getTick()/1000;
++    newSuspThread.threadNum=threadID;
++    newSuspThread.intPointID=intPointID;
++    newSuspThread.fileID=fileID; 
++    
++    {
++        Lock<Mutex> l(suspMutex);
++        proc->numActiveThreads--;
++        //FIXME: what if the system does not go in hibernation for a long time
++        //because the threshold is never met? this thing continues to push data
++        //in this list, causing a memory leak that will crash the whole OS!!
++        syscallReturnTime.push_back(newSuspThread);
++        if(proc->numActiveThreads==0)
++        {
++            proc->suspended=true;
++            suspendedProcesses.push_back(proc);
++        }
++        if(suspendedProcesses.size()==Process::processes.size())
++            hibernWaiting.broadcast();
++    }
++    
++}
++
++
++/*
++ *The following thread create the threds of processes at the time they myust be
++ * resumed
++ */
++void SuspendManager::wakeupDaemon(void*)
++{
++    map<pid_t,Process*>::iterator findProc;
++    Lock<Mutex> l(suspMutex);
++    while(syscallReturnTime.empty()==false)
++    {
++        SyscallResumeTime ret=syscallReturnTime.front();
++        if(ret.resumeTime>=getTick()/1000)
++        {
++            findProc=Process::processes.find(ret.pid);
++            //check if the process is already alive...it could happen that
++            //the main thread has already been spawned and is also terminated
++            //so other threads waiting to be resumed must be not be created.
++            //In any case, at the end of the cycle, the process must be 
++            //erased from the syscallReturnTime list
++            if(findProc!=Process::processes.end())
++                Process::create(ret.status,ret.threadNum);
++            syscallReturnTime.pop_front();
++        } else {
++            long long resumeTime=ret.resumeTime;
++            {    
++                Unlock<Mutex> u(l);
++                sleep(resumeTime-getTick()/1000);
++            }
++        }
++    }
++}
++
++/*
++ *The following thread function wait for all the processes to be suspended and
++ * then decide whether to hibernate or not..
++ */
++void SuspendManager::hibernateDaemon(void*)
++{
++    Lock<Mutex>l(suspMutex);
++    for(;;)
++    { 
++        hibernWaiting.wait(l);
++        syscallReturnTime.sort(compareResumeTime);
++        list<SyscallResumeTime>::iterator it;
++        it=syscallReturnTime.begin();
++        //NOTE: the following if, as well as the upper and lower bunds,
++        //will be replaced by the policy, once refined 
++        if((it->resumeTime-getTick()/1000)<=hibernationThreshold) continue;
++        ProcessStatus* proc=getProcessesBackupAreaBase();
++        iprintf("Swapping %d processes\n",suspendedProcesses.size());
++        list<Process*>::iterator findProc;
++        for(findProc=suspendedProcesses.begin();
++                findProc!=suspendedProcesses.end();findProc++)
++        {
++            (*findProc)->serialize(proc);
++
++            if((*findProc)->toBeSwappedOut)
++            {
++                //TODO: optimize
++                Mram& mram=Mram::instance();
++                mram.exitSleepMode();
++                //Copy the process image from RAM to MRAM
++                mram.write(reinterpret_cast<unsigned int>(
++                        (*findProc)->image.getProcessBasePointer())-
++                        ProcessPool::instance().getBaseAddress(),
++                        (*findProc)->image.getProcessBasePointer(),
++                        (*findProc)->image.getProcessImageSize());
++                mram.enterSleepMode();
++                //Now serialize the state of the SRAM allocator
++                ProcessPool::instance().serialize(getBackupSramBase());
++
++                //Now serialize the state of the backup SRAM allocator
++                (*(getBackupSramBase()+ 
++                        getAllocatorSramAreaSize()/sizeof(int)))=
++                        suspendedProcesses.size();
++            }
++            proc++;
++        }
++        
++//        iprintf("Backup SRAM\n");
++//        memDump((char*)getBackupSramBase(),getBackupSramSize());
++//        Mram& mram=Mram::instance();
++//        mram.exitSleepMode();
++//        char *buf=new char[131072];
++//        mram.read(0,buf,32768);
++//        mram.read(32768,buf+32768,32768);
++//        mram.read(2*32768,buf+2*32768,32768);
++//        mram.read(3*32768,buf+3*32768,32768);
++//        mram.enterSleepMode();
++//        iprintf("MRAM\n");
++//        memDump(buf,131072);
++//        delete[] buf;
++        
++        long long prev=getTick();
++        int sleepTime=syscallReturnTime.begin()->resumeTime-prev/1000;
++        iprintf("about to suspend, tick=%lld\n",prev);
++        getBackupSramBase()[1021]=prev & 0xffffffff; //FIXME: hack
++        getBackupSramBase()[1022]=prev>>32;
++        getBackupSramBase()[1023]=sleepTime;
++        doSuspend(sleepTime);
++    }
++}
++
++int SuspendManager::resume()
++{
++    ProcessStatus* proc=getProcessesBackupAreaBase();
++    
++    ProcessPool::instance().resume(getBackupSramBase(),
++            getProcessesBackupAreaBase(),
++            *(getBackupSramBase()+(getAllocatorSramAreaSize()/sizeof(int))));
++    //in the following block the processes map and 
++    //the list syscallReturnTime are populated
++    {
++        Lock<Mutex>l(SuspendManager::suspMutex);
++        SyscallResumeTime retTime;
++        int numProc=*(getBackupSramBase()+(getAllocatorSramAreaSize()/sizeof(int)));
++        iprintf("Reloading %d processes\n",numProc);
++        for(int i=0;i<numProc;i++)
++        {   
++            iprintf("reload base=%p size=%d\n",proc->programBase,proc->programSize);
++            Process::resume(ElfProgram(proc->programBase,proc->programSize),proc);
++            for(int i=0;i<proc->numThreads;i++)
++            {   
++                retTime.pid=proc->pid;
++                retTime.threadNum=i;
++                retTime.resumeTime=proc->interruptionPoints[i].absSyscallTime;
++                retTime.status=proc;
++                syscallReturnTime.push_back(retTime);
++            }
++            proc++;
++        }
++        syscallReturnTime.sort(compareResumeTime);
++    }
++
++    Thread::create(wakeupDaemon,2048);
++    return proc->pid;
++}
++
++void SuspendManager::startHibernationDaemon()
++{
++    Thread::create(hibernateDaemon,2048);
++}
++
++std::list<SyscallResumeTime> SuspendManager::syscallReturnTime;
++Mutex SuspendManager::suspMutex(Mutex::RECURSIVE);
++ConditionVariable SuspendManager::hibernWaiting;
++std::list<Process *> SuspendManager::suspendedProcesses;
++
++}//namespace miosix
++
++#endif //WITH_HIBERNATION
+diff --git a/miosix/kernel/suspend_manager.h b/miosix/kernel/suspend_manager.h
+new file mode 100644
+index 0000000..1c48e4f
+--- /dev/null
++++ b/miosix/kernel/suspend_manager.h
+@@ -0,0 +1,141 @@
++/***************************************************************************
++ *   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 SUSPEND_MANAGER_H
++#define	SUSPEND_MANAGER_H
++
++#include <list>
++#include <miosix.h>
++#include "interfaces/portability.h"
++#include "config/miosix_settings.h"
++
++#ifdef WITH_HIBERNATION
++
++namespace miosix {
++    
++///This struct is used to serialize the interrupion point status for processes
++///and threads spawned by that process
++struct IntPointStatus{
++    int intPointID; //ID of the syscall which caused the interruption
++    int fileID; //file eventually opened by the syscall, -1 if no file opened
++    long long absSyscallTime; //absolute time taken by the syscall to resume
++    unsigned int* backupQueue; //ptr to the process queue in the backupe SRAM
++    int queueSize; //size of the queue associated to the process
++    char wakeNow;//set to one if the process or thread has to wake up now
++    char sizeOfSample; //size of the data sampled in the hibernation period
++    char padding1[2];
++    int sampNum; //number of the samples eventually performed by smart driver
++    unsigned int registers[CTXSAVE_SIZE];
++    unsigned int* targetSampleMem; //process memory pointer to copy the queue
++}__attribute__((packed));
++    
++    
++///This struct is used to serialize the process status in the backup SRAM 
++struct ProcessStatus 
++{
++    int pid;
++    int ppid;
++    short int status;
++    short int numThreads;
++    int exitCode;
++    unsigned int* processImageBase;
++    int processImageSize;
++    const unsigned int* programBase;
++    int programSize;
++    int fileDescriptors[MAX_OPEN_FILES];
++    struct IntPointStatus interruptionPoints[1+MAX_THREADS_PER_PROCESS];
++} __attribute__((packed));
++
++//this struct is used to keep track of the resume time after a syscall for each
++//process and for each thread in a process
++struct SyscallResumeTime
++{
++    int pid;
++    short int threadNum;
++    long long resumeTime;
++    int intPointID;
++    int fileID;
++    ProcessStatus* status;
++}__attribute__((packed));
++
++
++class SuspendManager 
++{
++public:    
++    /**
++     * /return the base address of the process status backup area 
++     */
++    static ProcessStatus* getProcessesBackupAreaBase();
++    
++    /**
++     * Find the the serialized processes with invalid bit set,
++     * which must be serialzied again. Return -1 if no dirty processes status
++     * are found
++     */
++    static int resume();
++    
++    /**
++     * Enables the hibernation support
++     */
++    static void startHibernationDaemon();
++
++private:
++    static void wakeupDaemon(void*);
++    static void hibernateDaemon(void*);
++    /**
++     * @param pid pid of the process in which the syscall has benn called
++     * @param threadID id of the thread which called the system call
++     * @param resumeTime is the time at which the thread will be resumed after
++     * the suspension due to the system call
++     */
++    static void enterInterruptionPoint(Process* proc, int threadID, 
++        long long resumeTime, int syscallID, int fileID);
++    
++    static std::list<SyscallResumeTime> syscallReturnTime;
++    ///Used to guard access to the number of suspended processes
++    static Mutex suspMutex;
++    ///Used to wait on the condition that all process must be suspended to
++    ///decide if to hibernate or not the system. The suspension of all processes
++    ///is a necessary condition for hibernationm, but not sufficient. The final
++    ///decision is taken according to the hibernation policy.
++    static ConditionVariable hibernWaiting;
++    ///this map lists the suspended processes
++    static std::list<Process *> suspendedProcesses;
++    
++    //Sleep time below which hibernation will not occur (in seconds)
++    static const int hibernationThreshold=1;
++    
++    //Needs access to process table, serialization/loading methods
++    friend class Process;
++    
++};
++
++}//namespace miosix
++
++#endif //WITH_HIBERNATION
++
++#endif //SUSPEND_MANAGER_H
+diff --git a/miosix/kernel/sync.h b/miosix/kernel/sync.h
+index 26339a5..1f484c1 100644
+--- a/miosix/kernel/sync.h
++++ b/miosix/kernel/sync.h
+@@ -115,12 +115,9 @@ public:
+ 
+     /**
+      * \internal
+-     * \return the FastMutex implementation defined mutex type
++     * \return the FastMutex implemntation defined mutex type
+      */
+-    pthread_mutex_t *get()
+-    {
+-        return &impl;
+-    }
++    pthread_mutex_t *get();
+ 
+     /**
+      * Destructor
+diff --git a/miosix/temp/ram_test/mram_test.cpp b/miosix/temp/ram_test/mram_test.cpp
+new file mode 100644
+index 0000000..3c8133a
+--- /dev/null
++++ b/miosix/temp/ram_test/mram_test.cpp
+@@ -0,0 +1,67 @@
++
++// To test the MRAM for hibernation
++
++#include <cstdio>
++#include <cstdlib>
++#include <cstring>
++#include "sha1.h"
++#include <interfaces/suspend_support.h>
++
++using namespace std;
++
++bool shaCmp(unsigned int a[5], unsigned int b[5])
++{
++    if(memcmp(a,b,20)==0) return false;
++    iprintf("Mismatch\n");
++    for(int i=0;i<5;i++) iprintf("%04x",a[i]); iprintf("\n");
++    for(int i=0;i<5;i++) iprintf("%04x",b[i]); iprintf("\n");
++    return true;
++}
++
++bool mramTest(int writeSize, int readSize)
++{
++    char *writeBuffer=new char[writeSize];
++    char *readBuffer=new char[readSize];
++    Mram& mram=Mram::instance();
++    mram.exitSleepMode();
++    
++    SHA1 sha;
++    sha.Reset();
++    //Just to shuffle initialization between tests
++    srand(0x7ad3c099+0xad45fce0*writeSize+0x658da2fb*readSize);
++    for(unsigned int i=0;i<mram.size();i+=writeSize)
++    {
++        for(int j=0;j<writeSize;j++) writeBuffer[j]=rand() & 0xff;
++        mram.write(i,writeBuffer,writeSize);
++        sha.Input(writeBuffer,writeSize);
++    }
++    unsigned int a[5];
++    sha.Result(a);
++    
++    sha.Reset();
++    for(unsigned int i=0;i<mram.size();i+=readSize)
++    {
++        mram.read(i,readBuffer,readSize);
++        sha.Input(readBuffer,readSize);
++    }
++    unsigned int b[5];
++    sha.Result(b);
++    
++    delete[] writeBuffer;
++    delete[] readBuffer;
++    
++    return shaCmp(a,b);
++}
++
++int main()
++{  
++    getchar();
++    puts("MRAM test");
++    puts("Testing w=1024, r=1024");
++    if(mramTest(1024,1024)) return 1;
++    puts("Testing w=512, r=1024");
++    if(mramTest(512,1024)) return 1;
++    puts("Testing w=1024, r=512");
++    if(mramTest(1024,512)) return 1;
++    puts("Ok");
++}
+diff --git a/miosix/util/util.cpp b/miosix/util/util.cpp
+index 6f1ca57..242b64a 100644
+--- a/miosix/util/util.cpp
++++ b/miosix/util/util.cpp
+@@ -163,4 +163,12 @@ unsigned int MemoryProfiling::getCurrentFreeHeap()
+     return (unsigned int)&_heap_end - (unsigned int)highWatermark;
+ }
+ 
++int fhbs(unsigned int x)
++{
++    //TODO: Optimize!
++    int result=0;
++    while(x) { x>>=1; result++; }
++    return result;
++}
++
+ } //namespace miosix
+diff --git a/miosix/util/util.h b/miosix/util/util.h
+index 09a8af4..c0c433b 100644
+--- a/miosix/util/util.h
++++ b/miosix/util/util.h
+@@ -110,6 +110,15 @@ private:
+ void memDump(const char *start, int len);
+ 
+ /**
++ * Find highest bit set
++ * \param x a 32bit number
++ * \return 0 if the number is zero, or the position of the highest bit
++ * FIXME: Put this function in a more appropriate place, away from the
++ * interfaces/arch
++ */
++int fhbs(unsigned int x);
++
++/**
+  * \}
+  */
+ 
+diff --git a/miosix_np_processes/nbproject/configurations.xml b/miosix_np_processes/nbproject/configurations.xml
+index f048ef9..d1eaa78 100644
+--- a/miosix_np_processes/nbproject/configurations.xml
++++ b/miosix_np_processes/nbproject/configurations.xml
+@@ -7,12 +7,6 @@
+         <in>main.c</in>
+         <in>prog3.h</in>
+       </df>
+-      <df name="app_template_withlibs">
+-        <in>crt0.s</in>
+-        <in>main.c</in>
+-        <in>prog3.h</in>
+-        <in>syscallfuffa.c</in>
+-      </df>
+       <df name="miosix">
+         <df name="arch">
+           <df name="arm7_lpc2000">
+@@ -162,6 +156,8 @@
+                 <in>gpio_impl.h</in>
+                 <in>portability.cpp</in>
+                 <in>portability_impl.h</in>
++                <in>suspend_support_impl.cpp</in>
++                <in>suspend_support_impl.h</in>
+               </df>
+               <in>arch_settings.h</in>
+             </df>
+@@ -169,6 +165,10 @@
+               <df name="core">
+                 <in>stage_1_boot.cpp</in>
+               </df>
++              <df name="drivers">
++                <in>mram.cpp</in>
++                <in>mram.h</in>
++              </df>
+               <df name="interfaces-impl">
+                 <in>bsp.cpp</in>
+                 <in>bsp_impl.h</in>
+@@ -267,6 +267,7 @@
+           <in>endianness.h</in>
+           <in>gpio.h</in>
+           <in>portability.h</in>
++          <in>suspend_support.h</in>
+         </df>
+         <df name="kernel">
+           <df name="filesystem">
+@@ -315,6 +316,8 @@
+           <in>pthread.cpp</in>
+           <in>pthread_private.h</in>
+           <in>stage_2_boot.cpp</in>
++          <in>suspend_manager.cpp</in>
++          <in>suspend_manager.h</in>
+           <in>sync.cpp</in>
+           <in>sync.h</in>
+           <in>syscalls.cpp</in>
+diff --git a/profiling.patch b/profiling.patch
+new file mode 100644
+index 0000000..32295a7
+--- /dev/null
++++ b/profiling.patch
+@@ -0,0 +1,175 @@
++diff --git a/main.cpp b/main.cpp
++index b991f7f..8486f3b 100644
++--- a/main.cpp
+++++ b/main.cpp
++@@ -26,10 +26,11 @@ int main()
++ {
++     Thread::create(ledThread,STACK_MIN);
++     SuspendManager::startHibernationDaemon();
++-    iprintf("tick=%llu\n",getTick());
+++//    iprintf("tick=%llu\n",getTick());
++     if(firstBoot())
++     {
++-        puts("First boot");
+++        Gpio<GPIOC_BASE,7>::low(); //FIXME: remove
+++//        puts("First boot");
++ //        //Watermarking
++ //        memset(getBackupSramBase(),0xff,getBackupSramSize());
++ //        char *buf=new char[1024];
++@@ -41,7 +42,7 @@ int main()
++ //        mram.enterSleepMode();
++ //        delete[] buf;
++     } else {
++-        puts("RTC boot");
+++//        puts("RTC boot");
++         SuspendManager::resume();
++         
++         int ec;
++diff --git a/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/suspend_support_impl.cpp b/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/suspend_support_impl.cpp
++index dda8f03..688d725 100644
++--- a/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/suspend_support_impl.cpp
+++++ b/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/suspend_support_impl.cpp
++@@ -30,6 +30,7 @@
++ #include "kernel/process_pool.h"
++ #include "miosix.h"
++ #include "interfaces/arch_registers.h"
+++#include "interfaces/gpio.h" //FIXME: remove
++ 
++ #ifdef WITH_HIBERNATION
++ 
++@@ -81,6 +82,9 @@ void doSuspend(unsigned int seconds)
++ 
++         PWR->CR |= PWR_CR_PDDS | PWR_CR_CWUF;
++         SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
+++        
+++        Gpio<GPIOC_BASE,7>::low(); //FIXME: remove
+++        
++         //Using WFE instead of WFI because if while we are with interrupts
++         //disabled an interrupt (such as the tick interrupt) occurs, it
++         //remains pending and the WFI becomes a nop, and the device never goes
++diff --git a/miosix/arch/cortexM3_stm32f2/stm32f207ig_stm3220g-eval/core/stage_1_boot.cpp b/miosix/arch/cortexM3_stm32f2/stm32f207ig_stm3220g-eval/core/stage_1_boot.cpp
++index 18663fb..cfe8e6f 100644
++--- a/miosix/arch/cortexM3_stm32f2/stm32f207ig_stm3220g-eval/core/stage_1_boot.cpp
+++++ b/miosix/arch/cortexM3_stm32f2/stm32f207ig_stm3220g-eval/core/stage_1_boot.cpp
++@@ -2,6 +2,7 @@
++ #include "interfaces/arch_registers.h"
++ #include "core/interrupts.h" //For the unexpected interrupt call
++ #include <string.h>
+++#include "interfaces/gpio.h" //FIXME: remove
++ 
++ /*
++  * startup.cpp
++@@ -116,6 +117,10 @@ void Reset_Handler()
++     asm volatile("ldr sp, =_main_stack_top\n\t");
++     #endif //__CODE_IN_XRAM
++ 
+++    RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN; //FIXME: remove
+++    miosix::Gpio<GPIOC_BASE,7>::mode(miosix::Mode::OUTPUT);
+++    miosix::Gpio<GPIOC_BASE,7>::high();
+++
++ 	/*
++ 	 * SystemInit() is called *before* initializing .data and zeroing .bss
++ 	 * Despite all startup files provided by ST do the opposite, there are three
++diff --git a/miosix/arch/cortexM3_stm32f2/stm32f207ig_stm3220g-eval/interfaces-impl/bsp.cpp b/miosix/arch/cortexM3_stm32f2/stm32f207ig_stm3220g-eval/interfaces-impl/bsp.cpp
++index cd41faa..d8bb6de 100644
++--- a/miosix/arch/cortexM3_stm32f2/stm32f207ig_stm3220g-eval/interfaces-impl/bsp.cpp
+++++ b/miosix/arch/cortexM3_stm32f2/stm32f207ig_stm3220g-eval/interfaces-impl/bsp.cpp
++@@ -72,9 +72,9 @@ void IRQbspInit()
++     GPIOI->OSPEEDR=0xaaaaaaaa;
++     _led::mode(Mode::OUTPUT);
++     sdCardDetect::mode(Mode::INPUT_PULL_UP);
++-    ledOn();
++-    delayMs(100);
++-    ledOff();
+++//    ledOn();
+++//    delayMs(100);
+++//    ledOff();
++     #ifndef STDOUT_REDIRECTED_TO_DCC
++     IRQstm32f2serialPortInit();
++     #endif //STDOUT_REDIRECTED_TO_DCC
++diff --git a/miosix/config/miosix_settings.h b/miosix/config/miosix_settings.h
++index 648c3c4..a26da30 100644
++--- a/miosix/config/miosix_settings.h
+++++ b/miosix/config/miosix_settings.h
++@@ -123,7 +123,7 @@ const unsigned char MAX_THREADS_PER_PROCESS=2;
++ /// \def WITH_BOOTLOG
++ /// Uncomment to print bootlogs on stdout.
++ /// By default it is defined (bootlogs are printed)
++-#define WITH_BOOTLOG
+++//#define WITH_BOOTLOG
++ 
++ /// \def WITH_ERRLOG
++ /// Uncomment for debug information on stdout.
++@@ -142,7 +142,7 @@ const unsigned char MAX_THREADS_PER_PROCESS=2;
++  * mode, so to use debugging it is necessary to disble sleep in the idle thread.
++  * By default it is not defined (idle thread calls sleep).
++  */
++-#define JTAG_DISABLE_SLEEP
+++//#define JTAG_DISABLE_SLEEP
++ 
++ /// Minimum stack size (MUST be divisible by 4)
++ const unsigned int STACK_MIN=256;
++diff --git a/miosix/kernel/process.cpp b/miosix/kernel/process.cpp
++index 06d7e55..16f88d7 100644
++--- a/miosix/kernel/process.cpp
+++++ b/miosix/kernel/process.cpp
++@@ -354,7 +354,7 @@ void Process::serialize(ProcessStatus* ptr)
++     #ifndef __CODE_IN_XRAM
++     ptr->programBase=this->program->getElfBase();
++     ptr->programSize=this->program->getElfSize();
++-    iprintf("save base=%p size=%d\n",ptr->programBase,ptr->programSize);
+++//    iprintf("save base=%p size=%d\n",ptr->programBase,ptr->programSize);
++     #else //__CODE_IN_XRAM
++     ptr->programBase=this->loadedProgram;
++     ptr->programBase=reinterpret_cast<unsigned int*>(this->roundedSize);
++diff --git a/miosix/kernel/suspend_manager.cpp b/miosix/kernel/suspend_manager.cpp
++index fb11ee3..bc2cf7b 100644
++--- a/miosix/kernel/suspend_manager.cpp
+++++ b/miosix/kernel/suspend_manager.cpp
++@@ -68,6 +68,7 @@ bool compareResumeTime(SyscallResumeTime first, SyscallResumeTime second )
++ void SuspendManager::enterInterruptionPoint(Process* proc, int threadID,
++         long long resumeTime, int intPointID, int fileID)
++ {
+++    Gpio<GPIOC_BASE,7>::high(); //FIXME: remove
++     SyscallResumeTime newSuspThread;
++     newSuspThread.status=NULL;
++     newSuspThread.pid=proc->pid;
++@@ -125,6 +126,7 @@ void SuspendManager::wakeupDaemon(void*)
++             }
++         }
++     }
+++    Gpio<GPIOC_BASE,7>::low(); //FIXME: remove
++ }
++ 
++ /*
++@@ -144,7 +146,7 @@ void SuspendManager::hibernateDaemon(void*)
++         //will be replaced by the policy, once refined 
++         if((it->resumeTime-getTick()/1000)<=hibernationThreshold) continue;
++         ProcessStatus* proc=getProcessesBackupAreaBase();
++-        iprintf("Swapping %d processes\n",suspendedProcesses.size());
+++//        iprintf("Swapping %d processes\n",suspendedProcesses.size());
++         list<Process*>::iterator findProc;
++         for(findProc=suspendedProcesses.begin();
++                 findProc!=suspendedProcesses.end();findProc++)
++@@ -190,7 +192,7 @@ void SuspendManager::hibernateDaemon(void*)
++         
++         long long prev=getTick();
++         int sleepTime=syscallReturnTime.begin()->resumeTime-prev/1000;
++-        iprintf("about to suspend, tick=%lld\n",prev);
+++//        iprintf("about to suspend, tick=%lld\n",prev);
++         getBackupSramBase()[1021]=prev & 0xffffffff; //FIXME: hack
++         getBackupSramBase()[1022]=prev>>32;
++         getBackupSramBase()[1023]=sleepTime;
++@@ -211,10 +213,10 @@ int SuspendManager::resume()
++         Lock<Mutex>l(SuspendManager::suspMutex);
++         SyscallResumeTime retTime;
++         int numProc=*(getBackupSramBase()+(getAllocatorSramAreaSize()/sizeof(int)));
++-        iprintf("Reloading %d processes\n",numProc);
+++//        iprintf("Reloading %d processes\n",numProc);
++         for(int i=0;i<numProc;i++)
++         {   
++-            iprintf("reload base=%p size=%d\n",proc->programBase,proc->programSize);
+++//            iprintf("reload base=%p size=%d\n",proc->programBase,proc->programSize);
++             Process::resume(ElfProgram(proc->programBase,proc->programSize),proc);
++             for(int i=0;i<proc->numThreads;i++)
++             {   
+diff --git a/screenlog.0 b/screenlog.0
+new file mode 100644
+index 0000000..f9b725a
+--- /dev/null
++++ b/screenlog.0
+@@ -0,0 +1,52 @@
++Miosix v1.60 (stm32f207ig_stm3220g-eval, Jul 13 2012 12:46:00, gcc 4.5.2)
++Starting Kernel... Ok
++Starting Filesystem... No disk
++Available heap 24576 out of 29868 Bytes
++tick=40
++First boot
++
++0=divzero 1=sleep 5s, 2=exit 3=bkpt 4=dangling
++1
++Swapping 1 processes
++save base=0x1c3a8 size=468
++about to suspend, tick=3576
++Miosix v1.60 (stm32f207ig_stm3220g-eval, Jul 13 2012 12:46:00, gcc 4.5.2)
++Starting Kernel... Ok
++Starting Filesystem... No disk
++Available heap 24576 out of 29868 Bytes
++tick=8616
++RTC boot
++Reloading 1 processes
++reload base=0x1c3a8 size=468
++0=divzero 1=sleep 5s, 2=exit 3=bkpt 4=dangling
++2
++Process terminated
++Exit code is 0
++
++0=divzero 1=sleep 5s, 2=exit 3=bkpt 4=dangling
++1
++Swapping 1 processes
++save base=0x1c3a8 size=468
++about to suspend, tick=30342
++Miosix v1.60 (stm32f207ig_stm3220g-eval, Jul 13 2012 12:46:00, gcc 4.5.2)
++Starting Kernel... Ok
++Starting Filesystem... No disk
++Available heap 24576 out of 29868 Bytes
++tick=35382
++RTC boot
++Reloading 1 processes
++reload base=0x1c3a8 size=468
++0=divzero 1=sleep 5s, 2=exit 3=bkpt 4=dangling
++1
++Swapping 1 processes
++save base=0x1c3a8 size=468
++about to suspend, tick=38120
++Miosix v1.60 (stm32f207ig_stm3220g-eval, Jul 13 2012 12:46:00, gcc 4.5.2)
++Starting Kernel... Ok
++Starting Filesystem... No disk
++Available heap 24576 out of 29868 Bytes
++tick=43160
++RTC boot
++Reloading 1 processes
++reload base=0x1c3a8 size=468
++0=divzero 1=sleep 5s, 2=exit 3=bkpt 4=dangling
diff --git a/log.txt b/log.txt
new file mode 100644
index 00000000..947e1fa9
--- /dev/null
+++ b/log.txt
@@ -0,0 +1,5 @@
+arm-miosix-eabi-g++ -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 -fPIC -o main.elf main.o crt0.o -Wl,--start-group -lstdc++ -lc -lm -lgcc -Wl,--end-group
+/opt/arm-miosix-eabi/lib/gcc/arm-eabi/4.5.2/../../../../arm-eabi/bin/ld: /opt/arm-miosix-eabi/lib/gcc/arm-eabi/4.5.2/../../../../arm-eabi/lib/thumb/thumb2/libc.a(lib_a-syslseek.o): relocation R_ARM_THM_MOVW_ABS_NC against `_impure_ptr' can not be used when making a shared object; recompile with -fPIC
+/opt/arm-miosix-eabi/lib/gcc/arm-eabi/4.5.2/../../../../arm-eabi/lib/thumb/thumb2/libc.a: could not read symbols: Bad value
+collect2: ld returned 1 exit status
+make: *** [all] Error 1
diff --git a/main.cpp b/main.cpp
index 75f70ce4..27b83cd5 100644
--- a/main.cpp
+++ b/main.cpp
@@ -4,8 +4,12 @@
 #include <signal.h>
 #include "miosix.h"
 #include "kernel/process.h"
+#include "kernel/SystemMap.h"
+
 #include "app_template/prog3.h"
 
+#include "system_app_test/prog3.h"
+
 using namespace std;
 using namespace miosix;
 
@@ -23,6 +27,12 @@ void ledThread(void *)
 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++)
diff --git a/miosix/Makefile b/miosix/Makefile
index e601cfc6..2f87255a 100644
--- a/miosix/Makefile
+++ b/miosix/Makefile
@@ -26,6 +26,7 @@ kernel/scheduler/edf/edf_scheduler.cpp                                     \
 kernel/filesystem/filesystem.cpp                                           \
 kernel/filesystem/ff.c                                                     \
 kernel/filesystem/diskio.cpp                                               \
+kernel/SystemMap.cpp							   \
 util/util.cpp                                                              \
 util/version.cpp                                                           \
 util/crc16.cpp                                                             \
diff --git a/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/disk.cpp b/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/disk.cpp
index 970a5384..7fae5568 100644
--- a/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/disk.cpp
+++ b/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/disk.cpp
@@ -70,9 +70,9 @@ static CardType cardType=Invalid;
 
 //SD card GPIOs
 typedef Gpio<GPIOC_BASE,8>  sdD0;
-typedef Gpio<GPIOC_BASE,9>  sdD1;
-typedef Gpio<GPIOC_BASE,10> sdD2;
-typedef Gpio<GPIOC_BASE,11> sdD3;
+//typedef Gpio<GPIOC_BASE,9>  sdD1; //QUIRK: use serial port and SD
+//typedef Gpio<GPIOC_BASE,10> sdD2;
+//typedef Gpio<GPIOC_BASE,11> sdD3;
 typedef Gpio<GPIOC_BASE,12> sdCLK;
 typedef Gpio<GPIOD_BASE,2>  sdCMD;
 
@@ -705,8 +705,9 @@ private:
     static const unsigned int CLOCK_MAX=0;      //48MHz/(0+2)  =24MHz
 
     ///\internal Clock enabled, bus width 4bit, clock powersave enabled.
-    static const unsigned int CLKCR_FLAGS=SDIO_CLKCR_CLKEN |
-        SDIO_CLKCR_WIDBUS_0 | SDIO_CLKCR_PWRSAV;
+    //static const unsigned int CLKCR_FLAGS=SDIO_CLKCR_CLKEN |
+    //    SDIO_CLKCR_WIDBUS_0 | SDIO_CLKCR_PWRSAV;
+    static const unsigned int CLKCR_FLAGS=SDIO_CLKCR_CLKEN; //QUIRK: use serial port and SD
 
     ///\internal Maximum number of calls to IRQreduceClockSpeed() allowed
     static const unsigned char MAX_ALLOWED_REDUCTIONS=5;
@@ -1092,12 +1093,12 @@ static void initSDIOPeripheral()
         RCC->APB2ENR |= RCC_APB2ENR_SDIOEN;
         sdD0::mode(Mode::ALTERNATE);
         sdD0::alternateFunction(12);
-        sdD1::mode(Mode::ALTERNATE);
-        sdD1::alternateFunction(12);
-        sdD2::mode(Mode::ALTERNATE);
-        sdD2::alternateFunction(12);
-        sdD3::mode(Mode::ALTERNATE);
-        sdD3::alternateFunction(12);
+//        sdD1::mode(Mode::ALTERNATE); //QUIRK: use serial port and SD
+//        sdD1::alternateFunction(12);
+//        sdD2::mode(Mode::ALTERNATE);
+//        sdD2::alternateFunction(12);
+//        sdD3::mode(Mode::ALTERNATE);
+//        sdD3::alternateFunction(12);
         sdCLK::mode(Mode::ALTERNATE);
         sdCLK::alternateFunction(12);
         sdCMD::mode(Mode::ALTERNATE);
@@ -1273,8 +1274,8 @@ void Disk::init()
             return;
         }
 
-        r=Command::send(Command::ACMD6,2);   //Set 4 bit bus width
-        if(r.validateR1Response()==false) return;
+        //r=Command::send(Command::ACMD6,2);   //Set 4 bit bus width
+        //if(r.validateR1Response()==false) return; //QUIRK: use serial port and SD
 
         if(cardType!=SDHC)
         {
diff --git a/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/portability.cpp b/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/portability.cpp
index 47fe617a..fdfb9264 100644
--- a/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/portability.cpp
+++ b/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/portability.cpp
@@ -28,6 +28,7 @@
 
 #include "interfaces/portability.h"
 #include "kernel/kernel.h"
+#include "util/util.h"
 #include "kernel/error.h"
 #include "interfaces/bsp.h"
 #include "kernel/scheduler/scheduler.h"
@@ -263,27 +264,27 @@ MPUConfiguration::MPUConfiguration(unsigned int *elfBase, unsigned int elfSize,
     regValues[1]=2<<MPU_RASR_AP_Pos
                | MPU_RASR_C_Msk
                | 1 //Enable bit
-               | ((ffs(elfSize)-2)<<1);
+               | ((miosix::fhbs(elfSize)-2)<<1);
     regValues[3]=3<<MPU_RASR_AP_Pos
                | MPU_RASR_XN_Msk
                | MPU_RASR_C_Msk
                | MPU_RASR_S_Msk
                | 1 //Enable bit
-               | ((ffs(imageSize)-2)<<1);
+               | ((miosix::fhbs(imageSize)-2)<<1);
     #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
-               | ((ffs(elfSize)-2)<<1);
+               | ((miosix::fhbs(elfSize)-2)<<1);
     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
-               | ((ffs(imageSize)-2)<<1);
+               | ((miosix::fhbs(imageSize)-2)<<1);
     #endif //__CODE_IN_XRAM
 }
 
diff --git a/miosix/compiler/cleanup.sh b/miosix/compiler/cleanup.sh
old mode 100644
new mode 100755
diff --git a/miosix/compiler/download.sh b/miosix/compiler/download.sh
old mode 100644
new mode 100755
diff --git a/miosix/compiler/install-script.sh b/miosix/compiler/install-script.sh
old mode 100644
new mode 100755
diff --git a/miosix/compiler/mx-postlinker/Makefile b/miosix/compiler/mx-postlinker/Makefile
index b5fe7c84..581c0c83 100644
--- a/miosix/compiler/mx-postlinker/Makefile
+++ b/miosix/compiler/mx-postlinker/Makefile
@@ -1,5 +1,5 @@
-CXX:= g++
-CXXFLAGS:= -O2 -c
+CXX:= g++ -m32
+CXXFLAGS:= -O2 -c -m32
 OBJS:= postlinker.o main.o
 
 #create program target
diff --git a/miosix/compiler/uninstall.sh b/miosix/compiler/uninstall.sh
old mode 100644
new mode 100755
diff --git a/miosix/kernel/SystemMap.cpp b/miosix/kernel/SystemMap.cpp
new file mode 100644
index 00000000..2d76507e
--- /dev/null
+++ b/miosix/kernel/SystemMap.cpp
@@ -0,0 +1,66 @@
+#include "SystemMap.h"
+
+using namespace std;
+
+namespace miosix {
+
+static Mutex initMapMutex;//To guard initialization of the singleton
+
+SystemMap::SystemMap() {
+}
+
+SystemMap::SystemMap(const SystemMap& orig) {
+}
+
+SystemMap::~SystemMap() {
+}
+
+SystemMap &SystemMap::instance(){
+	static SystemMap *pSingleton = 0;
+	{
+		Lock<Mutex> lock(initMapMutex);
+		
+		if(pSingleton == 0)
+			pSingleton = new SystemMap();
+	}
+	
+	return *pSingleton;
+}
+
+void SystemMap::addElfProgram(const char* name, const unsigned int *elf, unsigned int size){
+	unsigned int hash = hashString(name);
+	
+	if(mPrograms.find(hash) == mPrograms.end())
+		mPrograms.insert(make_pair(hash, make_pair(elf, size)));
+}
+
+pair<const unsigned int*, unsigned int>  SystemMap::getElfProgram(const char* name) const {
+	ProgramsMap::const_iterator it = mPrograms.find(hashString(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();
+}
+
+unsigned int SystemMap::hashString(const char* pStr) const {
+	unsigned int hash = 0;
+        
+	for(; *pStr != '\0'; ++pStr){
+		hash += *pStr;
+		hash += (hash << 10);
+		hash += (hash >> 6);
+	}
+
+	hash += (hash << 3);
+	hash ^= (hash >> 11);
+	hash += (hash << 15);
+
+	return hash;
+}
+
+}
\ No newline at end of file
diff --git a/miosix/kernel/SystemMap.h b/miosix/kernel/SystemMap.h
new file mode 100644
index 00000000..1e82ed0b
--- /dev/null
+++ b/miosix/kernel/SystemMap.h
@@ -0,0 +1,34 @@
+#ifndef SYSTEMMAP_H
+#define	SYSTEMMAP_H
+
+#include "kernel/sync.h"
+
+#include <map>
+
+namespace miosix {
+
+class SystemMap {
+public:
+	SystemMap();
+	virtual ~SystemMap();
+	
+	static SystemMap &instance();
+	
+	//Privata ? and friendly
+	void addElfProgram(const char *name, const unsigned int *elf, unsigned int size);
+	std::pair<const unsigned int*, unsigned int> getElfProgram(const char *name) const;
+	
+	unsigned int getElfCount() const;
+	
+private:
+	unsigned int hashString(const char *pStr) const;
+	
+	SystemMap(const SystemMap& orig);
+	
+	typedef std::map<unsigned int, std::pair<const unsigned int*, unsigned int> > ProgramsMap;
+	ProgramsMap mPrograms;
+};
+
+}
+
+#endif	/* SYSTEMMAP_H */
diff --git a/miosix/kernel/filesystem/ff.c b/miosix/kernel/filesystem/ff.c
index 9a3a2cef..c9d60d0f 100644
--- a/miosix/kernel/filesystem/ff.c
+++ b/miosix/kernel/filesystem/ff.c
@@ -824,10 +824,9 @@ FRESULT f_open (
 	BYTE *dir;
 	char fn[8+3+1];
 
-
 	fp->fs = NULL;		/* Clear file object */
 #if !_FS_READONLY
-	mode &= (FA_READ|FA_WRITE|FA_CREATE_ALWAYS|FA_OPEN_ALWAYS|FA_CREATE_NEW);
+	mode &= (FA_READ|FA_WRITE|FA_CREATE_ALWAYS|FA_CREATE_NEW|FA_OPEN_ALWAYS);
 	res = auto_mount(&path, &dj.fs, (BYTE)(mode & (FA_WRITE|FA_CREATE_ALWAYS|FA_OPEN_ALWAYS|FA_CREATE_NEW)));
 #else
 	mode &= FA_READ;
diff --git a/miosix/kernel/filesystem/filesystem.cpp b/miosix/kernel/filesystem/filesystem.cpp
index 465d1c2f..a8191cc3 100644
--- a/miosix/kernel/filesystem/filesystem.cpp
+++ b/miosix/kernel/filesystem/filesystem.cpp
@@ -104,11 +104,18 @@ int Filesystem::openFile(const char *name, int flags, int mode)
         
         //Set file flags
         BYTE openflags=0;
-        if(flags & _FREAD)  openflags|=FA_READ;
-        if(flags & _FWRITE) openflags|=FA_WRITE;
-        if(flags & _FTRUNC) openflags|=FA_CREATE_ALWAYS;//Truncate
-        else if(flags & _FAPPEND) openflags|=FA_OPEN_ALWAYS;//If not exists create
-        else openflags|=FA_OPEN_EXISTING;//If not exists fail
+        if(flags & _FREAD)
+			openflags|=FA_READ;
+		
+        if(flags & _FWRITE)
+			openflags|=FA_WRITE;
+		
+        if(flags & _FTRUNC)
+			openflags|=FA_CREATE_ALWAYS;//Truncate
+        else if(flags & _FAPPEND)
+			openflags|=FA_OPEN_ALWAYS;//If not exists create
+        else 
+			openflags|=FA_OPEN_EXISTING;//If not exists fail
 
         //Allocate the FatFs file data structure
         #ifdef __NO_EXCEPTIONS
diff --git a/miosix/kernel/process.cpp b/miosix/kernel/process.cpp
index 9ac56c20..91c8a7b3 100644
--- a/miosix/kernel/process.cpp
+++ b/miosix/kernel/process.cpp
@@ -34,6 +34,7 @@
 #include "sync.h"
 #include "process_pool.h"
 #include "process.h"
+#include "SystemMap.h"
 
 using namespace std;
 
@@ -225,6 +226,10 @@ 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),
@@ -312,9 +317,63 @@ void *Process::start(void *argv)
                         reinterpret_cast<char*>(sp.getSecondParameter()),
                         sp.getThirdParameter()));
                     break;
-                case 5: 
-                    sp.setReturnValue(usleep(sp.getFirstParameter()));
+                case 5:
+					sp.setReturnValue(usleep(sp.getFirstParameter()));
                     break;
+				case 6:
+					//open
+				{
+					int fp = open(reinterpret_cast<const char*>(sp.getFirstParameter()),	//filename
+								  sp.getSecondParameter(),									//flags
+								  sp.getThirdParameter());									//permission, used?
+					if (fp != -1)
+						proc->mFiles.insert(fp);
+						
+					sp.setReturnValue(fp);
+				}
+                    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:
+					//lseek
+					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;
+				case 9:
+					//system, NOT TESTED YET!!!
+				{				
+					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(ret);
+				}
+					break;
                 default:
                     running=false;
                     proc->exitCode=SIGSYS; //Bad syscall
diff --git a/miosix/kernel/process.h b/miosix/kernel/process.h
index dc54e1af..466f0be9 100644
--- a/miosix/kernel/process.h
+++ b/miosix/kernel/process.h
@@ -31,6 +31,7 @@
 #include <vector>
 #include <map>
 #include <list>
+#include <set>
 #include <sys/types.h>
 #include "kernel.h"
 #include "sync.h"
@@ -125,6 +126,7 @@ private:
     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
diff --git a/miosix/kernel/syscalls.cpp b/miosix/kernel/syscalls.cpp
index 550da2fe..086af5cb 100644
--- a/miosix/kernel/syscalls.cpp
+++ b/miosix/kernel/syscalls.cpp
@@ -407,8 +407,7 @@ void *_sbrk_r(struct _reent *ptr, ptrdiff_t incr)
 
 /**
  * \internal
- * __malloc_lock, called by malloc to ensure no context switch happens during
- * memory allocation (the heap is global and shared between the threads, so
+ * __malloc_lock, called by malloc t_memory allocation (the heap is global and shared between the threads, so
  * memory allocation should not be interrupted by a context switch)
  *
  *	WARNING:
@@ -461,6 +460,7 @@ int _close_r(struct _reent *ptr, int fd)
     #endif //WITH_FILESYSTEM
 }
 
+
 /**
  * \internal
  * _write (for C++ library)
diff --git a/miosix/util/util.cpp b/miosix/util/util.cpp
index 6f1ca57c..e3d6df21 100644
--- a/miosix/util/util.cpp
+++ b/miosix/util/util.cpp
@@ -41,6 +41,13 @@ using namespace std;
 
 namespace miosix {
 
+int fhbs(unsigned int x){
+    //TODO: Optimize!
+    int result=0;
+    while(x) { x>>=1; result++; }
+    return result;
+}
+
 /**
  * \internal
  * used by memDump
diff --git a/miosix/util/util.h b/miosix/util/util.h
index 09a8af4d..addf775f 100644
--- a/miosix/util/util.h
+++ b/miosix/util/util.h
@@ -34,6 +34,15 @@
 #define UTIL_H
 
 namespace miosix {
+	
+/**
+* Find highest bit set
+* \param x a 32bit number
+* \return 0 if the number is zero, or the position of the highest bit
+* FIXME: Put this function in a more appropriate place, away from the
+* interfaces/arch
+**/
+int fhbs(unsigned int x);
 
 /**
  * \addtogroup Util
diff --git a/miosix_np_processes/nbproject/configurations.xml b/miosix_np_processes/nbproject/configurations.xml
index f048ef9d..f7cc6131 100644
--- a/miosix_np_processes/nbproject/configurations.xml
+++ b/miosix_np_processes/nbproject/configurations.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<configurationDescriptor version="80">
+<configurationDescriptor version="84">
   <logicalFolder name="root" displayName="root" projectFiles="true" kind="ROOT">
-    <df name="miosix_np_2" root="..">
+    <df name="miosix-kernel" root="..">
       <df name="app_template">
         <in>crt0.s</in>
         <in>main.c</in>
@@ -299,6 +299,8 @@
             <in>scheduler.h</in>
             <in>tick_interrupt.h</in>
           </df>
+          <in>SystemMap.cpp</in>
+          <in>SystemMap.h</in>
           <in>buffer_queue.h</in>
           <in>elf_program.cpp</in>
           <in>elf_program.h</in>
@@ -341,11 +343,17 @@
       </df>
       <df name="miosix_np_processes">
       </df>
+      <df name="system_app_test">
+        <in>crt0.s</in>
+        <in>main.c</in>
+        <in>prog3.h</in>
+      </df>
       <in>main.cpp</in>
     </df>
     <logicalFolder name="ExternalFiles"
                    displayName="Important Files"
-                   projectFiles="false">
+                   projectFiles="false"
+                   root="..">
       <itemPath>../makefile</itemPath>
       <itemPath>miosix_np_2-Makefile.mk</itemPath>
     </logicalFolder>
@@ -361,6 +369,8 @@
         <remote-sources-mode>LOCAL_SOURCES</remote-sources-mode>
         <compilerSet>ARM_MIOSIX_EABI|GNU</compilerSet>
       </toolsSet>
+      <codeAssistance>
+      </codeAssistance>
       <makefileType>
         <makeTool>
           <buildCommandWorkingDir>..</buildCommandWorkingDir>
@@ -409,6 +419,8 @@
         <remote-sources-mode>LOCAL_SOURCES</remote-sources-mode>
         <compilerSet>ARM_MIOSIX_EABI|GNU</compilerSet>
       </toolsSet>
+      <codeAssistance>
+      </codeAssistance>
       <makefileType>
         <makeTool>
           <buildCommandWorkingDir>..</buildCommandWorkingDir>
@@ -453,6 +465,8 @@
         <remote-sources-mode>LOCAL_SOURCES</remote-sources-mode>
         <compilerSet>ARM_MIOSIX_EABI|GNU</compilerSet>
       </toolsSet>
+      <codeAssistance>
+      </codeAssistance>
       <makefileType>
         <makeTool>
           <buildCommandWorkingDir>..</buildCommandWorkingDir>
@@ -499,6 +513,8 @@
         <remote-sources-mode>LOCAL_SOURCES</remote-sources-mode>
         <compilerSet>ARM_MIOSIX_EABI|GNU</compilerSet>
       </toolsSet>
+      <codeAssistance>
+      </codeAssistance>
       <makefileType>
         <makeTool>
           <buildCommandWorkingDir>..</buildCommandWorkingDir>
@@ -545,6 +561,8 @@
         <remote-sources-mode>LOCAL_SOURCES</remote-sources-mode>
         <compilerSet>ARM_MIOSIX_EABI|GNU</compilerSet>
       </toolsSet>
+      <codeAssistance>
+      </codeAssistance>
       <makefileType>
         <makeTool>
           <buildCommandWorkingDir>..</buildCommandWorkingDir>
@@ -591,6 +609,8 @@
         <remote-sources-mode>LOCAL_SOURCES</remote-sources-mode>
         <compilerSet>ARM_MIOSIX_EABI|GNU</compilerSet>
       </toolsSet>
+      <codeAssistance>
+      </codeAssistance>
       <makefileType>
         <makeTool>
           <buildCommandWorkingDir>..</buildCommandWorkingDir>
@@ -637,6 +657,8 @@
         <remote-sources-mode>LOCAL_SOURCES</remote-sources-mode>
         <compilerSet>ARM_MIOSIX_EABI|GNU</compilerSet>
       </toolsSet>
+      <codeAssistance>
+      </codeAssistance>
       <makefileType>
         <makeTool>
           <buildCommandWorkingDir>..</buildCommandWorkingDir>
@@ -683,6 +705,8 @@
         <remote-sources-mode>LOCAL_SOURCES</remote-sources-mode>
         <compilerSet>ARM_MIOSIX_EABI|GNU</compilerSet>
       </toolsSet>
+      <codeAssistance>
+      </codeAssistance>
       <makefileType>
         <makeTool>
           <buildCommandWorkingDir>..</buildCommandWorkingDir>
@@ -727,6 +751,8 @@
         <remote-sources-mode>LOCAL_SOURCES</remote-sources-mode>
         <compilerSet>ARM_MIOSIX_EABI|GNU</compilerSet>
       </toolsSet>
+      <codeAssistance>
+      </codeAssistance>
       <makefileType>
         <makeTool>
           <buildCommandWorkingDir>..</buildCommandWorkingDir>
@@ -736,8 +762,8 @@
           <cTool>
             <incDir>
               <pElem>..</pElem>
-              <pElem>../miosix</pElem>
               <pElem>../miosix/arch/common</pElem>
+              <pElem>../miosix</pElem>
               <pElem>../miosix/arch/cortexM3_stm32f2/common</pElem>
               <pElem>../miosix/arch/cortexM3_stm32f2/stm32f207ig_stm3220g-eval</pElem>
             </incDir>
@@ -751,8 +777,8 @@
           <ccTool>
             <incDir>
               <pElem>..</pElem>
-              <pElem>../miosix</pElem>
               <pElem>../miosix/arch/common</pElem>
+              <pElem>../miosix</pElem>
               <pElem>../miosix/arch/cortexM3_stm32f2/common</pElem>
               <pElem>../miosix/arch/cortexM3_stm32f2/stm32f207ig_stm3220g-eval</pElem>
             </incDir>
@@ -765,12 +791,545 @@
           </ccTool>
         </makeTool>
       </makefileType>
+      <item path="../app_template/main.c" ex="false" tool="0" flavor2="2">
+        <cTool>
+        </cTool>
+      </item>
+      <item path="../app_template_withlibs/main.c" ex="false" tool="0" flavor2="2">
+        <cTool>
+        </cTool>
+      </item>
+      <item path="../app_template_withlibs/syscallfuffa.c"
+            ex="false"
+            tool="0"
+            flavor2="2">
+        <cTool>
+        </cTool>
+      </item>
+      <item path="../main.cpp" ex="false" tool="1" flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/arch/arm7_lpc2000/lpc2138_miosix_board/core/interrupts.cpp"
+            ex="false"
+            tool="1"
+            flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/arch/arm7_lpc2000/lpc2138_miosix_board/drivers/serial.cpp"
+            ex="false"
+            tool="1"
+            flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/arch/arm7_lpc2000/lpc2138_miosix_board/interfaces-impl/bsp.cpp"
+            ex="false"
+            tool="1"
+            flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/arch/arm7_lpc2000/lpc2138_miosix_board/interfaces-impl/console.cpp"
+            ex="false"
+            tool="1"
+            flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/arch/arm7_lpc2000/lpc2138_miosix_board/interfaces-impl/delays.cpp"
+            ex="false"
+            tool="1"
+            flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/arch/arm7_lpc2000/lpc2138_miosix_board/interfaces-impl/disk.cpp"
+            ex="false"
+            tool="1"
+            flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/arch/arm7_lpc2000/lpc2138_miosix_board/interfaces-impl/portability.cpp"
+            ex="false"
+            tool="1"
+            flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/arch/common/drivers/dcc.cpp"
+            ex="false"
+            tool="1"
+            flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/arch/cortexM3_stm32/common/CMSIS/core_cm3.c"
+            ex="false"
+            tool="0"
+            flavor2="2">
+        <cTool>
+        </cTool>
+      </item>
+      <item path="../miosix/arch/cortexM3_stm32/common/CMSIS/system_stm32f10x.c"
+            ex="false"
+            tool="0"
+            flavor2="2">
+        <cTool>
+        </cTool>
+      </item>
+      <item path="../miosix/arch/cortexM3_stm32/common/core/interrupts.cpp"
+            ex="false"
+            tool="1"
+            flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/arch/cortexM3_stm32/common/drivers/serial.cpp"
+            ex="false"
+            tool="1"
+            flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/arch/cortexM3_stm32/common/interfaces-impl/delays.cpp"
+            ex="false"
+            tool="1"
+            flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/arch/cortexM3_stm32/common/interfaces-impl/disk.cpp"
+            ex="false"
+            tool="1"
+            flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/arch/cortexM3_stm32/common/interfaces-impl/gpio_impl.cpp"
+            ex="false"
+            tool="1"
+            flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/arch/cortexM3_stm32/common/interfaces-impl/portability.cpp"
+            ex="false"
+            tool="1"
+            flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/arch/cortexM3_stm32/stm32f100rb_stm32vldiscovery/core/stage_1_boot.cpp"
+            ex="false"
+            tool="1"
+            flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/arch/cortexM3_stm32/stm32f100rb_stm32vldiscovery/interfaces-impl/bsp.cpp"
+            ex="false"
+            tool="1"
+            flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/arch/cortexM3_stm32/stm32f100rb_stm32vldiscovery/interfaces-impl/console.cpp"
+            ex="false"
+            tool="1"
+            flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/arch/cortexM3_stm32/stm32f103ve_mp3v2/core/stage_1_boot.cpp"
+            ex="false"
+            tool="1"
+            flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/arch/cortexM3_stm32/stm32f103ve_mp3v2/interfaces-impl/bsp.cpp"
+            ex="false"
+            tool="1"
+            flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/arch/cortexM3_stm32/stm32f103ve_mp3v2/interfaces-impl/console.cpp"
+            ex="false"
+            tool="1"
+            flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/arch/cortexM3_stm32/stm32f103ve_strive_mini/core/stage_1_boot.cpp"
+            ex="false"
+            tool="1"
+            flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/arch/cortexM3_stm32/stm32f103ve_strive_mini/interfaces-impl/bsp.cpp"
+            ex="false"
+            tool="1"
+            flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/arch/cortexM3_stm32/stm32f103ve_strive_mini/interfaces-impl/console.cpp"
+            ex="false"
+            tool="1"
+            flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/arch/cortexM3_stm32/stm32f103ze_redbull_v2/core/stage_1_boot.cpp"
+            ex="false"
+            tool="1"
+            flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/arch/cortexM3_stm32/stm32f103ze_redbull_v2/interfaces-impl/bsp.cpp"
+            ex="false"
+            tool="1"
+            flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/arch/cortexM3_stm32/stm32f103ze_redbull_v2/interfaces-impl/console.cpp"
+            ex="false"
+            tool="1"
+            flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/arch/cortexM3_stm32/stm32f103ze_stm3210e-eval/core/stage_1_boot.cpp"
+            ex="false"
+            tool="1"
+            flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/arch/cortexM3_stm32/stm32f103ze_stm3210e-eval/interfaces-impl/bsp.cpp"
+            ex="false"
+            tool="1"
+            flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/arch/cortexM3_stm32/stm32f103ze_stm3210e-eval/interfaces-impl/console.cpp"
+            ex="false"
+            tool="1"
+            flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/arch/cortexM3_stm32f2/common/CMSIS/core_cm3.c"
+            ex="false"
+            tool="0"
+            flavor2="2">
+        <cTool>
+        </cTool>
+      </item>
+      <item path="../miosix/arch/cortexM3_stm32f2/common/CMSIS/system_stm32f2xx.c"
+            ex="false"
+            tool="0"
+            flavor2="2">
+        <cTool>
+        </cTool>
+      </item>
+      <item path="../miosix/arch/cortexM3_stm32f2/common/core/interrupts.cpp"
+            ex="false"
+            tool="1"
+            flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/arch/cortexM3_stm32f2/common/interfaces-impl/disk.cpp"
+            ex="false"
+            tool="1"
+            flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/arch/cortexM3_stm32f2/common/interfaces-impl/gpio_impl.cpp"
+            ex="false"
+            tool="1"
+            flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/arch/cortexM3_stm32f2/common/interfaces-impl/portability.cpp"
+            ex="false"
+            tool="1"
+            flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/arch/cortexM3_stm32f2/stm32f207ig_stm3220g-eval/core/stage_1_boot.cpp"
+            ex="false"
+            tool="1"
+            flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/arch/cortexM3_stm32f2/stm32f207ig_stm3220g-eval/interfaces-impl/bsp.cpp"
+            ex="false"
+            tool="1"
+            flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/arch/cortexM3_stm32f2/stm32f207ig_stm3220g-eval/interfaces-impl/console.cpp"
+            ex="false"
+            tool="1"
+            flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/arch/cortexM3_stm32f2/stm32f207ig_stm3220g-eval/interfaces-impl/delays.cpp"
+            ex="false"
+            tool="1"
+            flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/arch/cortexM3_stm32f2/stm32f207zg_EthBoardV2/core/stage_1_boot.cpp"
+            ex="false"
+            tool="1"
+            flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/arch/cortexM3_stm32f2/stm32f207zg_EthBoardV2/interfaces-impl/bsp.cpp"
+            ex="false"
+            tool="1"
+            flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/arch/cortexM3_stm32f2/stm32f207zg_EthBoardV2/interfaces-impl/console.cpp"
+            ex="false"
+            tool="1"
+            flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/arch/cortexM3_stm32f2/stm32f207zg_EthBoardV2/interfaces-impl/delays.cpp"
+            ex="false"
+            tool="1"
+            flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/arch/cortexM4_stm32f4/common/CMSIS/system_stm32f4xx.c"
+            ex="false"
+            tool="0"
+            flavor2="2">
+        <cTool>
+        </cTool>
+      </item>
+      <item path="../miosix/arch/cortexM4_stm32f4/common/core/interrupts.cpp"
+            ex="false"
+            tool="1"
+            flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/arch/cortexM4_stm32f4/common/interfaces-impl/delays.cpp"
+            ex="false"
+            tool="1"
+            flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/arch/cortexM4_stm32f4/common/interfaces-impl/gpio_impl.cpp"
+            ex="false"
+            tool="1"
+            flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/arch/cortexM4_stm32f4/common/interfaces-impl/portability.cpp"
+            ex="false"
+            tool="1"
+            flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/arch/cortexM4_stm32f4/stm32f407vg_stm32f4discovery/core/stage_1_boot.cpp"
+            ex="false"
+            tool="1"
+            flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/arch/cortexM4_stm32f4/stm32f407vg_stm32f4discovery/interfaces-impl/bsp.cpp"
+            ex="false"
+            tool="1"
+            flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/arch/cortexM4_stm32f4/stm32f407vg_stm32f4discovery/interfaces-impl/console.cpp"
+            ex="false"
+            tool="1"
+            flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/examples/sad_trombone/adpcm.c"
+            ex="false"
+            tool="0"
+            flavor2="2">
+        <cTool>
+        </cTool>
+      </item>
+      <item path="../miosix/examples/sad_trombone/convert.cpp"
+            ex="false"
+            tool="1"
+            flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/examples/sad_trombone/main.cpp"
+            ex="false"
+            tool="1"
+            flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/examples/sad_trombone/player.cpp"
+            ex="false"
+            tool="1"
+            flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/examples/thread_native/native_thread_example.cpp"
+            ex="false"
+            tool="1"
+            flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/examples/thread_pthread/pthread_example.cpp"
+            ex="false"
+            tool="1"
+            flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/kernel/elf_program.cpp" ex="false" tool="1" flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/kernel/error.cpp" ex="false" tool="1" flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/kernel/filesystem/diskio.cpp"
+            ex="false"
+            tool="1"
+            flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/kernel/filesystem/ff.c" ex="false" tool="0" flavor2="2">
+        <cTool>
+        </cTool>
+      </item>
+      <item path="../miosix/kernel/filesystem/filesystem.cpp"
+            ex="false"
+            tool="1"
+            flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/kernel/kernel.cpp" ex="false" tool="1" flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/kernel/process.cpp" ex="false" tool="1" flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/kernel/process_pool.cpp" ex="false" tool="1" flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/kernel/pthread.cpp" ex="false" tool="1" flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/kernel/scheduler/control/control_scheduler.cpp"
+            ex="false"
+            tool="1"
+            flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/kernel/scheduler/edf/edf_scheduler.cpp"
+            ex="false"
+            tool="1"
+            flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/kernel/scheduler/priority/priority_scheduler.cpp"
+            ex="false"
+            tool="1"
+            flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/kernel/stage_2_boot.cpp" ex="false" tool="1" flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/kernel/sync.cpp" ex="false" tool="1" flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/kernel/syscalls.cpp" ex="false" tool="1" flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/kernel/unistd.cpp" ex="false" tool="1" flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/testsuite/testsuite.cpp" ex="false" tool="1" flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/util/crc16.cpp" ex="false" tool="1" flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/util/lcd44780.cpp" ex="false" tool="1" flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/util/util.cpp" ex="false" tool="1" flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
+      <item path="../miosix/util/version.cpp" ex="false" tool="1" flavor2="4">
+        <ccTool>
+        </ccTool>
+      </item>
     </conf>
     <conf name="stm32f207zg_ethboard_v2" type="0">
       <toolsSet>
         <remote-sources-mode>LOCAL_SOURCES</remote-sources-mode>
         <compilerSet>ARM_MIOSIX_EABI|GNU</compilerSet>
       </toolsSet>
+      <codeAssistance>
+      </codeAssistance>
       <makefileType>
         <makeTool>
           <buildCommandWorkingDir>..</buildCommandWorkingDir>
diff --git a/miosix_np_processes/nbproject/private/configurations.xml b/miosix_np_processes/nbproject/private/configurations.xml
index ad5c7713..5cdaf53c 100644
--- a/miosix_np_processes/nbproject/private/configurations.xml
+++ b/miosix_np_processes/nbproject/private/configurations.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<configurationDescriptor version="80">
+<configurationDescriptor version="84">
   <projectmakefile>miosix_np_2-Makefile.mk</projectmakefile>
   <confs>
     <conf name="Default" type="0">
diff --git a/miosix_np_processes/nbproject/private/private.xml b/miosix_np_processes/nbproject/private/private.xml
index 3cbb1f78..8053867a 100644
--- a/miosix_np_processes/nbproject/private/private.xml
+++ b/miosix_np_processes/nbproject/private/private.xml
@@ -8,4 +8,11 @@
         <activeConfIndexElem>8</activeConfIndexElem>
     </data>
     <editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/1"/>
+    <editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/2" lastBookmarkId="0"/>
+    <preferences xmlns="http://www.netbeans.org/ns/auxiliary-configuration-preferences/1">
+        <module name="org-netbeans-modules-cnd-discovery">
+            <property name="folder" value="/home/andrea/embedded/from_git/miosix-kernel"/>
+            <property name="rootFolder" value="/home/andrea/embedded/from_git/miosix-kernel"/>
+        </module>
+    </preferences>
 </project-private>
diff --git a/miosix_np_processes/nbproject/private/stm32f207ig_stm3220g-eval.properties b/miosix_np_processes/nbproject/private/stm32f207ig_stm3220g-eval.properties
new file mode 100644
index 00000000..e69de29b
diff --git a/sd.patch b/sd.patch
new file mode 100644
index 00000000..a6f2cd40
--- /dev/null
+++ b/sd.patch
@@ -0,0 +1,59 @@
+diff --git a/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/disk.cpp b/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/disk.cpp
+index 970a538..7fae556 100644
+--- a/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/disk.cpp
++++ b/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/disk.cpp
+@@ -70,9 +70,9 @@ static CardType cardType=Invalid;
+ 
+ //SD card GPIOs
+ typedef Gpio<GPIOC_BASE,8>  sdD0;
+-typedef Gpio<GPIOC_BASE,9>  sdD1;
+-typedef Gpio<GPIOC_BASE,10> sdD2;
+-typedef Gpio<GPIOC_BASE,11> sdD3;
++//typedef Gpio<GPIOC_BASE,9>  sdD1; //QUIRK: use serial port and SD
++//typedef Gpio<GPIOC_BASE,10> sdD2;
++//typedef Gpio<GPIOC_BASE,11> sdD3;
+ typedef Gpio<GPIOC_BASE,12> sdCLK;
+ typedef Gpio<GPIOD_BASE,2>  sdCMD;
+ 
+@@ -705,8 +705,9 @@ private:
+     static const unsigned int CLOCK_MAX=0;      //48MHz/(0+2)  =24MHz
+ 
+     ///\internal Clock enabled, bus width 4bit, clock powersave enabled.
+-    static const unsigned int CLKCR_FLAGS=SDIO_CLKCR_CLKEN |
+-        SDIO_CLKCR_WIDBUS_0 | SDIO_CLKCR_PWRSAV;
++    //static const unsigned int CLKCR_FLAGS=SDIO_CLKCR_CLKEN |
++    //    SDIO_CLKCR_WIDBUS_0 | SDIO_CLKCR_PWRSAV;
++    static const unsigned int CLKCR_FLAGS=SDIO_CLKCR_CLKEN; //QUIRK: use serial port and SD
+ 
+     ///\internal Maximum number of calls to IRQreduceClockSpeed() allowed
+     static const unsigned char MAX_ALLOWED_REDUCTIONS=5;
+@@ -1092,12 +1093,12 @@ static void initSDIOPeripheral()
+         RCC->APB2ENR |= RCC_APB2ENR_SDIOEN;
+         sdD0::mode(Mode::ALTERNATE);
+         sdD0::alternateFunction(12);
+-        sdD1::mode(Mode::ALTERNATE);
+-        sdD1::alternateFunction(12);
+-        sdD2::mode(Mode::ALTERNATE);
+-        sdD2::alternateFunction(12);
+-        sdD3::mode(Mode::ALTERNATE);
+-        sdD3::alternateFunction(12);
++//        sdD1::mode(Mode::ALTERNATE); //QUIRK: use serial port and SD
++//        sdD1::alternateFunction(12);
++//        sdD2::mode(Mode::ALTERNATE);
++//        sdD2::alternateFunction(12);
++//        sdD3::mode(Mode::ALTERNATE);
++//        sdD3::alternateFunction(12);
+         sdCLK::mode(Mode::ALTERNATE);
+         sdCLK::alternateFunction(12);
+         sdCMD::mode(Mode::ALTERNATE);
+@@ -1273,8 +1274,8 @@ void Disk::init()
+             return;
+         }
+ 
+-        r=Command::send(Command::ACMD6,2);   //Set 4 bit bus width
+-        if(r.validateR1Response()==false) return;
++        //r=Command::send(Command::ACMD6,2);   //Set 4 bit bus width
++        //if(r.validateR1Response()==false) return; //QUIRK: use serial port and SD
+ 
+         if(cardType!=SDHC)
+         {
diff --git a/system_app_test/Makefile b/system_app_test/Makefile
new file mode 100644
index 00000000..c822afb4
--- /dev/null
+++ b/system_app_test/Makefile
@@ -0,0 +1,44 @@
+##
+## 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
+
+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)))/' > prog3.h
+
+clean:
+	-rm $(OBJ) crt0.o test.elf test.map test.txt
+
+%.o: %.s
+	$(AS) $(AFLAGS) $< -o $@
+
+%.o : %.c
+	$(CC) $(CFLAGS) $< -o $@
+
+%.o : %.cpp
+	$(CXX) $(CXXFLAGS) $< -o $@
diff --git a/system_app_test/crt0.o b/system_app_test/crt0.o
new file mode 100644
index 0000000000000000000000000000000000000000..45821e39a1ba00b79dc79f44dce1f616a26ba10c
GIT binary patch
literal 1464
zcmb<-^>JflWMqH=Mg|QA1doA12Et)A0V~j85MbbC`2YRie-LI;X1LF$%y7TJogGYa
zf=OmD$pR)>!K9-C0|P^1YGP6*1EUxN0|Tpbeo;wkg|4qL0~;5+FDDa&UU6k^Nn#R%
zUU5kggwBAmic)j*N>VFI81zySOA;CMl8TENzyf;lsTG+eP<DPnY95rCoReRi3S}2p
z7MG;vLOJC{nI$lZqSV9`sBmd<PHJiagPvoMuU=wFNl|7}X-R4^*t<j$@(c{%Fk^$N
z2Za>}lntUFLCC-$&A`CG2@-(f6|4*l0t^fcd{F%?3=9k)eX3ACGgO@ol!j3-^R%Jr
z38^!Hng??q$UKl;=;ndML1x3$IWRCVz}O(QAUP22j%J=44t2q3>U?mhOF&Z>ghO2p
znz{%a>dMj7#o<ub!oa}5%)n3p@)HQBFfcGEf*4Q?^RFO89aNNop_PGwVG5iFiF*(i
zq@D@HfZ{pK3=9_-85sB(7#Ktt7#Kid4vKG38i2(aNNEl$1A`Ta0mUG5piG<;GdRT|
zq?tiJL2wzE8CcL%pqk3ez=|f%iliG9E^KJ>$SDCN&yFU~j;5ajO&*l85lWaDIML)m
zp@J;Wg(lC1kOapEH<~;*nmi9UykWi;Vqj!IRso6!5Jt$eGJwh^1fLC@UlDwEaN0od
zIT$pc=?rAC5CbQJ9txj}!5D?l&A^~i!Vq6vl2}y2keis9#{en7z(p6N(1I3Mkb(+a
VL_rHDkPQqBT%wRP#3jbS0021faPj~E

literal 0
HcmV?d00001

diff --git a/system_app_test/crt0.s b/system_app_test/crt0.s
new file mode 100644
index 00000000..7733008e
--- /dev/null
+++ b/system_app_test/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/system_app_test/log.txt b/system_app_test/log.txt
new file mode 100644
index 00000000..947e1fa9
--- /dev/null
+++ b/system_app_test/log.txt
@@ -0,0 +1,5 @@
+arm-miosix-eabi-g++ -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 -fPIC -o main.elf main.o crt0.o -Wl,--start-group -lstdc++ -lc -lm -lgcc -Wl,--end-group
+/opt/arm-miosix-eabi/lib/gcc/arm-eabi/4.5.2/../../../../arm-eabi/bin/ld: /opt/arm-miosix-eabi/lib/gcc/arm-eabi/4.5.2/../../../../arm-eabi/lib/thumb/thumb2/libc.a(lib_a-syslseek.o): relocation R_ARM_THM_MOVW_ABS_NC against `_impure_ptr' can not be used when making a shared object; recompile with -fPIC
+/opt/arm-miosix-eabi/lib/gcc/arm-eabi/4.5.2/../../../../arm-eabi/lib/thumb/thumb2/libc.a: could not read symbols: Bad value
+collect2: ld returned 1 exit status
+make: *** [all] Error 1
diff --git a/system_app_test/main.c b/system_app_test/main.c
new file mode 100644
index 00000000..c6ba3cc4
--- /dev/null
+++ b/system_app_test/main.c
@@ -0,0 +1,20 @@
+#include <unistd.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdio.h>
+
+int main(){
+	int x[64 * 1024];
+	
+	int i = 123;
+	unsigned int *p = &i;
+	
+	p = p - 1;
+	*p = 567;
+
+	
+	return 123;
+}
diff --git a/system_app_test/main.c~ b/system_app_test/main.c~
new file mode 100644
index 00000000..482b2198
--- /dev/null
+++ b/system_app_test/main.c~
@@ -0,0 +1,51 @@
+
+#include <unistd.h>
+
+int mystrlen(const char *s)
+{
+	int result=0;
+	while(*s++) result++;
+	return result;
+}
+
+int main()
+{
+	static const char str[]="Test: 0=divzero 1=sleep 5s, 2=exit 3=bkpt 4=dangling 5=open\n";
+	static const char str2[]="Unexpected command\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("", 123);
+				if(fp == 123)
+					write(1, "ok\0", 3);
+				break;
+			default:
+				write(1,str2,mystrlen(str2));
+		}
+	}
+}
diff --git a/system_app_test/main.elf b/system_app_test/main.elf
new file mode 100755
index 0000000000000000000000000000000000000000..415be3f1ab0bc0cef7286b18c4a94ec83d56800d
GIT binary patch
literal 220
zcmb<-^>JflWMqH=CI$@#5N{>}1A_@vkcokT)r3KTff>pN$<JV5V1Qu(1_lNYW@TVt
z;9y_?>t6v;3lbIpnFGRX3=9k`3=9lR3=9lg7#J9M7#IXVSc8Fq0fb@lV67jRelUQr
lLV-JzGQ)k4I<Pnc1A{1x0kYNsY@YzgV&BaC;>-$!Bme_!59<H`

literal 0
HcmV?d00001

diff --git a/system_app_test/main.map b/system_app_test/main.map
new file mode 100644
index 00000000..d8545ea3
--- /dev/null
+++ b/system_app_test/main.map
@@ -0,0 +1,128 @@
+
+Discarded input sections
+
+ .text          0x0000000000000000        0x0 main.o
+ .data          0x0000000000000000        0x0 main.o
+ .bss           0x0000000000000000        0x0 main.o
+ .text.mystrlen
+                0x0000000000000000       0x14 main.o
+ .comment       0x0000000000000000       0x12 main.o
+ .ARM.attributes
+                0x0000000000000000       0x31 main.o
+ .data          0x0000000000000000        0x0 crt0.o
+ .bss           0x0000000000000000        0x0 crt0.o
+ .text.open     0x0000000000000000        0x6 crt0.o
+ .text.close    0x0000000000000000        0x6 crt0.o
+ .text.system   0x0000000000000000        0x6 crt0.o
+ .text.write    0x0000000000000000        0x6 crt0.o
+ .text.read     0x0000000000000000        0x6 crt0.o
+ .text.usleep   0x0000000000000000        0x6 crt0.o
+ .ARM.attributes
+                0x0000000000000000       0x21 crt0.o
+
+Memory Configuration
+
+Name             Origin             Length             Attributes
+*default*        0x0000000000000000 0xffffffffffffffff
+
+Linker script and memory map
+
+                0x0000000000000094                . = (0x0 + SIZEOF_HEADERS)
+
+.text           0x0000000000000098       0x10
+ *(.text)
+ .text          0x0000000000000098        0x8 crt0.o
+                0x0000000000000098                _start
+ *(.text.*)
+ .text.main     0x00000000000000a0        0x4 main.o
+                0x00000000000000a0                main
+ .text._exit    0x00000000000000a4        0x4 crt0.o
+                0x00000000000000a4                _exit
+ *(.gnu.linkonce.t.*)
+
+.glue_7         0x00000000000000a8        0x0
+ .glue_7        0x0000000000000000        0x0 linker stubs
+
+.glue_7t        0x00000000000000a8        0x0
+ .glue_7t       0x0000000000000000        0x0 linker stubs
+
+.vfp11_veneer   0x00000000000000a8        0x0
+ .vfp11_veneer  0x0000000000000000        0x0 linker stubs
+
+.v4_bx          0x00000000000000a8        0x0
+ .v4_bx         0x0000000000000000        0x0 linker stubs
+
+.plt            0x00000000000000a8        0x0
+ .plt           0x0000000000000000        0x0 main.o
+
+.rel.dyn        0x00000000000000a8        0x0
+ .rel.plt       0x0000000000000000        0x0 main.o
+
+.rel.data
+ *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*)
+
+.rel.got        0x00000000000000a8        0x0
+ *(.rel.got)
+ .rel.got       0x0000000000000000        0x0 main.o
+                0x0000000010000000                . = 0x10000000
+
+.got            0x0000000010000000        0xc
+ *(.got.plt)
+ .got.plt       0x0000000010000000        0xc main.o
+                0x0000000010000000                _GLOBAL_OFFSET_TABLE_
+ *(.igot.plt)
+ *(.got)
+ .got           0x0000000000000000        0x0 main.o
+ *(.igot)
+
+.dynamic        0x000000001000000c       0x28
+ *(.dynamic)
+ .dynamic       0x000000001000000c       0x28 main.o
+                0x000000001000000c                _DYNAMIC
+
+.rodata
+ *(.rodata)
+ *(.rodata.*)
+ *(.gnu.linkonce.r.*)
+
+.gnu.version_d  0x0000000010000034        0x0
+ .gnu.version_d
+                0x0000000000000000        0x0 main.o
+
+.gnu.version    0x0000000010000034        0x0
+ .gnu.version   0x0000000000000000        0x0 main.o
+
+.gnu.version_r  0x0000000010000034        0x0
+ .gnu.version_r
+                0x0000000000000000        0x0 main.o
+
+.data
+ *(.data)
+ *(.data.*)
+ *(.gnu.linkonce.d.*)
+
+.bss
+ *(.bss)
+ *(.bss.*)
+ *(.gnu.linkonce.b.*)
+ *(COMMON)
+
+.dynbss         0x0000000010000034        0x0
+ .dynbss        0x0000000000000000        0x0 main.o
+
+/DISCARD/
+ *(.interp)
+ *(.dynsym)
+ *(.dynstr)
+ *(.hash)
+ *(.comment)
+ *(.ARM.attributes)
+LOAD main.o
+LOAD crt0.o
+START GROUP
+LOAD /opt/arm-miosix-eabi/lib/gcc/arm-eabi/4.5.2/../../../../arm-eabi/lib/thumb/thumb2/libstdc++.a
+LOAD /opt/arm-miosix-eabi/lib/gcc/arm-eabi/4.5.2/../../../../arm-eabi/lib/thumb/thumb2/libc.a
+LOAD /opt/arm-miosix-eabi/lib/gcc/arm-eabi/4.5.2/../../../../arm-eabi/lib/thumb/thumb2/libm.a
+LOAD /opt/arm-miosix-eabi/lib/gcc/arm-eabi/4.5.2/thumb/thumb2/libgcc.a
+END GROUP
+OUTPUT(main.elf elf32-littlearm)
diff --git a/system_app_test/miosix.ld b/system_app_test/miosix.ld
new file mode 100644
index 00000000..c91c803e
--- /dev/null
+++ b/system_app_test/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/system_app_test/prog3.h b/system_app_test/prog3.h
new file mode 100644
index 00000000..df98510d
--- /dev/null
+++ b/system_app_test/prog3.h
@@ -0,0 +1,22 @@
+const unsigned char __attribute__((aligned(8))) test_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, 0x7b, 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 test_elf_len = 220;
diff --git a/system_app_test/test.txt b/system_app_test/test.txt
new file mode 100644
index 00000000..2c5c7a70
--- /dev/null
+++ b/system_app_test/test.txt
@@ -0,0 +1,76 @@
+
+test.elf:     file format elf32-littlearm
+test.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
+000000a4 g     F .text	00000000 _exit
+
+
+Contents of section .text:
+ 0098 00f002f8 00f002f8 7b207047 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:	207b      	movs	r0, #123	; 0x7b
+  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
+	...
-- 
GitLab