foxBMS  1.5.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-02-03 (date of last update)
47  * @version v1.5.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 };
93 
94 /*========== Static Function Prototypes =====================================*/
95 
96 /**
97  * @brief Saves the last state and last substate
98  * @param[in,out] pInstance
99  */
100 static void SBC_SaveLastStates(SBC_STATE_s *pInstance);
101 
102 /**
103  * @brief checks the state requests that are made.
104  * @details This function checks the validity of the state requests.
105  * The results of the checked is returned immediately.
106  * @param[in,out] pInstance
107  * @param[in] stateRequest state request to be checked
108  * @return result of the state request that was made, taken from
109  * #SBC_RETURN_TYPE_e
110  */
112 
113 /**
114  * @brief Re-entrance check of SBC state machine trigger function
115  * @details This function is not re-entrant and should only be called time- or
116  * event-triggered. It increments the triggerEntry counter from the
117  * state variable pInstance->triggerEntry. It should never be called
118  * by two different processes, so if it is the case, triggerEntry
119  * should never be higher than 0 when this function is called.
120  * @return #SBC_REENTRANCE_NO if no further instance of the function is
121  * active, otherwise #SBC_REENTRANCE_YES
122  */
124 
125 /**
126  * @brief Transfers the current state request to the state machine.
127  * @details This function takes the current state request from
128  * pInstance->stateRequest and transfers it to the state
129  * machine. It resets the value from stateRequest to
130  * #SBC_STATE_NO_REQUEST
131  * @param[in,out] pInstance
132  * @return retVal current state request, taken from
133  * #SYS_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 retVal current state request, taken from
143  * #SYS_STATE_REQUEST_e
144  */
145 static bool SBC_TriggerWatchdogIfRequired(SBC_STATE_s *pInstance);
146 
147 /*========== Static Function Implementations ================================*/
148 static void SBC_SaveLastStates(SBC_STATE_s *pInstance) {
149  FAS_ASSERT(pInstance != NULL_PTR);
150 
151  if (pInstance->lastState != pInstance->state) {
152  pInstance->lastState = pInstance->state;
153  pInstance->lastSubstate = pInstance->substate;
154  } else if (pInstance->lastSubstate != pInstance->substate) {
155  pInstance->lastSubstate = pInstance->substate;
156  } else {
157  /* Do not set new substate as nothing changed */
158  ;
159  }
160 }
161 
163  FAS_ASSERT(pInstance != NULL_PTR);
164 
166  if (stateRequest == SBC_STATE_ERROR_REQUEST) {
167  retval = SBC_OK;
168  } else {
169  if (pInstance->stateRequest == SBC_STATE_NO_REQUEST) {
170  /* init only allowed from the uninitialized state */
171  if (stateRequest == SBC_STATE_INIT_REQUEST) {
172  if (pInstance->state == SBC_STATEMACHINE_UNINITIALIZED) {
173  retval = SBC_OK;
174  } else {
175  retval = SBC_ALREADY_INITIALIZED;
176  }
177  } else {
178  retval = SBC_ILLEGAL_REQUEST;
179  }
180  } else {
181  retval = SBC_REQUEST_PENDING;
182  }
183  }
184  return retval;
185 }
186 
188  FAS_ASSERT(pInstance != NULL_PTR);
189 
191 
193  if (!pInstance->triggerEntry) {
194  pInstance->triggerEntry++;
195  } else {
196  isReEntrance = SBC_REENTRANCE_YES;
197  }
199 
200  return isReEntrance;
201 }
202 
204  FAS_ASSERT(pInstance != NULL_PTR);
205 
207 
209  retval = pInstance->stateRequest;
210  pInstance->stateRequest = SBC_STATE_NO_REQUEST;
212 
213  return (retval);
214 }
215 
217  FAS_ASSERT(pInstance != NULL_PTR);
218  bool watchdogHasBeenTriggered = false;
219  if (pInstance->watchdogTrigger > 0u) {
220  pInstance->watchdogTrigger--;
221  if (pInstance->watchdogTrigger == 0u) {
222  if (STD_OK != SBC_TriggerWatchdog(pInstance->pFs85xxInstance)) {
223  /* TODO: Do what if triggering of watchdog fails? */
224  } else {
225  watchdogHasBeenTriggered = true;
226  /* Debug LED Ball V2! :*/
227  /* gioToggleBit(hetPORT1, 1); */
228  /* Reset watchdog counter:
229  * Decremented every SBC_TASK_CYCLE_CONTEXT_MS and checked in next cycle -> Period-1 */
230  pInstance->watchdogTrigger = pInstance->watchdogPeriod_10ms;
231  }
232  }
233  }
234  return watchdogHasBeenTriggered;
235 }
236 
237 /*========== Extern Function Implementations ================================*/
239  FAS_ASSERT(pInstance != NULL_PTR);
240 
242 
244  retVal = SBC_CheckStateRequest(pInstance, stateRequest);
245 
246  if (retVal == SBC_OK) {
247  pInstance->stateRequest = stateRequest;
248  }
250 
251  return (retVal);
252 }
253 
255  FAS_ASSERT(pInstance != NULL_PTR);
256 
257  return pInstance->state;
258 }
259 
260 extern void SBC_Trigger(SBC_STATE_s *pInstance) {
261  FAS_ASSERT(pInstance != NULL_PTR);
262 
264 
265  /* Check re-entrance of function */
266  if (SBC_CheckReEntrance(pInstance) == SBC_REENTRANCE_YES) {
267  return;
268  }
269 
270  /* Periodic watchdog triggering */
272  /* return value is only for unit testing purposes */
273  (void)SBC_TriggerWatchdogIfRequired(pInstance);
274  }
275 
276  if (pInstance->timer > 0u) {
277  if ((--pInstance->timer) > 0u) {
278  pInstance->triggerEntry--;
279  return; /* handle state machine only if timer has elapsed */
280  }
281  }
282 
283  switch (pInstance->state) {
284  /****************************UNINITIALIZED***********************************/
286  /* waiting for Initialization Request */
287  stateRequest = SBC_TransferStateRequest(pInstance);
288  if (stateRequest == SBC_STATE_INIT_REQUEST) {
289  SBC_SaveLastStates(pInstance);
290  pInstance->timer = SBC_STATEMACHINE_SHORTTIME;
292  pInstance->substate = SBC_ENTRY;
293  } else if (stateRequest == SBC_STATE_NO_REQUEST) {
294  /* no actual request pending */
295  } else {
296  pInstance->illegalRequestsCounter++; /* illegal request pending */
297  }
298  break;
299  /****************************INITIALIZATION**********************************/
301  SBC_SaveLastStates(pInstance);
302  /* Initializations done here */
303 
304  if (pInstance->substate == SBC_ENTRY) {
305  /* Init SBC */
307  /* Retry init if it fails */
308  pInstance->retryCounter++;
309  if (pInstance->retryCounter > 3u) {
310  /* Maximum number of retries -> goto error */
311  pInstance->retryCounter = 0u;
312  pInstance->timer = SBC_STATEMACHINE_SHORTTIME;
313  pInstance->state = SBC_STATEMACHINE_ERROR;
314  pInstance->substate = SBC_ENTRY;
315  }
316  } else {
317  /* First part of init successful -> start periodic watchdog triggering */
319  pInstance->watchdogTrigger = pInstance->watchdogPeriod_10ms;
320  pInstance->timer = SBC_STATEMACHINE_SHORTTIME;
322  pInstance->retryCounter = 0u;
323  }
324  } else if (pInstance->substate == SBC_INIT_RESET_FAULT_ERROR_COUNTER_PART1) {
325  /* Fault error counter is reset with valid watchdog refreshes
326  * -> first get required numbers of refreshes */
327  uint8_t requiredWatchdogTrigger = 0;
329  pInstance->pFs85xxInstance, &requiredWatchdogTrigger)) {
330  /* Retry init if it fails */
331  pInstance->retryCounter++;
332  if (pInstance->retryCounter > 3u) {
333  /* Maximum number of retries -> goto error */
334  pInstance->retryCounter = 0;
335  pInstance->timer = SBC_STATEMACHINE_SHORTTIME;
336  pInstance->state = SBC_STATEMACHINE_ERROR;
337  pInstance->substate = SBC_ENTRY;
338  }
339  } else {
340  /* Wait requiredWatchdogTrigger's */
341  pInstance->retryCounter = 0;
342  pInstance->timer = (requiredWatchdogTrigger * pInstance->watchdogPeriod_10ms);
344  }
345  } else if (pInstance->substate == SBC_INIT_RESET_FAULT_ERROR_COUNTER_PART2) {
346  /* Check if fault error counter is zero */
348  pInstance->retryCounter++;
349  if (pInstance->retryCounter > 3u) {
350  /* Goto error state */
351  pInstance->retryCounter = 0;
352  pInstance->state = SBC_STATEMACHINE_ERROR;
353  pInstance->substate = SBC_ENTRY;
354  }
355  pInstance->timer = SBC_STATEMACHINE_SHORTTIME;
356  } else {
358  pInstance->timer = SBC_STATEMACHINE_SHORTTIME;
359  }
360  } else if (pInstance->substate == SBC_INITIALIZE_SAFETY_PATH_CHECK) {
361  if (STD_NOT_OK == FS85_SafetyPathChecks(pInstance->pFs85xxInstance)) {
362  pInstance->retryCounter++;
363  if (pInstance->retryCounter > 3u) {
364  /* Goto error state */
365  pInstance->retryCounter = 0;
366  pInstance->state = SBC_STATEMACHINE_ERROR;
367  pInstance->substate = SBC_ENTRY;
368  }
369  } else {
370  pInstance->retryCounter = 0;
371  pInstance->state = SBC_STATEMACHINE_RUNNING;
372  pInstance->substate = SBC_ENTRY;
373  }
374  pInstance->timer = SBC_STATEMACHINE_SHORTTIME;
375  } else {
377  }
378  break;
379 
380  /****************************RUNNING*************************************/
382  SBC_SaveLastStates(pInstance);
383  pInstance->timer = SBC_STATEMACHINE_LONGTIME;
384  break;
385 
386  /****************************ERROR*************************************/
388  SBC_SaveLastStates(pInstance);
389  pInstance->timer = SBC_STATEMACHINE_LONGTIME;
390  break;
391  /***************************DEFAULT CASE*************************************/
392  default:
393  /* invalid state */
395  break;
396  } /* end switch (sys_systemState.state) */
397  pInstance->triggerEntry--;
398 }
399 
400 /*========== Externalized Static Function Implementations (Unit Test) =======*/
401 #ifdef UNITY_UNIT_TEST
402 extern bool TEST_SBC_TriggerWatchdogIfRequired(SBC_STATE_s *pInstance) {
403  return SBC_TriggerWatchdogIfRequired(pInstance);
404 }
405 #endif
#define FAS_ASSERT(x)
Assertion macro that asserts that x is true.
Definition: fassert.h:254
#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_InitializeNumberOfRequiredWatchdogRefreshes(FS85_STATE_s *pInstance, uint8_t *requiredWatchdogRefreshes)
Calculates the number of required watchdog refresh to reset fault error counter.
Definition: nxpfs85xx.c:885
FS85_STATE_s fs85xx_mcuSupervisor
Definition: nxpfs85xx.c:84
STD_RETURN_TYPE_e FS85_InitializeFsPhase(FS85_STATE_s *pInstance)
Configures SBC during INIT_FS phase.
Definition: nxpfs85xx.c:500
STD_RETURN_TYPE_e SBC_TriggerWatchdog(FS85_STATE_s *pInstance)
Trigger watchdog.
Definition: nxpfs85xx.c:1023
STD_RETURN_TYPE_e FS85_SafetyPathChecks(FS85_STATE_s *pInstance)
Performs SBC safety path checks.
Definition: nxpfs85xx.c:957
STD_RETURN_TYPE_e FS85_CheckFaultErrorCounter(FS85_STATE_s *pInstance)
Checks if fault error counter is zero.
Definition: nxpfs85xx.c:942
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:138
void OS_EnterTaskCritical(void)
Enter Critical interface function for use in FreeRTOS-Tasks and FreeRTOS-ISR.
Definition: os_freertos.c:134
SBC_STATEMACHINE_e SBC_GetState(SBC_STATE_s *pInstance)
gets the current state of passed state variable
Definition: sbc.c:254
static bool SBC_TriggerWatchdogIfRequired(SBC_STATE_s *pInstance)
Triggers the watchdog if the timing requires it.
Definition: sbc.c:216
void SBC_Trigger(SBC_STATE_s *pInstance)
trigger function for the SYS driver state machine.
Definition: sbc.c:260
static void SBC_SaveLastStates(SBC_STATE_s *pInstance)
Saves the last state and last substate.
Definition: sbc.c:148
static SBC_CHECK_REENTRANCE_e SBC_CheckReEntrance(SBC_STATE_s *pInstance)
Re-entrance check of SBC state machine trigger function.
Definition: sbc.c:187
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:162
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:203
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:238
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
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