foxBMS  1.4.0
The foxBMS Battery Management System API Documentation
sbc.c
Go to the documentation of this file.
1 /**
2  *
3  * @copyright © 2010 - 2022, 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 sbc.c
44  * @author foxBMS Team
45  * @date 2020-07-14 (date of creation)
46  * @updated 2022-07-28 (date of last update)
47  * @version v1.4.0
48  * @ingroup DRIVERS
49  * @prefix SBC
50  *
51  * @brief Driver for the SBC module
52  *
53  * @details It must always be used when creating new c source files.
54  *
55  */
56 
57 /*========== Includes =======================================================*/
58 #include "sbc.h"
59 
60 #include "HL_gio.h"
61 
62 #include "os.h"
63 
64 /*========== Macros and Definitions =========================================*/
65 
66 /** Symbolic names to check re-entrance in #SBC_Trigger */
67 typedef enum {
68  SBC_REENTRANCE_NO, /*!< no re-entrance */
69  SBC_REENTRANCE_YES, /*!< re-entrance*/
71 
72 /*========== Static Constant and Variable Definitions =======================*/
73 
74 /*========== Extern Constant and Variable Definitions =======================*/
75 /** state of the SBC module */
77  .timer = 0u, /*!< time in milliseconds before the state machine processes the next state, in counts of 10ms */
78  .stateRequest = SBC_STATE_NO_REQUEST, /*!< current state request made to the state machine */
80  .substate = SBC_ENTRY,
81  .lastState = SBC_STATEMACHINE_UNINITIALIZED,
82  .lastSubstate = SBC_ENTRY,
83  .illegalRequestsCounter = 0u, /*!< counts the number of illegal requests to the SBC state machine */
84  .retryCounter = 0u, /*!< counter to retry subsystem initialization if fails */
85  .requestWatchdogTrigger = 0u, /*!< correct value set during init process */
86  .triggerEntry = 0u, /*!< counter for re-entrance protection (function running flag) */
87  .pFs85xxInstance = &fs85xx_mcuSupervisor, /*!< pointer to FS85xx instance */
88  .watchdogState = SBC_PERIODIC_WATCHDOG_DEACTIVATED,
89  .watchdogPeriod_10ms = 10u,
90 };
91 
92 /*========== Static Function Prototypes =====================================*/
93 
94 /**
95  * @brief Saves the last state and last substate
96  * @param[in,out] pInstance
97  */
98 static void SBC_SaveLastStates(SBC_STATE_s *pInstance);
99 
100 /**
101  * @brief checks the state requests that are made.
102  * @details This function checks the validity of the state requests.
103  * The results of the checked is returned immediately.
104  * @param[in,out] pInstance
105  * @param[in] stateRequest state request to be checked
106  * @return result of the state request that was made, taken from
107  * #SBC_RETURN_TYPE_e
108  */
110 
111 /**
112  * @brief Re-entrance check of SBC state machine trigger function
113  * @details This function is not re-entrant and should only be called time- or
114  * event-triggered. It increments the triggerEntry counter from the
115  * state variable pInstance->triggerEntry. It should never be called
116  * by two different processes, so if it is the case, triggerEntry
117  * should never be higher than 0 when this function is called.
118  * @return #SBC_REENTRANCE_NO if no further instance of the function is
119  * active, otherwise #SBC_REENTRANCE_YES
120  */
122 
123 /**
124  * @brief Transfers the current state request to the state machine.
125  * @details This function takes the current state request from
126  * pInstance->stateRequest and transfers it to the state
127  * machine. It resets the value from stateRequest to
128  * #SBC_STATE_NO_REQUEST
129  * @param[in,out] pInstance
130  * @return retVal current state request, taken from
131  * #SYS_STATE_REQUEST_e
132  */
134 
135 /**
136  * @brief Triggers the watchdog if the timing requires it.
137  * @details This function checks whether the watchdog timer elapses,
138  * and triggers the watchdog in that case.
139  * @param[in,out] pInstance
140  * @return retVal current state request, taken from
141  * #SYS_STATE_REQUEST_e
142  */
143 static bool SBC_TriggerWatchdogIfRequired(SBC_STATE_s *pInstance);
144 
145 /*========== Static Function Implementations ================================*/
146 static void SBC_SaveLastStates(SBC_STATE_s *pInstance) {
147  FAS_ASSERT(pInstance != NULL_PTR);
148 
149  if (pInstance->lastState != pInstance->state) {
150  pInstance->lastState = pInstance->state;
151  pInstance->lastSubstate = pInstance->substate;
152  } else if (pInstance->lastSubstate != pInstance->substate) {
153  pInstance->lastSubstate = pInstance->substate;
154  } else {
155  /* Do not set new substate as nothing changed */
156  ;
157  }
158 }
159 
161  FAS_ASSERT(pInstance != NULL_PTR);
162 
164  if (stateRequest == SBC_STATE_ERROR_REQUEST) {
165  retval = SBC_OK;
166  } else {
167  if (pInstance->stateRequest == SBC_STATE_NO_REQUEST) {
168  /* init only allowed from the uninitialized state */
169  if (stateRequest == SBC_STATE_INIT_REQUEST) {
170  if (pInstance->state == SBC_STATEMACHINE_UNINITIALIZED) {
171  retval = SBC_OK;
172  } else {
173  retval = SBC_ALREADY_INITIALIZED;
174  }
175  } else {
176  retval = SBC_ILLEGAL_REQUEST;
177  }
178  } else {
179  retval = SBC_REQUEST_PENDING;
180  }
181  }
182  return retval;
183 }
184 
186  FAS_ASSERT(pInstance != NULL_PTR);
187 
189 
191  if (!pInstance->triggerEntry) {
192  pInstance->triggerEntry++;
193  } else {
194  isReEntrance = SBC_REENTRANCE_YES;
195  }
197 
198  return isReEntrance;
199 }
200 
202  FAS_ASSERT(pInstance != NULL_PTR);
203 
205 
207  retval = pInstance->stateRequest;
208  pInstance->stateRequest = SBC_STATE_NO_REQUEST;
210 
211  return (retval);
212 }
213 
215  FAS_ASSERT(pInstance != NULL_PTR);
216  bool watchdogHasBeenTriggered = false;
217  if (pInstance->watchdogTrigger > 0u) {
218  pInstance->watchdogTrigger--;
219  if (pInstance->watchdogTrigger == 0u) {
220  if (STD_OK != SBC_TriggerWatchdog(pInstance->pFs85xxInstance)) {
221  /* TODO: Do what if triggering of watchdog fails? */
222  } else {
223  watchdogHasBeenTriggered = true;
224  /* Debug LED Ball V2! :*/
225  /* gioToggleBit(hetPORT1, 1); */
226  /* Reset watchdog counter:
227  * Decremented every SBC_TASK_CYCLE_CONTEXT_MS and checked in next cycle -> Period-1 */
228  pInstance->watchdogTrigger = pInstance->watchdogPeriod_10ms;
229  }
230  }
231  }
232  return watchdogHasBeenTriggered;
233 }
234 
235 /*========== Extern Function Implementations ================================*/
237  FAS_ASSERT(pInstance != NULL_PTR);
238 
240 
242  retVal = SBC_CheckStateRequest(pInstance, stateRequest);
243 
244  if (retVal == SBC_OK) {
245  pInstance->stateRequest = stateRequest;
246  }
248 
249  return (retVal);
250 }
251 
253  FAS_ASSERT(pInstance != NULL_PTR);
254 
255  return pInstance->state;
256 }
257 
258 extern void SBC_Trigger(SBC_STATE_s *pInstance) {
259  FAS_ASSERT(pInstance != NULL_PTR);
260 
262 
263  /* Check re-entrance of function */
264  if (SBC_CheckReEntrance(pInstance) == SBC_REENTRANCE_YES) {
265  return;
266  }
267 
268  /* Periodic watchdog triggering */
270  /* return value is only for unit testing purposes */
271  (void)SBC_TriggerWatchdogIfRequired(pInstance);
272  }
273 
274  if (pInstance->timer > 0u) {
275  if ((--pInstance->timer) > 0u) {
276  pInstance->triggerEntry--;
277  return; /* handle state machine only if timer has elapsed */
278  }
279  }
280 
281  switch (pInstance->state) {
282  /****************************UNINITIALIZED***********************************/
284  /* waiting for Initialization Request */
285  stateRequest = SBC_TransferStateRequest(pInstance);
286  if (stateRequest == SBC_STATE_INIT_REQUEST) {
287  SBC_SaveLastStates(pInstance);
288  pInstance->timer = SBC_STATEMACHINE_SHORTTIME;
290  pInstance->substate = SBC_ENTRY;
291  } else if (stateRequest == SBC_STATE_NO_REQUEST) {
292  /* no actual request pending */
293  } else {
294  pInstance->illegalRequestsCounter++; /* illegal request pending */
295  }
296  break;
297  /****************************INITIALIZATION**********************************/
299  SBC_SaveLastStates(pInstance);
300  /* Initializations done here */
301 
302  if (pInstance->substate == SBC_ENTRY) {
303  /* Init SBC */
305  /* Retry init if it fails */
306  pInstance->retryCounter++;
307  if (pInstance->retryCounter > 3u) {
308  /* Maximum number of retries -> goto error */
309  pInstance->retryCounter = 0u;
310  pInstance->timer = SBC_STATEMACHINE_SHORTTIME;
311  pInstance->state = SBC_STATEMACHINE_ERROR;
312  pInstance->substate = SBC_ENTRY;
313  }
314  } else {
315  /* First part of init successful -> start periodic watchdog triggering */
317  pInstance->watchdogTrigger = pInstance->watchdogPeriod_10ms;
318  pInstance->timer = SBC_STATEMACHINE_SHORTTIME;
320  pInstance->retryCounter = 0u;
321  }
322  } else if (pInstance->substate == SBC_INIT_RESET_FAULT_ERROR_COUNTER_PART1) {
323  /* Fault error counter is reset with valid watchdog refreshes
324  * -> first get required numbers of refreshes */
325  uint8_t requiredWatchdogTrigger = 0;
327  pInstance->pFs85xxInstance, &requiredWatchdogTrigger)) {
328  /* Retry init if it fails */
329  pInstance->retryCounter++;
330  if (pInstance->retryCounter > 3u) {
331  /* Maximum number of retries -> goto error */
332  pInstance->retryCounter = 0;
333  pInstance->timer = SBC_STATEMACHINE_SHORTTIME;
334  pInstance->state = SBC_STATEMACHINE_ERROR;
335  pInstance->substate = SBC_ENTRY;
336  }
337  } else {
338  /* Wait requiredWatchdogTrigger's */
339  pInstance->retryCounter = 0;
340  pInstance->timer = (requiredWatchdogTrigger * pInstance->watchdogPeriod_10ms);
342  }
343  } else if (pInstance->substate == SBC_INIT_RESET_FAULT_ERROR_COUNTER_PART2) {
344  /* Check if fault error counter is zero */
346  pInstance->retryCounter++;
347  if (pInstance->retryCounter > 3u) {
348  /* Goto error state */
349  pInstance->retryCounter = 0;
350  pInstance->state = SBC_STATEMACHINE_ERROR;
351  pInstance->substate = SBC_ENTRY;
352  }
353  pInstance->timer = SBC_STATEMACHINE_SHORTTIME;
354  } else {
356  pInstance->timer = SBC_STATEMACHINE_SHORTTIME;
357  }
358  } else if (pInstance->substate == SBC_INITIALIZE_SAFETY_PATH_CHECK) {
359  if (STD_NOT_OK == FS85_SafetyPathChecks(pInstance->pFs85xxInstance)) {
360  pInstance->retryCounter++;
361  if (pInstance->retryCounter > 3u) {
362  /* Goto error state */
363  pInstance->retryCounter = 0;
364  pInstance->state = SBC_STATEMACHINE_ERROR;
365  pInstance->substate = SBC_ENTRY;
366  }
367  } else {
368  pInstance->retryCounter = 0;
369  pInstance->state = SBC_STATEMACHINE_RUNNING;
370  pInstance->substate = SBC_ENTRY;
371  }
372  pInstance->timer = SBC_STATEMACHINE_SHORTTIME;
373  } else {
375  }
376  break;
377 
378  /****************************RUNNING*************************************/
380  SBC_SaveLastStates(pInstance);
381  pInstance->timer = SBC_STATEMACHINE_LONGTIME;
382  break;
383 
384  /****************************ERROR*************************************/
386  SBC_SaveLastStates(pInstance);
387  pInstance->timer = SBC_STATEMACHINE_LONGTIME;
388  break;
389  /***************************DEFAULT CASE*************************************/
390  default:
391  /* invalid state */
393  break;
394  } /* end switch (sys_systemState.state) */
395  pInstance->triggerEntry--;
396 }
397 
398 /*========== Externalized Static Function Implementations (Unit Test) =======*/
399 #ifdef UNITY_UNIT_TEST
400 extern bool TEST_SBC_TriggerWatchdogIfRequired(SBC_STATE_s *pInstance) {
401  return SBC_TriggerWatchdogIfRequired(pInstance);
402 }
403 #endif
#define FAS_ASSERT(x)
Assertion macro that asserts that x is true.
Definition: fassert.h:252
#define FAS_TRAP
Define that evaluates to essential boolean false thus tripping an assert.
Definition: fassert.h:126
@ STD_NOT_OK
Definition: fstd_types.h:83
@ STD_OK
Definition: fstd_types.h:82
#define NULL_PTR
Null pointer.
Definition: fstd_types.h:76
STD_RETURN_TYPE_e FS85_InitializeNumberOfRequiredWatchdogRefreshes(FS85_STATE_s *pInstance, uint8_t *requiredWatchdogRefreshes)
Calculates the number of required watchdog refresh to reset fault error counter.
Definition: nxpfs85xx.c:882
FS85_STATE_s fs85xx_mcuSupervisor
Definition: nxpfs85xx.c:81
STD_RETURN_TYPE_e FS85_InitializeFsPhase(FS85_STATE_s *pInstance)
Configures SBC during INIT_FS phase.
Definition: nxpfs85xx.c:497
STD_RETURN_TYPE_e SBC_TriggerWatchdog(FS85_STATE_s *pInstance)
Trigger watchdog.
Definition: nxpfs85xx.c:1020
STD_RETURN_TYPE_e FS85_SafetyPathChecks(FS85_STATE_s *pInstance)
Performs SBC safety path checks.
Definition: nxpfs85xx.c:954
STD_RETURN_TYPE_e FS85_CheckFaultErrorCounter(FS85_STATE_s *pInstance)
Checks if fault error counter is zero.
Definition: nxpfs85xx.c:939
Declaration of the OS wrapper interface.
void OS_ExitTaskCritical(void)
Exit Critical interface function for use in FreeRTOS-Tasks and FreeRTOS-ISR.
Definition: os_freertos.c:135
void OS_EnterTaskCritical(void)
Enter Critical interface function for use in FreeRTOS-Tasks and FreeRTOS-ISR.
Definition: os_freertos.c:131
SBC_STATEMACHINE_e SBC_GetState(SBC_STATE_s *pInstance)
gets the current state of passed state variable
Definition: sbc.c:252
static bool SBC_TriggerWatchdogIfRequired(SBC_STATE_s *pInstance)
Triggers the watchdog if the timing requires it.
Definition: sbc.c:214
void SBC_Trigger(SBC_STATE_s *pInstance)
trigger function for the SYS driver state machine.
Definition: sbc.c:258
static void SBC_SaveLastStates(SBC_STATE_s *pInstance)
Saves the last state and last substate.
Definition: sbc.c:146
static SBC_CHECK_REENTRANCE_e SBC_CheckReEntrance(SBC_STATE_s *pInstance)
Re-entrance check of SBC state machine trigger function.
Definition: sbc.c:185
static SBC_RETURN_TYPE_e SBC_CheckStateRequest(SBC_STATE_s *pInstance, SBC_STATE_REQUEST_e stateRequest)
checks the state requests that are made.
Definition: sbc.c:160
SBC_STATE_s sbc_stateMcuSupervisor
Definition: sbc.c:76
static SBC_STATE_REQUEST_e SBC_TransferStateRequest(SBC_STATE_s *pInstance)
Transfers the current state request to the state machine.
Definition: sbc.c:201
SBC_CHECK_REENTRANCE_e
Definition: sbc.c:67
@ SBC_REENTRANCE_YES
Definition: sbc.c:69
@ SBC_REENTRANCE_NO
Definition: sbc.c:68
SBC_RETURN_TYPE_e SBC_SetStateRequest(SBC_STATE_s *pInstance, SBC_STATE_REQUEST_e stateRequest)
sets the current state request of passed state variable
Definition: sbc.c:236
Header for the driver for the SBC module.
SBC_STATEMACHINE_e
Definition: sbc.h:132
@ SBC_STATEMACHINE_RUNNING
Definition: sbc.h:136
@ SBC_STATEMACHINE_UNINITIALIZED
Definition: sbc.h:134
@ SBC_STATEMACHINE_INITIALIZATION
Definition: sbc.h:135
@ SBC_STATEMACHINE_ERROR
Definition: sbc.h:137
SBC_RETURN_TYPE_e
Definition: sbc.h:122
@ SBC_ILLEGAL_REQUEST
Definition: sbc.h:126
@ SBC_REQUEST_PENDING
Definition: sbc.h:125
@ SBC_ALREADY_INITIALIZED
Definition: sbc.h:127
@ SBC_OK
Definition: sbc.h:123
SBC_STATE_REQUEST_e
Definition: sbc.h:109
@ SBC_STATE_INIT_REQUEST
Definition: sbc.h:110
@ SBC_STATE_ERROR_REQUEST
Definition: sbc.h:111
@ SBC_STATE_NO_REQUEST
Definition: sbc.h:112
@ SBC_PERIODIC_WATCHDOG_DEACTIVATED
Definition: sbc.h:118
@ SBC_PERIODIC_WATCHDOG_ACTIVATED
Definition: sbc.h:117
#define SBC_STATEMACHINE_LONGTIME
Definition: sbc.h:101
#define SBC_STATEMACHINE_SHORTTIME
Definition: sbc.h:89
@ SBC_ENTRY
Definition: sbc.h:143
@ SBC_INIT_RESET_FAULT_ERROR_COUNTER_PART2
Definition: sbc.h:145
@ SBC_INITIALIZE_SAFETY_PATH_CHECK
Definition: sbc.h:146
@ SBC_INIT_RESET_FAULT_ERROR_COUNTER_PART1
Definition: sbc.h:144
SBC_STATEMACHINE_SUB_e lastSubstate
Definition: sbc.h:162
FS85_STATE_s * pFs85xxInstance
Definition: sbc.h:168
uint16_t timer
Definition: sbc.h:156
uint8_t triggerEntry
Definition: sbc.h:166
uint16_t watchdogTrigger
Definition: sbc.h:157
SBC_STATE_REQUEST_e stateRequest
Definition: sbc.h:158
SBC_STATEMACHINE_e lastState
Definition: sbc.h:161
SBC_STATEMACHINE_e state
Definition: sbc.h:159
SBC_PERIODIC_WATCHDOG_STATE_e watchdogState
Definition: sbc.h:167
uint32_t illegalRequestsCounter
Definition: sbc.h:163
SBC_STATEMACHINE_SUB_e substate
Definition: sbc.h:160
uint16_t watchdogPeriod_10ms
Definition: sbc.h:169
uint8_t retryCounter
Definition: sbc.h:164