From fc4047e4b4b38c6c778f2d5f71c7412ecbab3152 Mon Sep 17 00:00:00 2001 From: Tomaz Solc Date: Mon, 24 Sep 2012 12:54:53 +0200 Subject: Add assert macros to aid in debugging. Adds libopencm3/cm3/assert.h header that provides assertion check macros similar to those provided by the standard C library. Thanks to Nicolas Schodet for help. --- include/libopencm3/cm3/assert.h | 136 ++++++++++++++++++++++++++++++++++++++++ lib/cm3/assert.c | 34 ++++++++++ lib/lm3s/Makefile | 4 +- lib/lpc13xx/Makefile | 4 +- lib/lpc17xx/Makefile | 4 +- lib/lpc43xx/Makefile | 5 +- lib/stm32/f1/Makefile | 4 +- lib/stm32/f1/rcc.c | 4 +- lib/stm32/f2/Makefile | 4 +- lib/stm32/f2/rcc.c | 4 +- lib/stm32/f4/Makefile | 3 +- lib/stm32/f4/rcc.c | 4 +- 12 files changed, 191 insertions(+), 19 deletions(-) create mode 100644 include/libopencm3/cm3/assert.h create mode 100644 lib/cm3/assert.c diff --git a/include/libopencm3/cm3/assert.h b/include/libopencm3/cm3/assert.h new file mode 100644 index 0000000..0ccb0f7 --- /dev/null +++ b/include/libopencm3/cm3/assert.h @@ -0,0 +1,136 @@ +/** @defgroup debugging Debugging + +@brief Macros and functions to aid in debugging + +@version 1.0.0 + +@date 25 September 2012 + +Two preprocessor defines control the behavior of assertion check macros in +this module. They allow the choice between generated code size and ease of +debugging. + +If NDEBUG is defined, all assertion checks are disabled and macros do not +generate any code. + +If CM3_ASSERT_VERBOSE is defined, information regarding the position of +assertion checks will be stored in the binary, allowing for more +informative error messages, but also significantly increased code size. As +default assertion checks do not use this information it is only useful if +the application linked with libopencm3 defines its own +cm3_assert_failed_verbose() implementation. + +LGPL License Terms @ref lgpl_license +*/ + +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2012 Tomaz Solc + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +/**@{*/ + +#ifndef LIBOPENCM3_CM3_ASSERT_H +#define LIBOPENCM3_CM3_ASSERT_H + +#include + +#define CM3_LIKELY(expr) (__builtin_expect (!!(expr), 1)) + +#ifdef NDEBUG +# define cm3_assert(expr) do { (void)0; } while(0) +# define cm3_assert_not_reached() while(1) +#else +# ifdef CM3_ASSERT_VERBOSE +# define cm3_assert(expr) do { \ + if(CM3_LIKELY(expr)) { (void)0; } else { \ + cm3_assert_failed_verbose( \ + __FILE__, __LINE__, \ + __func__, #expr); \ + } \ + } while(0) +# define cm3_assert_not_reached() do { \ + cm3_assert_failed_verbose( \ + __FILE__, __LINE__, \ + __func__, 0); \ + } while(0) +# else +/** @brief Check if assertion is true. + * + * If NDEBUG macro is defined, this macro generates no code. Otherwise + * cm3_assert_failed() or cm3_assert_failed_verbose() is called if assertion + * is false. + * + * The purpose of this macro is to aid in debugging libopencm3 and + * applications using it. It can be used for example to check if function + * arguments are within expected ranges and stop execution in case an + * unexpected state is reached. + * + * @param expr expression to check */ +# define cm3_assert(expr) do { \ + if(CM3_LIKELY(expr)) { (void)0; } else { \ + cm3_assert_failed(); \ + } \ + } while(0) +/** @brief Check if unreachable code is reached. + * + * If NDEBUG macro is defined, this macro generates code for an infinite loop. + * Otherwise cm3_assert_failed() or cm3_assert_failed_verbose() is called if + * the macro is ever reached. + * + * The purpose of this macro is to aid in debugging libopencm3 and + * applications using it. It can be used for example to stop execution if an + * unreachable portion of code is reached. */ +# define cm3_assert_not_reached() do { \ + cm3_assert_failed(); \ + } while(0) +# endif +#endif + +BEGIN_DECLS + +/** @brief Called on a failed assertion. + * + * Halts execution in an infinite loop. This function never returns. + * + * Defined as a weak symbol, so applications can define their own + * implementation. Usually, a custom implementation of this function should + * report an error in some way (print a message to a debug console, display, + * LED, ...) and halt execution or reboot the device. */ +void cm3_assert_failed(void) __attribute__ ((__noreturn__)); + +/** @brief Called on a failed assertion with verbose messages enabled. + * + * Halts execution in an infinite loop. This function never returns. + * + * Defined as a weak symbol, so applications can define their own + * implementation. Usually, a custom implementation of this function should + * report an error in some way (print a message to a debug console, display, + * LED, ...) and halt execution or reboot the device. + * + * @param file File name where the failed assertion occurred + * @param line Line number where the failed assertion occurred + * @param func Name of the function where the failed assertion occurred + * @param assert_expr Expression that evaluated to false (can be NULL) */ +void cm3_assert_failed_verbose(const char *file, int line, const char *func, + const char *assert_expr) __attribute__ ((__noreturn__)); + +END_DECLS + +#endif + +/**@}*/ diff --git a/lib/cm3/assert.c b/lib/cm3/assert.c new file mode 100644 index 0000000..d76c578 --- /dev/null +++ b/lib/cm3/assert.c @@ -0,0 +1,34 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2012 Tomaz Solc + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +#include + +void __attribute__((weak)) cm3_assert_failed(void) +{ + while(1); +} + +void __attribute__((weak)) cm3_assert_failed_verbose( + const char *file __attribute__((unused)), + int line __attribute__((unused)), + const char *func __attribute__((unused)), + const char *assert_expr __attribute__((unused))) +{ + cm3_assert_failed(); +} diff --git a/lib/lm3s/Makefile b/lib/lm3s/Makefile index bdad3a4..e471a00 100644 --- a/lib/lm3s/Makefile +++ b/lib/lm3s/Makefile @@ -28,8 +28,8 @@ CFLAGS = -Os -g -Wall -Wextra -I../../include -fno-common \ -ffunction-sections -fdata-sections -MD # ARFLAGS = rcsv ARFLAGS = rcs -OBJS = gpio.o vector.o +OBJS = gpio.o vector.o assert.o -# VPATH += ../usb +VPATH += ../cm3 include ../Makefile.include diff --git a/lib/lpc13xx/Makefile b/lib/lpc13xx/Makefile index 158a5bf..e1e69f7 100644 --- a/lib/lpc13xx/Makefile +++ b/lib/lpc13xx/Makefile @@ -28,8 +28,8 @@ CFLAGS = -Os -g -Wall -Wextra -I../../include -fno-common \ -ffunction-sections -fdata-sections -MD # ARFLAGS = rcsv ARFLAGS = rcs -OBJS = gpio.o +OBJS = gpio.o assert.o -# VPATH += ../usb +VPATH += ../cm3 include ../Makefile.include diff --git a/lib/lpc17xx/Makefile b/lib/lpc17xx/Makefile index f688716..d1da64a 100644 --- a/lib/lpc17xx/Makefile +++ b/lib/lpc17xx/Makefile @@ -28,8 +28,8 @@ CFLAGS = -O0 -g -Wall -Wextra -I../../include -fno-common \ -ffunction-sections -fdata-sections -MD # ARFLAGS = rcsv ARFLAGS = rcs -OBJS = gpio.o vector.o +OBJS = gpio.o vector.o assert.o -# VPATH += ../usb +VPATH += ../cm3 include ../Makefile.include diff --git a/lib/lpc43xx/Makefile b/lib/lpc43xx/Makefile index 67e74d7..6e08ea0 100644 --- a/lib/lpc43xx/Makefile +++ b/lib/lpc43xx/Makefile @@ -31,8 +31,9 @@ CFLAGS = -O2 -g3 -Wall -Wextra -I../../include -fno-common \ -mfloat-abi=hard -mfpu=fpv4-sp-d16 # ARFLAGS = rcsv ARFLAGS = rcs -OBJS = gpio.o vector.o scu.o i2c.o ssp.o nvic.o systick.o +OBJS = gpio.o vector.o scu.o i2c.o ssp.o nvic.o systick.o \ + assert.o -# VPATH += ../usb +VPATH += ../cm3 include ../Makefile.include diff --git a/lib/stm32/f1/Makefile b/lib/stm32/f1/Makefile index 3b4252b..4fdbf43 100644 --- a/lib/stm32/f1/Makefile +++ b/lib/stm32/f1/Makefile @@ -31,9 +31,9 @@ ARFLAGS = rcs OBJS = vector.o rcc.o gpio.o usart.o adc.o spi.o flash.o nvic.o \ rtc.o i2c.o dma.o systick.o exti.o scb.o ethernet.o \ usb_f103.o usb.o usb_control.o usb_standard.o can.o \ - timer.o usb_f107.o desig.o crc.o + timer.o usb_f107.o desig.o crc.o assert.o -VPATH += ../../usb:../ +VPATH += ../../usb:../:../../cm3 include ../../Makefile.include diff --git a/lib/stm32/f1/rcc.c b/lib/stm32/f1/rcc.c index 5fd9c62..ab3350b 100644 --- a/lib/stm32/f1/rcc.c +++ b/lib/stm32/f1/rcc.c @@ -48,6 +48,7 @@ LGPL License Terms @ref lgpl_license /**@{*/ +#include #include #include @@ -166,8 +167,7 @@ int rcc_osc_ready_int_flag(osc_t osc) break; } - /* Shouldn't be reached. */ - return -1; + cm3_assert_not_reached(); } /*-----------------------------------------------------------------------------*/ diff --git a/lib/stm32/f2/Makefile b/lib/stm32/f2/Makefile index bd6f275..c127d61 100644 --- a/lib/stm32/f2/Makefile +++ b/lib/stm32/f2/Makefile @@ -29,8 +29,8 @@ CFLAGS = -Os -g -Wall -Wextra -I../../../include -fno-common \ # ARFLAGS = rcsv ARFLAGS = rcs OBJS = vector.o rcc.o gpio.o usart.o spi.o flash.o nvic.o \ - i2c.o systick.o exti.o scb.o timer.o \ + i2c.o systick.o exti.o scb.o timer.o assert.o -VPATH += ../../usb:../ +VPATH += ../../usb:../:../../cm3 include ../../Makefile.include diff --git a/lib/stm32/f2/rcc.c b/lib/stm32/f2/rcc.c index 9461a24..cc2c9bb 100644 --- a/lib/stm32/f2/rcc.c +++ b/lib/stm32/f2/rcc.c @@ -19,6 +19,7 @@ * along with this library. If not, see . */ +#include #include #include @@ -125,8 +126,7 @@ int rcc_osc_ready_int_flag(osc_t osc) break; } - /* Shouldn't be reached. */ - return -1; + cm3_assert_not_reached(); } void rcc_css_int_clear(void) diff --git a/lib/stm32/f4/Makefile b/lib/stm32/f4/Makefile index 5760d29..85870a7 100644 --- a/lib/stm32/f4/Makefile +++ b/lib/stm32/f4/Makefile @@ -31,7 +31,8 @@ ARFLAGS = rcs OBJS = vector.o rcc.o gpio.o usart.o spi.o flash.o nvic.o \ i2c.o systick.o exti.o scb.o pwr.o timer.o \ usb.o usb_standard.o usb_control.o usb_f107.o \ + assert.o -VPATH += ../../usb:../ +VPATH += ../../usb:../:../../cm3 include ../../Makefile.include diff --git a/lib/stm32/f4/rcc.c b/lib/stm32/f4/rcc.c index 6294ff7..f506d4b 100644 --- a/lib/stm32/f4/rcc.c +++ b/lib/stm32/f4/rcc.c @@ -19,6 +19,7 @@ * along with this library. If not, see . */ +#include #include #include #include @@ -139,8 +140,7 @@ int rcc_osc_ready_int_flag(osc_t osc) break; } - /* Shouldn't be reached. */ - return -1; + cm3_assert_not_reached(); } void rcc_css_int_clear(void) -- cgit v1.2.3