Subdirectory provided by Embedded Artists

Dependencies:   DM_FATFileSystem DM_HttpServer DM_USBHost EthernetInterface USBDevice mbed-rpc mbed-rtos mbed-src

Dependents:   lpc4088_displaymodule_hello_world_Sept_2018

Fork of DMSupport by Embedded Artists

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers RtosLog.cpp Source File

RtosLog.cpp

00001 /*
00002  *  Copyright 2014 Embedded Artists AB
00003  *
00004  *  Licensed under the Apache License, Version 2.0 (the "License");
00005  *  you may not use this file except in compliance with the License.
00006  *  You may obtain a copy of the License at
00007  *
00008  *    http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  *  Unless required by applicable law or agreed to in writing, software
00011  *  distributed under the License is distributed on an "AS IS" BASIS,
00012  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  *  See the License for the specific language governing permissions and
00014  *  limitations under the License.
00015  */
00016 
00017 #include "mbed.h"
00018 #include "RtosLog.h"
00019 #include <cstdarg>
00020 
00021 /******************************************************************************
00022  * Defines and typedefs
00023  *****************************************************************************/
00024 
00025  
00026 /******************************************************************************
00027  * Local variables
00028  *****************************************************************************/
00029 
00030 /******************************************************************************
00031  * Private Functions
00032  *****************************************************************************/
00033 
00034 void RtosLog::logTask(void const* args)
00035 {
00036     RtosLog* instance = (RtosLog*)args;
00037     
00038     while (true) {
00039         osEvent evt = instance->_queue.get();
00040         if (evt.status == osEventMessage) {
00041             message_t *message = (message_t*)evt.value.p;
00042             if (message->ptr != NULL) {
00043                 instance->_serial.printf(message->ptr);
00044                 free(message->ptr);
00045             } else {
00046                 instance->_serial.printf(message->msg);
00047             }
00048             
00049             instance->_mpool.free(message);
00050             
00051             // Increase the number of available messages in the pool
00052             instance->_sem.release();
00053         }
00054     }    
00055 }
00056 
00057 /******************************************************************************
00058  * Public Functions
00059  *****************************************************************************/
00060 
00061 #if defined(DM_BOARD_USE_USBSERIAL_IN_RTOSLOG)
00062     RtosLog::RtosLog() :
00063         _sem(NumMessages), _serial(), _thr(NULL)
00064     {
00065     }
00066 #else
00067 RtosLog::RtosLog() :
00068     _sem(NumMessages), _serial(USBTX, USBRX), _thr(NULL)
00069 {
00070 #if defined(DM_BOARD_USE_FAST_UART)
00071     // This works because both the default serial (used by printf) and the s instance
00072     // (used by s.printf) would use the same underlying UART code so setting the baudrate
00073     // in one affects the other.
00074     _serial.baud(115200);
00075 #endif
00076 }
00077 #endif
00078 
00079 RtosLog::~RtosLog()
00080 {
00081     if (_thr != NULL) {
00082         _thr->terminate();
00083         delete _thr;
00084         _thr = NULL;
00085     }
00086 }
00087 
00088 void RtosLog::init()
00089 {
00090     if (_thr == NULL) {
00091         _thr = new Thread(&RtosLog::logTask, this);
00092     }
00093 }
00094 
00095 int RtosLog::printf(const char* format, ...)
00096 {
00097     // The pool has no "wait for free message" so we use a Sempahore
00098     // to keep track of the number of free messages and, if needed,
00099     // block the caller until a message is free
00100     _sem.wait();
00101     
00102     // Allocate a null terminated message. Will always succeed due to
00103     // the semaphore above
00104     message_t *message = _mpool.calloc();
00105     
00106     // Write the callers formatted message 
00107     std::va_list args;
00108     va_start(args, format);
00109     int ret = vsnprintf(message->msg, MessageLen, format, args);
00110     va_end(args);
00111     
00112     // If the entire message could not fit in the preallocated buffer
00113     // then allocate a new one and try again.
00114     if (ret > MessageLen) {
00115         message->ptr = (char*)malloc(ret + 1);
00116         if (message->ptr != NULL) {
00117             va_start(args, format);
00118             ret = vsnprintf(message->ptr, ret + 1, format, args);
00119             va_end(args);
00120         }
00121     }
00122     
00123     // Send message
00124     _queue.put(message);
00125     
00126     // Note that the Semaphore is not released here, that is done after
00127     // the message has been processed and released into the pool by
00128     // logTask()
00129     //_sem.release();
00130     
00131     return ret;
00132 }
00133 
00134 int RtosLog::isr_printf(const char* format, ...)
00135 {
00136     // The pool has no "wait for free message" so we use a Sempahore
00137     // to keep track of the number of free messages and, if needed,
00138     // block the caller until a message is free
00139     int available = _sem.wait(0);
00140     if (available <= 0) {
00141       // no free messages and it is not good to wait in an ISR so
00142       // we discard the message
00143       return 0;
00144     }
00145     
00146     // Allocate a null terminated message. Will always succeed due to
00147     // the semaphore above
00148     message_t *message = _mpool.calloc();
00149     
00150     // Write the callers formatted message 
00151     std::va_list args;
00152     va_start(args, format);
00153     int ret = vsnprintf(message->msg, MessageLen, format, args);
00154     va_end(args);
00155     
00156     // If the entire message could not fit in the preallocated buffer
00157     // then allocate a new one and try again.
00158     if (ret > MessageLen) {
00159         message->ptr = (char*)malloc(ret + 1);
00160         if (message->ptr != NULL) {
00161             va_start(args, format);
00162             ret = vsnprintf(message->ptr, ret + 1, format, args);
00163             va_end(args);
00164         }
00165     }
00166     
00167     // Send message
00168     _queue.put(message);
00169     
00170     // Note that the Semaphore is not released here, that is done after
00171     // the message has been processed and released into the pool by
00172     // logTask()
00173     //_sem.release();
00174     
00175     return ret;
00176 }