foxBMS - Unit Tests  1.2.1
The foxBMS Unit Tests API Documentation
fassert.h
Go to the documentation of this file.
1 /**
2  *
3  * @copyright © 2010 - 2021, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright notice, this
12  * list of conditions and the following disclaimer.
13  *
14  * 2. Redistributions in binary form must reproduce the above copyright notice,
15  * this list of conditions and the following disclaimer in the documentation
16  * and/or other materials provided with the distribution.
17  *
18  * 3. Neither the name of the copyright holder nor the names of its
19  * contributors may be used to endorse or promote products derived from
20  * this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  *
33  * We kindly request you to use one or more of the following phrases to refer to
34  * foxBMS in your hardware, software, documentation or advertising materials:
35  *
36  * - ″This product uses parts of foxBMS®″
37  * - ″This product includes parts of foxBMS®″
38  * - ″This product is derived from foxBMS®″
39  *
40  */
41 
42 /**
43  * @file fassert.h
44  * @author foxBMS Team
45  * @date 2020-03-20 (date of creation)
46  * @updated 2021-11-10 (date of last update)
47  * @ingroup ASSERT
48  * @prefix FAS
49  *
50  * @brief Assert macro implementation
51  *
52  * @details The default implementation accommodates three behaviors,
53  * based on ASSERT_LEVEL symbol:
54  *
55  * - When the ASSERT_LEVEL symbol is defined as
56  * ASSERT_LEVEL_INF_LOOP_AND_DISABLE_INTERRUPTS, the FAS_ASSERT macro is
57  * implemented as an infinite loop in which all interrupts are disabled. This
58  * will definitely trigger a watchdog reset.
59  *
60  * - When ASSERT_LEVEL symbol is defined as ASSERT_LEVEL_INF_LOOP_FOR_DEBUG,
61  * the validation performed by the FAS_ASSERT macro is enabled, and a failed
62  * validation triggers an infinite loop. This configuration is recommended
63  * for development environments, as it prevents further execution. Depending
64  * on the configuration this might lead to a watchdog reset. This mode is
65  * intended for investigation of problems by a developer.
66  *
67  * - When ASSERT_LEVEL symbol is defined as ASSERT_LEVEL_NO_OP, the FAS_ASSERT
68  * macro is defined as empty and does nothing. It might be necessary to
69  * activate this mode in ressource-constrained situations. Generally it is
70  * not recommended to use this option as it will not notice the undefined
71  * system-states that the assert should catch.
72  *
73  *
74  * Generally assertions should be used for asserting states and values that
75  * should occur when the program is executed correctly. Do *not* assert
76  * anything that *might* be false. As an example it is perfectly good
77  * practice to assert that the input to a function is not a null pointer
78  * if the function is not designed to accept null pointers, but it is not
79  * good to check if a communication error has occurred somewhere. Assertions
80  * should never trip in a bug-free program.
81  *
82  * Usage is FAS_ASSERT(condition that should be true).
83  */
84 
85 #ifndef FOXBMS__FASSERT_H_
86 #define FOXBMS__FASSERT_H_
87 
88 /*========== Includes =======================================================*/
89 #include <stdint.h>
90 
91 /*========== Macros and Definitions =========================================*/
92 /**
93  * @brief Disable interrupts
94  * @details This alias is mapped to an ASM function and disables all interrupts
95  * by writing to the SPSR (Saved Program Status Register) register
96  * through the control field mask byte PSR[7:0] (privileged
97  * software execution)
98  */
99 /* AXIVION Disable Style MisraC2012Directive-4.1: Function is implemented in Assembler see swiPortDisableInterrupts */
100 #pragma SWI_ALIAS(FAS_DisableInterrupts, 5)
101 extern void FAS_DisableInterrupts(void);
102 /* AXIVION Enable Style MisraC2012Directive-4.1: */
103 
104 /**
105  * @brief Define that evaluates to essential boolean false thus tripping
106  * an assert.
107  * @details Call FAS_ASSERT() with this define in order to stop the code
108  * and trip an assertion.
109  */
110 #define FAS_TRAP (0u == 1u)
111 
112 /**
113  * @brief Struct for storing assert information
114  * @details This struct is intended for storing, information on the place
115  * in the code where an assert has been violated.
116  */
117 typedef struct ASSERT_LOC {
118  uint32_t *pc; /*!< value of the program counter register */
119  uint32_t line; /*!< line number where an assert has triggered */
121 
122 /**
123  * @brief Stores the information on the last assert
124  */
126 
127 /**
128  * @brief Copy the assert location into the assert struct.
129  * @details Takes the location of the last assertion and writes it into
130  * #fas_assertLocation.
131  * This definition has to be at this position in order to be used by
132  * the macros below.
133  * If you get issues in a unit test with this being not defined, try
134  * to add this header to the unit tests includes explicitely.
135  * @param[in] pc address of the program counter where the assertion
136  * occurred
137  * @param[in] line line where the assertion occurred
138  */
139 extern void fas_storeAssertLoc(uint32_t *pc, uint32_t line);
140 
141 /**
142  * @def ASSERT_LEVEL_INF_LOOP_AND_DISABLE_INTERRUPTS
143  * @brief This assert level traps the complete program by going into an
144  * infinite loop and disabling all interrupts.
145  *
146  * @def ASSERT_LEVEL_INF_LOOP_FOR_DEBUG
147  * @brief This assert level traps the current task by going into an
148  * infinite loop.
149  *
150  * @def ASSERT_LEVEL_NO_OP
151  * @brief This assert level does nothing (except for the standard recording
152  * of the assert location which does every level).
153  */
154 #define ASSERT_LEVEL_INF_LOOP_AND_DISABLE_INTERRUPTS (0u)
155 #define ASSERT_LEVEL_INF_LOOP_FOR_DEBUG (1u)
156 #define ASSERT_LEVEL_NO_OP (2u)
157 
158 /**
159  * @def ASSERT_LEVEL
160  * @brief Set the assert level to a standard value if not set by the build.
161  */
162 #ifndef ASSERT_LEVEL
163 #define ASSERT_LEVEL ASSERT_LEVEL_INF_LOOP_AND_DISABLE_INTERRUPTS
164 #endif
165 
166 /*============= define how the assert shall behave =============*/
167 #if ASSERT_LEVEL == ASSERT_LEVEL_INF_LOOP_AND_DISABLE_INTERRUPTS
168 /** Assert macro will trigger a watchdog reset */
169 static inline void FAS_InfiniteLoop(void) {
170  /* disable IRQ interrupts */
172  while (1) { /* Stay here until watchdog reset happens */
173  }
174 }
175 #elif ASSERT_LEVEL == ASSERT_LEVEL_INF_LOOP_FOR_DEBUG
176 /** Assert macro will stay in infinite loop */
177 static inline void FAS_InfiniteLoop(void) {
178  while (1) {
179  /* Stay here to ease debugging */
180  }
181 }
182 #elif ASSERT_LEVEL == ASSERT_LEVEL_NO_OP
183 static inline void FAS_InfiniteLoop(void) {
184 }
185 #else
186 #error "Invalid value for ASSERT_LEVEL"
187 #endif
188 
189 /*============= define the recording macro =============*/
190 
191 #ifdef UNITY_UNIT_TEST
192 /**
193  * @def __curpc(x)
194  * @brief replaces in unit test the (platform-specific) function for the retrieval of the program counter
195  */
196 static inline uint32_t __curpc(void) {
197  return 0u;
198 }
199 #endif
200 
201 /**
202  * @brief Record the assert location
203  * @details Retrieves the program counter (with __curpc()) and line-number at
204  * the current location and passes it to #fas_storeAssertLoc().
205  *
206  * It is important that this is a macro in order to insert it directly
207  * at he assert location in the code
208  */
209 #define FAS_ASSERT_RECORD() \
210  do { \
211  void *pc = __curpc(); \
212  fas_storeAssertLoc(pc, __LINE__); \
213  } while (0)
214 
215 /*============= define the assertion-macro =============*/
216 /**
217  * @def FAS_ASSERT(x)
218  * @brief Assertion macro that asserts that x is true
219  * @details This macro asserts the taken argument x. If the assertion fails
220  * it calls #FAS_ASSERT_RECORD() and then #FAS_InfiniteLoop().
221  *
222  * In unit tests this is replace by an exception that is thrown in
223  * order to be able to test for a failed assertion.
224  *
225  * Use this macro if you want to assert. If the assertion fails
226  * the macro will take action based on the configuration of this module.
227  * See #ASSERT_LEVEL for reference.
228  *
229  * If the macro passes, it is just ignored. If you want to definitely
230  * fail, you can use the value #FAS_TRAP as an argument which is
231  * designed to fail in all cases.
232  */
233 #ifdef UNITY_UNIT_TEST
234 #include "CException.h"
235 #define FAS_ASSERT(x) \
236  if (!(x)) \
237  Throw(0)
238 #else
239 #define FAS_ASSERT(x) \
240  do { \
241  if (!(x)) { \
242  FAS_ASSERT_RECORD(); \
243  FAS_InfiniteLoop(); \
244  } \
245  } while (0)
246 #endif
247 
248 /**
249  * @brief static assertion macro
250  * @details This macro maps static_assert to a compiler intrinsic.
251  * This will fail during compilation if the condition is not
252  * true.
253  */
254 #define static_assert(cond, msg) _Static_assert(cond, msg)
255 
256 /*========== Extern Constant and Variable Declarations ======================*/
257 
258 /*========== Extern Function Prototypes =====================================*/
259 
260 /*========== Externalized Static Functions Prototypes (Unit Test) ===========*/
261 
262 #endif /* FOXBMS__FASSERT_H_ */
static uint32_t __curpc(void)
Definition: fassert.h:196
ASSERT_LOC_s fas_assertLocation
Stores the information on the last assert.
Definition: fassert.c:63
struct ASSERT_LOC ASSERT_LOC_s
Struct for storing assert information.
void fas_storeAssertLoc(uint32_t *pc, uint32_t line)
Copy the assert location into the assert struct.
Definition: fassert.c:70
void FAS_DisableInterrupts(void)
Disable interrupts.
static void FAS_InfiniteLoop(void)
Definition: fassert.h:169
Struct for storing assert information.
Definition: fassert.h:117
uint32_t line
Definition: fassert.h:119
uint32_t * pc
Definition: fassert.h:118