foxBMS  1.1.2
The foxBMS Battery Management System API Documentation
sbc_fs8x.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016 - 2018, NXP Semiconductors, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without modification,
6  * are permitted provided that the following conditions are met:
7  *
8  * o Redistributions of source code must retain the above copyright notice, this list
9  * of conditions and the following disclaimer.
10  *
11  * o Redistributions in binary form must reproduce the above copyright notice, this
12  * list of conditions and the following disclaimer in the documentation and/or
13  * other materials provided with the distribution.
14  *
15  * o Neither the name of the copyright holder nor the names of its
16  * contributors may be used to endorse or promote products derived from this
17  * software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
23  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 /** @file sbc_fs8x.c
32  * @brief Driver functions for the FS8x SBC.
33  *
34  * @author nxf44615
35  * @version 1.1
36  * @date 9-Oct-2018
37  * @copyright Copyright (c) 2016 - 2018, NXP Semiconductors, Inc.
38  *
39  * @updated 2020-03-18 (date of last update)
40  * Adapted driver to pass interface configuration as parameter into the
41  * functions to enable the usage of multiple ICs in the system.
42  */
43 
44 /*******************************************************************************
45  * Includes
46  ******************************************************************************/
47 
48 #include <stddef.h>
49 
50 #include "sbc_fs8x.h"
51 #include "sbc_fs8x_map.h"
52 #include "sbc_fs8x_assert.h"
53 #include "sbc_fs8x_communication.h"
54 #include "sbc_fs8x_common.h"
55 
56 /*******************************************************************************
57  * Definitions
58  ******************************************************************************/
59 
60 /** @brief Returns true if value VAL is in the range defined by MIN and MAX values
61  * (range includes the border values).
62  * @param val Comparison value.
63  * @param min Minimal value of the range.
64  * @param max Maximal value of the range.
65  * @return True if value is the range. False otherwise. */
66 #define FS8x_IS_IN_RANGE(val, min, max) (((val) >= (min)) && ((val) <= (max)))
67 
68 /*******************************************************************************
69  * Local Functions Prototypes
70  ******************************************************************************/
71 #if (FS8x_WD_TYPE == FS8x_WD_CHALLENGER)
72 
73 /* Reads challenge token (next generated LFSR state) from the SBC. */
74 static fs8x_status_t FS8x_WD_ReadChallengeToken(SPI_INTERFACE_CONFIG_s* spiInterface, fs8x_drv_data_t* drvData,
75  uint16_t* wdSeed);
76 
77 /* Compute Challenger Watchdog answer. */
78 static uint16_t FS8x_WD_ComputeAnswer(uint16_t token);
79 
80 #endif
81 
82 /*******************************************************************************
83  * Local Variables
84  ******************************************************************************/
85 
86 /*******************************************************************************
87  * Global Variables
88  ******************************************************************************/
89 
90 /*******************************************************************************
91  * Local Functions - Implementation
92  ******************************************************************************/
93 
94 #if (FS8x_WD_TYPE == FS8x_WD_CHALLENGER)
95 /* Reads challenge token (next generated LFSR state) from the SBC and stores it
96  * into the driver data structure. */
97 static fs8x_status_t FS8x_WD_ReadChallengeToken(SPI_INTERFACE_CONFIG_s* spiInterface, fs8x_drv_data_t* drvData,
98  uint16_t* wdSeed)
99 {
100  fs8x_status_t status = fs8xStatusOk; /* Status variable. */
101  fs8x_rx_frame_t response; /* Response to the command. */
102 
103  FS_ASSERT(drvData != NULL);
104 
105  status = FS8x_ReadRegister(spiInterface, drvData, true, FS8X_FS_WD_SEED_ADDR, &response);
106  if (status != fs8xStatusOk)
107  {
108  return status;
109  }
110 
111  /* Store the watchdog seed from the SBC device. */
112  *wdSeed = response.readData;
113 
114  return status;
115 }
116 
117 /* Compute Challenger Watchdog answer. */
118 static uint16_t FS8x_WD_ComputeAnswer(uint16_t token)
119 {
120  uint32_t mr = token; /* Monitoring result. */
121 
122  /* Simulates ALU Checker on the MCU side. */
123  mr *= 4U;
124  mr += 6U;
125  mr -= 4U;
126  mr = ~mr;
127  mr /= 4U;
128 
129  return (uint16_t)mr;
130 }
131 #endif
132 
133 /*******************************************************************************
134  * API - Implementation
135  ******************************************************************************/
136 /* Changes seed of LFSR used for watchdog. */
138 {
139  fs8x_status_t status = fs8xStatusOk; /* Status variable. */
140  fs8x_rx_frame_t rxData;
141  uint8_t registerAddress;
142 
143  FS_ASSERT(drvData != NULL);
144 
145 #if (FS8x_WD_TYPE == FS8x_WD_SIMPLE)
146  registerAddress = FS8X_FS_WD_ANSWER_ADDR;
147 #elif (FS8x_WD_TYPE == FS8x_WD_CHALLENGER)
148  registerAddress = FS8X_FS_WD_SEED_ADDR;
149 #endif
150  status = FS8x_WriteRegister(spiInterface, drvData, true, registerAddress, wdSeed);
151  status |= FS8x_ReadRegister(spiInterface, drvData, true, registerAddress, &rxData);
152  if (wdSeed != rxData.readData)
153  {
154  status = fs8xStatusError;
155  }
156  return status;
157 }
158 
159 /* Performs the watchdog refresh. */
161 {
162  fs8x_status_t status = fs8xStatusError; /* Status variable. */
163 
164  FS_ASSERT(drvData != NULL);
165 
166 #if (FS8x_WD_TYPE == FS8x_WD_SIMPLE)
167  status = FS8x_WriteRegister(spiInterface, drvData, true, FS8X_FS_WD_ANSWER_ADDR,
168  drvData->watchdogSeed);
169 #elif (FS8x_WD_TYPE == FS8x_WD_CHALLENGER)
170  uint16_t answer; /* Calculated monitoring result. */
171 
172  /* Synchronize with LFSR generator on the device. */
173  status = FS8x_WD_ReadChallengeToken(spiInterface, drvData, &(drvData->watchdogSeed));
174  if (status != fs8xStatusOk)
175  {
176  return status;
177  }
178  answer = FS8x_WD_ComputeAnswer(drvData->watchdogSeed);
179  status = FS8x_WriteRegister(spiInterface, drvData, true, FS8X_FS_WD_ANSWER_ADDR, answer);
180 #endif
181  return status; /* Return error if no WD is selected. */
182 }
183 
185 {
186  fs8x_status_t status; /* Status variable. */
187  fs8x_rx_frame_t rxData; /* Response to the command. */
188  uint16_t fs0b_write = 0; /* Value to be written to the FS_RELEASE_FS0B register. */
189  uint8_t i = 0; /* Counter. */
190  uint16_t diagSafetyMask; /* Mask for reading of value from the FS_DIAG_SAFETY reg. */
191  uint16_t diagSafetyValue; /* FS_DIAG_SAFETY bits defined by the former mask should have this value. */
192  uint8_t errorCounter; /* Fault Error Counter value. */
193 
194  FS_ASSERT(drvData != NULL);
195 
196  /* Preconditions check */
197  /* Fault Error Counter = 0 */
198  status = FS8x_GetFaultErrorCounterValue(spiInterface, drvData, &errorCounter);
199  if (status != fs8xStatusOk)
200  {
201  return status;
202  }
203  if (errorCounter > 0)
204  {
205  return fs8xStatusError;
206  }
207  /* LBIST_OK = ABIST1_OK = ABIST2_OK = 1 */
208  status = FS8x_ReadRegister(spiInterface, drvData, true, FS8X_FS_DIAG_SAFETY_ADDR, &rxData);
209  if (status != fs8xStatusOk)
210  {
211  return status;
212  }
215  if ((rxData.readData & diagSafetyMask) != diagSafetyValue)
216  {
217  return fs8xStatusError;
218  }
219  /* RELEASE_FS0B register filled with ongoing WD_SEED reversed and complemented */
220  status = FS8x_ReadRegister(spiInterface, drvData, true, FS8X_FS_WD_SEED_ADDR, &rxData);
221  if (status != fs8xStatusOk)
222  {
223  return status;
224  }
225 
226  for (i = 0; i < 16; i++)
227  {
228  fs0b_write |= (uint16_t)(((rxData.readData >> (15 - i)) & 1U) << i);
229  }
230  fs0b_write = ~fs0b_write;
231  return FS8x_WriteRegister(spiInterface, drvData, true, FS8X_FS_RELEASE_FS0B_ADDR, fs0b_write);
232 }
233 
234 /* Switches a desired channel to the AMUX pin. */
236 {
237  FS_ASSERT(drvData != NULL);
238 
239  /* Check of AMUX channel selection range. */
240 #pragma diag_push
241 #pragma diag_suppress 188
242  if ((!FS8x_IS_IN_RANGE(channelSelection, fs8xAmuxGnd, fs8xAmuxPsync) &&
244  channelSelection == FS8X_M_AMUX_RESERVED)
245 #pragma diag_pop
246  {
247  return fs8xStatusError;
248  }
249  return FS8x_WriteRegister(spiInterface, drvData, false, FS8X_M_AMUX_ADDR, (uint16_t)channelSelection);
250 }
251 
252 /* Sets state (enable/disable) of the selected voltage regulator. */
254  fs8x_reg_output_t vreg, bool enable)
255 {
256  uint16_t shift = (uint16_t)vreg; /* Shift of the mask for disable value. */
257 
258  FS_ASSERT(drvData != NULL);
259 
260  if (!enable)
261  {
262  shift += 8; /* Disable value is shifted 8 bits left. */
263  }
264 
265  /* Register read is not necessary here as a bit value of 0 is ignored anyway. */
266  return FS8x_WriteRegister(spiInterface, drvData, false, FS8X_M_REG_CTRL1_ADDR, (uint16_t)(1U << shift));
267 }
268 
269 /* Reads actual Fault Error Counter value. */
271  uint8_t* faultErrorCounterValue)
272 {
273  fs8x_status_t status; /* Status value. */
274  fs8x_rx_frame_t rxData; /* Register received data. */
275 
276  FS_ASSERT(drvData != NULL);
277  FS_ASSERT(faultErrorCounterValue != NULL);
278 
279  status = FS8x_ReadRegister(spiInterface, drvData, true, FS8X_FS_I_FSSM_ADDR, &rxData);
280  if (status != fs8xStatusOk)
281  {
282  return status;
283  }
284 
285  *faultErrorCounterValue = FS8x_BO_GET_REG_VALUE(rxData.readData, FS8X_FS_I_FLT_ERR_CNT_MASK,
287 
288  return fs8xStatusOk;
289 }
fs8x_status_t FS8x_GetFaultErrorCounterValue(SPI_INTERFACE_CONFIG_s *spiInterface, fs8x_drv_data_t *drvData, uint8_t *faultErrorCounterValue)
Reads actual Fault Error Counter value.
Definition: sbc_fs8x.c:270
fs8x_status_t FS8x_WD_Refresh(SPI_INTERFACE_CONFIG_s *spiInterface, fs8x_drv_data_t *drvData)
Performs the watchdog refresh.
Definition: sbc_fs8x.c:160
fs8x_status_t FS8x_WriteRegister(SPI_INTERFACE_CONFIG_s *pSpiInterface, fs8x_drv_data_t *drvData, bool isFailSafe, uint8_t address, uint16_t writeData)
Sends write command to the FS8x.
fs8x_status_t FS8x_WD_ChangeSeed(SPI_INTERFACE_CONFIG_s *spiInterface, fs8x_drv_data_t *drvData, uint16_t wdSeed)
Changes seed of LFSR used for watchdog.
Definition: sbc_fs8x.c:137
fs8x_status_t FS8x_FS0B_Release(SPI_INTERFACE_CONFIG_s *spiInterface, fs8x_drv_data_t *drvData)
FS0B release routine.
Definition: sbc_fs8x.c:184
fs8x_status_t FS8x_SetRegulatorState(SPI_INTERFACE_CONFIG_s *spiInterface, fs8x_drv_data_t *drvData, fs8x_reg_output_t vreg, bool enable)
Sets state (enable/disable) of the selected voltage regulator.
Definition: sbc_fs8x.c:253
fs8x_status_t FS8x_ReadRegister(SPI_INTERFACE_CONFIG_s *pSpiInterface, fs8x_drv_data_t *drvData, bool isFailSafe, uint8_t address, fs8x_rx_frame_t *rxData)
Performs a read from a single FS8x register.
fs8x_status_t FS8x_SwitchAMUXchannel(SPI_INTERFACE_CONFIG_s *spiInterface, fs8x_drv_data_t *drvData, fs8x_amux_selection_t channelSelection)
Switches a desired channel to the AMUX pin.
Definition: sbc_fs8x.c:235
fs8x_status_t
Status return codes.
fs8x_reg_output_t
Voltage outputs. Can be used with function FS8x_SetRegulatorState().
Definition: sbc_fs8x.h:65
fs8x_amux_selection_t
Definition: sbc_fs8x.h:77
@ fs8xStatusOk
@ fs8xStatusError
@ fs8xAmuxWake2VoltDiv14
Definition: sbc_fs8x.h:100
@ fs8xAmuxPsync
Definition: sbc_fs8x.h:97
@ fs8xAmuxVsup1VoltDiv14
Definition: sbc_fs8x.h:98
@ fs8xAmuxGnd
Definition: sbc_fs8x.h:78
#define FS8x_IS_IN_RANGE(val, min, max)
Returns true if value VAL is in the range defined by MIN and MAX values (range includes the border va...
Definition: sbc_fs8x.c:66
FS8x driver interface.
Assertion macro definition, for debugging purposes.
#define FS_ASSERT(x)
Assert macro for the SBC.
Driver common structures, enums, macros and configuration values.
#define FS8x_BO_GET_REG_VALUE(value, mask, shift)
Macro for getting value from register.
This file contains functions for SPI/I2C communication.
FS8x register map.
#define FS8X_FS_ABIST1_OK_PASS
#define FS8X_FS_ABIST2_OK_MASK
#define FS8X_FS_LBIST_OK_MASK
#define FS8X_FS_WD_ANSWER_ADDR
#define FS8X_FS_RELEASE_FS0B_ADDR
#define FS8X_FS_I_FLT_ERR_CNT_SHIFT
#define FS8X_FS_I_FLT_ERR_CNT_MASK
#define FS8X_M_REG_CTRL1_ADDR
Definition: sbc_fs8x_map.h:432
#define FS8X_FS_WD_SEED_ADDR
#define FS8X_FS_ABIST2_OK_PASS
#define FS8X_FS_I_FSSM_ADDR
#define FS8X_FS_DIAG_SAFETY_ADDR
#define FS8X_M_AMUX_RESERVED
Definition: sbc_fs8x_map.h:958
#define FS8X_FS_ABIST1_OK_MASK
#define FS8X_FS_LBIST_OK_PASS
#define FS8X_M_AMUX_ADDR
Definition: sbc_fs8x_map.h:882
This data structure is used by the FS8x driver (this is the first parameter of most the FS8x function...
uint16_t watchdogSeed
Actual watchdog seed value. See FS8x_WD_ChangeSeed() for details.
Structure representing received data frame.
uint16_t readData
Content of a read register.