foxBMS  1.6.0
The foxBMS Battery Management System API Documentation
sbc.c
Go to the documentation of this file.
1 /**
2  *
3  * @copyright © 2010 - 2023, 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 2023-10-12 (date of last update)
47  * @version v1.6.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 #include <stdint.h>
65 
66 /*========== Macros and Definitions =========================================*/
67 
68 /** Symbolic names to check re-entrance in #SBC_Trigger */
69 typedef enum {
70  SBC_REENTRANCE_NO, /*!< no re-entrance */
71  SBC_REENTRANCE_YES, /*!< re-entrance*/
73 
74 /*========== Static Constant and Variable Definitions =======================*/
75 
76 /*========== Extern Constant and Variable Definitions =======================*/
77 /** state of the SBC module */
79  .timer = 0u, /*!< time in milliseconds before the state machine processes the next state, in counts of 10ms */
80  .stateRequest = SBC_STATE_NO_REQUEST, /*!< current state request made to the state machine */
82  .substate = SBC_ENTRY,
83  .lastState = SBC_STATEMACHINE_UNINITIALIZED,
84  .lastSubstate = SBC_ENTRY,
85  .illegalRequestsCounter = 0u, /*!< counts the number of illegal requests to the SBC state machine */
86  .retryCounter = 0u, /*!< counter to retry subsystem initialization if fails */
87  .requestWatchdogTrigger = 0u, /*!< correct value set during init process */
88  .triggerEntry = 0u, /*!< counter for re-entrance protection (function running flag) */
89  .pFs85xxInstance = &fs85xx_mcuSupervisor, /*!< pointer to FS85xx instance */
90  .watchdogState = SBC_PERIODIC_WATCHDOG_DEACTIVATED,
91  .watchdogPeriod_10ms = 10u,
92  .useIgnitionForPowerDown = true,
93 };
94 
95 /*========== Static Function Prototypes =====================================*/
96 
97 /**
98  * @brief Saves the last state and last substate
99  * @param[in,out] pInstance
100  */
101 static void SBC_SaveLastStates(SBC_STATE_s *pInstance);
102 
103 /**
104  * @brief checks the state requests that are made.
105  * @details This function checks the validity of the state requests.
106  * The results of the checked is returned immediately.
107  * @param[in,out] pInstance
108  * @param[in] stateRequest state request to be checked
109  * @return result of the state request that was made, taken from
110  * #SBC_RETURN_TYPE_e
111  */
113 
114 /**
115  * @brief Re-entrance check of SBC state machine trigger function
116  * @details This function is not re-entrant and should only be called time- or
117  * event-triggered. It increments the triggerEntry counter from the
118  * state variable pInstance->triggerEntry. It should never be called
119  * by two different processes, so if it is the case, triggerEntry
120  * should never be higher than 0 when this function is called.
121  * @return #SBC_REENTRANCE_NO if no further instance of the function is
122  * active, otherwise #SBC_REENTRANCE_YES
123  */
125 
126 /**
127  * @brief Transfers the current state request to the state machine.
128  * @details This function takes the current state request from
129  * pInstance->stateRequest and transfers it to the state
130  * machine. It resets the value from stateRequest to
131  * #SBC_STATE_NO_REQUEST
132  * @param[in,out] pInstance
133  * @return current state request, taken from #SBC_STATE_REQUEST_e
134  */
136 
137 /**
138  * @brief Triggers the watchdog if the timing requires it.
139  * @details This function checks whether the watchdog timer elapses,
140  * and triggers the watchdog in that case.
141  * @param[in,out] pInstance
142  * @return true if watchdog has been triggered, false otherwise
143  * #SYS_STATE_REQUEST_e
144  */
145 static bool SBC_TriggerWatchdogIfRequired(SBC_STATE_s *pInstance);
146 
147 /**
148  * @brief Handle ignition/clamp 15 signal.
149  * @details Checks ignition signal (clamp 15) and put BMS in shutdown
150  * mode if ignition signal is not detected anymore.
151  * @param[in,out] pInstance SBC instance where ignition signal is connected
152  * @return true if ignition signal is detected, false otherwise
153  */
154 static bool SBC_IsIgnitionSignalDetected(SBC_STATE_s *pInstance);
155 
156 /*========== Static Function Implementations ================================*/
157 static void SBC_SaveLastStates(SBC_STATE_s *pInstance) {
158  FAS_ASSERT(pInstance != NULL_PTR);
159 
160  if (pInstance->lastState != pInstance->state) {
161  pInstance->lastState = pInstance->state;
162  pInstance->lastSubstate = pInstance->substate;
163  } else if (pInstance->lastSubstate != pInstance->substate) {
164  pInstance->lastSubstate = pInstance->substate;
165  } else {
166  /* Do not set new substate as nothing changed */
167  ;
168  }
169 }
170 
172  FAS_ASSERT(pInstance != NULL_PTR);
173 
175  if (stateRequest == SBC_STATE_ERROR_REQUEST) {
176  retval = SBC_OK;
177  } else {
178  if (pInstance->stateRequest == SBC_STATE_NO_REQUEST) {
179  /* init only allowed from the uninitialized state */
180  if (stateRequest == SBC_STATE_INIT_REQUEST) {
181  if (pInstance->state == SBC_STATEMACHINE_UNINITIALIZED) {
182  retval = SBC_OK;
183  } else {
184  retval = SBC_ALREADY_INITIALIZED;
185  }
186  } else {
187  retval = SBC_ILLEGAL_REQUEST;
188  }
189  } else {
190  retval = SBC_REQUEST_PENDING;
191  }
192  }
193  return retval;
194 }
195 
197  FAS_ASSERT(pInstance != NULL_PTR);
198 
200 
202  if (!pInstance->triggerEntry) {
203  pInstance->triggerEntry++;
204  } else {
205  isReEntrance = SBC_REENTRANCE_YES;
206  }
208 
209  return isReEntrance;
210 }
211 
213  FAS_ASSERT(pInstance != NULL_PTR);
214 
216 
218  retval = pInstance->stateRequest;
219  pInstance->stateRequest = SBC_STATE_NO_REQUEST;
221 
222  return (retval);
223 }
224 
226  FAS_ASSERT(pInstance != NULL_PTR);
227  bool watchdogHasBeenTriggered = false;
228  if (pInstance->watchdogTrigger > 0u) {
229  pInstance->watchdogTrigger--;
230  if (pInstance->watchdogTrigger == 0u) {
231  if (STD_OK != FS85_TriggerWatchdog(pInstance->pFs85xxInstance)) {
232  /* TODO: Do what if triggering of watchdog fails? */
233  } else {
234  watchdogHasBeenTriggered = true;
235  /* Debug LED Ball V2! :*/
236  /* gioToggleBit(hetPORT1, 1); */
237  /* Reset watchdog counter:
238  * Decremented every SBC_TASK_CYCLE_CONTEXT_MS and checked in next cycle -> Period-1 */
239  pInstance->watchdogTrigger = pInstance->watchdogPeriod_10ms;
240  }
241  }
242  }
243  return watchdogHasBeenTriggered;
244 }
245 
246 static bool SBC_IsIgnitionSignalDetected(SBC_STATE_s *pInstance) {
247  FAS_ASSERT(pInstance != NULL_PTR);
248 
249  return FS85_CheckIgnitionSignal(pInstance->pFs85xxInstance);
250 }
251 
252 /*========== Extern Function Implementations ================================*/
254  FAS_ASSERT(pInstance != NULL_PTR);
255 
257 
259  retVal = SBC_CheckStateRequest(pInstance, stateRequest);
260 
261  if (retVal == SBC_OK) {
262  pInstance->stateRequest = stateRequest;
263  }
265 
266  return (retVal);
267 }
268 
270  FAS_ASSERT(pInstance != NULL_PTR);
271 
272  return pInstance->state;
273 }
274 
275 extern void SBC_Trigger(SBC_STATE_s *pInstance) {
276  FAS_ASSERT(pInstance != NULL_PTR);
277 
279 
280  /* Check re-entrance of function */
281  if (SBC_CheckReEntrance(pInstance) == SBC_REENTRANCE_YES) {
282  return;
283  }
284 
285  /* Periodic watchdog triggering */
287  /* return value is only for unit testing purposes */
288  (void)SBC_TriggerWatchdogIfRequired(pInstance);
289  }
290 
291  if (pInstance->timer > 0u) {
292  if ((--pInstance->timer) > 0u) {
293  pInstance->triggerEntry--;
294  return; /* handle state machine only if timer has elapsed */
295  }
296  }
297 
298  switch (pInstance->state) {
299  /****************************UNINITIALIZED***********************************/
301  /* waiting for Initialization Request */
302  stateRequest = SBC_TransferStateRequest(pInstance);
303  if (stateRequest == SBC_STATE_INIT_REQUEST) {
304  SBC_SaveLastStates(pInstance);
305  pInstance->timer = SBC_STATEMACHINE_SHORTTIME;
307  pInstance->substate = SBC_ENTRY;
308  } else if (stateRequest == SBC_STATE_NO_REQUEST) {
309  /* no actual request pending */
310  } else {
311  pInstance->illegalRequestsCounter++; /* illegal request pending */
312  }
313  break;
314  /****************************INITIALIZATION**********************************/
316  SBC_SaveLastStates(pInstance);
317  /* Initializations done here */
318 
319  if (pInstance->substate == SBC_ENTRY) {
320  /* Init SBC */
322  /* Retry init if it fails */
323  pInstance->retryCounter++;
324  if (pInstance->retryCounter > 3u) {
325  /* Maximum number of retries -> goto error */
326  pInstance->retryCounter = 0u;
327  pInstance->timer = SBC_STATEMACHINE_SHORTTIME;
328  pInstance->state = SBC_STATEMACHINE_ERROR;
329  pInstance->substate = SBC_ENTRY;
330  }
331  } else {
332  /* First part of init successful -> start periodic watchdog triggering */
334  pInstance->watchdogTrigger = pInstance->watchdogPeriod_10ms;
335  pInstance->timer = SBC_STATEMACHINE_SHORTTIME;
337  pInstance->retryCounter = 0u;
338  }
339  } else if (pInstance->substate == SBC_INIT_RESET_FAULT_ERROR_COUNTER_PART1) {
340  /* Fault error counter is reset with valid watchdog refreshes
341  * -> first get required numbers of refreshes */
342  uint8_t requiredWatchdogTrigger = 0;
344  pInstance->pFs85xxInstance, &requiredWatchdogTrigger)) {
345  /* Retry init if it fails */
346  pInstance->retryCounter++;
347  if (pInstance->retryCounter > 3u) {
348  /* Maximum number of retries -> goto error */
349  pInstance->retryCounter = 0;
350  pInstance->timer = SBC_STATEMACHINE_SHORTTIME;
351  pInstance->state = SBC_STATEMACHINE_ERROR;
352  pInstance->substate = SBC_ENTRY;
353  }
354  } else {
355  /* Wait requiredWatchdogTrigger's */
356  pInstance->retryCounter = 0;
357  pInstance->timer = (requiredWatchdogTrigger * pInstance->watchdogPeriod_10ms);
359  }
360  } else if (pInstance->substate == SBC_INIT_RESET_FAULT_ERROR_COUNTER_PART2) {
361  /* Check if fault error counter is zero */
363  pInstance->retryCounter++;
364  if (pInstance->retryCounter > 3u) {
365  /* Goto error state */
366  pInstance->retryCounter = 0;
367  pInstance->state = SBC_STATEMACHINE_ERROR;
368  pInstance->substate = SBC_ENTRY;
369  }
370  pInstance->timer = SBC_STATEMACHINE_SHORTTIME;
371  } else {
373  pInstance->timer = SBC_STATEMACHINE_SHORTTIME;
374  }
375  } else if (pInstance->substate == SBC_INITIALIZE_SAFETY_PATH_CHECK) {
376  if (STD_NOT_OK == FS85_SafetyPathChecks(pInstance->pFs85xxInstance)) {
377  pInstance->retryCounter++;
378  if (pInstance->retryCounter > 3u) {
379  /* Goto error state */
380  pInstance->retryCounter = 0;
381  pInstance->state = SBC_STATEMACHINE_ERROR;
382  pInstance->substate = SBC_ENTRY;
383  }
384  } else {
385  pInstance->retryCounter = 0;
386  pInstance->state = SBC_STATEMACHINE_RUNNING;
387  pInstance->substate = SBC_ENTRY;
388  }
389  pInstance->timer = SBC_STATEMACHINE_SHORTTIME;
390  } else {
392  }
393  break;
394 
395  /****************************RUNNING*************************************/
397  SBC_SaveLastStates(pInstance);
398  pInstance->timer = SBC_STATEMACHINE_LONGTIME;
399  if (pInstance->useIgnitionForPowerDown == true) {
400  /* Return value is currently discarded, shutdown handling needs to be implemented */
401  (void)SBC_IsIgnitionSignalDetected(pInstance);
402  }
403  break;
404 
405  /****************************ERROR*************************************/
407  SBC_SaveLastStates(pInstance);
408  pInstance->timer = SBC_STATEMACHINE_LONGTIME;
409  break;
410  /***************************DEFAULT CASE*************************************/
411  default:
412  /* invalid state */
414  break;
415  } /* end switch (sys_systemState.state) */
416  pInstance->triggerEntry--;
417 }
418 
419 /*========== Externalized Static Function Implementations (Unit Test) =======*/
420 #ifdef UNITY_UNIT_TEST
421 extern void TEST_SBC_SaveLastStates(SBC_STATE_s *pInstance) {
422  SBC_SaveLastStates(pInstance);
423 }
424 extern SBC_RETURN_TYPE_e TEST_SBC_CheckStateRequest(SBC_STATE_s *pInstance, SBC_STATE_REQUEST_e stateRequest) {
425  return SBC_CheckStateRequest(pInstance, stateRequest);
426 }
427 
428 extern SBC_CHECK_REENTRANCE_e TEST_SBC_CheckReEntrance(SBC_STATE_s *pInstance) {
429  return TEST_SBC_CheckReEntrance(pInstance);
430 }
431 extern bool TEST_SBC_TriggerWatchdogIfRequired(SBC_STATE_s *pInstance) {
432  return SBC_TriggerWatchdogIfRequired(pInstance);
433 }
434 extern bool TEST_SBC_IsIgnitionSignalDetected(SBC_STATE_s *pInstance) {
435  return SBC_IsIgnitionSignalDetected(pInstance);
436 }
437 #endif
#define FAS_ASSERT(x)
Assertion macro that asserts that x is true.
Definition: fassert.h:255
#define FAS_TRAP
Define that evaluates to essential boolean false thus tripping an assert.
Definition: fassert.h:129
@ STD_NOT_OK
Definition: fstd_types.h:84
@ STD_OK
Definition: fstd_types.h:83
#define NULL_PTR
Null pointer.
Definition: fstd_types.h:77
STD_RETURN_TYPE_e FS85_TriggerWatchdog(FS85_STATE_s *pInstance)
Trigger watchdog.
Definition: nxpfs85xx.c:1086
STD_RETURN_TYPE_e FS85_InitializeNumberOfRequiredWatchdogRefreshes(FS85_STATE_s *pInstance, uint8_t *pRequiredWatchdogRefreshes)
Calculates the number of required watchdog refresh to reset fault error counter.
Definition: nxpfs85xx.c:946
FS85_STATE_s fs85xx_mcuSupervisor
Definition: nxpfs85xx.c:87
STD_RETURN_TYPE_e FS85_InitializeFsPhase(FS85_STATE_s *pInstance)
Configures SBC during INIT_FS phase.
Definition: nxpfs85xx.c:531
bool FS85_CheckIgnitionSignal(FS85_STATE_s *pInstance)
Check WAKE1 Signal at SBC.
Definition: nxpfs85xx.c:916
STD_RETURN_TYPE_e FS85_SafetyPathChecks(FS85_STATE_s *pInstance)
Performs SBC safety path checks.
Definition: nxpfs85xx.c:1018
STD_RETURN_TYPE_e FS85_CheckFaultErrorCounter(FS85_STATE_s *pInstance)
Checks if fault error counter is zero.
Definition: nxpfs85xx.c:1003
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:154
void OS_EnterTaskCritical(void)
Enter Critical interface function for use in FreeRTOS-Tasks and FreeRTOS-ISR.
Definition: os_freertos.c:150
SBC_STATEMACHINE_e SBC_GetState(SBC_STATE_s *pInstance)
gets the current state of passed state variable
Definition: sbc.c:269
static bool SBC_TriggerWatchdogIfRequired(SBC_STATE_s *pInstance)
Triggers the watchdog if the timing requires it.
Definition: sbc.c:225
void SBC_Trigger(SBC_STATE_s *pInstance)
trigger function for the SYS driver state machine.
Definition: sbc.c:275
static void SBC_SaveLastStates(SBC_STATE_s *pInstance)
Saves the last state and last substate.
Definition: sbc.c:157
static SBC_CHECK_REENTRANCE_e SBC_CheckReEntrance(SBC_STATE_s *pInstance)
Re-entrance check of SBC state machine trigger function.
Definition: sbc.c:196
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:171
SBC_STATE_s sbc_stateMcuSupervisor
Definition: sbc.c:78
static SBC_STATE_REQUEST_e SBC_TransferStateRequest(SBC_STATE_s *pInstance)
Transfers the current state request to the state machine.
Definition: sbc.c:212
SBC_CHECK_REENTRANCE_e
Definition: sbc.c:69
@ SBC_REENTRANCE_YES
Definition: sbc.c:71
@ SBC_REENTRANCE_NO
Definition: sbc.c:70
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:253
static bool SBC_IsIgnitionSignalDetected(SBC_STATE_s *pInstance)
Handle ignition/clamp 15 signal.
Definition: sbc.c:246
Header for the driver for the SBC module.
SBC_STATEMACHINE_e
Definition: sbc.h:133
@ SBC_STATEMACHINE_RUNNING
Definition: sbc.h:137
@ SBC_STATEMACHINE_UNINITIALIZED
Definition: sbc.h:135
@ SBC_STATEMACHINE_INITIALIZATION
Definition: sbc.h:136
@ SBC_STATEMACHINE_ERROR
Definition: sbc.h:138
SBC_RETURN_TYPE_e
Definition: sbc.h:123
@ SBC_ILLEGAL_REQUEST
Definition: sbc.h:127
@ SBC_REQUEST_PENDING
Definition: sbc.h:126
@ SBC_ALREADY_INITIALIZED
Definition: sbc.h:128
@ SBC_OK
Definition: sbc.h:124
SBC_STATE_REQUEST_e
Definition: sbc.h:110
@ SBC_STATE_INIT_REQUEST
Definition: sbc.h:111
@ SBC_STATE_ERROR_REQUEST
Definition: sbc.h:112
@ SBC_STATE_NO_REQUEST
Definition: sbc.h:113
@ SBC_PERIODIC_WATCHDOG_DEACTIVATED
Definition: sbc.h:119
@ SBC_PERIODIC_WATCHDOG_ACTIVATED
Definition: sbc.h:118
#define SBC_STATEMACHINE_LONGTIME
Definition: sbc.h:102
#define SBC_STATEMACHINE_SHORTTIME
Definition: sbc.h:90
@ SBC_ENTRY
Definition: sbc.h:144
@ SBC_INIT_RESET_FAULT_ERROR_COUNTER_PART2
Definition: sbc.h:146
@ SBC_INITIALIZE_SAFETY_PATH_CHECK
Definition: sbc.h:147
@ SBC_INIT_RESET_FAULT_ERROR_COUNTER_PART1
Definition: sbc.h:145
SBC_STATEMACHINE_SUB_e lastSubstate
Definition: sbc.h:163
FS85_STATE_s * pFs85xxInstance
Definition: sbc.h:169
uint16_t timer
Definition: sbc.h:157
bool useIgnitionForPowerDown
Definition: sbc.h:171
uint8_t triggerEntry
Definition: sbc.h:167
uint16_t watchdogTrigger
Definition: sbc.h:158
SBC_STATE_REQUEST_e stateRequest
Definition: sbc.h:159
SBC_STATEMACHINE_e lastState
Definition: sbc.h:162
SBC_STATEMACHINE_e state
Definition: sbc.h:160
SBC_PERIODIC_WATCHDOG_STATE_e watchdogState
Definition: sbc.h:168
uint32_t illegalRequestsCounter
Definition: sbc.h:164
SBC_STATEMACHINE_SUB_e substate
Definition: sbc.h:161
uint16_t watchdogPeriod_10ms
Definition: sbc.h:170
uint8_t retryCounter
Definition: sbc.h:165