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