From c05230e79f7902bbd56f1d4b69fce4cc085d5297 Mon Sep 17 00:00:00 2001 From: Niklas Hauser Date: Mon, 1 May 2017 20:34:28 +0200 Subject: [PATCH 1/7] [assert] Refactor implementation, keep interface. - Make header C-compatible so asserts can be called from C. - Specialize `assert_fail` function for context value. - Return condition from `xpcc_assert` for error handling. - Remove `exit()` calls from implementation. --- src/xpcc/architecture/interface/assert.h | 74 +++++++++++++++++++ src/xpcc/architecture/interface/assert.hpp | 50 +++++-------- .../platform/driver/core/avr/assert.cpp | 15 ++-- .../platform/driver/core/cortex/assert.cpp | 14 +++- .../platform/driver/core/hosted/assert.cpp | 16 ++-- 5 files changed, 124 insertions(+), 45 deletions(-) create mode 100644 src/xpcc/architecture/interface/assert.h diff --git a/src/xpcc/architecture/interface/assert.h b/src/xpcc/architecture/interface/assert.h new file mode 100644 index 000000000..d5f17bfb6 --- /dev/null +++ b/src/xpcc/architecture/interface/assert.h @@ -0,0 +1,74 @@ +// coding: utf-8 +/* Copyright (c) 2016-2017, Niklas Hauser + * All Rights Reserved. + * + * The file is part of the xpcc library and is released under the 3-clause BSD + * license. See the file `LICENSE` for the full license governing this code. + */ +// ---------------------------------------------------------------------------- + +#ifndef XPCC_ASSERT_H +#define XPCC_ASSERT_H + +#if defined(__cplusplus) && !defined(XPCC_ASSERT_HPP) +# error "Don't include this file directly, use 'assert.hpp' instead!" +#endif + +#include +#include +#include + +#ifndef __DOXYGEN__ + +// FIXME: is not C compatible! +#ifdef XPCC__CPU_AVR +# include +# define xpcc_ifss(s) PSTR(s) +#else +# define xpcc_ifss(s) ((const char *)(s)) +#endif + +#define xpcc_assert4(condition, module, location, failure) \ + ({ \ + bool xpcc_assert_evaluated_condition = (bool) (condition); \ + if (!xpcc_assert_evaluated_condition) { \ + xpcc_assert_fail(xpcc_ifss(module "\0" location "\0" failure)); } \ + xpcc_assert_evaluated_condition; \ + }) + + +#define xpcc_assert5(condition, module, location, failure, context) \ + ({ \ + bool xpcc_assert_evaluated_condition = (bool) (condition); \ + if (!xpcc_assert_evaluated_condition) { \ + xpcc_assert_fail_context(xpcc_ifss(module "\0" location "\0" failure), (uintptr_t) context); } \ + xpcc_assert_evaluated_condition; \ + }) + +#define xpcc_assert_get_macro(_1,_2,_3,_4,_5,foo,...) foo +#define xpcc_assert(...) \ + xpcc_assert_get_macro(__VA_ARGS__, xpcc_assert5, xpcc_assert4)(__VA_ARGS__) + +#ifdef XPCC_DEBUG_BUILD +#define xpcc_assert_debug(...) \ + xpcc_assert_get_macro(__VA_ARGS__, xpcc_assert5, xpcc_assert4)(__VA_ARGS__) +#else +# define xpcc_assert_debug(condition, ...) \ + ({ \ + bool xpcc_unused xpcc_assert_evaluated_condition = (bool) (condition); \ + xpcc_assert_evaluated_condition; \ + }) +#endif + +xpcc_extern_c void +xpcc_assert_fail_context(const char * identifier, uintptr_t context); + +xpcc_extern_c void +xpcc_assert_fail(const char * identifier); + +xpcc_extern_c void +xpcc_abandon(const char * module, const char * location, const char * failure, uintptr_t context); + +#endif // __DOXYGEN__ + +#endif // XPCC_ASSERT_H diff --git a/src/xpcc/architecture/interface/assert.hpp b/src/xpcc/architecture/interface/assert.hpp index cafcee850..6ffea8cfa 100644 --- a/src/xpcc/architecture/interface/assert.hpp +++ b/src/xpcc/architecture/interface/assert.hpp @@ -1,5 +1,5 @@ // coding: utf-8 -/* Copyright (c) 2016, Roboterclub Aachen e.V. +/* Copyright (c) 2016-2017, Niklas Hauser * All Rights Reserved. * * The file is part of the xpcc library and is released under the 3-clause BSD @@ -13,7 +13,6 @@ #include #include #include -#include /** * @ingroup interface @@ -106,42 +105,50 @@ using AssertionHandler = Abandonment (*)(const char * module, /** * Assert a condition to be true with failure identifier. * This assert is always included in the source code. + * @returns result of condition evaluation * * @note On AVR targets the failure identifier string is placed in Flash memory! * * @ingroup assert */ -#define xpcc_assert(condition, module, location, failure) +xpcc_extern_c bool +xpcc_assert(bool condition, const char * module, const char * location, const char * failure); /** * Assert a condition to be true with failure identifier and context. * This assert is always included in the source code. + * @returns result of condition evaluation * * @note On AVR targets the failure identifier string is placed in Flash memory! * * @ingroup assert */ -#define xpcc_assert(condition, module, location, failure, context) +xpcc_extern_c bool +xpcc_assert(bool condition, const char * module, const char * location, const char * failure, uintptr_t context); /** * Assert a condition to be true with failure identifier. - * This assert is only included in the source code on debug builds! + * This assert is only triggered in the source code on debug builds! + * @returns result of condition evaluation * * @note On AVR targets the strings are placed in Flash memory! * * @ingroup assert */ -#define xpcc_assert_debug(condition, module, location, failure) +xpcc_extern_c bool +xpcc_assert_debug(bool condition, const char * module, const char * location, const char * failure); /** * Assert a condition to be true with failure identifier and context. - * This assert is only included in the source code on debug builds! + * This assert is only triggered in the source code on debug builds! + * @returns result of condition evaluation * * @note On AVR targets the strings are placed in Flash memory! * * @ingroup assert */ -#define xpcc_assert_debug(condition, module, location, failure, context) +xpcc_extern_c bool +xpcc_assert_debug(bool condition, const char * module, const char * location, const char * failure, uintptr_t context); /** * Overwriteable abandonment handler for all targets. @@ -151,7 +158,7 @@ using AssertionHandler = Abandonment (*)(const char * module, * * @ingroup assert */ -extern "C" void +xpcc_extern_c void xpcc_abandon(const char * module, const char * location, const char * failure, @@ -173,37 +180,18 @@ xpcc_abandon(const char * module, const xpcc::AssertionHandler \ handler ## _assertion_handler_ptr = handler #else +# warning "XPCC_ASSERTION_HANDLER(handler) ignored, due to missing linker section definition!" # define XPCC_ASSERTION_HANDLER(handler) #endif -#define xpcc_assert4(condition, module, location, failure) \ - xpcc_assert5(condition, module, location, failure, 0) - -#define xpcc_assert5(condition, module, location, failure, context) \ - if ((bool) (condition)) {} else { \ - xpcc_assert_fail(INLINE_FLASH_STORAGE_STRING(module "\0" location "\0" failure), (uintptr_t) context); } - -#define xpcc_assert_get_macro(_1,_2,_3,_4,_5,foo,...) foo -#define xpcc_assert(...) \ - xpcc_assert_get_macro(__VA_ARGS__, xpcc_assert5, xpcc_assert4)(__VA_ARGS__) - -#ifndef NDEBUG -#define xpcc_assert_debug(...) \ - xpcc_assert_get_macro(__VA_ARGS__, xpcc_assert5, xpcc_assert4)(__VA_ARGS__) +#ifdef XPCC_DEBUG_BUILD # define XPCC_ASSERTION_HANDLER_DEBUG(handler) \ XPCC_ASSERTION_HANDLER(handler) #else -# define xpcc_assert_debug(...) # define XPCC_ASSERTION_HANDLER_DEBUG(handler) #endif -extern "C" { - -void xpcc_assert_fail(const char * identifier, uintptr_t context); - -void xpcc_abandon(const char * module, const char * location, const char * failure, uintptr_t context); - -} +#include "assert.h" #endif // __DOXYGEN__ diff --git a/src/xpcc/architecture/platform/driver/core/avr/assert.cpp b/src/xpcc/architecture/platform/driver/core/avr/assert.cpp index dddfd11a3..0e9f2ead5 100644 --- a/src/xpcc/architecture/platform/driver/core/avr/assert.cpp +++ b/src/xpcc/architecture/platform/driver/core/avr/assert.cpp @@ -7,10 +7,8 @@ */ // ---------------------------------------------------------------------------- -#include -#include -#include #include +#include using xpcc::AssertionHandler; using xpcc::Abandonment; @@ -21,7 +19,14 @@ extern AssertionHandler __assertion_table_end; extern "C" { -void xpcc_assert_fail(const char * identifier, uintptr_t context) +void +xpcc_assert_fail(const char * identifier) +{ + // just forward this call + xpcc_assert_fail_context(identifier, 0); +} + +void xpcc_assert_fail_context(const char * identifier, uintptr_t context) { uint8_t state(uint8_t(Abandonment::DontCare)); const char * module = identifier; @@ -39,7 +44,7 @@ void xpcc_assert_fail(const char * identifier, uintptr_t context) state & (uint8_t) Abandonment::Fail) { xpcc_abandon(module, location, failure, context); - exit(1); + while(1) ; } } diff --git a/src/xpcc/architecture/platform/driver/core/cortex/assert.cpp b/src/xpcc/architecture/platform/driver/core/cortex/assert.cpp index 5e1031a2e..2dd7d82a3 100644 --- a/src/xpcc/architecture/platform/driver/core/cortex/assert.cpp +++ b/src/xpcc/architecture/platform/driver/core/cortex/assert.cpp @@ -7,10 +7,9 @@ */ // ---------------------------------------------------------------------------- +#include #include -extern "C" void exit(int); - using xpcc::AssertionHandler; using xpcc::Abandonment; @@ -20,7 +19,14 @@ extern AssertionHandler __assertion_table_end; extern "C" { -void xpcc_assert_fail(const char * identifier, uintptr_t context) +void +xpcc_assert_fail(const char * identifier) +{ + // just forward this call + xpcc_assert_fail_context(identifier, 0); +} + +void xpcc_assert_fail_context(const char * identifier, uintptr_t context) { uint8_t state(uint8_t(Abandonment::DontCare)); const char * module = identifier; @@ -37,7 +43,7 @@ void xpcc_assert_fail(const char * identifier, uintptr_t context) state & (uint8_t) Abandonment::Fail) { xpcc_abandon(module, location, failure, context); - exit(1); + while(1) ; } } diff --git a/src/xpcc/architecture/platform/driver/core/hosted/assert.cpp b/src/xpcc/architecture/platform/driver/core/hosted/assert.cpp index 35684a268..4584032fc 100644 --- a/src/xpcc/architecture/platform/driver/core/hosted/assert.cpp +++ b/src/xpcc/architecture/platform/driver/core/hosted/assert.cpp @@ -36,7 +36,14 @@ XPCC_ASSERTION_HANDLER(empty_assertion_handler); extern "C" { -void xpcc_assert_fail(const char * identifier, uintptr_t context) +void +xpcc_assert_fail(const char * identifier) +{ + // just forward this call + xpcc_assert_fail_context(identifier, 0); +} + +void xpcc_assert_fail_context(const char * identifier, uintptr_t context) { uint8_t state((uint8_t) Abandonment::DontCare); const char * module = identifier; @@ -60,10 +67,9 @@ void xpcc_assert_fail(const char * identifier, uintptr_t context) xpcc_weak void xpcc_abandon(const char * module, const char * location, const char * failure, uintptr_t context) { - XPCC_LOG_ERROR << "Assertion '" - << module << "." << location << "." << failure - << "' @ " << (void *) context - << " failed! Abandoning..." << xpcc::endl; + XPCC_LOG_ERROR.printf("Assertion '%s.%s.%s'", module, location, failure); + if (context) { XPCC_LOG_ERROR.printf(" @ %p (%d)", (void *) context, context); } + XPCC_LOG_ERROR.printf(" failed! Abandoning...\n"); } } From d049d4dc7cdb1162c948c1e7408dc44bf007e426 Mon Sep 17 00:00:00 2001 From: Niklas Hauser Date: Mon, 1 May 2017 23:12:36 +0200 Subject: [PATCH 2/7] [assert] Assert on all heap implementations. --- .../platform/driver/core/avr/newdelete.cpp | 22 +++++--- .../platform/driver/core/avr/ram.cpp.in | 10 ++-- .../platform/driver/core/cortex/cxxabi.cpp | 52 +++++++++++++++---- .../core/cortex/heap_block_allocator.cpp.in | 21 ++++---- .../driver/core/cortex/heap_newlib.c.in | 20 ++++--- .../driver/core/cortex/heap_tlsf.c.in | 26 ++++------ 6 files changed, 97 insertions(+), 54 deletions(-) diff --git a/src/xpcc/architecture/platform/driver/core/avr/newdelete.cpp b/src/xpcc/architecture/platform/driver/core/avr/newdelete.cpp index 29a9b8c32..48ea92a56 100644 --- a/src/xpcc/architecture/platform/driver/core/avr/newdelete.cpp +++ b/src/xpcc/architecture/platform/driver/core/avr/newdelete.cpp @@ -8,30 +8,40 @@ // ---------------------------------------------------------------------------- #include "ram.hpp" +#include #include +#include void * operator new(size_t size) { - return xpcc::avr::allocateMemory(size); + void * ptr = xpcc::avr::allocateMemory(size); + xpcc_assert(ptr, "core", "heap", "new", size); + return ptr; } void * operator new[](size_t size) { - return xpcc::avr::allocateMemory(size); + void * ptr = xpcc::avr::allocateMemory(size); + xpcc_assert(ptr, "core", "heap", "new", size); + return ptr; } void * operator new(size_t size, xpcc::MemoryTraits) { - return xpcc::avr::allocateMemory(size); + void * ptr = xpcc::avr::allocateMemory(size); + xpcc_assert(ptr, "core", "heap", "new", size); + return ptr; } void * operator new[](size_t size, xpcc::MemoryTraits) { - return xpcc::avr::allocateMemory(size); + void * ptr = xpcc::avr::allocateMemory(size); + xpcc_assert(ptr, "core", "heap", "new", size); + return ptr; } void @@ -41,7 +51,7 @@ operator delete(void* ptr) } void -operator delete(void* ptr, size_t size __attribute__((unused))) +operator delete(void* ptr, size_t) { xpcc::avr::freeMemory(ptr); } @@ -53,7 +63,7 @@ operator delete[](void* ptr) } void -operator delete[](void* ptr, size_t size __attribute__((unused))) +operator delete[](void* ptr, size_t) { xpcc::avr::freeMemory(ptr); } diff --git a/src/xpcc/architecture/platform/driver/core/avr/ram.cpp.in b/src/xpcc/architecture/platform/driver/core/avr/ram.cpp.in index cd2cde87e..338e2929c 100644 --- a/src/xpcc/architecture/platform/driver/core/avr/ram.cpp.in +++ b/src/xpcc/architecture/platform/driver/core/avr/ram.cpp.in @@ -9,6 +9,7 @@ #include #include +#include #include "ram.hpp" @@ -76,11 +77,9 @@ initializeMemory(void) void * xpcc::avr::allocateMemory(std::size_t requestedSize) { - if (requestedSize == 0 || - requestedSize > MAX_BLOCK_PARTS * BLOCK_SIZE) - { + if (!xpcc_assert_debug(requestedSize > 0 && requestedSize <= MAX_BLOCK_PARTS * BLOCK_SIZE, + "core", "heap", "malloc", requestedSize)) return 0; - } requestedSize += 2; // bytes needed for the mangement uint8_t neededSlots = requestedSize / BLOCK_SIZE; @@ -139,9 +138,8 @@ xpcc::avr::allocateMemory(std::size_t requestedSize) avail = cp - __brkval; */ - if (slotsAvailable < neededSlots) { + if (!xpcc_assert_debug(slotsAvailable >= neededSlots, "core", "heap", "malloc", requestedSize)) return 0; - } *p = neededSlots; *(p + neededSlots * BLOCK_SIZE - 1) = neededSlots; diff --git a/src/xpcc/architecture/platform/driver/core/cortex/cxxabi.cpp b/src/xpcc/architecture/platform/driver/core/cortex/cxxabi.cpp index 81ad341e5..7a7b3ccf7 100644 --- a/src/xpcc/architecture/platform/driver/core/cortex/cxxabi.cpp +++ b/src/xpcc/architecture/platform/driver/core/cortex/cxxabi.cpp @@ -33,7 +33,9 @@ // ---------------------------------------------------------------------------- #include // for prototypes of malloc() and free() +#include #include +#include extern "C" { @@ -80,35 +82,67 @@ extern "C" void * operator new(size_t size) throw () { - return malloc(size); + void * ptr = malloc(size); + xpcc_assert(ptr, "core", "heap", "new", size); + return ptr; } void * operator new[](size_t size) throw () +{ + void * ptr = malloc(size); + xpcc_assert(ptr, "core", "heap", "new", size); + return ptr; +} + +void * +operator new(size_t size, std::nothrow_t) noexcept +{ + return malloc(size); +} + +void * +operator new[](size_t size, std::nothrow_t) noexcept { return malloc(size); } void * -operator new(size_t size, xpcc::MemoryTraits traits) +operator new(size_t size, xpcc::MemoryTraits traits) noexcept { - return malloc_tr(size, traits.value); + void * ptr = malloc_tr(size, traits.value); + xpcc_assert(ptr, "core", "heap", "new", size); + return ptr; } void * -operator new[](size_t size, xpcc::MemoryTraits traits) +operator new[](size_t size, xpcc::MemoryTraits traits) noexcept +{ + void * ptr = malloc_tr(size, traits.value); + xpcc_assert(ptr, "core", "heap", "new", size); + return ptr; +} + +void +operator delete(void *ptr) noexcept +{ + free(ptr); +} + +void +operator delete(void* ptr, size_t) noexcept { - return malloc_tr(size, traits.value); + free(ptr); } void -operator delete(void *p) throw () +operator delete[](void* ptr) noexcept { - free(p); + free(ptr); } void -operator delete[](void* p) throw () +operator delete[](void* ptr, size_t) noexcept { - free(p); + free(ptr); } diff --git a/src/xpcc/architecture/platform/driver/core/cortex/heap_block_allocator.cpp.in b/src/xpcc/architecture/platform/driver/core/cortex/heap_block_allocator.cpp.in index 3ee78a0fc..cdd09f8c2 100644 --- a/src/xpcc/architecture/platform/driver/core/cortex/heap_block_allocator.cpp.in +++ b/src/xpcc/architecture/platform/driver/core/cortex/heap_block_allocator.cpp.in @@ -16,6 +16,7 @@ #include #include #include +#include // ---------------------------------------------------------------------------- %% if parameters.allocator == "block_allocator" @@ -45,7 +46,7 @@ void __xpcc_initialize_memory(void) uint32_t *heap_start, *heap_end; // find the largest heap that is DMA-able and S-Bus accessible xpcc_heap_table_find_largest(0x9, &heap_start, &heap_end); - if (!heap_start) exit(ENOMEM); + xpcc_assert(heap_start, "core", "heap", "init"); // clamp the heap size to the maximum if ((size_t) heap_end - (size_t) heap_start > max_heap_size) { heap_end = (uint32_t *) ((char *) heap_start + max_heap_size); @@ -57,16 +58,18 @@ void __xpcc_initialize_memory(void) void *__wrap__malloc_r(struct _reent *r, size_t size) { (void) r; - void *p = allocator.allocate(size); - if (!p) exit(ENOMEM); - return p; + void *ptr = allocator.allocate(size); + xpcc_assert_debug(ptr, "core", "heap", "malloc", size); + return ptr; } void *__wrap__calloc_r(struct _reent *r, size_t size) { - void *p = __wrap__malloc_r(r, size); - if (p) memset(p, 0, size); - return p; + void *ptr = __wrap__malloc_r(r, size); + if (xpcc_assert_debug(ptr, "core", "heap", "calloc", size)) { + memset(ptr, 0, size); + } + return ptr; } void *__wrap__realloc_r(struct _reent *r, void *p, size_t size) @@ -75,7 +78,7 @@ void *__wrap__realloc_r(struct _reent *r, void *p, size_t size) (void) p; (void) size; // NOT IMPLEMENTED! - exit(ENOSYS); + xpcc_assert_debug(0, "core", "heap", "realloc", size); return NULL; } @@ -91,7 +94,7 @@ _sbrk_r(struct _reent *r, ptrdiff_t size) { (void) r; (void) size; - return 0; + return NULL; } // memory traits are ignored for newlib allocator diff --git a/src/xpcc/architecture/platform/driver/core/cortex/heap_newlib.c.in b/src/xpcc/architecture/platform/driver/core/cortex/heap_newlib.c.in index 878e80381..b66514e2d 100644 --- a/src/xpcc/architecture/platform/driver/core/cortex/heap_newlib.c.in +++ b/src/xpcc/architecture/platform/driver/core/cortex/heap_newlib.c.in @@ -16,6 +16,7 @@ #include #include #include +#include // ---------------------------------------------------------------------------- %% if parameters.allocator == "newlib" @@ -28,7 +29,7 @@ void __xpcc_initialize_memory(void) { // find the largest heap that is DMA-able and S-Bus accessible xpcc_heap_table_find_largest(0x9, (uint32_t **) &__brkval, (uint32_t **) &heap_end); - if (!__brkval) exit(ENOMEM); + xpcc_assert(__brkval, "core", "heap", "init"); } /* Support function. Adjusts end of heap to provide more memory to @@ -52,10 +53,7 @@ _sbrk_r(struct _reent *r, ptrdiff_t size) uint8_t *heap = __brkval; __brkval += size; - if (__brkval >= heap_end) { - // ERROR: out of memory! - exit(ENOMEM); - } + xpcc_assert(__brkval < heap_end, "core", "heap", "sbrk", size); // Return pointer to start of new heap area. return heap; @@ -64,15 +62,21 @@ _sbrk_r(struct _reent *r, ptrdiff_t size) // FIXME: "Unwrap" the malloc for newlib allocator void *__real__malloc_r(struct _reent *r, size_t size); void *__wrap__malloc_r(struct _reent *r, size_t size) { - return __real__malloc_r(r, size); + void * ptr = __real__malloc_r(r, size); + xpcc_assert_debug(ptr, "core", "heap", "malloc", size); + return ptr; } void *__real__calloc_r(struct _reent *r, size_t size); void *__wrap__calloc_r(struct _reent *r, size_t size) { - return __real__calloc_r(r, size); + void * ptr = __real__calloc_r(r, size); + xpcc_assert_debug(ptr, "core", "heap", "calloc", size); + return ptr; } void *__real__realloc_r(struct _reent *r, void *p, size_t size); void *__wrap__realloc_r(struct _reent *r, void *p, size_t size) { - return __real__realloc_r(r, p, size); + void * ptr = __real__realloc_r(r, p, size); + xpcc_assert_debug(ptr, "core", "heap", "realloc", size); + return ptr; } void __real__free_r(struct _reent *r, void *p); void __wrap__free_r(struct _reent *r, void *p) { diff --git a/src/xpcc/architecture/platform/driver/core/cortex/heap_tlsf.c.in b/src/xpcc/architecture/platform/driver/core/cortex/heap_tlsf.c.in index 0073b0215..59081e795 100644 --- a/src/xpcc/architecture/platform/driver/core/cortex/heap_tlsf.c.in +++ b/src/xpcc/architecture/platform/driver/core/cortex/heap_tlsf.c.in @@ -16,6 +16,7 @@ #include #include #include +#include // ---------------------------------------------------------------------------- %% if parameters.allocator == "tlsf" @@ -46,7 +47,7 @@ __xpcc_initialize_memory(void) uint32_t traits; uint32_t * start; uint32_t * end; - } __attribute__((packed)) table_pool_t; + } xpcc_packed table_pool_t; uint32_t current_traits = 0; mem_pool_t *current_pool = mem_pools; @@ -90,6 +91,7 @@ get_tlsf_for_ptr(void *p) return pool->tlsf; } } + xpcc_assert_debug(0, "core", "heap", "pool"); return NULL; } @@ -120,8 +122,7 @@ try_again: goto try_again; } // there is no memory left even after fallback. - - exit(ENOMEM); + xpcc_assert_debug(0, "core", "heap", "malloc", size); return NULL; } @@ -135,9 +136,9 @@ void *__wrap__malloc_r(struct _reent *r, size_t size) void *__wrap__calloc_r(struct _reent *r, size_t size) { (void) r; - void *p = __wrap__malloc_r(r, size); - if (p) memset(p, 0, size); - return p; + void *ptr = __wrap__malloc_r(r, size); + if (ptr) memset(ptr, 0, size); + return ptr; } void *__wrap__realloc_r(struct _reent *r, void *p, size_t size) @@ -145,14 +146,10 @@ void *__wrap__realloc_r(struct _reent *r, void *p, size_t size) (void) r; tlsf_t pool = get_tlsf_for_ptr(p); // if pointer belongs to no pool, exit. - if (!pool) { - exit(EINVAL); - return NULL; - } + if (!pool) return NULL; void *ptr = tlsf_realloc(pool, p, size); - - if (!ptr) exit(ENOMEM); + xpcc_assert_debug(p, "core", "heap", "realloc", size); return ptr; } @@ -161,10 +158,7 @@ void __wrap__free_r(struct _reent *r, void *p) (void) r; tlsf_t pool = get_tlsf_for_ptr(p); // if pointer belongs to no pool, exit. - if (!pool) { - exit(EINVAL); - return; - } + if (!pool) return; tlsf_free(pool, p); } From 93d237795fa9dedb7c2ffdbe220cb7d5cf660ee2 Mon Sep 17 00:00:00 2001 From: Niklas Hauser Date: Mon, 1 May 2017 23:13:52 +0200 Subject: [PATCH 3/7] [cortex] Assert undefined IRQ handler. --- .../platform/driver/core/cortex/startup.c.in | 37 +++++++------------ 1 file changed, 13 insertions(+), 24 deletions(-) diff --git a/src/xpcc/architecture/platform/driver/core/cortex/startup.c.in b/src/xpcc/architecture/platform/driver/core/cortex/startup.c.in index d0aed0b62..00ab6bbae 100644 --- a/src/xpcc/architecture/platform/driver/core/cortex/startup.c.in +++ b/src/xpcc/architecture/platform/driver/core/cortex/startup.c.in @@ -31,23 +31,28 @@ #include #include +#include #include "../../../device.hpp" #include "xpcc_config.hpp" {{ platform.defines() }} // ---------------------------------------------------------------------------- -/* - * Provide weak aliases for each Exception handler to defaultHandler. +void Undefined_Handler(void) +{ + uint32_t irqn; + asm volatile("mrs %[irqn], ipsr" :[irqn] "=r" (irqn)); + xpcc_assert(0, "core", "nvic", "undefined", irqn); +} +/* Provide weak aliases for each Exception handler to Undefined_Handler. * As they are weak aliases, any function with the same name will override - * this definition. - */ + * this definition. */ void Reset_Handler(void) __attribute__((noreturn)); -void NMI_Handler(void) __attribute__ ((weak, alias("defaultHandler"))); +void NMI_Handler(void) __attribute__((weak, alias("Undefined_Handler"))); %% if target is stm32 void HardFault_Handler(void); %% else -void HardFault_Handler(void) __attribute__ ((weak, alias("defaultHandler"))); +void HardFault_Handler(void) __attribute__((weak, alias("Undefined_Handler"))); %% endif %# Remember declarations to avoid redeclarations %% set declarations = [] @@ -58,7 +63,7 @@ void HardFault_Handler(void) __attribute__ ((weak, alias("defaultHandler"))); %% if addr < 0 %% set suffix = "" %% endif -{{ ("void " + interrupt[0] + suffix + "(void)") | xpcc.pad(36)}}__attribute__ ((weak, alias("defaultHandler"))); +{{ ("void " + interrupt[0] + suffix + "(void)") | xpcc.pad(36)}}__attribute__((weak, alias("Undefined_Handler"))); %% endif %% endfor // ---------------------------------------------------------------------------- @@ -90,7 +95,7 @@ FunctionPointer flashVectors[] = %% endif {{ (i[addr][0] + suffix + ",") | xpcc.pad(36) }}// {{ (addr|string).rjust(3) }} %% else - 0, // {{ (addr|string).rjust(3) }} + Undefined_Handler, // {{ (addr|string).rjust(3) }} %% endif %% endfor }; @@ -292,19 +297,3 @@ Reset_Handler(void) { } } - -// ---------------------------------------------------------------------------- -/** - * @brief Default interrupt handler - * - * This functions gets called if an interrupt handler is not defined. It just - * enters an infinite loop leaving the processor state intact for a debugger - * to be examined. -*/ -void -defaultHandler(void) -{ - while (1) - { - } -} From c876d9605838f827243477c1f3821d7f6ed1fe0e Mon Sep 17 00:00:00 2001 From: Niklas Hauser Date: Fri, 5 May 2017 20:27:46 +0100 Subject: [PATCH 4/7] [cortex] Assert main function exit. --- .../platform/driver/core/cortex/startup.c.in | 26 ++++++++----------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/src/xpcc/architecture/platform/driver/core/cortex/startup.c.in b/src/xpcc/architecture/platform/driver/core/cortex/startup.c.in index 00ab6bbae..96552a53b 100644 --- a/src/xpcc/architecture/platform/driver/core/cortex/startup.c.in +++ b/src/xpcc/architecture/platform/driver/core/cortex/startup.c.in @@ -76,11 +76,11 @@ extern uint32_t __process_stack_top[]; %% if parameters.vector_table_in_ram // reserve space for the remapped vector table in RAM -__attribute__(( section(".vectors") )) +xpcc_section(".vectors") FunctionPointer ramVectors[{{number_of_interrupts + 16}}]; %% endif // Define the vector table -__attribute__(( section(".reset") )) +xpcc_section(".reset") FunctionPointer flashVectors[] = { (FunctionPointer)__main_stack_top, // -16: stack pointer @@ -122,24 +122,23 @@ extern uint32_t __vector_table_rom_start[]; extern uint32_t __vector_table_ram_start[]; // Application's main function -int +int __attribute__((noreturn)) main(void); // calls CTORS of static objects void __libc_init_array(void); -extern void -exit(int) __attribute__ ((noreturn, weak)); - // default implementation is empty and does nothing -void xpcc_hook_hardware_init(void) __attribute__(( weak )); -void xpcc_hook_hardware_init(void) {} +xpcc_weak void +xpcc_hook_hardware_init(void) {} -extern void __xpcc_initialize_memory(void); +extern void +__xpcc_initialize_memory(void); %% if parameters.enable_gpio -extern void xpcc_gpio_enable(void); +extern void +xpcc_gpio_enable(void); %% endif static void @@ -291,9 +290,6 @@ Reset_Handler(void) // Call the application's entry point main(); - exit(1); - - while (1) - { - } + xpcc_assert_debug(0, "core", "main", "exit"); + while(1) ; } From 5c05ba971020b5a145ddde8c5f41e2a45b95b51e Mon Sep 17 00:00:00 2001 From: Niklas Hauser Date: Wed, 3 May 2017 21:40:45 +0100 Subject: [PATCH 5/7] [cpp] Assert on pure virtual call. --- src/xpcc/architecture/platform/driver/core/avr/cxxabi.cpp | 4 +++- src/xpcc/architecture/platform/driver/core/cortex/cxxabi.cpp | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/xpcc/architecture/platform/driver/core/avr/cxxabi.cpp b/src/xpcc/architecture/platform/driver/core/avr/cxxabi.cpp index ccfe90fd9..a3488fcc6 100644 --- a/src/xpcc/architecture/platform/driver/core/avr/cxxabi.cpp +++ b/src/xpcc/architecture/platform/driver/core/avr/cxxabi.cpp @@ -7,6 +7,8 @@ */ // ---------------------------------------------------------------------------- +#include + extern "C" { /** @@ -18,7 +20,7 @@ extern "C" void __cxa_pure_virtual() { - // put error handling here + xpcc_assert_debug(0, "core", "cxa", "purevirtual"); } __extension__ typedef int __guard __attribute__((mode (__DI__))); diff --git a/src/xpcc/architecture/platform/driver/core/cortex/cxxabi.cpp b/src/xpcc/architecture/platform/driver/core/cortex/cxxabi.cpp index 7a7b3ccf7..692879266 100644 --- a/src/xpcc/architecture/platform/driver/core/cortex/cxxabi.cpp +++ b/src/xpcc/architecture/platform/driver/core/cortex/cxxabi.cpp @@ -45,7 +45,7 @@ extern "C" void __cxa_pure_virtual() { - // put error handling here + xpcc_assert_debug(0, "core", "cxa", "purevirtual"); } // ------------------------------------------------------------------------ From 2e12569af3280afe752581102b29ded6f5fef941 Mon Sep 17 00:00:00 2001 From: Niklas Hauser Date: Sat, 6 May 2017 14:44:55 +0100 Subject: [PATCH 6/7] [boards] Add default assertion handler to all. --- examples/stm32f469_discovery/assert/main.cpp | 19 --------------- .../board/nucleo_f031k6/nucleo_f031k6.cpp | 23 ++++++++++++++++++ .../board/nucleo_f103rb/nucleo_f103rb.cpp | 23 ++++++++++++++++++ .../board/nucleo_f303k8/nucleo_f303k8.cpp | 23 ++++++++++++++++++ .../board/nucleo_f401re/nucleo_f401re.cpp | 23 ++++++++++++++++++ .../board/nucleo_f411re/nucleo_f411re.cpp | 23 ++++++++++++++++++ .../board/nucleo_f429zi/nucleo_f429zi.cpp | 19 +++++++++++++++ .../stm32f469_discovery.cpp | 19 +++++++++++++++ .../stm32f746g_discovery.cpp | 24 +++++++++++++++++++ .../stm32f769i_discovery.cpp | 19 +++++++++++++++ 10 files changed, 196 insertions(+), 19 deletions(-) diff --git a/examples/stm32f469_discovery/assert/main.cpp b/examples/stm32f469_discovery/assert/main.cpp index 3585f23ab..2629939d7 100644 --- a/examples/stm32f469_discovery/assert/main.cpp +++ b/examples/stm32f469_discovery/assert/main.cpp @@ -6,25 +6,6 @@ using namespace Board; -extern "C" void xpcc_abandon(const char * module, - const char * location, - const char * failure, - uintptr_t context) -{ - XPCC_LOG_ERROR << "Assertion '" - << module << "." << location << "." << failure - << "' @ " << (void *) context - << " failed! Abandoning..." << xpcc::endl; - - LedGreen::setOutput(); - while(1) { - LedBlue::set(); - xpcc::delayMilliseconds(20); - LedBlue::reset(); - xpcc::delayMilliseconds(180); - } -} - static xpcc::Abandonment test_assertion_handler(const char * module, const char * /* location */, diff --git a/src/xpcc/architecture/platform/board/nucleo_f031k6/nucleo_f031k6.cpp b/src/xpcc/architecture/platform/board/nucleo_f031k6/nucleo_f031k6.cpp index 9077e0ad4..a76e4e901 100644 --- a/src/xpcc/architecture/platform/board/nucleo_f031k6/nucleo_f031k6.cpp +++ b/src/xpcc/architecture/platform/board/nucleo_f031k6/nucleo_f031k6.cpp @@ -15,3 +15,26 @@ xpcc::log::Logger xpcc::log::debug(loggerDevice); xpcc::log::Logger xpcc::log::info(loggerDevice); xpcc::log::Logger xpcc::log::warning(loggerDevice); xpcc::log::Logger xpcc::log::error(loggerDevice); + +xpcc_extern_c void +xpcc_abandon(const char * module, + const char * location, + const char * failure, + uintptr_t context) +{ + XPCC_LOG_ERROR << "Assertion '" << module << "." << location << "." << failure << "'"; + if (context) { XPCC_LOG_ERROR << " @ " << (void *) context << " (" << (uint32_t) context << ")"; } + XPCC_LOG_ERROR << " failed! Abandoning..." << xpcc::endl; + + // Since LedD13 is also a GPIO pin, we don't force this pin to output, + // in case something sensitive is connected to this pin. + // The user must "enable" the use of this pin as an LED output, by + // explicitly setting the pin to output in the application. + // Board::LedD13::setOutput(); + while(1) { + Board::LedD13::set(); + xpcc::delayMilliseconds(20); + Board::LedD13::reset(); + xpcc::delayMilliseconds(180); + } +} diff --git a/src/xpcc/architecture/platform/board/nucleo_f103rb/nucleo_f103rb.cpp b/src/xpcc/architecture/platform/board/nucleo_f103rb/nucleo_f103rb.cpp index 24851fe78..3ddb796b6 100644 --- a/src/xpcc/architecture/platform/board/nucleo_f103rb/nucleo_f103rb.cpp +++ b/src/xpcc/architecture/platform/board/nucleo_f103rb/nucleo_f103rb.cpp @@ -15,3 +15,26 @@ xpcc::log::Logger xpcc::log::debug(loggerDevice); xpcc::log::Logger xpcc::log::info(loggerDevice); xpcc::log::Logger xpcc::log::warning(loggerDevice); xpcc::log::Logger xpcc::log::error(loggerDevice); + +xpcc_extern_c void +xpcc_abandon(const char * module, + const char * location, + const char * failure, + uintptr_t context) +{ + XPCC_LOG_ERROR << "Assertion '" << module << "." << location << "." << failure << "'"; + if (context) { XPCC_LOG_ERROR << " @ " << (void *) context << " (" << (uint32_t) context << ")"; } + XPCC_LOG_ERROR << " failed! Abandoning..." << xpcc::endl; + + // Since LedD13 is also a GPIO pin, we don't force this pin to output, + // in case something sensitive is connected to this pin. + // The user must "enable" the use of this pin as an LED output, by + // explicitly setting the pin to output in the application. + // Board::LedD13::setOutput(); + while(1) { + Board::LedD13::set(); + xpcc::delayMilliseconds(20); + Board::LedD13::reset(); + xpcc::delayMilliseconds(180); + } +} diff --git a/src/xpcc/architecture/platform/board/nucleo_f303k8/nucleo_f303k8.cpp b/src/xpcc/architecture/platform/board/nucleo_f303k8/nucleo_f303k8.cpp index ba0e51310..94ef0b1f1 100644 --- a/src/xpcc/architecture/platform/board/nucleo_f303k8/nucleo_f303k8.cpp +++ b/src/xpcc/architecture/platform/board/nucleo_f303k8/nucleo_f303k8.cpp @@ -15,3 +15,26 @@ xpcc::log::Logger xpcc::log::debug(loggerDevice); xpcc::log::Logger xpcc::log::info(loggerDevice); xpcc::log::Logger xpcc::log::warning(loggerDevice); xpcc::log::Logger xpcc::log::error(loggerDevice); + +xpcc_extern_c void +xpcc_abandon(const char * module, + const char * location, + const char * failure, + uintptr_t context) +{ + XPCC_LOG_ERROR << "Assertion '" << module << "." << location << "." << failure << "'"; + if (context) { XPCC_LOG_ERROR << " @ " << (void *) context << " (" << (uint32_t) context << ")"; } + XPCC_LOG_ERROR << " failed! Abandoning..." << xpcc::endl; + + // Since LedD13 is also a GPIO pin, we don't force this pin to output, + // in case something sensitive is connected to this pin. + // The user must "enable" the use of this pin as an LED output, by + // explicitly setting the pin to output in the application. + // Board::LedD13::setOutput(); + while(1) { + Board::LedD13::set(); + xpcc::delayMilliseconds(20); + Board::LedD13::reset(); + xpcc::delayMilliseconds(180); + } +} diff --git a/src/xpcc/architecture/platform/board/nucleo_f401re/nucleo_f401re.cpp b/src/xpcc/architecture/platform/board/nucleo_f401re/nucleo_f401re.cpp index 415b712f8..a34d6eea0 100644 --- a/src/xpcc/architecture/platform/board/nucleo_f401re/nucleo_f401re.cpp +++ b/src/xpcc/architecture/platform/board/nucleo_f401re/nucleo_f401re.cpp @@ -15,3 +15,26 @@ xpcc::log::Logger xpcc::log::debug(loggerDevice); xpcc::log::Logger xpcc::log::info(loggerDevice); xpcc::log::Logger xpcc::log::warning(loggerDevice); xpcc::log::Logger xpcc::log::error(loggerDevice); + +xpcc_extern_c void +xpcc_abandon(const char * module, + const char * location, + const char * failure, + uintptr_t context) +{ + XPCC_LOG_ERROR << "Assertion '" << module << "." << location << "." << failure << "'"; + if (context) { XPCC_LOG_ERROR << " @ " << (void *) context << " (" << (uint32_t) context << ")"; } + XPCC_LOG_ERROR << " failed! Abandoning..." << xpcc::endl; + + // Since LedD13 is also a GPIO pin, we don't force this pin to output, + // in case something sensitive is connected to this pin. + // The user must "enable" the use of this pin as an LED output, by + // explicitly setting the pin to output in the application. + // Board::LedD13::setOutput(); + while(1) { + Board::LedD13::set(); + xpcc::delayMilliseconds(20); + Board::LedD13::reset(); + xpcc::delayMilliseconds(180); + } +} diff --git a/src/xpcc/architecture/platform/board/nucleo_f411re/nucleo_f411re.cpp b/src/xpcc/architecture/platform/board/nucleo_f411re/nucleo_f411re.cpp index 3791fa2c4..48edf16f2 100644 --- a/src/xpcc/architecture/platform/board/nucleo_f411re/nucleo_f411re.cpp +++ b/src/xpcc/architecture/platform/board/nucleo_f411re/nucleo_f411re.cpp @@ -15,3 +15,26 @@ xpcc::log::Logger xpcc::log::debug(loggerDevice); xpcc::log::Logger xpcc::log::info(loggerDevice); xpcc::log::Logger xpcc::log::warning(loggerDevice); xpcc::log::Logger xpcc::log::error(loggerDevice); + +xpcc_extern_c void +xpcc_abandon(const char * module, + const char * location, + const char * failure, + uintptr_t context) +{ + XPCC_LOG_ERROR << "Assertion '" << module << "." << location << "." << failure << "'"; + if (context) { XPCC_LOG_ERROR << " @ " << (void *) context << " (" << (uint32_t) context << ")"; } + XPCC_LOG_ERROR << " failed! Abandoning..." << xpcc::endl; + + // Since LedD13 is also a GPIO pin, we don't force this pin to output, + // in case something sensitive is connected to this pin. + // The user must "enable" the use of this pin as an LED output, by + // explicitly setting the pin to output in the application. + // Board::LedD13::setOutput(); + while(1) { + Board::LedD13::set(); + xpcc::delayMilliseconds(20); + Board::LedD13::reset(); + xpcc::delayMilliseconds(180); + } +} diff --git a/src/xpcc/architecture/platform/board/nucleo_f429zi/nucleo_f429zi.cpp b/src/xpcc/architecture/platform/board/nucleo_f429zi/nucleo_f429zi.cpp index 7d27fcd65..25e122714 100644 --- a/src/xpcc/architecture/platform/board/nucleo_f429zi/nucleo_f429zi.cpp +++ b/src/xpcc/architecture/platform/board/nucleo_f429zi/nucleo_f429zi.cpp @@ -15,3 +15,22 @@ xpcc::log::Logger xpcc::log::debug(loggerDevice); xpcc::log::Logger xpcc::log::info(loggerDevice); xpcc::log::Logger xpcc::log::warning(loggerDevice); xpcc::log::Logger xpcc::log::error(loggerDevice); + +xpcc_extern_c void +xpcc_abandon(const char * module, + const char * location, + const char * failure, + uintptr_t context) +{ + XPCC_LOG_ERROR << "Assertion '" << module << "." << location << "." << failure << "'"; + if (context) { XPCC_LOG_ERROR << " @ " << (void *) context << " (" << (uint32_t) context << ")"; } + XPCC_LOG_ERROR << " failed! Abandoning..." << xpcc::endl; + + Board::LedBlue::setOutput(); + while(1) { + Board::LedBlue::set(); + xpcc::delayMilliseconds(20); + Board::LedBlue::reset(); + xpcc::delayMilliseconds(180); + } +} diff --git a/src/xpcc/architecture/platform/board/stm32f469_discovery/stm32f469_discovery.cpp b/src/xpcc/architecture/platform/board/stm32f469_discovery/stm32f469_discovery.cpp index 6cbdde53b..571b905f7 100644 --- a/src/xpcc/architecture/platform/board/stm32f469_discovery/stm32f469_discovery.cpp +++ b/src/xpcc/architecture/platform/board/stm32f469_discovery/stm32f469_discovery.cpp @@ -44,3 +44,22 @@ xpcc_hook_hardware_init(void) Board::systemClock::enable(); board_initialize_sdram(); } + +xpcc_extern_c void +xpcc_abandon(const char * module, + const char * location, + const char * failure, + uintptr_t context) +{ + XPCC_LOG_ERROR << "Assertion '" << module << "." << location << "." << failure << "'"; + if (context) { XPCC_LOG_ERROR << " @ " << (void *) context << " (" << (uint32_t) context << ")"; } + XPCC_LOG_ERROR << " failed! Abandoning..." << xpcc::endl; + + Board::LedBlue::setOutput(); + while(1) { + Board::LedBlue::set(); + xpcc::delayMilliseconds(20); + Board::LedBlue::reset(); + xpcc::delayMilliseconds(180); + } +} diff --git a/src/xpcc/architecture/platform/board/stm32f746g_discovery/stm32f746g_discovery.cpp b/src/xpcc/architecture/platform/board/stm32f746g_discovery/stm32f746g_discovery.cpp index e41bf4a84..829c8ff7c 100644 --- a/src/xpcc/architecture/platform/board/stm32f746g_discovery/stm32f746g_discovery.cpp +++ b/src/xpcc/architecture/platform/board/stm32f746g_discovery/stm32f746g_discovery.cpp @@ -23,3 +23,27 @@ xpcc::log::Logger xpcc::log::debug(loggerDevice); xpcc::log::Logger xpcc::log::info(loggerDevice); xpcc::log::Logger xpcc::log::warning(loggerDevice); xpcc::log::Logger xpcc::log::error(loggerDevice); + + +xpcc_extern_c void +xpcc_abandon(const char * module, + const char * location, + const char * failure, + uintptr_t context) +{ + XPCC_LOG_ERROR << "Assertion '" << module << "." << location << "." << failure << "'"; + if (context) { XPCC_LOG_ERROR << " @ " << (void *) context << " (" << (uint32_t) context << ")"; } + XPCC_LOG_ERROR << " failed! Abandoning..." << xpcc::endl; + + // Since LedD13 is also a GPIO pin, we don't force this pin to output, + // in case something sensitive is connected to this pin. + // The user must "enable" the use of this pin as an LED output, by + // explicitly setting the pin to output in the application. + // Board::LedD13::setOutput(); + while(1) { + Board::LedD13::set(); + xpcc::delayMilliseconds(20); + Board::LedD13::reset(); + xpcc::delayMilliseconds(180); + } +} diff --git a/src/xpcc/architecture/platform/board/stm32f769i_discovery/stm32f769i_discovery.cpp b/src/xpcc/architecture/platform/board/stm32f769i_discovery/stm32f769i_discovery.cpp index 77c3db0cf..12dab0f70 100644 --- a/src/xpcc/architecture/platform/board/stm32f769i_discovery/stm32f769i_discovery.cpp +++ b/src/xpcc/architecture/platform/board/stm32f769i_discovery/stm32f769i_discovery.cpp @@ -23,3 +23,22 @@ xpcc::log::Logger xpcc::log::debug(loggerDevice); xpcc::log::Logger xpcc::log::info(loggerDevice); xpcc::log::Logger xpcc::log::warning(loggerDevice); xpcc::log::Logger xpcc::log::error(loggerDevice); + +xpcc_extern_c void +xpcc_abandon(const char * module, + const char * location, + const char * failure, + uintptr_t context) +{ + XPCC_LOG_ERROR << "Assertion '" << module << "." << location << "." << failure << "'"; + if (context) { XPCC_LOG_ERROR << " @ " << (void *) context << " (" << (uint32_t) context << ")"; } + XPCC_LOG_ERROR << " failed! Abandoning..." << xpcc::endl; + + Board::LedJ13::setOutput(); + while(1) { + Board::LedJ13::set(); + xpcc::delayMilliseconds(20); + Board::LedJ13::reset(); + xpcc::delayMilliseconds(180); + } +} From 0ce8983d120a23177b591f0107983449b193afff Mon Sep 17 00:00:00 2001 From: Niklas Hauser Date: Mon, 1 May 2017 23:22:30 +0200 Subject: [PATCH 7/7] [assert] Update STM32F469 example. --- examples/stm32f469_discovery/assert/main.cpp | 56 ++++++++++++++----- .../stm32f469_discovery/assert/project.cfg | 3 + 2 files changed, 45 insertions(+), 14 deletions(-) diff --git a/examples/stm32f469_discovery/assert/main.cpp b/examples/stm32f469_discovery/assert/main.cpp index 2629939d7..4791206c7 100644 --- a/examples/stm32f469_discovery/assert/main.cpp +++ b/examples/stm32f469_discovery/assert/main.cpp @@ -1,9 +1,5 @@ #include -#define XPCC_CAN_MODULE_NAME "can" -#define XPCC_IOBUFFER_MODULE_NAME "iobuffer" -#define XPCC_UART_MODULE_NAME "uart" - using namespace Board; static xpcc::Abandonment @@ -12,29 +8,61 @@ test_assertion_handler(const char * module, const char * /* failure */, uintptr_t /* context */) { - if (strcmp(module, XPCC_IOBUFFER_MODULE_NAME) == 0) + if (!strcmp(module, "iobuffer")) { + XPCC_LOG_ERROR << "Ignoring iobuffer full!" << xpcc::endl; return xpcc::Abandonment::Ignore; + } return xpcc::Abandonment::DontCare; } XPCC_ASSERTION_HANDLER(test_assertion_handler); +static xpcc::Abandonment +core_assertion_handler(const char * module, + const char * /* location */, + const char * failure, + uintptr_t context) +{ + if (!memcmp(module, "core\0nvic\0undefined", 19)) { + XPCC_LOG_ERROR.printf("Ignoring undefined IRQ handler %d!\n", context); + return xpcc::Abandonment::Ignore; + } + if (!memcmp(module, "core\0heap", 9)) { + XPCC_LOG_ERROR.printf("Ignoring 'core.heap.%s' of size 0x%x!\n", failure, context); + return xpcc::Abandonment::Ignore; + } + return xpcc::Abandonment::DontCare; +} +XPCC_ASSERTION_HANDLER(core_assertion_handler); + // ---------------------------------------------------------------------------- int main() { Board::initialize(); - xpcc_assert(true, XPCC_CAN_MODULE_NAME, "init", "timeout"); + // trigger an IRQ with undefined handler + NVIC_EnableIRQ(RTC_Alarm_IRQn); + NVIC_SetPendingIRQ(RTC_Alarm_IRQn); - xpcc_assert_debug(false, XPCC_IOBUFFER_MODULE_NAME, "tx", "full"); + // trigger an out of memory + // we definitely don't have 32MB RAM on this board + // returns NULL, asserts in debug mode + volatile void * ptr = malloc(1 << 25); + // returns NULL, asserts in debug mode + ptr = new (std::nothrow) uint8_t[1 << 25]; + // always asserts + ptr = new uint8_t[1 << 25]; + (void) ptr; - xpcc_assert(false, XPCC_UART_MODULE_NAME, "init", "mode"); + // does not fail, should not be optimized away + volatile bool true_condition = true; + xpcc_assert(true_condition, "can", "init", "timeout"); - while(1) - { - LedRed::toggle(); - xpcc::delayMilliseconds(500); - } + // only fails for debug builds, but is ignored anyways + xpcc_assert_debug(false, "iobuffer", "tx", "full"); - return 0; + // "accidentally" return from main, without even returning properly! + // This should be cought by the debug assert core.main.exit! + // while(1) ; + // return 0; } diff --git a/examples/stm32f469_discovery/assert/project.cfg b/examples/stm32f469_discovery/assert/project.cfg index b1ba0515f..59b0d4f74 100644 --- a/examples/stm32f469_discovery/assert/project.cfg +++ b/examples/stm32f469_discovery/assert/project.cfg @@ -1,3 +1,6 @@ [build] board = stm32f469_discovery buildpath = ${xpccpath}/build/stm32f469_discovery/${name} + +[defines] +XPCC_DEBUG_BUILD=1