From 0acd008184270a5dc18c7cb23aac41054aa7471f Mon Sep 17 00:00:00 2001
From: Terraneo Federico <fede.tft@hotmail.it>
Date: Sun, 30 Oct 2011 16:30:17 +0100
Subject: [PATCH] Faster boot, changed getMiosixVersion()

---
 .../core/stage_1_boot.cpp                     | 42 ++++++++----------
 .../stm32f103ve_mp3v2/core/stage_1_boot.cpp   | 42 ++++++++----------
 .../stm32f103ve_mp3v2/stm32_512k+64k_ram.ld   |  3 +-
 .../core/stage_1_boot.cpp                     | 44 +++++++++----------
 .../stm32_512k+64k_all_in_xram.ld             |  3 +-
 miosix/config/Makefile.inc                    |  4 +-
 miosix/doc/textdoc/Changelog.txt              |  4 ++
 miosix/kernel/kernel.cpp                      | 39 ++++++----------
 miosix/util/version.cpp                       | 17 ++++---
 miosix/util/version.h                         |  6 ++-
 10 files changed, 94 insertions(+), 110 deletions(-)

diff --git a/miosix/arch/cortexM3_stm32/stm32f100rb_stm32vldiscovery/core/stage_1_boot.cpp b/miosix/arch/cortexM3_stm32/stm32f100rb_stm32vldiscovery/core/stage_1_boot.cpp
index 433920d1..5f663809 100644
--- a/miosix/arch/cortexM3_stm32/stm32f100rb_stm32vldiscovery/core/stage_1_boot.cpp
+++ b/miosix/arch/cortexM3_stm32/stm32f100rb_stm32vldiscovery/core/stage_1_boot.cpp
@@ -1,6 +1,7 @@
 
 #include "CMSIS/stm32f10x.h"
 #include "core/interrupts.h" //For the unexpected interrupt call
+#include <string.h>
 
 /*
  * startup.cpp
@@ -22,16 +23,13 @@ extern "C" void _init();
  * \param end one past the last function pointer to call
  * Declared "noinline" to optimize code size
  */
-static void call_constructors(unsigned long *start, unsigned long *end)
-		__attribute__((noinline));
+static void call_constructors(unsigned long *start, unsigned long *end) __attribute__((noinline));
 static void call_constructors(unsigned long *start, unsigned long *end)
 {
-	unsigned long *i;
-	void (*funcptr)();
-
-	for(i=start; i<end; i++)
+	for(unsigned long *i=start; i<end; i++)
 	{
-		funcptr=reinterpret_cast<void (*)()>(*i);
+		void (*funcptr)();
+        funcptr=reinterpret_cast<void (*)()>(*i);
 		funcptr();
 	}
 }
@@ -59,11 +57,11 @@ void program_startup()
     SystemInit();
 
 	//These are defined in the linker script
-	extern unsigned long _etext asm("_etext");
-	extern unsigned long _data asm("_data");
-	extern unsigned long _edata asm("_edata");
-	extern unsigned long _bss_start asm("_bss_start");
-	extern unsigned long _bss_end asm("_bss_end");
+	extern unsigned char _etext asm("_etext");
+	extern unsigned char _data asm("_data");
+	extern unsigned char _edata asm("_edata");
+	extern unsigned char _bss_start asm("_bss_start");
+	extern unsigned char _bss_end asm("_bss_end");
 	extern unsigned long __preinit_array_start asm("__preinit_array_start");
 	extern unsigned long __preinit_array_end asm("__preinit_array_end");
 	extern unsigned long __init_array_start asm("__init_array_start");
@@ -71,18 +69,14 @@ void program_startup()
 	extern unsigned long _ctor_start asm("_ctor_start");
 	extern unsigned long _ctor_end asm("_ctor_end");
 
-	unsigned long *src, *dest;
-
-	//Initialize .data section
-	for(src=&_etext, dest=&_data; dest<&_edata; src++, dest++)
-	{
-		*dest=*src;
-	}
-	//Clear .bss section
-	for(dest=&_bss_start; dest<&_bss_end; dest++)
-	{
-		*dest=0;
-	}
+    //Initialize .data section, clear .bss section
+    unsigned char *etext=&_etext;
+    unsigned char *data=&_data;
+    unsigned char *edata=&_edata;
+    unsigned char *bss_start=&_bss_start;
+    unsigned char *bss_end=&_bss_end;
+    memcpy(data, etext, edata-data);
+    memset(bss_start, 0, bss_end-bss_start);
 
 	//Initialize C++ global constructors
 	call_constructors(&__preinit_array_start, &__preinit_array_end);
diff --git a/miosix/arch/cortexM3_stm32/stm32f103ve_mp3v2/core/stage_1_boot.cpp b/miosix/arch/cortexM3_stm32/stm32f103ve_mp3v2/core/stage_1_boot.cpp
index 6f3c00e0..d7e0fc4d 100644
--- a/miosix/arch/cortexM3_stm32/stm32f103ve_mp3v2/core/stage_1_boot.cpp
+++ b/miosix/arch/cortexM3_stm32/stm32f103ve_mp3v2/core/stage_1_boot.cpp
@@ -1,6 +1,7 @@
 
 #include "CMSIS/stm32f10x.h"
 #include "core/interrupts.h" //For the unexpected interrupt call
+#include <string.h>
 
 /*
  * startup.cpp
@@ -21,16 +22,13 @@ extern "C" void _init();
  * \param end one past the last function pointer to call
  * Declared "noinline" to optimize code size
  */
-static void call_constructors(unsigned long *start, unsigned long *end)
-		__attribute__((noinline));
+static void call_constructors(unsigned long *start, unsigned long *end) __attribute__((noinline));
 static void call_constructors(unsigned long *start, unsigned long *end)
 {
-	unsigned long *i;
-	void (*funcptr)();
-
-	for(i=start; i<end; i++)
+	for(unsigned long *i=start; i<end; i++)
 	{
-		funcptr=reinterpret_cast<void (*)()>(*i);
+		void (*funcptr)();
+        funcptr=reinterpret_cast<void (*)()>(*i);
 		funcptr();
 	}
 }
@@ -50,11 +48,11 @@ void program_startup()
     //SystemInit();
 
 	//These are defined in the linker script
-	extern unsigned long _etext asm("_etext");
-	extern unsigned long _data asm("_data");
-	extern unsigned long _edata asm("_edata");
-	extern unsigned long _bss_start asm("_bss_start");
-	extern unsigned long _bss_end asm("_bss_end");
+	extern unsigned char _etext asm("_etext");
+	extern unsigned char _data asm("_data");
+	extern unsigned char _edata asm("_edata");
+	extern unsigned char _bss_start asm("_bss_start");
+	extern unsigned char _bss_end asm("_bss_end");
 	extern unsigned long __preinit_array_start asm("__preinit_array_start");
 	extern unsigned long __preinit_array_end asm("__preinit_array_end");
 	extern unsigned long __init_array_start asm("__init_array_start");
@@ -62,18 +60,14 @@ void program_startup()
 	extern unsigned long _ctor_start asm("_ctor_start");
 	extern unsigned long _ctor_end asm("_ctor_end");
 
-	unsigned long *src, *dest;
-
-	//Initialize .data section
-	for(src=&_etext, dest=&_data; dest<&_edata; src++, dest++)
-	{
-		*dest=*src;
-	}
-	//Clear .bss section
-	for(dest=&_bss_start; dest<&_bss_end; dest++)
-	{
-		*dest=0;
-	}
+	//Initialize .data section, clear .bss section
+    unsigned char *etext=&_etext;
+    unsigned char *data=&_data;
+    unsigned char *edata=&_edata;
+    unsigned char *bss_start=&_bss_start;
+    unsigned char *bss_end=&_bss_end;
+    memcpy(data, etext, edata-data);
+    memset(bss_start, 0, bss_end-bss_start);
 
 	//Initialize C++ global constructors
 	call_constructors(&__preinit_array_start, &__preinit_array_end);
diff --git a/miosix/arch/cortexM3_stm32/stm32f103ve_mp3v2/stm32_512k+64k_ram.ld b/miosix/arch/cortexM3_stm32/stm32f103ve_mp3v2/stm32_512k+64k_ram.ld
index 54e2453c..d0ae2edc 100644
--- a/miosix/arch/cortexM3_stm32/stm32f103ve_mp3v2/stm32_512k+64k_ram.ld
+++ b/miosix/arch/cortexM3_stm32/stm32f103ve_mp3v2/stm32_512k+64k_ram.ld
@@ -110,8 +110,7 @@ SECTIONS
     . = ALIGN(8);
     _etext = .;
 
-	/* .data section: global variables go to ram, but also store a copy to
-       flash to initialize them */
+	/* .data section: global variables go to ram */
     .data : ALIGN(8)
     {
         _data = .;
diff --git a/miosix/arch/cortexM3_stm32/stm32f103ze_stm3210e-eval/core/stage_1_boot.cpp b/miosix/arch/cortexM3_stm32/stm32f103ze_stm3210e-eval/core/stage_1_boot.cpp
index ec3d4160..55f1073c 100644
--- a/miosix/arch/cortexM3_stm32/stm32f103ze_stm3210e-eval/core/stage_1_boot.cpp
+++ b/miosix/arch/cortexM3_stm32/stm32f103ze_stm3210e-eval/core/stage_1_boot.cpp
@@ -1,6 +1,7 @@
 
 #include "CMSIS/stm32f10x.h"
 #include "core/interrupts.h" //For the unexpected interrupt call
+#include <string.h>
 
 /*
  * startup.cpp
@@ -21,16 +22,13 @@ extern "C" void _init();
  * \param end one past the last function pointer to call
  * Declared "noinline" to optimize code size
  */
-static void call_constructors(unsigned long *start, unsigned long *end)
-		__attribute__((noinline));
+static void call_constructors(unsigned long *start, unsigned long *end) __attribute__((noinline));
 static void call_constructors(unsigned long *start, unsigned long *end)
 {
-	unsigned long *i;
-	void (*funcptr)();
-
-	for(i=start; i<end; i++)
+	for(unsigned long *i=start; i<end; i++)
 	{
-		funcptr=reinterpret_cast<void (*)()>(*i);
+		void (*funcptr)();
+        funcptr=reinterpret_cast<void (*)()>(*i);
 		funcptr();
 	}
 }
@@ -58,11 +56,11 @@ void program_startup()
     SystemInit();
 
 	//These are defined in the linker script
-	extern unsigned long _etext asm("_etext");
-	extern unsigned long _data asm("_data");
-	extern unsigned long _edata asm("_edata");
-	extern unsigned long _bss_start asm("_bss_start");
-	extern unsigned long _bss_end asm("_bss_end");
+	extern unsigned char _etext asm("_etext");
+	extern unsigned char _data asm("_data");
+	extern unsigned char _edata asm("_edata");
+	extern unsigned char _bss_start asm("_bss_start");
+	extern unsigned char _bss_end asm("_bss_end");
 	extern unsigned long __preinit_array_start asm("__preinit_array_start");
 	extern unsigned long __preinit_array_end asm("__preinit_array_end");
 	extern unsigned long __init_array_start asm("__init_array_start");
@@ -70,18 +68,16 @@ void program_startup()
 	extern unsigned long _ctor_start asm("_ctor_start");
 	extern unsigned long _ctor_end asm("_ctor_end");
 
-	unsigned long *src, *dest;
-
-	//Initialize .data section
-	for(src=&_etext, dest=&_data; dest<&_edata; src++, dest++)
-	{
-		*dest=*src;
-	}
-	//Clear .bss section
-	for(dest=&_bss_start; dest<&_bss_end; dest++)
-	{
-		*dest=0;
-	}
+	//Initialize .data section, clear .bss section
+    unsigned char *etext=&_etext;
+    unsigned char *data=&_data;
+    unsigned char *edata=&_edata;
+    unsigned char *bss_start=&_bss_start;
+    unsigned char *bss_end=&_bss_end;
+    #ifndef __CODE_IN_XRAM
+    memcpy(data, etext, edata-data);
+    #endif //__CODE_IN_XRAM
+    memset(bss_start, 0, bss_end-bss_start);
 
 	//Initialize C++ global constructors
 	call_constructors(&__preinit_array_start, &__preinit_array_end);
diff --git a/miosix/arch/cortexM3_stm32/stm32f103ze_stm3210e-eval/stm32_512k+64k_all_in_xram.ld b/miosix/arch/cortexM3_stm32/stm32f103ze_stm3210e-eval/stm32_512k+64k_all_in_xram.ld
index 8429fdc8..36e3e2d1 100644
--- a/miosix/arch/cortexM3_stm32/stm32f103ze_stm3210e-eval/stm32_512k+64k_all_in_xram.ld
+++ b/miosix/arch/cortexM3_stm32/stm32f103ze_stm3210e-eval/stm32_512k+64k_all_in_xram.ld
@@ -111,8 +111,7 @@ SECTIONS
     . = ALIGN(8);
     _etext = .;
 
-	/* .data section: global variables go to ram, but also store a copy to
-       flash to initialize them */
+    /* .data section: global variables go to ram */
     .data : ALIGN(8)
     {
         _data = .;
diff --git a/miosix/config/Makefile.inc b/miosix/config/Makefile.inc
index e6636563..c8a53075 100644
--- a/miosix/config/Makefile.inc
+++ b/miosix/config/Makefile.inc
@@ -130,8 +130,8 @@ endif
 ## Then, initialize C/C++ flags with -D_MIOSIX so that application code can
 ## know if the OS is MIOSIX
 ##
-CFLAGS_BASE   := -D_MIOSIX
-CXXFLAGS_BASE := -D_MIOSIX
+CFLAGS_BASE   := -D_MIOSIX="\"$(OPT_BOARD)\""
+CXXFLAGS_BASE := -D_MIOSIX="\"$(OPT_BOARD)\""
 
 ##
 ## Now two big switch-like constructs nested. The first lists all possible
diff --git a/miosix/doc/textdoc/Changelog.txt b/miosix/doc/textdoc/Changelog.txt
index 271edd73..5d5e4bd9 100644
--- a/miosix/doc/textdoc/Changelog.txt
+++ b/miosix/doc/textdoc/Changelog.txt
@@ -1,6 +1,10 @@
 Changelog for Miosix np embedded OS
 
 v1.59
+- Improved boot speed by replacing for loops to initialize .data, .bss and
+  to initialize the stack of threads with memset/memcpy.
+- Improved getMiosixVersion(), new format contains more information, including
+  board name, build date and compiler version.
 - The files binutils-2.21.tar.bz2 and gdb-7.0.tar.bz2 no longer exist on the
   ftp.gnu.org and mirrors.kernel.org, and this broke the compiler installation
   script. Fixed by downloading binutils-2.21.1 and gdb-7.0.1a.
diff --git a/miosix/kernel/kernel.cpp b/miosix/kernel/kernel.cpp
index a2431cef..681d8c21 100644
--- a/miosix/kernel/kernel.cpp
+++ b/miosix/kernel/kernel.cpp
@@ -35,6 +35,7 @@
 #include "kernel/scheduler/scheduler.h"
 #include <stdexcept>
 #include <algorithm>
+#include <string.h>
 
 /*
 Used by assembler context switch macros
@@ -166,19 +167,12 @@ void startKernel()
     void *threadClass=base+((STACK_IDLE+CTXSAVE_ON_STACK+WATERMARK_LEN)/
             sizeof(unsigned int));
     Thread *idle=new (threadClass) Thread(base,STACK_IDLE);
-    //Fill watermark
-    for(unsigned int i=0;i<(WATERMARK_LEN/sizeof(unsigned int));i++)
-    {
-        *base=WATERMARK_FILL;
-        base++;
-    }
-    //Fill stack
-    for(unsigned int i=0;
-            i<((STACK_IDLE+CTXSAVE_ON_STACK)/sizeof(unsigned int));i++)
-    {
-        *base=STACK_FILL;
-        base++;
-    }
+
+    //Fill watermark and stack
+    memset(base, WATERMARK_FILL, WATERMARK_LEN);
+    base+=WATERMARK_LEN/sizeof(unsigned int);
+    memset(base, STACK_FILL, STACK_IDLE);
+
     //On some architectures some registers are saved on the stack, therefore
     //initCtxsave *must* be called after filling the stack.
     miosix_private::initCtxsave(idle->ctxsave,idleThread,
@@ -312,19 +306,12 @@ Thread *Thread::create(void *(*startfunc)(void *), unsigned int stacksize,
     void *threadClass=base+((stacksize+WATERMARK_LEN+CTXSAVE_ON_STACK)/
             sizeof(unsigned int));
     Thread *thread=new (threadClass) Thread(base,stacksize);
-    //Fill watermark
-    for(unsigned int i=0;i<(WATERMARK_LEN/sizeof(unsigned int));i++)
-    {
-        *base=WATERMARK_FILL;
-        base++;
-    }
-    //Fill stack
-    for(unsigned int i=0;
-            i<((stacksize+CTXSAVE_ON_STACK)/sizeof(unsigned int));i++)
-    {
-        *base=STACK_FILL;
-        base++;
-    }
+
+    //Fill watermark and stack
+    memset(base, WATERMARK_FILL, WATERMARK_LEN);
+    base+=WATERMARK_LEN/sizeof(unsigned int);
+    memset(base, STACK_FILL, stacksize);
+
     //On some architectures some registers are saved on the stack, therefore
     //initCtxsave *must* be called after filling the stack.
     miosix_private::initCtxsave(thread->ctxsave,startfunc,
diff --git a/miosix/util/version.cpp b/miosix/util/version.cpp
index 134b69a3..10b7bce9 100644
--- a/miosix/util/version.cpp
+++ b/miosix/util/version.cpp
@@ -1,14 +1,21 @@
 
 namespace miosix {
 
-/**
- * Kernel verision is stored in this string.
- */
-const char *const versionString="Miosix v1.59";
+#ifdef __GNUC__
+#define tts(x) #x
+#define ts(x) tts(x)
+#define CV ", gcc "ts(__GNUC__)"."ts(__GNUC_MINOR__)"."ts(__GNUC_PATCHLEVEL__)
+#define AU __attribute__((used))
+#else
+#define CV
+#define AU
+#endif
+
+const char AU ver[]="Miosix v1.59 (" _MIOSIX ", " __DATE__ " " __TIME__ CV ")";
 
 const char *getMiosixVersion()
 {
-    return versionString;
+    return ver;
 }
 
 } //namespace miosix
diff --git a/miosix/util/version.h b/miosix/util/version.h
index 715264d8..96d4b02d 100644
--- a/miosix/util/version.h
+++ b/miosix/util/version.h
@@ -38,7 +38,11 @@ namespace miosix {
 /**
  * Allows to know the version of the kernel at runtime.
  * \return a string with the kernel version.
- * The format is "Miosix vX.XX" where X.XX is the version number
+ * The format is "Miosix vX.XX (board, builddate, compiler)" where
+ * vX.XX is the kernel version number, like "v1.59"
+ * board is the board name, like "stm32f103ze_stm3210e-eval"
+ * builddate is the date the kernel was built, like "Oct 30 2011 00:58:10"
+ * compiler is the compiler version, like "gcc 4.5.2"
  */
 const char *getMiosixVersion();
 
-- 
GitLab