Andrew Reed / Mbed OS CITY1082-i2c_master_wifi_mqtt
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers cy_log.c Source File

cy_log.c

00001 /*
00002  * Copyright 2019-2021, Cypress Semiconductor Corporation (an Infineon company) or
00003  * an affiliate of Cypress Semiconductor Corporation.  All rights reserved.
00004  *
00005  * This software, including source code, documentation and related
00006  * materials ("Software") is owned by Cypress Semiconductor Corporation
00007  * or one of its affiliates ("Cypress") and is protected by and subject to
00008  * worldwide patent protection (United States and foreign),
00009  * United States copyright laws and international treaty provisions.
00010  * Therefore, you may use this Software only as provided in the license
00011  * agreement accompanying the software package from which you
00012  * obtained this Software ("EULA").
00013  * If no EULA applies, Cypress hereby grants you a personal, non-exclusive,
00014  * non-transferable license to copy, modify, and compile the Software
00015  * source code solely for use in connection with Cypress's
00016  * integrated circuit products.  Any reproduction, modification, translation,
00017  * compilation, or representation of this Software except as specified
00018  * above is prohibited without the express written permission of Cypress.
00019  *
00020  * Disclaimer: THIS SOFTWARE IS PROVIDED AS-IS, WITH NO WARRANTY OF ANY KIND,
00021  * EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, NONINFRINGEMENT, IMPLIED
00022  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. Cypress
00023  * reserves the right to make changes to the Software without notice. Cypress
00024  * does not assume any liability arising out of the application or use of the
00025  * Software or any product or circuit described in the Software. Cypress does
00026  * not authorize its products for use in any products where a malfunction or
00027  * failure of the Cypress product may reasonably be expected to result in
00028  * significant property damage, injury or death ("High Risk Product"). By
00029  * including Cypress's product in a High Risk Product, the manufacturer
00030  * of such system or application assumes all risk of such use and in doing
00031  * so agrees to indemnify Cypress against all liability.
00032  */
00033 
00034 /**
00035  * @file Cypress log routines
00036  */
00037 
00038 #include <stdio.h>
00039 #include <stdlib.h>
00040 #include <string.h>
00041 #include <stdarg.h>
00042 
00043 #include "cy_result.h"
00044 #include "cyabs_rtos.h"
00045 #include "cy_log.h "
00046 
00047 #ifdef __cplusplus
00048 extern "C" {
00049 #endif
00050 /******************************************************
00051  *                      Macros
00052  ******************************************************/
00053 
00054 /******************************************************
00055  *                    Constants
00056  ******************************************************/
00057 
00058 /** Size of the logging buffer */
00059 #ifndef CY_LOGBUF_SIZE
00060 #define CY_LOGBUF_SIZE (1024)
00061 #endif
00062 
00063 /******************************************************
00064  *                   Enumerations
00065  ******************************************************/
00066 
00067 /******************************************************
00068  *                 Type Definitions
00069  ******************************************************/
00070 
00071 /******************************************************
00072  *                    Structures
00073  ******************************************************/
00074 
00075 typedef struct
00076 {
00077     bool                init;
00078     cy_mutex_t          mutex;
00079     CY_LOG_LEVEL_T      loglevel[CYLF_MAX];
00080     uint32_t            start_time;
00081     char                logbuf[CY_LOGBUF_SIZE];
00082     uint16_t            seq_num;
00083     log_output          platform_log;
00084     platform_get_time   platform_time;
00085     void                *worker_thread;
00086 } cy_log_data_t;
00087 
00088 /******************************************************
00089  *               Function Declarations
00090  ******************************************************/
00091 
00092 /******************************************************
00093  *               Variables Definitions
00094  ******************************************************/
00095 
00096 static cy_log_data_t cy_log;
00097 
00098 /******************************************************
00099  *               Function Definitions
00100  ******************************************************/
00101 
00102 
00103 /*
00104  * Default implementation to output the log messages. This function is called, if the user doesn't define a output logging function.
00105  */
00106 static int cy_log_output(CY_LOG_FACILITY_T facility, CY_LOG_LEVEL_T level, char *logmsg)
00107 {
00108     (void)facility;
00109     (void)level;
00110     printf("[F%d] : [L%d] : %s", facility, level, logmsg);
00111 
00112     return 1;
00113 }
00114 
00115 /*
00116  * Default implementation to get the time. This function is called, if the user doesn't provide a callback function to get time.
00117  */
00118 static cy_rslt_t cy_log_get_time(uint32_t* time)
00119 {
00120     cy_rtos_get_time(time);
00121     return CY_RSLT_SUCCESS;
00122 }
00123 
00124 
00125 cy_rslt_t cy_log_init(CY_LOG_LEVEL_T level, log_output platform_output, platform_get_time platform_time)
00126 {
00127     cy_rslt_t result = CY_RSLT_SUCCESS;
00128     int i;
00129 
00130     if (cy_log.init)
00131     {
00132         return CY_RSLT_SUCCESS;
00133     }
00134 
00135     memset(&cy_log, 0x00, sizeof(cy_log));
00136     cy_rtos_get_time(&cy_log.start_time);
00137 
00138     /*
00139      * Create our mutex.
00140      */
00141 
00142     result = cy_rtos_init_mutex(&cy_log.mutex);
00143     if (result != CY_RSLT_SUCCESS)
00144     {
00145         return result;
00146     }
00147 
00148     /*
00149      * Set the starting log level.
00150      */
00151 
00152     if ( level >= CY_LOG_MAX )
00153     {
00154         level = (CY_LOG_LEVEL_T)(CY_LOG_MAX - 1);
00155     }
00156 
00157     /* For all facilities */
00158 
00159     for (i = 0; i < CYLF_MAX; i++)
00160     {
00161         cy_log.loglevel[i] = level;
00162     }
00163 
00164     /*
00165      * Set the platform output and time routines.
00166      */
00167 
00168     if (platform_output != NULL)
00169     {
00170         cy_log.platform_log  = platform_output;
00171     }
00172     else
00173     {
00174         cy_log.platform_log = cy_log_output;
00175     }
00176 
00177     if (platform_time != NULL)
00178     {
00179         cy_log.platform_time = platform_time;
00180     }
00181     else
00182     {
00183         cy_log.platform_time = cy_log_get_time;
00184     }
00185     /*
00186      * All done.
00187      */
00188 
00189     cy_log.init = true;
00190 
00191     return result;
00192 }
00193 
00194 
00195 cy_rslt_t cy_log_shutdown(void)
00196 {
00197     if (!cy_log.init)
00198     {
00199         return CY_RSLT_TYPE_ERROR;
00200     }
00201 
00202     cy_log.init = false;
00203 
00204     cy_rtos_deinit_mutex(&cy_log.mutex);
00205 
00206     return CY_RSLT_SUCCESS;
00207 }
00208 
00209 cy_rslt_t cy_log_set_platform_output(log_output platform_output_func)
00210 {
00211     if (!cy_log.init)
00212     {
00213         return CY_RSLT_TYPE_ERROR;
00214     }
00215 
00216     cy_log.platform_log = platform_output_func;
00217 
00218     return CY_RSLT_SUCCESS;
00219 }
00220 
00221 
00222 cy_rslt_t cy_log_set_platform_time(platform_get_time platform_time)
00223 {
00224     if (!cy_log.init)
00225     {
00226         return CY_RSLT_TYPE_ERROR;
00227     }
00228 
00229     cy_log.platform_time = platform_time;
00230 
00231     return CY_RSLT_SUCCESS;
00232 }
00233 
00234 cy_rslt_t cy_log_set_facility_level(CY_LOG_FACILITY_T facility, CY_LOG_LEVEL_T level)
00235 {
00236     if (!cy_log.init)
00237     {
00238         return CY_RSLT_TYPE_ERROR;
00239     }
00240 
00241     if (facility >= CYLF_MAX)
00242     {
00243         facility = CYLF_DEF;
00244     }
00245 
00246     if (level >= CY_LOG_MAX)
00247     {
00248         level = (CY_LOG_LEVEL_T)(CY_LOG_MAX - 1);
00249     }
00250     cy_log.loglevel[facility] = level;
00251 
00252     return CY_RSLT_SUCCESS;
00253 }
00254 
00255 
00256 cy_rslt_t cy_log_set_all_levels(CY_LOG_LEVEL_T level)
00257 {
00258     int i;
00259 
00260     if (!cy_log.init)
00261     {
00262         return CY_RSLT_TYPE_ERROR;
00263     }
00264 
00265     if (level >= CY_LOG_MAX)
00266     {
00267         level = (CY_LOG_LEVEL_T)(CY_LOG_MAX - 1);
00268     }
00269 
00270     for (i = 0; i < CYLF_MAX; i++)
00271     {
00272         cy_log.loglevel[i] = level;
00273     }
00274 
00275     return CY_RSLT_SUCCESS;
00276 }
00277 
00278 
00279 CY_LOG_LEVEL_T cy_log_get_facility_level(CY_LOG_FACILITY_T facility)
00280 {
00281     CY_LOG_LEVEL_T local_loglevel = CY_LOG_OFF;
00282 
00283     if (!cy_log.init)
00284     {
00285         return local_loglevel;
00286     }
00287 
00288     if (facility >= CYLF_MAX)
00289     {
00290         facility = CYLF_DEF;
00291     }
00292 
00293     local_loglevel = cy_log.loglevel[facility];
00294 
00295     return local_loglevel;
00296 }
00297 
00298 
00299 cy_rslt_t cy_log_msg(CY_LOG_FACILITY_T facility, CY_LOG_LEVEL_T level, const char *fmt, ...)
00300 {
00301     cy_rslt_t result = CY_RSLT_SUCCESS;
00302     uint32_t time_from_start;
00303     uint32_t cur_time;
00304     int hrs, mins, secs, ms;
00305     va_list args;
00306     int len;
00307 
00308     if (!cy_log.init)
00309     {
00310         return CY_RSLT_TYPE_ERROR;
00311     }
00312 
00313     /* Is logging enabled for the requested level of the requested facility? */
00314     if (facility >= CYLF_MAX)
00315     {
00316         facility = CYLF_DEF;
00317     }
00318     if ((cy_log.platform_log == NULL) || (cy_log.loglevel[facility] == CY_LOG_OFF) || (level > cy_log.loglevel[facility]))
00319     {
00320         return CY_RSLT_SUCCESS;
00321     }
00322 
00323     /*
00324      * Create the time stamp.
00325      */
00326 
00327     if (cy_log.platform_time != NULL)
00328     {
00329         result = cy_log.platform_time(&time_from_start);
00330         if (result != CY_RSLT_SUCCESS)
00331         {
00332             return result;
00333         }
00334     }
00335     else
00336     {
00337         cy_rtos_get_time(&cur_time);
00338         time_from_start = cur_time - cy_log.start_time;
00339     }
00340 
00341     ms   = time_from_start % 1000;
00342     time_from_start /= 1000;
00343 
00344     secs = time_from_start % 60;
00345     time_from_start /= 60;
00346 
00347     mins = time_from_start % 60;
00348     hrs  = (time_from_start / 60) % 24;
00349 
00350     /*
00351      * We use a common buffer for composing the log messages so we need to protect against
00352      * multiple threads calling us simultaneously.
00353      */
00354 
00355     result = cy_rtos_get_mutex(&cy_log.mutex, CY_RTOS_NEVER_TIMEOUT);
00356     if (result != CY_RSLT_SUCCESS)
00357     {
00358         return CY_RSLT_TYPE_ERROR;
00359     }
00360 
00361     len = snprintf(cy_log.logbuf, CY_LOGBUF_SIZE, "%04d %02d:%02d:%02d.%03d ", cy_log.seq_num, hrs, mins, secs, ms);
00362 
00363     va_start(args, fmt);
00364     len = vsnprintf(&cy_log.logbuf[len], CY_LOGBUF_SIZE - len, fmt, args);
00365     if ((len == -1) || (len >= CY_LOGBUF_SIZE))
00366     {
00367         /* The vsnprintf() output was truncated. */
00368         cy_log.logbuf[CY_LOGBUF_SIZE - 1] = '\0';
00369     }
00370     va_end(args);
00371 
00372     cy_log.platform_log(facility, level, cy_log.logbuf);
00373 
00374     /* increment sequence number for next line*/
00375     cy_log.seq_num++;
00376 
00377     cy_rtos_set_mutex(&cy_log.mutex);
00378 
00379     return result;
00380 }
00381 
00382 cy_rslt_t cy_log_printf(const char *fmt, ...)
00383 {
00384     cy_rslt_t result;
00385     va_list args;
00386 
00387     va_start(args, fmt);
00388     result = cy_log_vprintf(fmt, args);
00389     va_end(args);
00390 
00391     return result;
00392 }
00393 
00394 cy_rslt_t cy_log_vprintf(const char *fmt, va_list varg)
00395 {
00396     cy_rslt_t result = CY_RSLT_SUCCESS;
00397     int len;
00398 
00399     if (!cy_log.init)
00400     {
00401         return CY_RSLT_TYPE_ERROR;
00402     }
00403 
00404     /*
00405      * We use a common buffer for composing the log messages so we need to protect against
00406      * multiple threads calling us simultaneously.
00407      */
00408 
00409     result = cy_rtos_get_mutex(&cy_log.mutex, CY_RTOS_NEVER_TIMEOUT);
00410     if (result != CY_RSLT_SUCCESS)
00411     {
00412         return CY_RSLT_TYPE_ERROR;
00413     }
00414 
00415     len = vsnprintf(cy_log.logbuf, CY_LOGBUF_SIZE, fmt, varg);
00416     if ((len == -1) || (len >= CY_LOGBUF_SIZE))
00417     {
00418         /* The vsnprintf() output was truncated. */
00419         cy_log.logbuf[CY_LOGBUF_SIZE - 1] = '\0';
00420     }
00421 
00422     cy_log.platform_log(CYLF_DEF, CY_LOG_PRINTF, cy_log.logbuf);
00423 
00424     cy_rtos_set_mutex(&cy_log.mutex);
00425 
00426     return result;
00427 }
00428 #ifdef __cplusplus
00429 }
00430 #endif