diff --git a/Makefile b/Makefile
index 55a19c0c2da48fec3be2ffdd4547a533c0cd8d36..4af847029ee7b2667fb9c14747e3825eb1196688 100644
--- a/Makefile
+++ b/Makefile
@@ -13,7 +13,7 @@ SUBDIRS := miosix
 ## List here your source files (both .s, .c and .cpp)
 ##
 SRC :=                                  \
-testsuite.cpp
+main.cpp
 
 ##
 ## List here additional static libraries with relative path
diff --git a/Readme.txt b/Readme.txt
new file mode 100644
index 0000000000000000000000000000000000000000..ce3f37b6466d8ef7ecba7544a81ef0ba43089116
--- /dev/null
+++ b/Readme.txt
@@ -0,0 +1,9 @@
+
+Welcome to the Miosix kernel
+============================
+
+You can find information on how to configure and use the kernel
+at the following url: http://www.webalice.it/fede.tft/miosix
+
+The testsuite has been moved in the miosix/testsuite directory.
+The examples have been moved in the miosix/examples directory. 
diff --git a/main.cpp b/main.cpp
index 6bb0660a6eafb6fca7389f0156f7395a0e918788..8764b9fabb7ead786e8a9eae3d8bd03873dc6ec4 100644
--- a/main.cpp
+++ b/main.cpp
@@ -1,7 +1,5 @@
 
 #include <cstdio>
-#include <cstdlib>
-#include <vector>
 #include "miosix.h"
 
 using namespace std;
diff --git a/miosix/doc/textdoc/Changelog.txt b/miosix/doc/textdoc/Changelog.txt
index 2726089217157df4fabf21ec578448d5b21e7e18..66c9034d4b9201535d1d9f26e554cbd82d37bc4a 100644
--- a/miosix/doc/textdoc/Changelog.txt
+++ b/miosix/doc/textdoc/Changelog.txt
@@ -1,6 +1,12 @@
 Changelog for Miosix np embedded OS
 
 v1.59
+- Added test to testsuite for BufferQueue
+- Refactored top level directory, now the testsuite and examples have
+  been moved in their directories within the miosix directory
+- Improved Queue class
+- Added class BufferQueue to simplify the development of double buffered
+  data transfers between threads and interrupt routines
 - Some const-ness fixes in util
 - Extended boot improvements to strive mini board
 - Forgot to add util/crc16.cpp to the makefile buid rules
diff --git a/miosix/examples/thread_native/Readme.txt b/miosix/examples/thread_native/Readme.txt
new file mode 100644
index 0000000000000000000000000000000000000000..9f0e03314e4a4f29d91b5b929a8f7582fbfd5260
--- /dev/null
+++ b/miosix/examples/thread_native/Readme.txt
@@ -0,0 +1,11 @@
+
+To run this example, copy the content of this directory into
+the top level directory, and modify the Makefile from 
+
+SRC :=                                  \
+main.cpp
+
+to
+
+SRC :=                                  \
+native_thread_example.cpp
\ No newline at end of file
diff --git a/native_thread_example.cpp b/miosix/examples/thread_native/native_thread_example.cpp
similarity index 100%
rename from native_thread_example.cpp
rename to miosix/examples/thread_native/native_thread_example.cpp
diff --git a/miosix/examples/thread_pthread/Readme.txt b/miosix/examples/thread_pthread/Readme.txt
new file mode 100644
index 0000000000000000000000000000000000000000..870fa05dd5600020a211b7ee072872745f3789bf
--- /dev/null
+++ b/miosix/examples/thread_pthread/Readme.txt
@@ -0,0 +1,11 @@
+
+To run this example, copy the content of this directory into
+the top level directory, and modify the Makefile from 
+
+SRC :=                                  \
+main.cpp
+
+to
+
+SRC :=                                  \
+pthread_example.cpp
\ No newline at end of file
diff --git a/pthread_example.cpp b/miosix/examples/thread_pthread/pthread_example.cpp
similarity index 100%
rename from pthread_example.cpp
rename to miosix/examples/thread_pthread/pthread_example.cpp
diff --git a/miosix/kernel/buffer_queue.h b/miosix/kernel/buffer_queue.h
new file mode 100644
index 0000000000000000000000000000000000000000..4c94f33d06a6ce5b65ffb124d946efbc92abd1e5
--- /dev/null
+++ b/miosix/kernel/buffer_queue.h
@@ -0,0 +1,182 @@
+/***************************************************************************
+ *   Copyright (C) 2011 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 "kernel.h"
+#include "error.h"
+
+#ifndef BUFFER_QUEUE_H
+#define	BUFFER_QUEUE_H
+
+namespace miosix {
+
+/**
+ * \addtogroup Sync
+ * \{
+ */
+
+/**
+ * A class to handle double buffering, but also triple buffering and in general
+ * N-buffering. Works between two threads but is especially suited to
+ * synchronize between a thread and an interrupt routine.<br>
+ * Note that unlike Queue, this class is only a data structure and not a
+ * synchronization primitive. The synchronization between the thread and
+ * the IRQ (or the other thread) must be done by the caller. Therefore, to
+ * avoid race conditions all the member function are on purpose marked IRQ
+ * meaning that can only be called with interrupt disabled or within an IRQ.<br>
+ * The internal implementation treats the buffers as a circular queue of N
+ * elements, hence the name.
+ * \tparam T type of elements of the buffer, usually char or unsigned char
+ * \tparam size maximum size of a buffer
+ * \tparam numbuf number of buffers, the default is two resulting in a
+ * double buffering scheme. Values 0 and 1 are forbidden
+ */
+template<typename T, unsigned int size, unsigned char numbuf=2>
+class BufferQueue
+{
+public:
+    /**
+     * Constructor, all buffers are empty
+     */
+    BufferQueue() : put(0), get(0), cnt(0) {}
+
+    ///Maximum size of a buffer
+    static const unsigned int bufferMaxSize=size;
+
+    ///Number of buffers available
+    static const unsigned char numberOfBuffers=numbuf;
+
+    /**
+     * \return true if no buffer is available for reading
+     */
+    bool IRQisEmpty() const { return cnt==0; }
+
+    /**
+     * \return true if no buffer is available for writing
+     */
+    bool IRQisFull() const { return cnt==numbuf; }
+
+    /**
+     * This member function allows to retrieve a buffer ready to be written,
+     * if available.
+     * \param buffer the available buffer will be assigned here if available
+     * \return true if a writable buffer has been found, false otherwise.
+     * In this case the buffer parameter is not modified
+     */
+    bool IRQgetWritableBuffer(T *&buffer)
+    {
+        if(cnt==numbuf) return false;
+        buffer=buf[put];
+        return true;
+    }
+
+    /**
+     * After having called getWritableBuffer() or IRQgetWritableBuffer() to
+     * retrieve a buffer and having filled it, this member function allows
+     * to mark the buffer as available on the reader side.
+     * \param actualSize actual size of buffer. It usually equals bufferMaxSize
+     * but can be a lower value in case there is less available data
+     */
+    void IRQbufferFilled(unsigned int actualSize)
+    {
+        if(++cnt>numbuf) errorHandler(UNEXPECTED);
+        bufSize[put]=actualSize;
+        put++;
+        put%=numbuf;
+    }
+
+    /**
+     * \return The number of buffers available for writing (0 to numbuf)
+     */
+    unsigned char IRQavailableForWriting() const { return numbuf-cnt; }
+
+    /**
+     * This member function allows to retrieve a buffer ready to be read,
+     * if available.
+     * \param buffer the available buffer will be assigned here if available
+     * \param actualSize the actual size of the buffer, as reported by the
+     * writer side
+     * \return true if a readable buffer has been found, false otherwise.
+     * In this case the buffer and actualSize parameters are not modified
+     */
+    bool IRQgetReadableBuffer(const T *&buffer, unsigned int& actualSize)
+    {
+        if(cnt==0) return false;
+        buffer=buf[get];
+        actualSize=bufSize[get];
+        return true;
+    }
+
+    /**
+     * After having called getReadableBuffer() or IRQgetReadableBuffer() to
+     * retrieve a buffer and having read it, this member function allows
+     * to mark the buffer as available on the writer side.
+     */
+    void IRQbufferEmptied()
+    {
+        if(--cnt<0) errorHandler(UNEXPECTED);
+        get++;
+        get%=numbuf;
+    }
+
+    /**
+     * \return The number of buffers available for reading (0, to numbuf)
+     */
+    unsigned char IRQavailableForReading() const { return cnt; }
+
+    /**
+     * Reset the buffers. As a consequence, the queue becomes empty.
+     */
+    void IRQreset()
+    {
+        put=get=cnt=0;
+    }
+
+private:
+    //Unwanted methods
+    BufferQueue(const BufferQueue&);
+    BufferQueue& operator=(const BufferQueue&);
+
+    T buf[numbuf][size]; // The buffers
+    unsigned int bufSize[numbuf]; //To handle partially empty buffers
+    unsigned char put; //Put pointer, either 0 or 1
+    unsigned char get; //Get pointer, either 0 or 1
+    volatile unsigned char cnt; //Number of filled buffers, either (0 to numbuf)
+};
+
+//These two partial specialization are meant to produce compiler errors in case
+//an attempt is made to allocate a BufferQueue with zero or one buffer, as it
+//is forbidden
+template<typename T, unsigned int size> class BufferQueue<T,size,0> {};
+template<typename T, unsigned int size> class BufferQueue<T,size,1> {};
+
+/**
+ * \}
+ */
+
+} //namespace miosix
+
+#endif //BUFFER_QUEUE_H
diff --git a/miosix/kernel/sync.h b/miosix/kernel/sync.h
index fe96991c491cecf78166bb0fb445a303c1a37c00..1f484c14cc94f6e91e726e92fe0f4a48871cc860 100644
--- a/miosix/kernel/sync.h
+++ b/miosix/kernel/sync.h
@@ -510,7 +510,7 @@ private:
  * queue with a waiting thread, and to avoid situations where a thread tries to
  * access a deleted queue.
  * \tparam T the type of elements in the queue
- * \tparam len the length of the Queue
+ * \tparam len the length of the Queue. Value 0 is forbidden
  */
 template <typename T, unsigned int len>
 class Queue
@@ -519,27 +519,20 @@ public:
     /**
      * Constructor, create a new empty queue.
      */
-    Queue()
-    {
-        put_pos=get_pos=num_elem=0;
-        waiting=NULL;
-    }
+    Queue() : waiting(0), num_elem(0), put_pos(0), get_pos(0) {}
+
+    ///Size of the queue
+    static const unsigned int queueSize=len;
 
     /**
      * \return true if the queue is empty
      */
-    bool isEmpty() const
-    {
-        return (put_pos==get_pos)&&(num_elem==0);
-    }
+    bool isEmpty() const { return num_elem==0; }
 
     /**
      * \return true if the queue is full
      */
-    bool isFull() const
-    {
-        return (put_pos==get_pos)&&(num_elem!=0);
-    }
+    bool isFull() const { return num_elem==len; }
 	
     /**
      * If a queue is empty, waits until the queue is not empty.
@@ -766,6 +759,10 @@ private:
     volatile unsigned int get_pos; ///< index of buffer where to put next element
 };
 
+//This partial specialization is meant to to produce compiler errors in case an
+//attempt is made to instantiate a Queue with zero size, as it is forbidden
+template<typename T> class Queue<T,0> {};
+
 /**
  * \}
  */
diff --git a/miosix/testsuite/Readme.txt b/miosix/testsuite/Readme.txt
new file mode 100644
index 0000000000000000000000000000000000000000..ca5e8a5c5389d936b063d69a28845e9298a67423
--- /dev/null
+++ b/miosix/testsuite/Readme.txt
@@ -0,0 +1,11 @@
+
+To run the testsuite, copy the content of this directory into
+the top level directory, and modify the Makefile from 
+
+SRC :=                                  \
+main.cpp
+
+to
+
+SRC :=                                  \
+testsuite.cpp
\ No newline at end of file
diff --git a/testsuite.cpp b/miosix/testsuite/testsuite.cpp
similarity index 93%
rename from testsuite.cpp
rename to miosix/testsuite/testsuite.cpp
index 2eff786fa9d2d1f5f246891f2f76333fadaea383..5075d55f8dfe52964417a4822ab2934c63e5d0b7 100644
--- a/testsuite.cpp
+++ b/miosix/testsuite/testsuite.cpp
@@ -41,6 +41,7 @@
 #include <errno.h>
 
 #include "miosix.h"
+#include "miosix/kernel/buffer_queue.h"
 #include "config/miosix_settings.h"
 #include "interfaces/console.h"
 #include "board_settings.h"
@@ -79,6 +80,7 @@ static void test_15();
 static void test_16();
 static void test_17();
 static void test_18();
+static void test_19();
 //Filesystem test functions
 #ifdef WITH_FILESYSTEM
 static void fs_test_1();
@@ -136,6 +138,7 @@ int main()
                 test_16();
                 test_17();
                 test_18();
+                test_19();
                 
                 ledOff();
                 Thread::sleep(500);//Ensure all threads are deleted.
@@ -2330,6 +2333,196 @@ static void test_18()
     pass();
 }
 
+//
+// Test 19
+//
+/*
+tests:
+class BufferQueue
+*/
+
+BufferQueue<char,10,3> bq;
+Thread *t19_v1;
+
+static const char b1c[]="b1c----";
+static const char b2c[]="b2c----x";
+static const char b3c[]="b3c----xx";
+static const char b4c[]="";
+
+static char *IRQgbw(FastInterruptDisableLock& dLock)
+{
+    char *buffer=0;
+    if(bq.IRQgetWritableBuffer(buffer)==false)
+    {
+        FastInterruptEnableLock eLock(dLock);
+        fail("BufferQueue::get");
+    }
+    return buffer;
+}
+
+static void gbr(const char *&buffer, unsigned int& size)
+{
+    FastInterruptDisableLock dLock;
+    while(bq.IRQgetReadableBuffer(buffer,size)==false)
+    {
+        Thread::IRQwait();
+        {
+            FastInterruptEnableLock eLock(dLock);
+            Thread::yield();
+        }
+    }
+}
+
+static void be()
+{
+    FastInterruptDisableLock dLock;
+    bq.IRQbufferEmptied();
+}
+
+static void t19_p1(void *argv)
+{
+    Thread::sleep(50);
+    {
+        FastInterruptDisableLock dLock;
+        char *buffer=IRQgbw(dLock);
+        strcpy(buffer,b1c);
+        bq.IRQbufferFilled(strlen(b1c));
+        t19_v1->IRQwakeup();
+        {
+            FastInterruptEnableLock eLock(dLock);
+            Thread::sleep(10);
+        }
+        buffer=IRQgbw(dLock);
+        strcpy(buffer,b2c);
+        bq.IRQbufferFilled(strlen(b2c));
+        t19_v1->IRQwakeup();
+        {
+            FastInterruptEnableLock eLock(dLock);
+            Thread::sleep(10);
+        }
+        buffer=IRQgbw(dLock);
+        strcpy(buffer,b3c);
+        bq.IRQbufferFilled(strlen(b3c));
+        t19_v1->IRQwakeup();
+        {
+            FastInterruptEnableLock eLock(dLock);
+            Thread::sleep(10);
+        }
+        buffer=IRQgbw(dLock);
+        strcpy(buffer,b4c);
+        bq.IRQbufferFilled(strlen(b4c));
+        t19_v1->IRQwakeup();
+    }
+}
+
+static void test_19()
+{
+    test_name("BufferQueue");
+    if(bq.bufferMaxSize!=10) fail("bufferMaxSize");
+    if(bq.numberOfBuffers!=3) fail("numberOfBuffers");
+    //NOTE: in theory we should disable interrupts before calling these, but
+    //since we are accessing it from one thread only, for now it isn't required
+    if(bq.IRQisEmpty()==false) fail("IRQisEmpty");
+    if(bq.IRQisFull()==true) fail("IRQisFull");
+
+    //Test filling only one slot
+    char *buf=0;
+    const char *buffer=0;
+    unsigned int size;
+    if(bq.IRQgetReadableBuffer(buffer,size)==true) fail("IRQgetReadableBuffer");
+    if(bq.IRQgetWritableBuffer(buf)==false) fail("IRQgetWritableBuffer");
+    const char b1a[]="b1a";
+    strcpy(buf,b1a);
+    bq.IRQbufferFilled(strlen(b1a));
+    buf=0;
+    if(bq.IRQisEmpty()==true) fail("IRQisEmpty");
+    if(bq.IRQisFull()==true) fail("IRQisFull");
+    if(bq.IRQgetReadableBuffer(buffer,size)==false) fail("IRQgetReadableBuffer");
+    if(size!=strlen(b1a)) fail("returned size");
+    if(strcmp(buffer,b1a)!=0) fail("returned buffer");
+    bq.IRQbufferEmptied();
+    if(bq.IRQisEmpty()==false) fail("IRQisEmpty");
+    if(bq.IRQisFull()==true) fail("IRQisFull");
+    if(bq.IRQgetReadableBuffer(buffer,size)==true) fail("IRQgetReadableBuffer");
+    if(bq.IRQgetWritableBuffer(buf)==false) fail("IRQgetWritableBuffer");
+
+    //Test filling all three slots
+    const char b1b[]="b1b0";
+    strcpy(buf,b1b);
+    bq.IRQbufferFilled(strlen(b1b));
+    buf=0;
+    if(bq.IRQisEmpty()==true) fail("IRQisEmpty");
+    if(bq.IRQisFull()==true) fail("IRQisFull");
+    if(bq.IRQgetWritableBuffer(buf)==false) fail("IRQgetWritableBuffer");
+    const char b2b[]="b2b01";
+    strcpy(buf,b2b);
+    bq.IRQbufferFilled(strlen(b2b));
+    buf=0;
+    if(bq.IRQisEmpty()==true) fail("IRQisEmpty");
+    if(bq.IRQisFull()==true) fail("IRQisFull");
+    if(bq.IRQgetWritableBuffer(buf)==false) fail("IRQgetWritableBuffer");
+    const char b3b[]="b2b012";
+    strcpy(buf,b3b);
+    bq.IRQbufferFilled(strlen(b3b));
+    buf=0;
+    if(bq.IRQisEmpty()==true) fail("IRQisEmpty");
+    if(bq.IRQisFull()==false) fail("IRQisFull");
+    if(bq.IRQgetWritableBuffer(buf)==true) fail("IRQgetWritableBuffer");
+    buf=0;
+    //Filled entirely, now emptying
+    if(bq.IRQgetReadableBuffer(buffer,size)==false) fail("IRQgetReadableBuffer");
+    if(size!=strlen(b1b)) fail("returned size");
+    if(strcmp(buffer,b1b)!=0) fail("returned buffer");
+    bq.IRQbufferEmptied();
+    if(bq.IRQisEmpty()==true) fail("IRQisEmpty");
+    if(bq.IRQisFull()==true) fail("IRQisFull");
+    if(bq.IRQgetReadableBuffer(buffer,size)==false) fail("IRQgetReadableBuffer");
+    if(size!=strlen(b2b)) fail("returned size");
+    if(strcmp(buffer,b2b)!=0) fail("returned buffer");
+    bq.IRQbufferEmptied();
+    if(bq.IRQisEmpty()==true) fail("IRQisEmpty");
+    if(bq.IRQisFull()==true) fail("IRQisFull");
+    if(bq.IRQgetReadableBuffer(buffer,size)==false) fail("IRQgetReadableBuffer");
+    if(size!=strlen(b3b)) fail("returned size");
+    if(strcmp(buffer,b3b)!=0) fail("returned buffer");
+    bq.IRQbufferEmptied();
+    if(bq.IRQgetReadableBuffer(buffer,size)==true) fail("IRQgetReadableBuffer");
+    if(bq.IRQisEmpty()==false) fail("IRQisEmpty");
+    if(bq.IRQisFull()==true) fail("IRQisFull");
+
+    //Now real multithreaded test
+    t19_v1=Thread::getCurrentThread();
+    Thread *t=Thread::create(t19_p1,STACK_MIN,0,0,Thread::JOINABLE);
+    gbr(buffer,size);
+    if(size!=strlen(b1c)) fail("returned size");
+    if(strcmp(buffer,b1c)!=0) fail("returned buffer");
+    be();
+    gbr(buffer,size);
+    if(size!=strlen(b2c)) fail("returned size");
+    if(strcmp(buffer,b2c)!=0) fail("returned buffer");
+    be();
+    gbr(buffer,size);
+    if(size!=strlen(b3c)) fail("returned size");
+    if(strcmp(buffer,b3c)!=0) fail("returned buffer");
+    be();
+    gbr(buffer,size);
+    if(size!=strlen(b4c)) fail("returned size");
+    if(strcmp(buffer,b4c)!=0) fail("returned buffer");
+    be();
+    t->join();
+    if(bq.IRQisEmpty()==false) fail("IRQisEmpty");
+    if(bq.IRQisFull()==true) fail("IRQisFull");
+
+    //Last, check Reset (again, single thread mode)
+    if(bq.IRQgetWritableBuffer(buf)==false) fail("IRQgetWritableBuffer");
+    strcpy(buf,b1a);
+    bq.IRQbufferFilled(strlen(b1a));
+    bq.IRQreset();
+    if(bq.IRQisEmpty()==false) fail("IRQisEmpty");
+    if(bq.IRQisFull()==true) fail("IRQisFull");
+    pass();
+}
+
 #ifdef WITH_FILESYSTEM
 //
 // Filesystem test 1