M Target_RT1051.cmake => Target_RT1051.cmake +2 -0
@@ 60,6 60,8 @@ add_compile_options(
set(TARGET_SOURCES
${CMAKE_CURRENT_LIST_DIR}/module-os/board/rt1051/_exit.cpp
+ ${CMAKE_CURRENT_LIST_DIR}/module-os/board/rt1051/__atexit.c
+ ${CMAKE_CURRENT_LIST_DIR}/module-os/board/rt1051/__call_atexit.c
CACHE INTERNAL ""
)
M board/rt1051/ldscripts/sections.ld => board/rt1051/ldscripts/sections.ld +11 -1
@@ 24,6 24,9 @@ EXTERN(image_vector_table);
EXTERN(boot_data);
EXTERN(hyperflash_config);
+/* Ensure that newlib runs the finalizers. */
+__libc_fini = _fini;
+
SECTIONS
{
/* Image Vector Table and Boot Data for booting from external flash */
@@ 123,9 126,16 @@ SECTIONS
KEEP (*(.init_array))
__init_array_end = .;
- KEEP(*(.fini));
+ . = ALIGN(4);
+ KEEP(*(.fini))
. = ALIGN(4);
+ __fini_array_start = .;
+ KEEP (*(.fini_array))
+ KEEP (*(SORT(.fini_array.*)))
+ __fini_array_end = .;
+
+ . = ALIGN(4);
KEEP (*crtbegin.o(.ctors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
M module-bsp/board/rt1051/common/board.cpp => module-bsp/board/rt1051/common/board.cpp +27 -0
@@ 188,9 188,36 @@ namespace bsp
rebootProgress = rebootState::reboot;
}
+ struct PlatformExitObject
+ {
+ void (*func)();
+ };
+ static unsigned short iObject = 0;
+ constexpr auto MAX_PLATFORM_EXIT_OBJECTS = 16u;
+
+ static PlatformExitObject objects[MAX_PLATFORM_EXIT_OBJECTS];
+
+ int RegisterPlatformExitFunction(void (*func)())
+ {
+ if (iObject >= sizeof(objects))
+ return -1;
+ objects[iObject].func = func;
+ ++iObject;
+ return 0;
+ }
+
+ void CallPlatformExitFunctions()
+ {
+ while (iObject > 0) {
+ objects[--iObject].func();
+ }
+ }
+
extern "C" {
void _platform_exit(void)
{
+ CallPlatformExitFunctions();
+
static constexpr auto POWER_SWITCH_PIN = 7;
static const auto POWER_SWITCH_PORT = GPIO2;
switch(rebootProgress)
M module-bsp/board/rt1051/common/startup_mimxrt1052.cpp => module-bsp/board/rt1051/common/startup_mimxrt1052.cpp +4 -1
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
//*****************************************************************************
@@ 58,6 58,7 @@
extern "C"
{
extern void __libc_init_array(void);
+ extern void __call_exitprocs(int code, void *d);
}
#endif
#endif
@@ 750,6 751,8 @@ __attribute__((section(".after_vectors.reset"))) void ResetISR(void)
#else
main();
#endif
+ // call global destructors and functions registered using atexit
+ __call_exitprocs(0, 0);
_platform_exit();
//
// main() shouldn't return, but if it does, we'll just enter an infinite loop
M module-bsp/bsp/bsp.hpp => module-bsp/bsp/bsp.hpp +3 -0
@@ 11,6 11,9 @@ namespace bsp
// Board system reset
void BoardReboot();
+
+ // Register platform exit functions
+ int RegisterPlatformExitFunction(void (*func)());
}
A module-os/board/rt1051/__atexit.c => module-os/board/rt1051/__atexit.c +159 -0
@@ 0,0 1,159 @@
+/*
+ * Common routine to implement atexit-like functionality.
+ *
+ * This is also the key function to be configured as lite exit, a size-reduced
+ * implementation of exit that doesn't invoke clean-up functions such as _fini
+ * or global destructors.
+ *
+ * Default (without lite exit) call graph is like:
+ * _start -> atexit -> __register_exitproc
+ * _start -> __libc_init_array -> __cxa_atexit -> __register_exitproc
+ * on_exit -> __register_exitproc
+ * _start -> exit -> __call_exitprocs
+ *
+ * Here an -> means arrow tail invokes arrow head. All invocations here
+ * are non-weak reference in current newlib/libgloss.
+ *
+ * Lite exit makes some of above calls as weak reference, so that size expansive
+ * functions __register_exitproc and __call_exitprocs may not be linked. These
+ * calls are:
+ * _start w-> atexit
+ * __cxa_atexit w-> __register_exitproc
+ * exit w-> __call_exitprocs
+ *
+ * Lite exit also makes sure that __call_exitprocs will be referenced as non-weak
+ * whenever __register_exitproc is referenced as non-weak.
+ *
+ * Thus with lite exit libs, a program not explicitly calling atexit or on_exit
+ * will escape from the burden of cleaning up code. A program with atexit or on_exit
+ * will work consistently to normal libs.
+ *
+ * Lite exit is enabled with --enable-lite-exit, and is controlled with macro
+ * _LITE_EXIT.
+ */
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <reent.h>
+#include <sys/lock.h>
+#include "atexit.h"
+
+/* Make this a weak reference to avoid pulling in malloc. */
+#ifndef MALLOC_PROVIDED
+void * malloc(size_t) _ATTRIBUTE((__weak__));
+#endif
+
+#ifdef _LITE_EXIT
+/* As __call_exitprocs is weak reference in lite exit, make a
+ non-weak reference to it here. */
+const void * __atexit_dummy = &__call_exitprocs;
+#endif
+
+#ifndef __SINGLE_THREAD__
+extern _LOCK_RECURSIVE_T __atexit_recursive_mutex;
+#endif
+
+#ifdef _REENT_GLOBAL_ATEXIT
+static struct _atexit _global_atexit0 = _ATEXIT_INIT;
+# define _GLOBAL_ATEXIT0 (&_global_atexit0)
+#else
+# define _GLOBAL_ATEXIT0 (&_GLOBAL_REENT->_atexit0)
+#endif
+
+/*
+ * Register a function to be performed at exit or on shared library unload.
+ */
+
+int
+__register_exitproc (int type,
+ void (*fn) (void),
+ void *arg,
+ void *d)
+{
+ struct _on_exit_args * args;
+ register struct _atexit *p;
+
+#ifndef __SINGLE_THREAD__
+ __lock_acquire_recursive(__atexit_recursive_mutex);
+#endif
+
+ p = _GLOBAL_ATEXIT;
+ if (p == NULL)
+ {
+ _GLOBAL_ATEXIT = p = _GLOBAL_ATEXIT0;
+#ifdef _REENT_SMALL
+ extern struct _on_exit_args * const __on_exit_args _ATTRIBUTE ((weak));
+ if (&__on_exit_args != NULL)
+ p->_on_exit_args_ptr = __on_exit_args;
+#endif /* def _REENT_SMALL */
+ }
+ if (p->_ind >= _ATEXIT_SIZE)
+ {
+#if !defined (_ATEXIT_DYNAMIC_ALLOC) || !defined (MALLOC_PROVIDED)
+#ifndef __SINGLE_THREAD__
+ __lock_release_recursive(__atexit_recursive_mutex);
+#endif
+ return -1;
+#else
+ p = (struct _atexit *) malloc (sizeof *p);
+ if (p == NULL)
+ {
+#ifndef __SINGLE_THREAD__
+ __lock_release_recursive(__atexit_recursive_mutex);
+#endif
+ return -1;
+ }
+ p->_ind = 0;
+ p->_next = _GLOBAL_ATEXIT;
+ _GLOBAL_ATEXIT = p;
+#ifndef _REENT_SMALL
+ p->_on_exit_args._fntypes = 0;
+ p->_on_exit_args._is_cxa = 0;
+#else
+ p->_on_exit_args_ptr = NULL;
+#endif
+#endif
+ }
+
+ if (type != __et_atexit)
+ {
+#ifdef _REENT_SMALL
+ args = p->_on_exit_args_ptr;
+ if (args == NULL)
+ {
+#ifndef _ATEXIT_DYNAMIC_ALLOC
+#ifndef __SINGLE_THREAD__
+ __lock_release_recursive(__atexit_recursive_mutex);
+#endif
+ return -1;
+#else
+ if (malloc)
+ args = malloc (sizeof * p->_on_exit_args_ptr);
+
+ if (args == NULL)
+ {
+#ifndef __SINGLE_THREAD__
+ __lock_release(__atexit_recursive_mutex);
+#endif
+ return -1;
+ }
+ args->_fntypes = 0;
+ args->_is_cxa = 0;
+ p->_on_exit_args_ptr = args;
+#endif
+ }
+#else
+ args = &p->_on_exit_args;
+#endif
+ args->_fnargs[p->_ind] = arg;
+ args->_fntypes |= (1 << p->_ind);
+ args->_dso_handle[p->_ind] = d;
+ if (type == __et_cxa)
+ args->_is_cxa |= (1 << p->_ind);
+ }
+ p->_fns[p->_ind++] = fn;
+#ifndef __SINGLE_THREAD__
+ __lock_release_recursive(__atexit_recursive_mutex);
+#endif
+ return 0;
+}
A module-os/board/rt1051/__call_atexit.c => module-os/board/rt1051/__call_atexit.c +162 -0
@@ 0,0 1,162 @@
+/*
+ * COmmon routine to call call registered atexit-like routines.
+ */
+
+
+#include <stdlib.h>
+#include <reent.h>
+#include <sys/lock.h>
+#include "atexit.h"
+
+/* Make this a weak reference to avoid pulling in free. */
+#ifndef MALLOC_PROVIDED
+void free(void *) _ATTRIBUTE((__weak__));
+#endif
+
+#ifndef __SINGLE_THREAD__
+__LOCK_INIT_RECURSIVE(, __atexit_recursive_mutex);
+#endif
+
+#ifdef _REENT_GLOBAL_ATEXIT
+struct _atexit *_global_atexit = _NULL;
+#endif
+
+//#undef _WANT_REGISTER_FINI
+#ifdef _WANT_REGISTER_FINI
+
+/* If "__libc_fini" is defined, finalizers (either
+ "__libc_fini_array", or "_fini", as appropriate) will be run after
+ all user-specified atexit handlers. For example, you can define
+ "__libc_fini" to "_fini" in your linker script if you want the C
+ library, rather than startup code, to register finalizers. If you
+ do that, then your startup code need not contain references to
+ "atexit" or "exit". As a result, only applications that reference
+ "exit" explicitly will pull in finalization code.
+
+ The choice of whether to register finalizers from libc or from
+ startup code is deferred to link-time, rather than being a
+ configure-time option, so that the same C library binary can be
+ used with multiple BSPs, some of which register finalizers from
+ startup code, while others defer to the C library. */
+extern char __libc_fini __attribute__((weak));
+
+/* Register the application finalization function with atexit. These
+ finalizers should run last. Therefore, we want to call atexit as
+ soon as possible. */
+static void
+register_fini(void) __attribute__((constructor (0)));
+
+static void
+register_fini(void)
+{
+ if (&__libc_fini) {
+#ifdef HAVE_INITFINI_ARRAY
+ extern void __libc_fini_array (void);
+ atexit (__libc_fini_array);
+#else
+ extern void _fini (void);
+ atexit (_fini);
+#endif
+ }
+}
+
+#endif /* _WANT_REGISTER_FINI */
+
+/*
+ * Call registered exit handlers. If D is null then all handlers are called,
+ * otherwise only the handlers from that DSO are called.
+ */
+
+void
+__call_exitprocs (int code, void *d)
+{
+ register struct _atexit *p;
+ struct _atexit **lastp;
+ register struct _on_exit_args * args;
+ register int n;
+ int i;
+ void (*fn) (void);
+
+
+#ifndef __SINGLE_THREAD__
+ __lock_acquire_recursive(__atexit_recursive_mutex);
+#endif
+
+ restart:
+
+ p = _GLOBAL_ATEXIT;
+ lastp = &_GLOBAL_ATEXIT;
+ while (p)
+ {
+#ifdef _REENT_SMALL
+ args = p->_on_exit_args_ptr;
+#else
+ args = &p->_on_exit_args;
+#endif
+ for (n = p->_ind - 1; n >= 0; n--)
+ {
+ int ind;
+
+ i = 1 << n;
+
+ /* Skip functions not from this dso. */
+ if (d && (!args || args->_dso_handle[n] != d))
+ continue;
+
+ /* Remove the function now to protect against the
+ function calling exit recursively. */
+ fn = p->_fns[n];
+ if (n == p->_ind - 1)
+ p->_ind--;
+ else
+ p->_fns[n] = NULL;
+
+ /* Skip functions that have already been called. */
+ if (!fn)
+ continue;
+
+ ind = p->_ind;
+
+ /* Call the function. */
+ if (!args || (args->_fntypes & i) == 0)
+ fn ();
+ else if ((args->_is_cxa & i) == 0)
+ (*((void (*)(int, void *)) fn))(code, args->_fnargs[n]);
+ else
+ (*((void (*)(void *)) fn))(args->_fnargs[n]);
+
+ /* The function we called call atexit and registered another
+ function (or functions). Call these new functions before
+ continuing with the already registered functions. */
+ if (ind != p->_ind || *lastp != p)
+ goto restart;
+ }
+
+#if !defined (_ATEXIT_DYNAMIC_ALLOC) || !defined (MALLOC_PROVIDED)
+ break;
+#else
+ /* Move to the next block. Free empty blocks except the last one,
+ which is part of _GLOBAL_REENT. */
+ if (p->_ind == 0 && p->_next)
+ {
+ /* Remove empty block from the list. */
+ *lastp = p->_next;
+#ifdef _REENT_SMALL
+ if (args)
+ free (args);
+#endif
+ free (p);
+ p = *lastp;
+ }
+ else
+ {
+ lastp = &p->_next;
+ p = p->_next;
+ }
+#endif
+ }
+#ifndef __SINGLE_THREAD__
+ __lock_release_recursive(__atexit_recursive_mutex);
+#endif
+
+}
M module-os/board/rt1051/_exit.cpp => module-os/board/rt1051/_exit.cpp +13 -8
@@ 40,26 40,25 @@
#include <string.h>
#include <exit_backtrace.h>
#include <purefs/vfs_subsystem.hpp>
-#include <bsp/bsp.hpp>
-
static void __attribute__((noreturn)) stop_system(void)
{
- if(!isIRQ()) {
+ if (!isIRQ()) {
if (dumpLogs() != 1) {
LOG_ERROR("Cannot dump logs");
}
const auto err = purefs::subsystem::unmount_all();
- if(err) {
+ if (err) {
LOG_WARN("Unable unmount all filesystems with error: %i.", err);
- } else {
+ }
+ else {
LOG_INFO("Filesystems unmounted successfully...");
}
}
- LOG_INFO("Restarting the system...");
+ vTaskSuspendAll();
haltIfDebugging();
- bsp::BoardReboot();
- vTaskEndScheduler();
+ LOG_INFO("Restarting the system...");
+ NVIC_SystemReset();
// waiting for system reset
while (1) {
#ifndef DEBUG
@@ 82,3 81,9 @@ void __attribute__((noreturn, used)) _exit(int code)
{
_exit_backtrace(code, code!=0);
}
+
+void __attribute__((noreturn, used)) exit(int code)
+{
+ // do not call global destructors and atexit registered functions
+ _exit(code);
+}
A module-os/board/rt1051/atexit.h => module-os/board/rt1051/atexit.h +15 -0
@@ 0,0 1,15 @@
+/*
+ * Common definitions for atexit-like routines
+ */
+
+enum __atexit_types
+{
+ __et_atexit,
+ __et_onexit,
+ __et_cxa
+};
+
+#define MALLOC_PROVIDED
+
+void __call_exitprocs (int, void *);
+int __register_exitproc (int, void (*fn) (void), void *, void *);
M module-os/board/rt1051/include/exit_backtrace.h => module-os/board/rt1051/include/exit_backtrace.h +1 -2
@@ 24,6 24,7 @@ void __attribute__((noreturn, used)) _exit_backtrace(int code, bool bt_dump);
* @note Function never returns and dump backtrace when code is not equal EXIT_SUCCESS
*/
void __attribute__((noreturn, used)) _exit(int code);
+void __attribute__((noreturn, used)) exit(int code);
/** This is internal backtrce function
@@ 52,5 53,3 @@ static inline void __attribute__((always_inline)) _StackTrace_Dump_And_Abort(voi
#ifdef __cplusplus
}
#endif
-
-
M module-platform/rt1051/CMakeLists.txt => module-platform/rt1051/CMakeLists.txt +1 -1
@@ 28,5 28,5 @@ target_link_libraries(
platform
PRIVATE
- module-vfs
+ module-vfs log
)
M module-platform/rt1051/src/RT1051Platform.cpp => module-platform/rt1051/src/RT1051Platform.cpp +3 -1
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include <platform/rt1051/RT1051Platform.hpp>
@@ 8,6 8,7 @@
#include <bsp/bsp.hpp>
#include <purefs/vfs_subsystem.hpp>
#include <exception>
+#include <Logger.hpp>
using platform::rt1051::BlockDeviceFactory;
using platform::rt1051::RT1051Platform;
@@ 15,6 16,7 @@ using platform::rt1051::RT1051Platform;
RT1051Platform::RT1051Platform()
{
bsp::BoardInit();
+ bsp::RegisterPlatformExitFunction(Log::Logger::destroyInstance);
}
void RT1051Platform::init()
M module-sys/SystemManager/SystemManagerCommon.cpp => module-sys/SystemManager/SystemManagerCommon.cpp +1 -1
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include <SystemManager/SystemManagerCommon.hpp>
M module-utils/log/Logger.cpp => module-utils/log/Logger.cpp +37 -21
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "critical.hpp"
@@ 12,25 12,8 @@
namespace Log
{
- std::map<std::string, logger_level> Logger::filtered = {{"ApplicationManager", logger_level::LOGINFO},
-#if (!LOG_SENSITIVE_DATA_ENABLED)
- {"CellularMux", logger_level::LOGINFO},
- {"ServiceCellular", logger_level::LOGINFO},
-#endif
- {"ServiceAntenna", logger_level::LOGERROR},
- {"ServiceAudio", logger_level::LOGINFO},
- {"ServiceBluetooth", logger_level::LOGINFO},
- {"ServiceBluetooth_w1", logger_level::LOGINFO},
- {"ServiceFota", logger_level::LOGINFO},
- {"ServiceEink", logger_level::LOGINFO},
- {"ServiceDB", logger_level::LOGINFO},
- {CRIT_STR, logger_level::LOGTRACE},
- {IRQ_STR, logger_level::LOGTRACE},
- {"FileIndexer", logger_level::LOGINFO},
- {"ServiceAudio", logger_level::LOGERROR},
- {"EventManager", logger_level::LOGINFO}};
-
- const char *Logger::levelNames[] = {"TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL"};
+ const char *Logger::levelNames[] = {"TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL"};
+ Logger *Logger::_logger = nullptr;
std::ostream &operator<<(std::ostream &stream, const Application &application)
{
@@ 40,7 23,27 @@ namespace Log
}
Logger::Logger() : circularBuffer{circularBufferSize}, rotator{".log"}
- {}
+ {
+ filtered = {
+ {"ApplicationManager", logger_level::LOGINFO},
+#if (!LOG_SENSITIVE_DATA_ENABLED)
+ {"CellularMux", logger_level::LOGINFO},
+ {"ServiceCellular", logger_level::LOGINFO},
+#endif
+ {"ServiceAntenna", logger_level::LOGERROR},
+ {"ServiceAudio", logger_level::LOGINFO},
+ {"ServiceBluetooth", logger_level::LOGINFO},
+ {"ServiceBluetooth_w1", logger_level::LOGINFO},
+ {"ServiceFota", logger_level::LOGINFO},
+ {"ServiceEink", logger_level::LOGINFO},
+ {"ServiceDB", logger_level::LOGINFO},
+ {CRIT_STR, logger_level::LOGTRACE},
+ {IRQ_STR, logger_level::LOGTRACE},
+ {"FileIndexer", logger_level::LOGINFO},
+ {"ServiceAudio", logger_level::LOGERROR},
+ {"EventManager", logger_level::LOGINFO}
+ };
+ }
void Logger::enableColors(bool enable)
{
@@ 54,6 57,19 @@ namespace Log
}
}
+ void Logger::destroyInstance()
+ {
+ delete _logger;
+ _logger = nullptr;
+ }
+
+ Logger &Logger::get()
+ {
+ static auto *logger = new Logger;
+ _logger = logger;
+ return *logger;
+ }
+
auto Logger::getLogLevel(const std::string &name) -> logger_level
{
return filtered[name];
M module-utils/log/Logger.hpp => module-utils/log/Logger.hpp +5 -7
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 34,11 34,8 @@ namespace Log
{
public:
void enableColors(bool enable);
- [[nodiscard]] static Logger &get()
- {
- static Logger logger;
- return logger;
- }
+ [[nodiscard]] static Logger &get();
+ static void destroyInstance();
auto getLogs() -> std::string;
void init(Application app, size_t fileSize = MAX_LOG_FILE_SIZE);
auto log(Device device, const char *fmt, va_list args) -> int;
@@ 89,7 86,8 @@ namespace Log
static constexpr size_t circularBufferSize = 1000;
static const char *levelNames[];
- static std::map<std::string, logger_level> filtered;
+ std::map<std::string, logger_level> filtered;
+ static Logger *_logger;
};
const char *getTaskDesc();
M products/BellHybrid/CMakeLists.txt => products/BellHybrid/CMakeLists.txt +1 -0
@@ 12,6 12,7 @@ target_compile_options(BellHybrid
PRIVATE
$<$<COMPILE_LANGUAGE:C>:-Wno-discarded-qualifiers>
"-Wno-error=deprecated-declarations"
+ "-Wno-prio-ctor-dtor"
)
M products/PurePhone/CMakeLists.txt => products/PurePhone/CMakeLists.txt +1 -0
@@ 19,6 19,7 @@ target_compile_options(PurePhone
PRIVATE
$<$<COMPILE_LANGUAGE:C>:-Wno-discarded-qualifiers>
"-Wno-error=deprecated-declarations"
+ "-Wno-prio-ctor-dtor"
)
target_sources(PurePhone
M products/PurePhone/PurePhoneMain.cpp => products/PurePhone/PurePhoneMain.cpp +24 -4
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "config.h"
@@ 70,6 70,24 @@
#include <memory>
#include <vector>
+#include <cstdlib>
+
+void atexit_cleanup_handler()
+{
+ LOG_INFO("Starting clean up");
+}
+
+class Cleanup
+{
+ public:
+ ~Cleanup()
+ {
+ const int result_2 = std::atexit(atexit_cleanup_handler);
+ if (result_2 != 0) {
+ LOG_FATAL("at exit failed");
+ }
+ }
+};
int main()
{
@@ 204,9 222,11 @@ int main()
return true;
});
- LOG_PRINTF("Launching %s \n", ApplicationName);
- LOG_PRINTF("commit: %s version: %s branch: %s\n", GIT_REV, VERSION, GIT_BRANCH);
+ LOG_INFO("Launching %s ", ApplicationName);
+ LOG_INFO("commit: %s version: %s branch: %s", GIT_REV, VERSION, GIT_BRANCH);
cpp_freertos::Thread::StartScheduler();
- LOG_PRINTF("Scheduler is terminated properly\n");
+ LOG_INFO("Scheduler is terminated properly");
+ Cleanup cleanup;
+
return 0;
}