TI Utilities API
Log.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2019-2023 Texas Instruments Incorporated - https://www.ti.com
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * * Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *
12  * * Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in the
14  * documentation and/or other materials provided with the distribution.
15  *
16  * * Neither the name of Texas Instruments Incorporated nor the names of
17  * its contributors may be used to endorse or promote products derived
18  * from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
432 #ifndef ti_log_Log__include
433 #define ti_log_Log__include
434 
437 
438 /*
439  * ======== Log.h ========
440  * @brief Contains Log library APIs
441  */
442 #include <stdint.h>
443 #include <stddef.h>
444 
445 #if defined (__cplusplus)
446 extern "C" {
447 #endif
448 
449 /*
450  * ======== ti_log_Log_ENABLE ========
451  * Enable instrumentation using link-time optimization implementation
452  *
453  * Define this symbol to add instrumentation at compile time.
454  * It must be defined before including this header file.
455  */
456 #if ti_log_Log_ENABLE
457 /*
458  * =============================
459  * ======== Log Enabled ========
460  * =============================
461  */
462 
463 #define Log_TI_LOG_VERSION 0.1.0
464 
489 #define Log_MODULE_DEFINE(name, init) const Log_Module LogMod_ ## name = init
490 
501 #define Log_MODULE_USE(name) extern const Log_Module LogMod_ ## name
502 
509 #define LOG_MODULE_SYM(name) LogMod_ ## name
510 
513 /* This macro protects against sideffects of the C preprocessor expansion
514  * of log statements. Each log API should be guarded by it.
515  * An article explaining this behavior can be found here:
516  * https://gcc.gnu.org/onlinedocs/cpp/Swallowing-the-Semicolon.html
517  */
518 #define _Log_GUARD_MACRO(x) do{ x }while(0)
519 
520 /*
521  *
522  * ======== Log Private Macros ========
523  *
524  * The following macros are intended to be private to the log module and
525  * are not intended for use by the user. Private macros will start with _Log.
526  *
527  * In the case of multi level macros (macros that invoke other macros), a
528  * letter is appended at the end of the definition. With each level of nesting,
529  * the appended letter is incremented.
530  *
531  * For example: _Log_test --> _Log_test_A --> _Log_test_B
532  */
533 /* Extracts the first/remaining argument from __VA_ARGS__ */
534 #define _Log_CAR_ARG(N, ...) N
535 #define _Log_CDR_ARG(N, ...) __VA_ARGS__
536 
537 
538 /*
539  * ======== Meta string tokenization macros ========
540  */
541 /* Helper macro to concatenate two symbols */
542 #define _Log_CONCAT2_A(x,y) x ## _ ## y
543 #define _Log_CONCAT2(x,y) _Log_CONCAT2_A(x,y)
544 #define _Log_CONCAT3(x,y,z) _Log_CONCAT2(x,_Log_CONCAT2(y,z))
545 
546 /* Helper macro to concatenate two symbols */
547 #define _Log__TOKEN2STRING_A(x) #x
548 #define _Log_TOKEN2STRING(x) _Log__TOKEN2STRING_A(x)
549 
550 /* Helper macro to convert a log_ptr address to a pseudo-index, that needs to be divided by 4.
551  * If needed, the division is handled by the sink
552  */
553 #define _Log_LOG_PTR_TO_INDEX(ptr) (((uint32_t)(&ptr) - 0x08) & 0x7FFFC)
554 
555 /* Macro to place meta string in a memory section separated by record separator */
556 #define _Log_APPEND_META_TO_FORMAT(opcode, \
557  file, \
558  line, \
559  level, \
560  module, \
561  format, \
562  nargs) \
563  _Log_TOKEN2STRING(opcode) "\x1e" \
564  _Log_TOKEN2STRING(file) "\x1e" \
565  _Log_TOKEN2STRING(line) "\x1e" \
566  _Log_TOKEN2STRING(level) "\x1e" \
567  _Log_TOKEN2STRING(module) "\x1e" \
568  _Log_TOKEN2STRING(format) "\x1e" \
569  _Log_TOKEN2STRING(nargs)
570 
571 /* Place a string in trace format section named ".log_data" locally
572  * This section must exist in the linker file
573  */
574 #if defined(__IAR_SYSTEMS_ICC__)
575 #define _Log_PLACE_FORMAT_IN_SECTOR(name, opcode, level, module, format, nargs)\
576  __root static const char name[] @ ".log_data" = \
577  _Log_APPEND_META_TO_FORMAT(opcode, \
578  __FILE__, \
579  __LINE__, \
580  level, \
581  module, \
582  format, \
583  nargs); \
584  __root static const char * const _Log_CONCAT2(Ptr, name) @ _Log_TOKEN2STRING(_Log_CONCAT2(.log_ptr, module)) = name;
585 #elif defined(__TI_COMPILER_VERSION__) || (defined(__clang__) && defined(__ti_version__)) || defined(__GNUC__)
586 #define _Log_PLACE_FORMAT_IN_SECTOR(name, opcode, level, module, format, nargs)\
587  static const char name[] \
588  __attribute__((used,section(".log_data"))) = \
589  _Log_APPEND_META_TO_FORMAT(opcode, \
590  __FILE__, \
591  __LINE__, \
592  level, \
593  module, \
594  format, \
595  nargs); \
596  static const char * const _Log_CONCAT2(Ptr, name) \
597  __attribute__((used,section(_Log_TOKEN2STRING(_Log_CONCAT3(.log_ptr, __LINE__, module))))) = name;
598 #else
599 #error Incompatible compiler: Logging is currently supported by the following \
600 compilers: TI ARM Compiler, TI CLANG Compiler, GCC, IAR. Please migrate to a \
601 a supported compiler.
602 #endif
603 
604 /*
605  * ======== Variadic macro workaround ========
606  */
607 /* Helper macro to count the number of arguments in __VA_ARGS_ */
608 #define _Log_NUMARGS(...) _Log_NUMARGS_A(__VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1, 0)
609 #define _Log_NUMARGS_A(...) _Log_NUMARGS_B(__VA_ARGS__)
610 #define _Log_NUMARGS_B(_first, _8, _7, _6, _5, _4, _3, _2, _1, N, ...) N
611 
612 /*
613  * Helper to select arg/noarg variant macro since empty va_arg fails
614  * when arguments are expected. Eg
615  * Log_VARIANT(test, A, 7, "Hello") -> test__noarg(A, 7, "Hello")
616  * Log_VARIANT(test, A, 7, "Hello %d", 42) -> test__arg1(A, 7, "Hello %d", 42)
617  */
618 #define _Log_VARIANT(x, module, level, ...) \
619  _Log_CONCAT2(x, _Log_NUMARGS_B(__VA_ARGS__, _arg8, _arg7, _arg6, _arg5, _arg4, _arg3, _arg2, _arg1, _noarg)) ( module, level, __VA_ARGS__ )
620 
621 #define _Log_buf_B(module , level, format, data, size) \
622  Log_MODULE_USE(module); \
623  if ((Log_ENABLED & LogMod_ ## module.levels) && \
624  ((level) & LogMod_ ## module.levels)) { \
625  _Log_PLACE_FORMAT_IN_SECTOR(_Log_CONCAT2(LogSymbol, __LINE__), \
626  LOG_OPCODE_BUFFER, \
627  level, \
628  LogMod_ ## module, \
629  format, \
630  0); \
631  LogMod_ ## module.buf(&LogMod_ ## module, \
632  (uint32_t)&_Log_CONCAT2(LogSymbol, __LINE__), \
633  _Log_LOG_PTR_TO_INDEX(_Log_CONCAT3(Ptr, LogSymbol, __LINE__)), \
634  data, \
635  size); \
636  }
637 
638 /*
639  * Redirects to cast all printf arguments to uintptr_t to avoid surprises if
640  * passing wider values and the compiler silently allows it.
641  */
642 #define _Log_printf__arg1(module, level, fmt, a0) \
643  _Log_printf__arg(module, level, fmt, (uintptr_t)a0)
644 #define _Log_printf__arg2(module, level, fmt, a0, a1) \
645  _Log_printf__arg(module, level, fmt, (uintptr_t)a0, \
646  (uintptr_t)a1)
647 #define _Log_printf__arg3(module, level, fmt, a0, a1, a2) \
648  _Log_printf__arg(module, level, fmt, (uintptr_t)a0, \
649  (uintptr_t)a1, \
650  (uintptr_t)a2)
651 #define _Log_printf__arg4(module, level, fmt, a0, a1, a2, a3) \
652  _Log_printf__arg(module, level, fmt, (uintptr_t)a0, \
653  (uintptr_t)a1, \
654  (uintptr_t)a2, \
655  (uintptr_t)a3)
656 #define _Log_printf__arg5(module, level, fmt, a0, a1, a2, a3, a4) \
657  _Log_printf__arg(module, level, fmt, (uintptr_t)a0, \
658  (uintptr_t)a1, \
659  (uintptr_t)a2, \
660  (uintptr_t)a3, \
661  (uintptr_t)a4)
662 #define _Log_printf__arg6(module, level, fmt, a0, a1, a2, a3, a4, a5) \
663  _Log_printf__arg(module, level, fmt, (uintptr_t)a0, \
664  (uintptr_t)a1, \
665  (uintptr_t)a2, \
666  (uintptr_t)a3, \
667  (uintptr_t)a4, \
668  (uintptr_t)a5)
669 #define _Log_printf__arg7(module, level, fmt, a0, a1, a2, a3, a4, a5, a6) \
670  _Log_printf__arg(module, level, fmt, (uintptr_t)a0, \
671  (uintptr_t)a1, \
672  (uintptr_t)a2, \
673  (uintptr_t)a3, \
674  (uintptr_t)a4, \
675  (uintptr_t)a5, \
676  (uintptr_t)a6)
677 #define _Log_printf__arg8(module, level, fmt, a0, a1, a2, a3, a4, a5, a6, a7) \
678  _Log_printf__arg(module, level, fmt, (uintptr_t)a0, \
679  (uintptr_t)a1, \
680  (uintptr_t)a2, \
681  (uintptr_t)a3, \
682  (uintptr_t)a4, \
683  (uintptr_t)a5, \
684  (uintptr_t)a6, \
685  (uintptr_t)a7)
686 
687 #define _Log_printf__arg(module, level, ...) \
688  module.printf(&module, \
689  (uint32_t)&_Log_CONCAT2(LogSymbol, __LINE__), \
690  _Log_LOG_PTR_TO_INDEX(_Log_CONCAT3(Ptr, LogSymbol, __LINE__)), \
691  _Log_NUMARGS(__VA_ARGS__), \
692  _Log_CDR_ARG(__VA_ARGS__))
693 
694 #define _Log_printf__noarg(module, level, ...) \
695  module.printf(&module, \
696  (uint32_t)&_Log_CONCAT2(LogSymbol, __LINE__), \
697  _Log_LOG_PTR_TO_INDEX(_Log_CONCAT3(Ptr, LogSymbol, __LINE__)), \
698  _Log_NUMARGS(__VA_ARGS__))
699 
700 #define _Log_printf_B(opcode, module, level, ...) \
701  Log_MODULE_USE(module); \
702  if ((Log_ENABLED & LogMod_ ## module.levels) && \
703  ((level) & LogMod_ ## module.levels)) { \
704  _Log_PLACE_FORMAT_IN_SECTOR(_Log_CONCAT2(LogSymbol, __LINE__), \
705  opcode, \
706  level, \
707  LogMod_ ## module, \
708  _Log_CAR_ARG(__VA_ARGS__), \
709  _Log_NUMARGS(__VA_ARGS__)) \
710  _Log_VARIANT(_Log_printf, LogMod_ ## module, level, __VA_ARGS__); \
711  }
712 
726 #if defined(__IAR_SYSTEMS_ICC__)
727 #define Log_EVENT_DEFINE(name, fmt) \
728  __root const char LogSymbol_ ## name[] @ ".log_data" = \
729  _Log_APPEND_META_TO_FORMAT(LOG_EVENT_CONSTRUCT, \
730  __FILE__, \
731  __LINE__, \
732  name, \
733  global, \
734  fmt, \
735  0)
736 
737 #elif defined(__TI_COMPILER_VERSION__) || (defined(__clang__) && defined(__ti_version__)) || defined(__GNUC__)
738 #define Log_EVENT_DEFINE(name, fmt) \
739  const char LogSymbol_ ## name[] \
740  __attribute__((used,section(".log_data"))) = \
741  _Log_APPEND_META_TO_FORMAT(LOG_EVENT_CONSTRUCT, \
742  __FILE__, \
743  __LINE__, \
744  name, \
745  global, \
746  fmt, \
747  0)
748 #else
749 #error Incompatible compiler: Logging is currently supported by the following \
750 compilers: TI ARM Compiler, TI CLANG Compiler, GCC, IAR. Please migrate to a \
751 a supported compiler.
752 #endif
753 
762 #define Log_EVENT_USE(name) extern const char[] LogSymbol_ ## name;
763 
764 
779 #define Log_buf(module, level, format, data, size) \
780  _Log_GUARD_MACRO(_Log_buf_B(module , level, format, data, size))
781 
802 #define Log_printf(module, level, ...) \
803  _Log_GUARD_MACRO(_Log_printf_B(LOG_OPCODE_FORMATED_TEXT, module, level, __VA_ARGS__))
804 
805 #define Log_event(module, level, ...) \
806  _Log_GUARD_MACRO(_Log_printf_B(LOG_OPCODE_EVENT, module, level, __VA_ARGS__))
807 
808 /* Macro for defining the version of the Log API */
809 
810 
811 
812 #if defined(__IAR_SYSTEMS_ICC__)
813 #define _Log_DEFINE_LOG_VERSION(module, version) \
814  __root static const char _Log_CONCAT2(Log_ti_log_version, __COUNTER__)[] @ ".log_data" = \
815  _Log_APPEND_META_TO_FORMAT(LOG_OPCODE_VERSION, \
816  module, \
817  version, \
818  0, \
819  0, \
820  0, \
821  0)
822 #elif defined(__TI_COMPILER_VERSION__) || (defined(__clang__) && defined(__ti_version__)) || defined(__GNUC__)
823 #define _Log_DEFINE_LOG_VERSION(module, version) \
824  static const char _Log_CONCAT2(Log_ti_log_version, __COUNTER__)[] \
825  __attribute__((used,section(".log_data"))) = \
826  _Log_APPEND_META_TO_FORMAT(LOG_OPCODE_VERSION, \
827  module, \
828  version, \
829  0, \
830  0, \
831  0, \
832  0)
833 #else
834 #error Incompatible compiler: Logging is currently supported by the following \
835 compilers: TI ARM Compiler, TI CLANG Compiler, GCC, IAR. Please migrate to a \
836 a supported compiler.
837 #endif
838 
839 /* Generate a symbol in the elf file that defines the version of the Log API */
840 _Log_DEFINE_LOG_VERSION(Log, Log_TI_LOG_VERSION);
841 
842 #else /* ti_log_Log_ENABLE */
843 
844 /*
845  * =================================================
846  * ======== Log Disabled (default behavior) ========
847  * =================================================
848  */
849 
850 #define Log_MODULE_DEFINE(...)
851 #define Log_MODULE_USE(...)
852 #define Log_EVENT_DEFINE(name, fmt)
853 #define Log_EVENT_USE(name, fmt)
854 #define Log_printf(module, level, ...)
855 #define Log_event(module, level, ...)
856 #define Log_buf(module, level, ...)
857 #define _Log_DEFINE_LOG_VERSION(module, version)
858 
859 #endif /* ti_log_Log_ENABLE */
860 
861 /*
862  * ======== Log_Level ========
863  */
864 typedef enum Log_Level {
865  Log_DEBUG = 1,
867  Log_INFO = 16,
868  Log_WARNING = 64,
869  Log_ERROR = 256,
870  Log_ALL = 1 + 4 + 16 + 64 + 256,
871  Log_ENABLED = 512
872 } Log_Level;
873 
874 typedef const struct Log_Module Log_Module;
875 
876 typedef void (*Log_printf_fxn)(const Log_Module *handle,
877  uint32_t header,
878  uint32_t index,
879  uint32_t numArgs,
880  ...);
881 
882 typedef void (*Log_buf_fxn)(const Log_Module *handle,
883  uint32_t header,
884  uint32_t index,
885  uint8_t *data,
886  size_t size);
887 
888 struct Log_Module {
889  void *sinkConfig;
892  uint32_t levels;
893 };
894 
895 
897 #if defined (__cplusplus)
898 }
899 #endif
900 
901 #endif // ti_log_Log__include
Definition: Log.h:865
Log_Level
Definition: Log.h:864
const Log_buf_fxn buf
Definition: Log.h:891
Definition: Log.h:871
const Log_printf_fxn printf
Definition: Log.h:890
Definition: Log.h:866
Definition: Log.h:888
#define _Log_DEFINE_LOG_VERSION(module, version)
Definition: Log.h:857
Definition: Log.h:870
void(* Log_buf_fxn)(const Log_Module *handle, uint32_t header, uint32_t index, uint8_t *data, size_t size)
Definition: Log.h:882
Definition: Log.h:869
uint32_t levels
Definition: Log.h:892
Definition: Log.h:867
void(* Log_printf_fxn)(const Log_Module *handle, uint32_t header, uint32_t index, uint32_t numArgs,...)
Definition: Log.h:876
Definition: Log.h:868
void * sinkConfig
Definition: Log.h:889
© Copyright 1995-2023, Texas Instruments Incorporated. All rights reserved.
Trademarks | Privacy policy | Terms of use | Terms of sale