Skip to content

Commit

Permalink
[hosted] Add binary error implementation.
Browse files Browse the repository at this point in the history
  • Loading branch information
salkinium committed Sep 10, 2016
1 parent eed15f6 commit 2fc66fd
Show file tree
Hide file tree
Showing 7 changed files with 194 additions and 17 deletions.
57 changes: 49 additions & 8 deletions examples/linux/assert/main.cpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,55 @@
#include <xpcc/architecture/platform.hpp>
#include <xpcc/debug/logger.hpp>

enum
{
CAN_OK = 0,
CAN_ERROR_INIT_TIMEOUT,
CAN_ERROR_RX_MAILBOX_FULL,
CAN_ERROR_TX_MAILBOX_FULL
};

static const char * error_stringify(uint8_t error)
// XPCC_MODULE_ERROR_STRINGIFY("Can")(uint8_t error)
{
switch (error)
{
case CAN_ERROR_INIT_TIMEOUT:
return "init.timeout";
case CAN_ERROR_RX_MAILBOX_FULL:
return "rx.full";
case CAN_ERROR_TX_MAILBOX_FULL:
return "tx.full";
default:
return "unknown";
}
}

__attribute__((section(XPCC_MODULE_ERROR_NAME_LINKER_SECTION), used))
const xpcc_module_error_stringify_t
module_error_stringify = {"Can", error_stringify};

xpcc_extern_c uint8_t xpcc_get_module_id_from_stringify(const xpcc_module_error_stringify_t * const module);
static inline uint8_t module_id() { return xpcc_get_module_id_from_stringify(&module_error_stringify); }

namespace CanModule
{
uint8_t id()
{
return module_id();
}

xpcc_error_t create_error(uint8_t error)
{
return {id(), error};
}
}

static xpcc::Abandonment
test_assertion_handler(const char *id)
test_assertion_handler(xpcc_error_t error)
{
if (strncmp(id, "iobuffer", 8) == 0)
return xpcc::Abandonment::Ignore;
if (error.module == CanModule::id())
return xpcc::Abandonment::Fail;
return xpcc::Abandonment::DontCare;
}
XPCC_ASSERTION_HANDLER(test_assertion_handler);
Expand All @@ -13,11 +58,7 @@ XPCC_ASSERTION_HANDLER(test_assertion_handler);
int
main()
{
xpcc_assert(true, "can.init");

xpcc_assert_debug(false, "iobuffer.full");

xpcc_assert(false, "uart.init");
xpcc_assert(false, CanModule::create_error(CAN_ERROR_INIT_TIMEOUT));

return 0;
}
8 changes: 5 additions & 3 deletions src/xpcc/architecture/interface/assert.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <stdint.h>
#include <xpcc/architecture/utils.hpp>
#include <xpcc/utils/bit_constants.hpp>
#include "error.hpp"

/**
* @ingroup interface
Expand All @@ -37,7 +38,8 @@ Abandonment : uint8_t
Fail = Bit2 ///< This failure is reason for abandonment
};

using AssertionHandler = Abandonment (*)(const char * identifier);
/// @ingroup assert
using AssertionHandler = Abandonment (*)(xpcc_error_t error);

} // namespace xpcc

Expand Down Expand Up @@ -66,9 +68,9 @@ using AssertionHandler = Abandonment (*)(const char * identifier);

extern "C" {

void xpcc_assert(bool condition, const char * identifier);
void xpcc_assert(bool condition, xpcc_error_t error);

void xpcc_abandon(const char * identifier);
void xpcc_abandon(xpcc_error_t error);

}

Expand Down
70 changes: 70 additions & 0 deletions src/xpcc/architecture/interface/error.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// coding: utf-8
/* Copyright (c) 2016, Roboterclub Aachen e.V.
* 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_ERROR_HPP
#define XPCC_ERROR_HPP

#include <stdint.h>
#include <xpcc/architecture/utils.hpp>

/**
* @ingroup interface
* @defgroup error Errors
*
* Errors at runtime
*
* @see driver
* @author Niklas Hauser
*/

#if defined XPCC__CPU_ARM || defined XPCC__CPU_AVR
# define XPCC_MODULE_ERROR_NAME_LINKER_SECTION ".errorname"
#elif defined XPCC__OS_OSX
# define XPCC_MODULE_ERROR_NAME_LINKER_SECTION "__DATA,xpcc_errorname"
#elif defined XPCC__OS_LINUX
# define XPCC_MODULE_ERROR_NAME_LINKER_SECTION "xpcc_errorname"
#endif

xpcc_extern_c_begin

typedef struct
{
uint8_t module;
uint8_t error;
} xpcc_error_t;

typedef struct
{
const char * module_name;
const char * (*stringify)(uint8_t error);
} xpcc_module_error_stringify_t;

const char * xpcc_error_module(xpcc_error_t error);
const char * xpcc_error_stringify(xpcc_error_t error);

xpcc_extern_c_end

#ifdef XPCC_ERROR_LINKER_SECTION
# define XPCC_MODULE_ERROR_STRINGIFY(module_name) \
static const char * error_stringify(xpcc_error_t); \
\
__attribute__((section(XPCC_MODULE_ERROR_NAME_LINKER_SECTION), used)) \
static const xpcc_module_error_stringify_t \
module_error_stringify = {module_name, error_stringify}; \
\
xpcc_extern_c uint8_t xpcc_get_module_id_from_stringify(const xpcc_module_error_stringify_t * module); \
static inline uint8_t module_id() { return xpcc_get_module_id_from_stringify(&module_error_stringify); } \
\
const char * error_stringify
#else
# define XPCC_MODULE_ERROR_STRINGIFY(module_name) \
const char * error_stringify
#endif

#endif // XPCC_ASSERT_HPP
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,12 @@ SECTIONS
__assertion_table_end = .;
. = ALIGN (4);

/* Module error names. */
__errorname_table_start = .;
KEEP(*(.error_modname))
__errorname_table_end = .;
. = ALIGN (4);

/* Position independent code will call non-static functions via the
* Procedure Linkage Table or PLT. This PLT does not exist in .o files.
* In a .o file, use of the PLT is indicated by a special relocation.
Expand Down
12 changes: 6 additions & 6 deletions src/xpcc/architecture/platform/driver/core/hosted/assert.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ extern AssertionHandler __assertion_table_end __asm("__stop_xpcc_assertion");

extern "C" {

void xpcc_assert(bool condition, const char *identifier)
void xpcc_assert(bool condition, xpcc_error_t error)
{
if (!condition)
{
Expand All @@ -33,21 +33,21 @@ void xpcc_assert(bool condition, const char *identifier)
AssertionHandler * handler = &__assertion_table_start;
for (; handler < &__assertion_table_end; handler++)
{
state |= (uint8_t) (*handler)(identifier);
state |= (uint8_t) (*handler)(error);
}

if (state == (uint8_t) Abandonment::DontCare or
state & (uint8_t) Abandonment::Fail)
{
xpcc_abandon(identifier);
xpcc_abandon(error);
}
}
}

void xpcc_abandon(const char *identifier) __attribute__((weak));
void xpcc_abandon(const char *identifier)
void xpcc_abandon(xpcc_error_t error) __attribute__((weak));
void xpcc_abandon(xpcc_error_t error)
{
XPCC_LOG_ERROR << "Assertion '" << identifier << "' failed! Abandoning." << xpcc::endl;
XPCC_LOG_ERROR << "Module '" << xpcc_error_module(error) << "' failed assertion '" << xpcc_error_stringify(error) << "'! Abandoning." << xpcc::endl;
exit(1);
}

Expand Down
47 changes: 47 additions & 0 deletions src/xpcc/architecture/platform/driver/core/hosted/error.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// coding: utf-8
/* Copyright (c) 2016, Roboterclub Aachen e.V.
* 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.
*/
// ----------------------------------------------------------------------------

#include <stdlib.h>
#include <xpcc/debug/logger.hpp>
#include <xpcc/architecture/interface/error.hpp>

#ifdef XPCC__OS_OSX
extern xpcc_module_error_stringify_t __errorname_table_start __asm("section$start$__DATA$xpcc_errorname");
extern xpcc_module_error_stringify_t __errorname_table_end __asm("section$end$__DATA$xpcc_errorname");
#else
extern xpcc_module_error_stringify_t __errorname_table_start __asm("__start_xpcc_errorname");
extern xpcc_module_error_stringify_t __errorname_table_end __asm("__stop_xpcc_errorname");
#endif

extern "C" {

static uint8_t number_of_error_modules = 0;

uint8_t xpcc_get_module_id_from_stringify(const xpcc_module_error_stringify_t * const module)
{
number_of_error_modules = &__errorname_table_end - &__errorname_table_start;

if (module < &__errorname_table_start || &__errorname_table_end <= module) return -1;
return (module - &__errorname_table_start);
}

const char * xpcc_error_module(xpcc_error_t error)
{
if (error.module >= number_of_error_modules) return "Invalid";

return (&__errorname_table_start)[error.module].module_name;
}
const char * xpcc_error_stringify(xpcc_error_t error)
{
if (error.module >= number_of_error_modules) return "Invalid";
if (error.error == 0) return "Ok";
return (&__errorname_table_start)[error.module].stringify(error.error);
}

}
11 changes: 11 additions & 0 deletions src/xpcc/architecture/utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,10 +114,20 @@
#define XPCC_CONCAT5_(a,b,c,d,e) XPCC_CONCAT5__(a,b,c,d,e)
#define XPCC_CONCAT5__(a,b,c,d,e) a ## b ## c ## d ## e

#ifdef __cplusplus
# define xpcc_extern_c extern "C"
# define xpcc_extern_c_begin extern "C" {
# define xpcc_extern_c_end }
#else
# define xpcc_extern_c extern
# define xpcc_extern_c_begin
# define xpcc_extern_c_end
#endif

#if defined(XPCC__COMPILER_GCC) || defined(XPCC__COMPILER_CLANG)
# define xpcc_always_inline inline __attribute__((always_inline))
# define xpcc_unused __attribute__((unused))
# define xpcc_used __attribute__((used))
# define xpcc_weak __attribute__((weak))
# define xpcc_aligned(n) __attribute__((aligned(n)))
# define xpcc_packed __attribute__((packed))
Expand All @@ -129,6 +139,7 @@
#else
# define xpcc_always_inline inline
# define xpcc_unused
# define xpcc_used
# define xpcc_weak
# define xpcc_aligned(n)
# define xpcc_packed
Expand Down

0 comments on commit 2fc66fd

Please sign in to comment.