A board support package for the LPC4088 Display Module.

Dependencies:   DM_HttpServer DM_USBHost

Dependents:   lpc4088_displaymodule_emwin lpc4088_displaymodule_demo_sphere sampleGUI sampleEmptyGUI ... more

Fork of DMSupport by EmbeddedArtists AB

Files at this revision

API Documentation at this revision

Comitter:
embeddedartists
Date:
Tue Dec 02 15:21:18 2014 +0000
Parent:
1:2846fb4d6435
Child:
3:2fa7755f2cef
Commit message:
Added RTOS-safe logger (RtosLog). Switched USBHost library so that it works in an RTOS setting. Modified the FAT file system to work in an RTOS setting.

Changed in this revision

DMBoard.cpp Show annotated file Show diff for this revision Revisions of this file
DMBoard.h Show annotated file Show diff for this revision Revisions of this file
DM_FATFileSystem.lib Show annotated file Show diff for this revision Revisions of this file
DM_USBHost.lib Show annotated file Show diff for this revision Revisions of this file
Display/Display.cpp Show annotated file Show diff for this revision Revisions of this file
FileSystems/ff_rtos_helpers.cpp Show annotated file Show diff for this revision Revisions of this file
RtosLog.cpp Show annotated file Show diff for this revision Revisions of this file
RtosLog.h Show annotated file Show diff for this revision Revisions of this file
dm_board_config.h.txt Show annotated file Show diff for this revision Revisions of this file
mbed-rtos.lib Show annotated file Show diff for this revision Revisions of this file
--- a/DMBoard.cpp	Fri Nov 21 11:46:48 2014 +0000
+++ b/DMBoard.cpp	Tue Dec 02 15:21:18 2014 +0000
@@ -26,6 +26,20 @@
  * Defines and typedefs
  *****************************************************************************/
 
+#if defined(DM_BOARD_DISABLE_STANDARD_PRINTF)
+class DevNull : public Stream {
+ 
+public:
+    DevNull(const char *name=NULL) : Stream(name) {}
+ 
+protected:
+    virtual int _getc()      {return 0;}
+    virtual int _putc(int c) {return c;}
+};
+ 
+static DevNull null("null");
+#endif
+
 /******************************************************************************
  * Local variables
  *****************************************************************************/
@@ -56,10 +70,12 @@
 
 DMBoard::~DMBoard()
 {
+#if defined(DM_BOARD_USE_TOUCH)
   if (_touch != NULL) {
     delete _touch;
     _touch = NULL;
   }
+#endif
 }
 
 DMBoard::BoardError DMBoard::readConfiguration()
@@ -72,16 +88,16 @@
   mem.powerDown();
 #if 0  
   uint8_t* p = buff;
-  printf("\n-------\nBEFORE:\n-------\n");
+  _logger.printf("\n-------\nBEFORE:\n-------\n");
   for (int i = 0; i < 63; i++) {
     for (int j = 0; j < 4; j++) {
-      printf("0x%04x  %02x %02x %02x %02x %02x %02x %02x %02x  %02x %02x %02x %02x %02x %02x %02x %02x\n",
+      _logger.printf("0x%04x  %02x %02x %02x %02x %02x %02x %02x %02x  %02x %02x %02x %02x %02x %02x %02x %02x\n",
         i,
         p[0],p[1],p[2],p[3],p[4],p[5],p[6],p[7],
         p[8],p[9],p[10],p[11],p[12],p[13],p[14],p[15]);
       p += 16;
     }
-    printf("\n");
+    _logger.printf("\n");
   }
   
   // find first non-zero page and write to that
@@ -94,7 +110,7 @@
       }
     }
     if (zeroPage) {
-      printf("Will fill page 0x%04x (%d) with 0x00..0x3f\n", page, page);
+      _logger.printf("Will fill page 0x%04x (%d) with 0x00..0x3f\n", page, page);
       p = buff;
       for (int i = 0; i < mem.pageSize(); i++) {
         *p++ = i;
@@ -103,16 +119,16 @@
       memset(buff, 0, mem.memorySize());
       mem.read(0, 0, buff, mem.memorySize());
       p = buff;
-      printf("\n-------\nAFTER:\n-------\n");
+      _logger.printf("\n-------\nAFTER:\n-------\n");
       for (int i = 0; i < 63; i++) {
         for (int j = 0; j < 4; j++) {
-          printf("0x%04x  %02x %02x %02x %02x %02x %02x %02x %02x  %02x %02x %02x %02x %02x %02x %02x %02x\n",
+          _logger.printf("0x%04x  %02x %02x %02x %02x %02x %02x %02x %02x  %02x %02x %02x %02x %02x %02x %02x %02x\n",
             i,
             p[0],p[1],p[2],p[3],p[4],p[5],p[6],p[7],
             p[8],p[9],p[10],p[11],p[12],p[13],p[14],p[15]);
           p += 16;
         }
-        printf("\n");
+        _logger.printf("\n");
       }
       break;
     }
@@ -199,6 +215,17 @@
       _led3 = 0;
       _led4 = 0;
 
+      // Make sure that the logger is always initialized even if
+      // other initialization tasks fail
+      _logger.init();
+
+#if defined(DM_BOARD_DISABLE_STANDARD_PRINTF)
+      // Kill all ouput of calls to printf() so that there is no
+      // simultaneous calls into the non-thread-safe standard libraries.
+      // User code should use the RtosLogger anyway.
+      freopen("/null", "w", stdout);
+#endif
+
 #if defined(DM_BOARD_USE_QSPI) && !defined(DM_BOARD_USE_QSPI_FS)
       if (SPIFI::instance().init() != SPIFI::Ok) {
         err = SpifiError;
@@ -206,14 +233,6 @@
       }
 #endif
       
-#if defined(DM_BOARD_USE_FAST_UART)
-      // This works because both the default serial (used by printf) and the s instance
-      // (used by s.printf) would use the same underlying UART code so setting the baudrate
-      // in one affects the other.
-      Serial s(USBTX, USBRX);
-      s.baud(115200);
-#endif
-
       readConfiguration();
       
 #if defined(DM_BOARD_USE_DISPLAY)
@@ -240,19 +259,19 @@
   return err;
 }
 
-void DMBoard::setLED(int led, bool on)
+void DMBoard::setLED(Leds led, bool on)
 {
   switch(led) {
-    case 1:
+    case Led1:
       _led1 = (on ? 0 : 1);
       break;
-    case 2:
+    case Led2:
       _led2 = (on ? 0 : 1);
       break;
-    case 3:
+    case Led3:
       _led3 = (on ? 1 : 0);
       break;
-    case 4:
+    case Led4:
       _led4 = (on ? 1 : 0);
       break;
   }
--- a/DMBoard.h	Fri Nov 21 11:46:48 2014 +0000
+++ b/DMBoard.h	Tue Dec 02 15:21:18 2014 +0000
@@ -19,6 +19,7 @@
 
 #include "mbed.h"
 #include "dm_board_config.h"
+#include "RtosLog.h"
 
 #if defined(DM_BOARD_USE_MCI_FS)
   #include "MCIFileSystem.h"
@@ -52,8 +53,11 @@
  */
 class DMBoard {
 public:
-    enum Constants {
-        NumLEDs       =  4,
+    enum Leds {
+        Led1,
+        Led2,
+        Led3,
+        Led4,
     };
   
     enum BoardError {
@@ -79,7 +83,7 @@
      */
     BoardError init();
   
-    void setLED(int led, bool on);
+    void setLED(Leds led, bool on);
     void buzzer(float value);
     bool buttonPressed();
     
@@ -91,6 +95,7 @@
 
     friend class Display;
 #endif
+    RtosLog* logger() { return &_logger; }
 
 private:
 
@@ -113,6 +118,8 @@
     DigitalOut _led3;
     DigitalOut _led4;
 
+    RtosLog _logger;
+
     explicit DMBoard();
     // hide copy constructor
     DMBoard(const DMBoard&);
--- a/DM_FATFileSystem.lib	Fri Nov 21 11:46:48 2014 +0000
+++ b/DM_FATFileSystem.lib	Tue Dec 02 15:21:18 2014 +0000
@@ -1,1 +1,1 @@
-http://developer.mbed.org/users/embeddedartists/code/DM_FATFileSystem/#e9018c2396af
+http://developer.mbed.org/users/embeddedartists/code/DM_FATFileSystem/#4b97221ac12e
--- a/DM_USBHost.lib	Fri Nov 21 11:46:48 2014 +0000
+++ b/DM_USBHost.lib	Tue Dec 02 15:21:18 2014 +0000
@@ -1,1 +1,1 @@
-http://developer.mbed.org/users/embeddedartists/code/DM_USBHost/#a4c606c0439d
+http://developer.mbed.org/users/embeddedartists/code/DM_USBHost/#aa2fd412f1d3
--- a/Display/Display.cpp	Fri Nov 21 11:46:48 2014 +0000
+++ b/Display/Display.cpp	Tue Dec 02 15:21:18 2014 +0000
@@ -18,6 +18,7 @@
 #include "Display.h"
 #include "DMBoard.h"
 
+#if defined(DM_BOARD_USE_DISPLAY)
 
 /******************************************************************************
  * Defines and typedefs
@@ -611,3 +612,5 @@
   LPC_LCD->UPBASE = (uint32_t)buff;
   return (void*)old;
 }
+
+#endif //defined(DM_BOARD_USE_DISPLAY)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/FileSystems/ff_rtos_helpers.cpp	Tue Dec 02 15:21:18 2014 +0000
@@ -0,0 +1,197 @@
+/*
+ *  Copyright 2014 Embedded Artists AB
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+/******************************************************************************
+ * Includes
+ *****************************************************************************/
+
+#include "ff.h"
+#include "mbed.h"
+#include "rtos.h"
+
+/******************************************************************************
+ * Defines and typedefs
+ *****************************************************************************/
+
+/******************************************************************************
+ * External global variables
+ *****************************************************************************/
+
+/******************************************************************************
+ * Local variables
+ *****************************************************************************/
+
+/******************************************************************************
+ * Global Functions
+ *****************************************************************************/
+
+#if _FS_REENTRANT
+/*------------------------------------------------------------------------*/
+/* Create a Synchronization Object                                        */
+/*------------------------------------------------------------------------*/
+/* This function is called in f_mount function to create a new
+/  synchronization object, such as semaphore and mutex. When a zero is
+/  returned, the f_mount function fails with FR_INT_ERR.
+*/
+
+int ff_cre_syncobj (	/* TRUE:Function succeeded, FALSE:Could not create due to any error */
+	BYTE vol,			/* Corresponding logical drive being processed */
+	_SYNC_t *sobj		/* Pointer to return the created sync object */
+)
+{
+	int ret;
+
+//	*sobj = CreateMutex(NULL, FALSE, NULL);	/* Win32 */
+//	ret = (*sobj != INVALID_HANDLE_VALUE);
+
+//	*sobj = SyncObjects[vol];	/* uITRON (give a static sync object) */
+//	ret = 1;					/* The initial value of the semaphore must be 1. */
+
+//	*sobj = OSMutexCreate(0, &err);			/* uC/OS-II */
+//	ret = (err == OS_NO_ERR);
+
+//	*sobj = xSemaphoreCreateMutex();		/* FreeRTOS */
+//	ret = (*sobj != NULL);
+
+	*sobj = new Mutex();					/* MBED RTOS */
+//	*sobj = new Semaphore(1);				/* MBED RTOS */
+	ret = (*sobj != NULL);
+
+	return ret;
+}
+
+
+
+/*------------------------------------------------------------------------*/
+/* Delete a Synchronization Object                                        */
+/*------------------------------------------------------------------------*/
+/* This function is called in f_mount function to delete a synchronization
+/  object that created with ff_cre_syncobj function. When a zero is
+/  returned, the f_mount function fails with FR_INT_ERR.
+*/
+
+int ff_del_syncobj (	/* TRUE:Function succeeded, FALSE:Could not delete due to any error */
+	_SYNC_t sobj		/* Sync object tied to the logical drive to be deleted */
+)
+{
+	BOOL ret;
+
+//	ret = CloseHandle(sobj);	/* Win32 */
+
+//	ret = 1;					/* uITRON (nothing to do) */
+
+//	OSMutexDel(sobj, OS_DEL_ALWAYS, &err);	/* uC/OS-II */
+//	ret = (err == OS_NO_ERR);
+
+//	ret = 1;					/* FreeRTOS (nothing to do) */
+
+	if (sobj != NULL) {			/* MBED RTOS */
+		free(sobj);
+	}
+	ret = 1;
+
+	return ret;
+}
+
+
+
+/*------------------------------------------------------------------------*/
+/* Request Grant to Access the Volume                                     */
+/*------------------------------------------------------------------------*/
+/* This function is called on entering file functions to lock the volume.
+/  When a zero is returned, the file function fails with FR_TIMEOUT.
+*/
+
+int ff_req_grant (	/* TRUE:Got a grant to access the volume, FALSE:Could not get a grant */
+	_SYNC_t sobj	/* Sync object to wait */
+)
+{
+	int ret;
+
+//	ret = (WaitForSingleObject(sobj, _FS_TIMEOUT) == WAIT_OBJECT_0);	/* Win32 */
+
+//	ret = (wai_sem(sobj) == E_OK);	/* uITRON */
+
+//	OSMutexPend(sobj, _FS_TIMEOUT, &err));			/* uC/OS-II */
+//	ret = (err == OS_NO_ERR);
+
+//	ret = (xSemaphoreTake(sobj, _FS_TIMEOUT) == pdTRUE);	/* FreeRTOS */
+
+	ret = ((*((Mutex*)sobj)).lock(_FS_TIMEOUT) == osOK);   /* MBED RTOS */
+//    static volatile osThreadId lastid = Thread::gettid();
+//	ret = ((*((Semaphore*)sobj)).wait(_FS_TIMEOUT) == 1);   /* MBED RTOS */
+
+	return ret;
+}
+
+
+
+/*------------------------------------------------------------------------*/
+/* Release Grant to Access the Volume                                     */
+/*------------------------------------------------------------------------*/
+/* This function is called on leaving file functions to unlock the volume.
+*/
+
+void ff_rel_grant (
+	_SYNC_t sobj	/* Sync object to be signaled */
+)
+{
+//	ReleaseMutex(sobj);		/* Win32 */
+
+//	sig_sem(sobj);			/* uITRON */
+
+//	OSMutexPost(sobj);		/* uC/OS-II */
+
+//	xSemaphoreGive(sobj);	/* FreeRTOS */
+
+	(*((Mutex*)sobj)).unlock();			/* MBED RTOS */
+//	(*((Semaphore*)sobj)).release();	/* MBED RTOS */
+}
+
+#endif
+
+
+
+
+#if _USE_LFN == 3	/* LFN with a working buffer on the heap */
+/*------------------------------------------------------------------------*/
+/* Allocate a memory block                                                */
+/*------------------------------------------------------------------------*/
+/* If a NULL is returned, the file function fails with FR_NOT_ENOUGH_CORE.
+*/
+
+void* ff_memalloc (	/* Returns pointer to the allocated memory block */
+	UINT size		/* Number of bytes to allocate */
+)
+{
+	return malloc(size);
+}
+
+
+/*------------------------------------------------------------------------*/
+/* Free a memory block                                                    */
+/*------------------------------------------------------------------------*/
+
+void ff_memfree(
+	void* mblock	/* Pointer to the memory block to free */
+)
+{
+	free(mblock);
+}
+
+#endif
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RtosLog.cpp	Tue Dec 02 15:21:18 2014 +0000
@@ -0,0 +1,126 @@
+/*
+ *  Copyright 2014 Embedded Artists AB
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+#include "mbed.h"
+#include "RtosLog.h"
+#include <cstdarg>
+
+/******************************************************************************
+ * Defines and typedefs
+ *****************************************************************************/
+
+ 
+/******************************************************************************
+ * Local variables
+ *****************************************************************************/
+
+/******************************************************************************
+ * Private Functions
+ *****************************************************************************/
+
+void RtosLog::logTask(void const* args)
+{
+    RtosLog* instance = (RtosLog*)args;
+    
+    while (true) {
+        osEvent evt = instance->_queue.get();
+        if (evt.status == osEventMessage) {
+            message_t *message = (message_t*)evt.value.p;
+            if (message->ptr != NULL) {
+                instance->_serial.printf(message->ptr);
+                free(message->ptr);
+            } else {
+                instance->_serial.printf(message->msg);
+            }
+            
+            instance->_mpool.free(message);
+            
+            // Increase the number of available messages in the pool
+            instance->_sem.release();
+        }
+    }    
+}
+
+/******************************************************************************
+ * Public Functions
+ *****************************************************************************/
+
+RtosLog::RtosLog() :
+    _sem(NumMessages), _serial(USBTX, USBRX), _thr(NULL)
+{
+#if defined(DM_BOARD_USE_FAST_UART)
+    // This works because both the default serial (used by printf) and the s instance
+    // (used by s.printf) would use the same underlying UART code so setting the baudrate
+    // in one affects the other.
+    _serial.baud(115200);
+#endif
+}
+
+RtosLog::~RtosLog()
+{
+    if (_thr != NULL) {
+        _thr->terminate();
+        delete _thr;
+        _thr = NULL;
+    }
+}
+
+void RtosLog::init()
+{
+    if (_thr == NULL) {
+        _thr = new Thread(&RtosLog::logTask, this);
+    }
+}
+
+int RtosLog::printf(const char* format, ...)
+{
+    // The pool has no "wait for free message" so we use a Sempahore
+    // to keep track of the number of free messages and, if needed,
+    // block the caller until a message is free
+    _sem.wait();
+    
+    // Allocate a null terminated message. Will always succeed due to
+    // the semaphore above
+    message_t *message = _mpool.calloc();
+    
+    // Write the callers formatted message 
+    std::va_list args;
+    va_start(args, format);
+    int ret = vsnprintf(message->msg, MessageLen, format, args);
+    va_end(args);
+    
+    // If the entire message could not fit in the preallocated buffer
+    // then allocate a new one and try again.
+    if (ret > MessageLen) {
+        message->ptr = (char*)malloc(ret + 1);
+        if (message->ptr != NULL) {
+            va_start(args, format);
+            ret = vsnprintf(message->ptr, ret + 1, format, args);
+            va_end(args);
+        }
+    }
+    
+    // Send message
+    _queue.put(message);
+    
+    // Note that the Semaphore is not released here, that is done after
+    // the message has been processed and released into the pool by
+    // logTask()
+    //_sem.release();
+    
+    return ret;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RtosLog.h	Tue Dec 02 15:21:18 2014 +0000
@@ -0,0 +1,64 @@
+/*
+ *  Copyright 2014 Embedded Artists AB
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+#ifndef RTOSLOG_H
+#define RTOSLOG_H
+
+#include "mbed.h"
+#include "rtos.h"
+#include "dm_board_config.h"
+
+/**
+ * All threads can independantly call the printf function in the RtosLog class
+ * without risc of getting the output tangled up.
+ *
+ * The RtosLog class uses a Thread to process the messages one at a time.
+ */
+class RtosLog {
+public:
+    enum Constants {
+        MessageLen  = 80,
+        NumMessages =  16,
+    };
+  
+    RtosLog();
+    ~RtosLog();
+    
+    /** Starts the logger thread
+     */
+    void init();
+    
+    int printf(const char* format, ...);
+  
+private:
+    
+    typedef struct {
+        char*  ptr;                 /* Non-NULL if memory is allocated */
+        char   msg[MessageLen+1];   /* A counter value                 */
+    } message_t;
+ 
+    MemoryPool<message_t, NumMessages> _mpool;
+    Queue<message_t, NumMessages> _queue;
+    Semaphore _sem;
+    Serial _serial;
+    Thread* _thr;
+    
+    static void logTask(void const* args);
+};
+
+#endif
+
+
--- a/dm_board_config.h.txt	Fri Nov 21 11:46:48 2014 +0000
+++ b/dm_board_config.h.txt	Tue Dec 02 15:21:18 2014 +0000
@@ -31,6 +31,7 @@
 // #define DM_BOARD_USE_XBEE
 #define DM_BOARD_USE_FAST_UART
 // #define DM_BOARD_USE_INT_EEPROM_WRITE
+// #define DM_BOARD_DISABLE_STANDARD_PRINTF
 
 // #define DM_BOARD_USE_4_3_DISPLAY_TMP /* temporary while debugging */
 
--- a/mbed-rtos.lib	Fri Nov 21 11:46:48 2014 +0000
+++ b/mbed-rtos.lib	Tue Dec 02 15:21:18 2014 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/users/mbed_official/code/mbed-rtos/#02f5cf381388
+http://mbed.org/users/mbed_official/code/mbed-rtos/#c35dab33c427