foxBMS - Unit Tests  1.2.0
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 2020-05-26 (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 #pragma SWI_ALIAS(FAS_DisableInterrupts, 5)
100 extern void FAS_DisableInterrupts(void);
101 
102 /**
103  * @brief Define that evaluates to essential boolean false thus tripping
104  * an assert.
105  * @details Call FAS_ASSERT() with this define in order to stop the code
106  * and trip an assertion.
107  */
108 #define FAS_TRAP (0u == 1u)
109 
110 /**
111  * @brief Struct for storing assert information
112  * @details This struct is intended for storing, information on the place
113  * in the code where an assert has been violated.
114  */
115 typedef struct ASSERT_LOC {
116  uint32_t *pc; /*!< value of the program counter register */
117  uint32_t line; /*!< line number where an assert has triggered */
119 
120 /**
121  * @brief Stores the information on the last assert
122  */
124 
125 /**
126  * @brief Copy the assert location into the assert struct.
127  * @details Takes the location of the last assertion and writes it into
128  * #fas_assertLocation.
129  * This definition has to be at this position in order to be used by
130  * the macros below.
131  * If you get issues in a unit test with this being not defined, try
132  * to add this header to the unit tests includes explicitely.
133  * @param[in] pc address of the program counter where the assertion
134  * occurred
135  * @param[in] line line where the assertion occurred
136  */
137 extern void fas_storeAssertLoc(uint32_t *pc, uint32_t line);
138 
139 /**
140  * @def ASSERT_LEVEL_INF_LOOP_AND_DISABLE_INTERRUPTS
141  * @brief This assert level traps the complete program by going into an
142  * infinite loop and disabling all interrupts.
143  *
144  * @def ASSERT_LEVEL_INF_LOOP_FOR_DEBUG
145  * @brief This assert level traps the current task by going into an
146  * infinite loop.
147  *
148  * @def ASSERT_LEVEL_NO_OP
149  * @brief This assert level does nothing (except for the standard recording
150  * of the assert location which does every level).
151  */
152 #define ASSERT_LEVEL_INF_LOOP_AND_DISABLE_INTERRUPTS (0u)
153 #define ASSERT_LEVEL_INF_LOOP_FOR_DEBUG (1u)
154 #define ASSERT_LEVEL_NO_OP (2u)
155 
156 /**
157  * @def ASSERT_LEVEL
158  * @brief Set the assert level to a standard value if not set by the build.
159  */
160 #ifndef ASSERT_LEVEL
161 #define ASSERT_LEVEL ASSERT_LEVEL_INF_LOOP_AND_DISABLE_INTERRUPTS
162 #endif
163 
164 /*============= define how the assert shall behave =============*/
165 #if ASSERT_LEVEL == ASSERT_LEVEL_INF_LOOP_AND_DISABLE_INTERRUPTS
166 /** Assert macro will trigger a watchdog reset */
167 static inline void FAS_infiniteLoop() {
168  /* disable IRQ interrupts */
170  while (1) { /* Stay here until watchdog reset happens */
171  }
172 }
173 #elif ASSERT_LEVEL == ASSERT_LEVEL_INF_LOOP_FOR_DEBUG
174 /** Assert macro will stay in infinite loop */
175 static inline void FAS_infiniteLoop() {
176  while (1) {
177  /* Stay here to ease debugging */
178  }
179 }
180 #elif ASSERT_LEVEL == ASSERT_LEVEL_NO_OP
181 static inline void FAS_infiniteLoop() {
182 }
183 #else
184 #error "Invalid value for ASSERT_LEVEL"
185 #endif
186 
187 /*============= define the recording macro =============*/
188 
189 #ifdef UNITY_UNIT_TEST
190 /**
191  * @def __curpc(x)
192  * @brief replaces in unit test the (platform-specific) function for the retrieval of the program counter
193  */
194 static inline uint32_t __curpc(void) {
195  return 0u;
196 }
197 #endif
198 
199 /**
200  * @brief Record the assert location
201  * @details Retrieves the program counter (with __curpc()) and line-number at
202  * the current location and passes it to #fas_storeAssertLoc().
203  *
204  * It is important that this is a macro in order to insert it directly
205  * at he assert location in the code
206  */
207 #define FAS_ASSERT_RECORD() \
208  do { \
209  void *pc = __curpc(); \
210  fas_storeAssertLoc(pc, __LINE__); \
211  } while (0)
212 
213 /*============= define the assertion-macro =============*/
214 /**
215  * @def FAS_ASSERT(x)
216  * @brief Assertion macro that asserts that x is true
217  * @details This macro asserts the taken argument x. If the assertion fails
218  * it calls #FAS_ASSERT_RECORD() and then #FAS_infiniteLoop().
219  *
220  * In unit tests this is replace by an exception that is thrown in
221  * order to be able to test for a failed assertion.
222  *
223  * Use this macro if you want to assert. If the assertion fails
224  * the macro will take action based on the configuration of this module.
225  * See #ASSERT_LEVEL for reference.
226  *
227  * If the macro passes, it is just ignored. If you want to definitely
228  * fail, you can use the value #FAS_TRAP as an argument which is
229  * designed to fail in all cases.
230  */
231 #ifdef UNITY_UNIT_TEST
232 #include "CException.h"
233 #define FAS_ASSERT(x) \
234  if (!(x)) \
235  Throw(0)
236 #else
237 #define FAS_ASSERT(x) \
238  do { \
239  if (!(x)) { \
240  FAS_ASSERT_RECORD(); \
241  FAS_infiniteLoop(); \
242  } \
243  } while (0)
244 #endif
245 
246 /**
247  * @brief static assertion macro
248  * @details This macro maps static_assert to a compiler intrinsic.
249  * This will fail during compilation if the condition is not
250  * true.
251  */
252 #define static_assert(cond, msg) _Static_assert(cond, msg)
253 
254 /*========== Extern Constant and Variable Declarations ======================*/
255 
256 /*========== Extern Function Prototypes =====================================*/
257 
258 /*========== Externalized Static Functions Prototypes (Unit Test) ===========*/
259 
260 #endif /* FOXBMS__FASSERT_H_ */
static uint32_t __curpc(void)
Definition: fassert.h:194
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
static void FAS_infiniteLoop()
Definition: fassert.h:167
void FAS_DisableInterrupts(void)
Disable interrupts.
Struct for storing assert information.
Definition: fassert.h:115
uint32_t line
Definition: fassert.h:117
uint32_t * pc
Definition: fassert.h:116