foxBMS  1.6.0
The foxBMS Battery Management System API Documentation
mxm_1785x.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 mxm_1785x.c
44  * @author foxBMS Team
45  * @date 2019-01-15 (date of creation)
46  * @updated 2023-10-12 (date of last update)
47  * @version v1.6.0
48  * @ingroup DRIVERS
49  * @prefix MXM
50  *
51  * @brief Driver for the MAX17841B ASCI and MAX1785x analog front-end
52  *
53  * @details This file contains the main-state-machine that drives the
54  * monitoring ICs of the MAX1785x family by Maxim Integrated.
55  *
56  */
57 
58 /*========== Includes =======================================================*/
59 #include "general.h"
60 
61 #include "mxm_1785x.h"
62 
63 #include "afe_plausibility.h"
64 #include "database.h"
65 #include "diag.h"
66 #include "fassert.h"
67 #include "fstd_types.h"
68 #include "mxm_1785x_tools.h"
69 #include "mxm_battery_management.h"
70 #include "mxm_registry.h"
71 #include "os.h"
72 #include "tsi.h"
73 
74 #include <math.h>
75 #include <stdbool.h>
76 #include <stdint.h>
77 
78 /*========== Macros and Definitions =========================================*/
79 
80 #define MXM_OFFSET_CELL_1 (0u) /*!< storage offset for cell 1 */
81 #define MXM_OFFSET_CELL_2 (1u) /*!< storage offset for cell 2 */
82 #define MXM_OFFSET_CELL_3 (2u) /*!< storage offset for cell 3 */
83 #define MXM_OFFSET_CELL_4 (3u) /*!< storage offset for cell 4 */
84 #define MXM_OFFSET_CELL_5 (4u) /*!< storage offset for cell 5 */
85 #define MXM_OFFSET_CELL_6 (5u) /*!< storage offset for cell 6 */
86 #define MXM_OFFSET_CELL_7 (6u) /*!< storage offset for cell 7 */
87 #define MXM_OFFSET_CELL_8 (7u) /*!< storage offset for cell 8 */
88 #define MXM_OFFSET_CELL_9 (8u) /*!< storage offset for cell 9 */
89 #define MXM_OFFSET_CELL_10 (9u) /*!< storage offset for cell 10 */
90 #define MXM_OFFSET_CELL_11 (10u) /*!< storage offset for cell 11 */
91 #define MXM_OFFSET_CELL_12 (11u) /*!< storage offset for cell 12 */
92 #define MXM_OFFSET_CELL_13 (12u) /*!< storage offset for cell 13 */
93 #define MXM_OFFSET_CELL_14 (13u) /*!< storage offset for cell 14 */
94 #define MXM_OFFSET_AUX0 (0u) /*!< storage offset for AUX0 */
95 #define MXM_OFFSET_AUX2 (2u) /*!< storage offset for AUX2 */
96 #define MXM_OFFSET_AUX3 (3u) /*!< storage offset for AUX3 */
97 #define MXM_OFFSET_BLOCK (0u) /*!< storage offset for block voltage */
98 
99 /** maximum number of errors that may occur before the next error triggers a reset */
100 #define MXM_MAXIMUM_ERROR_COUNT (10u)
101 
102 /** timeout after which the error counter will be reset */
103 #define MXM_TIMEOUT_RESET_ERROR_COUNTER_ms (500)
104 
105 /** maximum length of a test buffer */
106 #define MXM_TEST_BUFFER_MAXIMUM_LENGTH (120u)
107 
108 /** local definition of plausible cell voltage values */
111  .minimumPlausibleVoltage_mV = -2500,
112 };
113 
114 /*========== Static Constant and Variable Definitions =======================*/
115 /** @brief VAA reference voltage (3.3V) */
116 #define MXM_REF_VAA_mV (3300u)
117 
118 /*========== Extern Constant and Variable Definitions =======================*/
119 
120 /*========== Static Function Prototypes =====================================*/
121 
122 /** @brief Retrieves data from lower state machine and writes it to the rx buffer. */
124 
125 /**
126  * @brief Parse voltage values from a READALL receive buffer into an
127  * array.
128  * @details This function expects a preprocessed RX buffer with an answer
129  * to a READALL command. It will parse the data bytes from this
130  * message into an array structured like mxm_local_cellVoltages.
131  * The offset of the measured cell has to be defined. For example
132  * cell 1 has an offset of 0 and cell 4 has an offset of 3. The
133  * offset for the READALL command is always defined in reference
134  * to module 0.
135  *
136  * If is_temperature_measurement is set to true, the function
137  * expects an auxiliary measurement (e.g. temperatures).
138  * @param[in] kpkVoltRxBuffer array-pointer to the RX buffer
139  * @param[in] voltRxBufferLength length of the RX buffer
140  * @param[in] measurementOffset offset of the data in the cell voltage
141  * array (target)
142  * @param[in] conversionType type of conversion that has been used
143  * for the measured data
144  * @param[out] pVoltagesTarget array-pointer to the cell voltages
145  * array
146  * @param[in] measurementType whether the measurement is temperature
147  * or cell
148  * @param[in] fullScaleReference_mV reference voltage of full scale
149  */
150 static void MXM_ParseVoltageLineReadall(
151  const uint8_t *const kpkVoltRxBuffer,
152  uint16_t voltRxBufferLength,
153  uint8_t measurementOffset,
154  MXM_CONVERSION_TYPE_e conversionType,
155  uint16_t *pVoltagesTarget,
156  MXM_MEASURE_TYPE_e measurementType,
157  uint32_t fullScaleReference_mV);
158 
159 /**
160  * @brief Parse a RX buffer containing voltage values.
161  * @details This function parses a RX buffer containing the answer to a
162  * READALL command. It will check whether the message contains a
163  * READALL command and whether a supported register has been
164  * queried.
165  * Depending on the queried register, it will pass the proper
166  * parameters to #MXM_ParseVoltageLineReadall(). The contained
167  * data from this message will be parsed into a struct structured
168  * like #MXM_MONITORING_INSTANCE_s::localVoltages.
169  * @param[in] kpkVoltageRxBuffer array-pointer to the RX buffer
170  * @param[in] voltageRxBufferLength length of the RX buffer
171  * @param[out] datastorage contains all measured voltages for local
172  * consumption in the module
173  * @param[in] conversionType type of conversion that has been used for
174  * the measured data
175  * @return #STD_NOT_OK in the case that the RX buffer does not contain a
176  * valid message or the conversion-type is unknown,
177  * otherwise #STD_OK
178  */
180  const uint8_t *const kpkVoltageRxBuffer,
181  uint16_t voltageRxBufferLength,
182  MXM_DATA_STORAGE_s *datastorage,
183  MXM_CONVERSION_TYPE_e conversionType);
184 
185 /**
186  * @brief Test the #MXM_ParseVoltageReadall()-function
187  * @details Test the function #MXM_ParseVoltageReadall() by passing predefined
188  * RX buffer to it and checking the outcome. This function writes to
189  * the variable #MXM_MONITORING_INSTANCE_s::localVoltages and nulls it
190  * completely after execution. It is intended as a self-check that can
191  * be performed during startup of the driver.
192  * @return #STD_OK if the self-check has been performed successfully,
193  * otherwise #STD_NOT_OK
194  */
196 
197 /*========== Static Function Implementations ================================*/
198 
200  FAS_ASSERT(pInstance != NULL_PTR);
201  STD_RETURN_TYPE_e getBufferResult =
203  FAS_ASSERT(getBufferResult == STD_OK);
204  pInstance->dcByte = MXM_5XGetLastDCByte(pInstance->pInstance5X);
205 }
206 
208  const uint8_t *const kpkVoltRxBuffer,
209  uint16_t voltRxBufferLength,
210  uint8_t measurementOffset,
211  MXM_CONVERSION_TYPE_e conversionType,
212  uint16_t *pVoltagesTarget,
213  MXM_MEASURE_TYPE_e measurementType,
214  uint32_t fullScaleReference_mV) {
215  FAS_ASSERT(kpkVoltRxBuffer != NULL_PTR);
216  FAS_ASSERT(pVoltagesTarget != NULL_PTR);
217  /* AXIVION Routine Generic-MissingParameterAssert: voltRxBufferLength: parameter accepts whole range */
218  /* AXIVION Routine Generic-MissingParameterAssert: measurementOffset: parameter accepts whole range */
219  /* AXIVION Routine Generic-MissingParameterAssert: conversionType: parameter accepts whole range */
220  /* AXIVION Routine Generic-MissingParameterAssert: measurementType: parameter accepts whole range */
221  /* AXIVION Routine Generic-MissingParameterAssert: fullScaleReference_mV: parameter accepts whole range */
222 
223  /* assert that assumptions behind computation of numberOfConnectedDevices
224  are correct */
225  FAS_ASSERT(voltRxBufferLength >= (2u + 2u));
226  FAS_ASSERT(((voltRxBufferLength - 2u - 2u) / 2u) <= (uint16_t)UINT8_MAX);
227  /* buffer-length - length of start - length of end divided by two (LSB and MSB) */
228  const uint8_t numberOfConnectedDevices = (uint8_t)(((voltRxBufferLength - 2u - 2u) / 2u) & (uint8_t)UINT8_MAX);
229  /* TODO impact of alive counter on rxBufferLength
230  * otherwise offset at the end of message is currently 2 (DATACHECKBYTE and CRC) */
231  for (uint8_t i = 2u; i < (voltRxBufferLength - 2u); i = i + 2u) {
232  const uint8_t calculatedModuleNumber = numberOfConnectedDevices - ((i / 2u) - 1u) - 1u;
233  uint16_t calculatedModulePosition = 0u;
234  switch (measurementType) {
235  case MXM_MEASURE_TEMP:
236  calculatedModulePosition = (uint16_t)calculatedModuleNumber * MXM_MAXIMUM_NR_OF_AUX_PER_MODULE;
237  break;
239  calculatedModulePosition = (uint16_t)calculatedModuleNumber * MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE;
240  break;
242  calculatedModulePosition = calculatedModuleNumber;
243  break;
244  default:
246  break; /* LCOV_EXCL_LINE */
247  }
248  FAS_ASSERT((calculatedModulePosition + measurementOffset) <= (uint16_t)UINT16_MAX);
249  uint16_t calculatedArrayPosition = calculatedModulePosition + measurementOffset;
250 
251  /* check calculated array position */
252  switch (measurementType) {
253  case MXM_MEASURE_TEMP:
255  break;
258  break;
260  FAS_ASSERT(calculatedArrayPosition < (MXM_MAXIMUM_NR_OF_MODULES));
261  break;
262  default:
264  break; /* LCOV_EXCL_LINE */
265  }
266 
267  FAS_ASSERT(i <= voltRxBufferLength);
268  FAS_ASSERT((i + (uint16_t)1u) <= voltRxBufferLength);
269  MXM_Convert(
270  kpkVoltRxBuffer[i],
271  kpkVoltRxBuffer[i + 1u],
272  &pVoltagesTarget[calculatedArrayPosition],
273  conversionType,
274  fullScaleReference_mV);
275  }
276 }
277 
279  const uint8_t *const kpkVoltageRxBuffer,
280  uint16_t voltageRxBufferLength,
281  MXM_DATA_STORAGE_s *datastorage,
282  MXM_CONVERSION_TYPE_e conversionType) {
283  STD_RETURN_TYPE_e retval = STD_OK;
284  FAS_ASSERT(kpkVoltageRxBuffer != NULL_PTR);
285  FAS_ASSERT(datastorage != NULL_PTR);
286  /* AXIVION Routine Generic-MissingParameterAssert: voltageRxBufferLength: parameter accepts whole range */
287  /* AXIVION Routine Generic-MissingParameterAssert: conversionType: parameter accepts whole range */
288 
289  if (kpkVoltageRxBuffer[0] != BATTERY_MANAGEMENT_READALL) {
290  /* rxBuffer does not contain a READALL command */
291  retval = STD_NOT_OK;
292  } else if ((voltageRxBufferLength % 2u) != 0u) {
293  /* without alive counter rx-buffer always should be of even length */
294  /* TODO impact of alive-counter-byte */
295  retval = STD_NOT_OK;
296  } else if (
297  (conversionType != MXM_CONVERSION_UNIPOLAR) && (conversionType != MXM_CONVERSION_BIPOLAR) &&
298  (conversionType != MXM_CONVERSION_BLOCK_VOLTAGE)) {
299  /* conversion type is not supported */
300  retval = STD_NOT_OK;
301  } else {
302  switch (kpkVoltageRxBuffer[1]) {
303  case (uint8_t)MXM_REG_CELL1:
305  kpkVoltageRxBuffer,
306  voltageRxBufferLength,
308  conversionType,
309  datastorage->cellVoltages_mV,
312  break;
313  case (uint8_t)MXM_REG_CELL2:
315  kpkVoltageRxBuffer,
316  voltageRxBufferLength,
318  conversionType,
319  datastorage->cellVoltages_mV,
322  break;
323  case (uint8_t)MXM_REG_CELL3:
325  kpkVoltageRxBuffer,
326  voltageRxBufferLength,
328  conversionType,
329  datastorage->cellVoltages_mV,
332  break;
333  case (uint8_t)MXM_REG_CELL4:
335  kpkVoltageRxBuffer,
336  voltageRxBufferLength,
338  conversionType,
339  datastorage->cellVoltages_mV,
342  break;
343  case (uint8_t)MXM_REG_CELL5:
345  kpkVoltageRxBuffer,
346  voltageRxBufferLength,
348  conversionType,
349  datastorage->cellVoltages_mV,
352  break;
353  case (uint8_t)MXM_REG_CELL6:
355  kpkVoltageRxBuffer,
356  voltageRxBufferLength,
358  conversionType,
359  datastorage->cellVoltages_mV,
362  break;
363  case (uint8_t)MXM_REG_CELL7:
365  kpkVoltageRxBuffer,
366  voltageRxBufferLength,
368  conversionType,
369  datastorage->cellVoltages_mV,
372  break;
373  case (uint8_t)MXM_REG_CELL8:
375  kpkVoltageRxBuffer,
376  voltageRxBufferLength,
378  conversionType,
379  datastorage->cellVoltages_mV,
382  break;
383  case (uint8_t)MXM_REG_CELL9:
385  kpkVoltageRxBuffer,
386  voltageRxBufferLength,
388  conversionType,
389  datastorage->cellVoltages_mV,
392  break;
393  case (uint8_t)MXM_REG_CELL10:
395  kpkVoltageRxBuffer,
396  voltageRxBufferLength,
398  conversionType,
399  datastorage->cellVoltages_mV,
402  break;
403  case (uint8_t)MXM_REG_CELL11:
405  kpkVoltageRxBuffer,
406  voltageRxBufferLength,
408  conversionType,
409  datastorage->cellVoltages_mV,
412  break;
413  case (uint8_t)MXM_REG_CELL12:
415  kpkVoltageRxBuffer,
416  voltageRxBufferLength,
418  conversionType,
419  datastorage->cellVoltages_mV,
422  break;
423  case (uint8_t)MXM_REG_CELL13:
425  kpkVoltageRxBuffer,
426  voltageRxBufferLength,
428  conversionType,
429  datastorage->cellVoltages_mV,
432  break;
433  case (uint8_t)MXM_REG_CELL14:
435  kpkVoltageRxBuffer,
436  voltageRxBufferLength,
438  conversionType,
439  datastorage->cellVoltages_mV,
442  break;
443  case (uint8_t)MXM_REG_AUX0:
445  kpkVoltageRxBuffer,
446  voltageRxBufferLength,
448  conversionType,
449  datastorage->auxVoltages_mV,
452  break;
453  case (uint8_t)MXM_REG_AUX2:
455  kpkVoltageRxBuffer,
456  voltageRxBufferLength,
458  conversionType,
459  datastorage->auxVoltages_mV,
462  break;
463  case (uint8_t)MXM_REG_AUX3:
465  kpkVoltageRxBuffer,
466  voltageRxBufferLength,
468  conversionType,
469  datastorage->auxVoltages_mV,
472  break;
473  case (uint8_t)MXM_REG_BLOCK:
475  kpkVoltageRxBuffer,
476  voltageRxBufferLength,
478  conversionType,
479  datastorage->blockVoltages,
481  65000u);
482  /* TODO scaling and variable size (65000)*/
483  break;
484  default:
485  /* the read register is not a valid cell register */
486  retval = STD_NOT_OK;
487  break;
488  }
489  }
490  return retval;
491 }
492 
494  FAS_ASSERT(pInstance != NULL_PTR);
495  STD_RETURN_TYPE_e retval = STD_OK;
496 
497  /* AXIVION Disable Style Generic-NoMagicNumbers: This test function uses magic numbers to test predefined values. */
498 
499  uint8_t testBuffer[MXM_TEST_BUFFER_MAXIMUM_LENGTH] = {0};
500  uint16_t testBufferLength = MXM_TEST_BUFFER_MAXIMUM_LENGTH;
501  /* init test buffer */
502  for (uint8_t i = 0u; i < MXM_TEST_BUFFER_MAXIMUM_LENGTH; i++) {
503  testBuffer[i] = 0u;
504  }
505 
506  /* not a readall buffer */
507  testBuffer[0] = BATTERY_MANAGEMENT_HELLOALL;
508  if (MXM_ParseVoltageReadall(testBuffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
509  STD_NOT_OK) {
510  /* AXIVION Next Codeline Style FaultDetection-UnusedAssignments: return value collects all negative results. */
511  retval = STD_NOT_OK;
512  }
513 
514  /* not a cell voltage register */
515  testBuffer[0] = BATTERY_MANAGEMENT_READALL;
516  testBuffer[1] = (uint8_t)MXM_REG_VERSION;
517  if (MXM_ParseVoltageReadall(testBuffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
518  STD_NOT_OK) {
519  /* AXIVION Next Codeline Style FaultDetection-UnusedAssignments: return value collects all negative results. */
520  retval = STD_NOT_OK;
521  }
522 
523  /* bogus conversion type */
524  testBuffer[0] = BATTERY_MANAGEMENT_READALL;
525  testBuffer[1] = (uint8_t)MXM_REG_CELL1;
526  /* AXIVION Next Codeline Style MisraC2012Directive-4.1 MisraC2012-10.5: explicitly invalid value in order to provoke error response */
527  if (MXM_ParseVoltageReadall(testBuffer, testBufferLength, &pInstance->localVoltages, (MXM_CONVERSION_TYPE_e)42) !=
528  STD_NOT_OK) {
529  /* AXIVION Next Codeline Style FaultDetection-UnusedAssignments: return value collects all negative results. */
530  retval = STD_NOT_OK;
531  }
532 
533  /* not an even length of rxBuffer */
534  testBuffer[0] = BATTERY_MANAGEMENT_READALL;
535  testBuffer[1] = (uint8_t)MXM_REG_CELL1;
536  testBufferLength = 5;
537  if (MXM_ParseVoltageReadall(testBuffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
538  STD_NOT_OK) {
539  /* AXIVION Next Codeline Style FaultDetection-UnusedAssignments: return value collects all negative results. */
540  retval = STD_NOT_OK;
541  }
542 
543  /* test data for CELL1REG */
544  testBuffer[0] = BATTERY_MANAGEMENT_READALL;
545  testBuffer[1] = (uint8_t)MXM_REG_CELL1;
546  testBuffer[2] = 0xFCu;
547  testBuffer[3] = 0xFFu;
548  testBuffer[4] = 0x00u;
549  testBuffer[5] = 0x00u;
550  testBuffer[6] = 0xFCu;
551  testBuffer[7] = 0xFFu;
552  testBuffer[8] = 0x42u; /* DATACHECKBYTE, irrelevant for function, filled with dummy bytes */
553  testBuffer[9] = 0x44u; /* CRCBYTE, irrelevant for function, filled with dummy bytes */
554  testBufferLength = 10u;
555  if (MXM_ParseVoltageReadall(testBuffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
556  STD_OK) {
557  /* AXIVION Next Codeline Style FaultDetection-UnusedAssignments: return value collects all negative results. */
558  retval = STD_NOT_OK;
559  } else {
560  if ((pInstance->localVoltages.cellVoltages_mV[0] != MXM_REF_UNIPOLAR_CELL_mV) ||
561  (pInstance->localVoltages.cellVoltages_mV[14] != 0u) ||
563  /* AXIVION Next Codeline Style FaultDetection-UnusedAssignments: return value collects all negative results. */
564  retval = STD_NOT_OK;
565  }
566  }
567 
568  /* null mxm_local_cellVoltages */
569  for (uint16_t i_0 = 0; i_0 < (MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE * MXM_MAXIMUM_NR_OF_MODULES); i_0++) {
570  pInstance->localVoltages.cellVoltages_mV[i_0] = 0;
571  }
572 
573  /* test data for CELL2REG */
574  testBuffer[0] = BATTERY_MANAGEMENT_READALL;
575  testBuffer[1] = (uint8_t)MXM_REG_CELL2;
576  testBuffer[2] = 0xFCu;
577  testBuffer[3] = 0xFFu;
578  testBuffer[4] = 0x00u;
579  testBuffer[5] = 0x00u;
580  testBuffer[6] = 0xFCu;
581  testBuffer[7] = 0xFFu;
582  testBuffer[8] = 0x42u; /* DATACHECKBYTE, irrelevant for function, filled with dummy bytes */
583  testBuffer[9] = 0x44u; /* CRCBYTE, irrelevant for function, filled with dummy bytes */
584  testBufferLength = 10;
585  if (MXM_ParseVoltageReadall(testBuffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
586  STD_OK) {
587  /* AXIVION Next Codeline Style FaultDetection-UnusedAssignments: return value collects all negative results. */
588  retval = STD_NOT_OK;
589  } else {
590  if ((pInstance->localVoltages.cellVoltages_mV[1] != MXM_REF_UNIPOLAR_CELL_mV) ||
591  (pInstance->localVoltages.cellVoltages_mV[15] != 0u) ||
593  /* AXIVION Next Codeline Style FaultDetection-UnusedAssignments: return value collects all negative results. */
594  retval = STD_NOT_OK;
595  }
596  }
597 
598  /* null mxm_local_cellVoltages */
599  for (uint16_t i_1 = 0; i_1 < (MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE * MXM_MAXIMUM_NR_OF_MODULES); i_1++) {
600  pInstance->localVoltages.cellVoltages_mV[i_1] = 0;
601  }
602 
603  /* test data for CELL3REG */
604  testBuffer[0] = BATTERY_MANAGEMENT_READALL;
605  testBuffer[1] = (uint8_t)MXM_REG_CELL3;
606  testBuffer[2] = 0xFCu;
607  testBuffer[3] = 0xFFu;
608  testBuffer[4] = 0x42u; /* DATACHECKBYTE, irrelevant for function, filled with dummy bytes */
609  testBuffer[5] = 0x44u; /* CRCBYTE, irrelevant for function, filled with dummy bytes */
610  testBufferLength = 6;
611  if (MXM_ParseVoltageReadall(testBuffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
612  STD_OK) {
613  /* AXIVION Next Codeline Style FaultDetection-UnusedAssignments: return value collects all negative results. */
614  retval = STD_NOT_OK;
615  } else {
617  /* AXIVION Next Codeline Style FaultDetection-UnusedAssignments: return value collects all negative results. */
618  retval = STD_NOT_OK;
619  }
620  }
621 
622  /* null mxm_local_cellVoltages */
623  for (uint16_t i_2 = 0; i_2 < (MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE * MXM_MAXIMUM_NR_OF_MODULES); i_2++) {
624  pInstance->localVoltages.cellVoltages_mV[i_2] = 0;
625  }
626 
627  /* test data for CELL4REG */
628  testBuffer[0] = BATTERY_MANAGEMENT_READALL;
629  testBuffer[1] = (uint8_t)MXM_REG_CELL4;
630  testBuffer[2] = 0xFCu;
631  testBuffer[3] = 0xFFu;
632  testBuffer[4] = 0x42u; /* DATACHECKBYTE, irrelevant for function, filled with dummy bytes */
633  testBuffer[5] = 0x44u; /* CRCBYTE, irrelevant for function, filled with dummy bytes */
634  testBufferLength = 6;
635  if (MXM_ParseVoltageReadall(testBuffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
636  STD_OK) {
637  /* AXIVION Next Codeline Style FaultDetection-UnusedAssignments: return value collects all negative results. */
638  retval = STD_NOT_OK;
639  } else {
641  /* AXIVION Next Codeline Style FaultDetection-UnusedAssignments: return value collects all negative results. */
642  retval = STD_NOT_OK;
643  }
644  }
645 
646  /* null mxm_local_cellVoltages */
647  for (uint16_t i_3 = 0; i_3 < (MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE * MXM_MAXIMUM_NR_OF_MODULES); i_3++) {
648  pInstance->localVoltages.cellVoltages_mV[i_3] = 0;
649  }
650 
651  /* test data for CELL5REG */
652  testBuffer[0] = BATTERY_MANAGEMENT_READALL;
653  testBuffer[1] = (uint8_t)MXM_REG_CELL5;
654  testBuffer[2] = 0xFCu;
655  testBuffer[3] = 0xFFu;
656  testBuffer[4] = 0x42u; /* DATACHECKBYTE, irrelevant for function, filled with dummy bytes */
657  testBuffer[5] = 0x44u; /* CRCBYTE, irrelevant for function, filled with dummy bytes */
658  testBufferLength = 6;
659  if (MXM_ParseVoltageReadall(testBuffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
660  STD_OK) {
661  /* AXIVION Next Codeline Style FaultDetection-UnusedAssignments: return value collects all negative results. */
662  retval = STD_NOT_OK;
663  } else {
665  /* AXIVION Next Codeline Style FaultDetection-UnusedAssignments: return value collects all negative results. */
666  retval = STD_NOT_OK;
667  }
668  }
669 
670  /* null mxm_local_cellVoltages */
671  for (uint16_t i_4 = 0; i_4 < (MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE * MXM_MAXIMUM_NR_OF_MODULES); i_4++) {
672  pInstance->localVoltages.cellVoltages_mV[i_4] = 0;
673  }
674 
675  /* test data for CELL6REG */
676  testBuffer[0] = BATTERY_MANAGEMENT_READALL;
677  testBuffer[1] = (uint8_t)MXM_REG_CELL6;
678  testBuffer[2] = 0xFCu;
679  testBuffer[3] = 0xFFu;
680  testBuffer[4] = 0x42u; /* DATACHECKBYTE, irrelevant for function, filled with dummy bytes */
681  testBuffer[5] = 0x44u; /* CRCBYTE, irrelevant for function, filled with dummy bytes */
682  testBufferLength = 6;
683  if (MXM_ParseVoltageReadall(testBuffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
684  STD_OK) {
685  /* AXIVION Next Codeline Style FaultDetection-UnusedAssignments: return value collects all negative results. */
686  retval = STD_NOT_OK;
687  } else {
689  /* AXIVION Next Codeline Style FaultDetection-UnusedAssignments: return value collects all negative results. */
690  retval = STD_NOT_OK;
691  }
692  }
693 
694  /* null mxm_local_cellVoltages */
695  for (uint16_t i_5 = 0; i_5 < (MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE * MXM_MAXIMUM_NR_OF_MODULES); i_5++) {
696  pInstance->localVoltages.cellVoltages_mV[i_5] = 0;
697  }
698 
699  /* test data for CELL7REG */
700  testBuffer[0] = BATTERY_MANAGEMENT_READALL;
701  testBuffer[1] = (uint8_t)MXM_REG_CELL7;
702  testBuffer[2] = 0xFCu;
703  testBuffer[3] = 0xFFu;
704  testBuffer[4] = 0x42u; /* DATACHECKBYTE, irrelevant for function, filled with dummy bytes */
705  testBuffer[5] = 0x44u; /* CRCBYTE, irrelevant for function, filled with dummy bytes */
706  testBufferLength = 6;
707  if (MXM_ParseVoltageReadall(testBuffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
708  STD_OK) {
709  /* AXIVION Next Codeline Style FaultDetection-UnusedAssignments: return value collects all negative results. */
710  retval = STD_NOT_OK;
711  } else {
713  /* AXIVION Next Codeline Style FaultDetection-UnusedAssignments: return value collects all negative results. */
714  retval = STD_NOT_OK;
715  }
716  }
717 
718  /* null mxm_local_cellVoltages */
719  for (uint16_t i_6 = 0; i_6 < (MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE * MXM_MAXIMUM_NR_OF_MODULES); i_6++) {
720  pInstance->localVoltages.cellVoltages_mV[i_6] = 0;
721  }
722 
723  /* test data for CELL8REG */
724  testBuffer[0] = BATTERY_MANAGEMENT_READALL;
725  testBuffer[1] = (uint8_t)MXM_REG_CELL8;
726  testBuffer[2] = 0xFCu;
727  testBuffer[3] = 0xFFu;
728  testBuffer[4] = 0x42u; /* DATACHECKBYTE, irrelevant for function, filled with dummy bytes */
729  testBuffer[5] = 0x44u; /* CRCBYTE, irrelevant for function, filled with dummy bytes */
730  testBufferLength = 6;
731  if (MXM_ParseVoltageReadall(testBuffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
732  STD_OK) {
733  /* AXIVION Next Codeline Style FaultDetection-UnusedAssignments: return value collects all negative results. */
734  retval = STD_NOT_OK;
735  } else {
737  /* AXIVION Next Codeline Style FaultDetection-UnusedAssignments: return value collects all negative results. */
738  retval = STD_NOT_OK;
739  }
740  }
741 
742  /* null mxm_local_cellVoltages */
743  for (uint16_t i_7 = 0; i_7 < (MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE * MXM_MAXIMUM_NR_OF_MODULES); i_7++) {
744  pInstance->localVoltages.cellVoltages_mV[i_7] = 0;
745  }
746 
747  /* test data for CELL9REG */
748  testBuffer[0] = BATTERY_MANAGEMENT_READALL;
749  testBuffer[1] = (uint8_t)MXM_REG_CELL9;
750  testBuffer[2] = 0xFCu;
751  testBuffer[3] = 0xFFu;
752  testBuffer[4] = 0x42u; /* DATACHECKBYTE, irrelevant for function, filled with dummy bytes */
753  testBuffer[5] = 0x44u; /* CRCBYTE, irrelevant for function, filled with dummy bytes */
754  testBufferLength = 6;
755  if (MXM_ParseVoltageReadall(testBuffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
756  STD_OK) {
757  /* AXIVION Next Codeline Style FaultDetection-UnusedAssignments: return value collects all negative results. */
758  retval = STD_NOT_OK;
759  } else {
761  /* AXIVION Next Codeline Style FaultDetection-UnusedAssignments: return value collects all negative results. */
762  retval = STD_NOT_OK;
763  }
764  }
765 
766  /* null mxm_local_cellVoltages */
767  for (uint16_t i_8 = 0; i_8 < (MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE * MXM_MAXIMUM_NR_OF_MODULES); i_8++) {
768  pInstance->localVoltages.cellVoltages_mV[i_8] = 0;
769  }
770 
771  /* test data for CELL10REG */
772  testBuffer[0] = BATTERY_MANAGEMENT_READALL;
773  testBuffer[1] = (uint8_t)MXM_REG_CELL10;
774  testBuffer[2] = 0xFCu;
775  testBuffer[3] = 0xFFu;
776  testBuffer[4] = 0x42u; /* DATACHECKBYTE, irrelevant for function, filled with dummy bytes */
777  testBuffer[5] = 0x44u; /* CRCBYTE, irrelevant for function, filled with dummy bytes */
778  testBufferLength = 6;
779  if (MXM_ParseVoltageReadall(testBuffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
780  STD_OK) {
781  /* AXIVION Next Codeline Style FaultDetection-UnusedAssignments: return value collects all negative results. */
782  retval = STD_NOT_OK;
783  } else {
785  /* AXIVION Next Codeline Style FaultDetection-UnusedAssignments: return value collects all negative results. */
786  retval = STD_NOT_OK;
787  }
788  }
789 
790  /* null mxm_local_cellVoltages */
791  for (uint16_t i_9 = 0; i_9 < (MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE * MXM_MAXIMUM_NR_OF_MODULES); i_9++) {
792  pInstance->localVoltages.cellVoltages_mV[i_9] = 0;
793  }
794 
795  /* test data for CELL11REG */
796  testBuffer[0] = BATTERY_MANAGEMENT_READALL;
797  testBuffer[1] = (uint8_t)MXM_REG_CELL11;
798  testBuffer[2] = 0xFCu;
799  testBuffer[3] = 0xFFu;
800  testBuffer[4] = 0x42u; /* DATACHECKBYTE, irrelevant for function, filled with dummy bytes */
801  testBuffer[5] = 0x44u; /* CRCBYTE, irrelevant for function, filled with dummy bytes */
802  testBufferLength = 6;
803  if (MXM_ParseVoltageReadall(testBuffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
804  STD_OK) {
805  /* AXIVION Next Codeline Style FaultDetection-UnusedAssignments: return value collects all negative results. */
806  retval = STD_NOT_OK;
807  } else {
809  /* AXIVION Next Codeline Style FaultDetection-UnusedAssignments: return value collects all negative results. */
810  retval = STD_NOT_OK;
811  }
812  }
813 
814  /* null mxm_local_cellVoltages */
815  for (uint16_t i_10 = 0; i_10 < (MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE * MXM_MAXIMUM_NR_OF_MODULES); i_10++) {
816  pInstance->localVoltages.cellVoltages_mV[i_10] = 0;
817  }
818 
819  /* test data for CELL12REG */
820  testBuffer[0] = BATTERY_MANAGEMENT_READALL;
821  testBuffer[1] = (uint8_t)MXM_REG_CELL12;
822  testBuffer[2] = 0xFCu;
823  testBuffer[3] = 0xFFu;
824  testBuffer[4] = 0x42u; /* DATACHECKBYTE, irrelevant for function, filled with dummy bytes */
825  testBuffer[5] = 0x44u; /* CRCBYTE, irrelevant for function, filled with dummy bytes */
826  testBufferLength = 6;
827  if (MXM_ParseVoltageReadall(testBuffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
828  STD_OK) {
829  /* AXIVION Next Codeline Style FaultDetection-UnusedAssignments: return value collects all negative results. */
830  retval = STD_NOT_OK;
831  } else {
833  /* AXIVION Next Codeline Style FaultDetection-UnusedAssignments: return value collects all negative results. */
834  retval = STD_NOT_OK;
835  }
836  }
837 
838  /* null mxm_local_cellVoltages */
839  for (uint16_t i_11 = 0; i_11 < (MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE * MXM_MAXIMUM_NR_OF_MODULES); i_11++) {
840  pInstance->localVoltages.cellVoltages_mV[i_11] = 0;
841  }
842 
843  /* test data for CELL13REG */
844  testBuffer[0] = BATTERY_MANAGEMENT_READALL;
845  testBuffer[1] = (uint8_t)MXM_REG_CELL13;
846  testBuffer[2] = 0xFCu;
847  testBuffer[3] = 0xFFu;
848  testBuffer[4] = 0x42u; /* DATACHECKBYTE, irrelevant for function, filled with dummy bytes */
849  testBuffer[5] = 0x44u; /* CRCBYTE, irrelevant for function, filled with dummy bytes */
850  testBufferLength = 6;
851  if (MXM_ParseVoltageReadall(testBuffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
852  STD_OK) {
853  /* AXIVION Next Codeline Style FaultDetection-UnusedAssignments: return value collects all negative results. */
854  retval = STD_NOT_OK;
855  } else {
857  /* AXIVION Next Codeline Style FaultDetection-UnusedAssignments: return value collects all negative results. */
858  retval = STD_NOT_OK;
859  }
860  }
861 
862  /* null mxm_local_cellVoltages */
863  for (uint16_t i_12 = 0; i_12 < (MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE * MXM_MAXIMUM_NR_OF_MODULES); i_12++) {
864  pInstance->localVoltages.cellVoltages_mV[i_12] = 0;
865  }
866 
867  /* test data for CELL14REG */
868  testBuffer[0] = BATTERY_MANAGEMENT_READALL;
869  testBuffer[1] = (uint8_t)MXM_REG_CELL14;
870  testBuffer[2] = 0xFCu;
871  testBuffer[3] = 0xFFu;
872  testBuffer[4] = 0x42u; /* DATACHECKBYTE, irrelevant for function, filled with dummy bytes */
873  testBuffer[5] = 0x44u; /* CRCBYTE, irrelevant for function, filled with dummy bytes */
874  testBufferLength = 6;
875  if (MXM_ParseVoltageReadall(testBuffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
876  STD_OK) {
877  /* AXIVION Next Codeline Style FaultDetection-UnusedAssignments: return value collects all negative results. */
878  retval = STD_NOT_OK;
879  } else {
881  retval = STD_NOT_OK;
882  }
883  }
884 
885  /* null mxm_local_cellVoltages */
886  for (uint16_t i_13 = 0; i_13 < (MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE * MXM_MAXIMUM_NR_OF_MODULES); i_13++) {
887  pInstance->localVoltages.cellVoltages_mV[i_13] = 0;
888  }
889 
890  /* AXIVION Enable Style Generic-NoMagicNumbers: */
891 
892  return retval;
893 }
894 
895 /*========== Extern Function Implementations ================================*/
897  FAS_ASSERT(pInstance != NULL_PTR);
898 
899  if (pInstance->errorCounter != 0u) {
900  const bool counterCanBeReset =
902  if (counterCanBeReset == true) {
903  pInstance->errorCounter = 0u;
904  pInstance->timestampLastError = 0u;
905  }
906  }
907 }
908 
909 extern void MXM_ErrorHandlerReset(MXM_MONITORING_INSTANCE_s *pInstance, bool immediateReset) {
910  FAS_ASSERT(pInstance != NULL_PTR);
911 
912  pInstance->timestampLastError = OS_GetTickCount();
913  pInstance->errorCounter++;
914 
915  if ((pInstance->errorCounter > MXM_MAXIMUM_ERROR_COUNT) || (immediateReset == true)) {
916  pInstance->resetNecessary = true;
917  }
918 }
919 
921  MXM_MONITORING_INSTANCE_s *pInstance,
923  FAS_ASSERT(pInstance != NULL_PTR);
924 
925  if (pInstance->requestStatus5x == MXM_5X_STATE_UNSENT) {
926  const STD_RETURN_TYPE_e setStateRequestReturn = MXM_5XSetStateRequest(
927  pInstance->pInstance5X,
929  pInstance->batteryCmdBuffer,
930  &pInstance->requestStatus5x);
931  FAS_ASSERT(setStateRequestReturn == STD_OK);
932  } else if (pInstance->requestStatus5x == MXM_5X_STATE_UNPROCESSED) {
933  /* wait for processing */
934  } else if (pInstance->requestStatus5x == MXM_5X_STATE_PROCESSED) {
935  /* continue to the substate specified by the request */
936  pInstance->operationSubstate = nextState;
938  } else if (pInstance->requestStatus5x == MXM_5X_STATE_ERROR) {
939  /* default-behavior: retry */
941  MXM_ErrorHandlerReset(pInstance, false);
942  } else {
943  /* invalid value, trap */
945  }
946 }
947 
949  MXM_MONITORING_INSTANCE_s *pInstance,
950  MXM_REG_NAME_e registerName,
952  FAS_ASSERT(pInstance != NULL_PTR);
953 
954  bool retval = false;
955  if (pInstance->requestStatus5x == MXM_5X_STATE_UNSENT) {
956  pInstance->batteryCmdBuffer.regAddress = registerName;
957  const STD_RETURN_TYPE_e setStateRequestReturn = MXM_5XSetStateRequest(
958  pInstance->pInstance5X, MXM_STATEMACH_5X_READALL, pInstance->batteryCmdBuffer, &pInstance->requestStatus5x);
959  FAS_ASSERT(setStateRequestReturn == STD_OK);
960  } else if (pInstance->requestStatus5x == MXM_5X_STATE_PROCESSED) {
962  pInstance->operationSubstate = nextState;
964  retval = true;
965  } else if (pInstance->requestStatus5x == MXM_5X_STATE_UNPROCESSED) {
966  /* wait for processing */
967  } else if (pInstance->requestStatus5x == MXM_5X_STATE_ERROR) {
968  /* try to reset state */
970  MXM_ErrorHandlerReset(pInstance, false);
971  } else {
972  /* invalid state */
974  }
975 
976  return retval;
977 }
978 
980  FAS_ASSERT(kpkInstance != NULL_PTR);
981  FAS_ASSERT(kpkInstance->pOpenWire_table != NULL_PTR);
982 
983  const uint8_t numberOfSatellites = MXM_5XGetNumberOfSatellites(kpkInstance->pInstance5X);
985  (((uint16_t)BATTERY_MANAGEMENT_TX_LENGTH_READALL + (2u * MXM_MAXIMUM_NR_OF_MODULES)) <= (uint8_t)UINT8_MAX),
986  "please check assumptions: code cannot handle number of modules");
987  const uint8_t messageLength = BATTERY_MANAGEMENT_TX_LENGTH_READALL + (2u * numberOfSatellites);
988  /* step over every byte-tuple in the RX-buffer */
989  for (uint8_t i = 2u; i < (messageLength - 2u); i = i + 2u) {
990  /* calculate current module number (first in RX-buffer is last in line) */
991  const uint8_t calculatedModuleNumberInDaisyChain = numberOfSatellites - ((i / 2u) - 1u) - 1u;
992  uint8_t stringNumber = 0u;
993  uint16_t moduleNumber = 0u;
994  MXM_ConvertModuleToString(calculatedModuleNumberInDaisyChain, &stringNumber, &moduleNumber);
995  const uint16_t calculatedModulePosition = moduleNumber * MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE;
996 
997  /* step over every cell in the module and update the openWire struct accordingly */
998  for (uint8_t c = 0u; c < MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE; c++) {
999  if (c < MXM_CELLS_IN_LSB) {
1000  /* cell numbers under 8 can be found in the LSB */
1001  const uint8_t mask = 1u << c;
1002  if ((uint8_t)(mask & kpkInstance->rxBuffer[i]) > 0u) {
1003  kpkInstance->pOpenWire_table->openWire[stringNumber][calculatedModulePosition + c] = 1;
1004  } else {
1005  kpkInstance->pOpenWire_table->openWire[stringNumber][calculatedModulePosition + c] = 0;
1006  }
1007  } else {
1008  /* cell numbers over or equal 8 can be found in the MSB */
1009  const uint8_t mask = 1u << (c - MXM_CELLS_IN_LSB);
1010  if ((uint8_t)(mask & kpkInstance->rxBuffer[i + 1u]) > 0u) {
1011  kpkInstance->pOpenWire_table->openWire[stringNumber][calculatedModulePosition + c] = 1;
1012  } else {
1013  kpkInstance->pOpenWire_table->openWire[stringNumber][calculatedModulePosition + c] = 0;
1014  }
1015  }
1016  }
1017  }
1018 
1019  /* write database block */
1020  const STD_RETURN_TYPE_e dataReturn = DATA_WRITE_DATA(kpkInstance->pOpenWire_table);
1021  return dataReturn;
1022 }
1023 
1025  FAS_ASSERT(pBalancingInstance != NULL_PTR);
1026  FAS_ASSERT(pBalancingInstance->pBalancingControl_table != NULL_PTR);
1027  /* check for impossible configuration */
1029  STD_RETURN_TYPE_e retval = STD_OK;
1030 
1031  /* Re-Initialize the cells to balance at each iteration */
1032  pBalancingInstance->cellsToBalance = 0u;
1033 
1034  /* /!\ WARNING
1035  In this function, EVEN cells refer to the even cells IN THE REAL MODULE, and NOT in the database index.
1036  --> EVEN cells in a module = ODD database index
1037  --> ODD cells in a module = EVEN database index
1038  e.g. : Cell 2 in the module corresponds to index 1 in the database
1039  the cell index is even, but the database index is odd. */
1040 
1041  /* Iterate over all the cells of the module 'moduleBalancingIndex' in a daisy-chain */
1042  if (pBalancingInstance->moduleBalancingIndex < MXM_MAXIMUM_NR_OF_MODULES) {
1043  for (uint8_t c = 0; c < BS_NR_OF_CELL_BLOCKS_PER_MODULE; c++) {
1044  /* Determine the position of the cell 'c' of module 'moduleBalancingIndex' in the DB */
1045  uint8_t stringNumber = 0u;
1046  uint16_t moduleNumber = 0u;
1047  MXM_ConvertModuleToString(pBalancingInstance->moduleBalancingIndex, &stringNumber, &moduleNumber);
1048  const uint16_t dBIndex = (moduleNumber * BS_NR_OF_CELL_BLOCKS_PER_MODULE) + c;
1049  if (pBalancingInstance->pBalancingControl_table->balancingState[stringNumber][dBIndex] == 1u) {
1050  /* Cell 'c' of module '::moduleBalancingIndex' needs to be balanced.
1051  Need to determine the balancing order --> even or odd cells?
1052  If the balancing order has not been determined before, need to do it. */
1053  if ((pBalancingInstance->evenCellsNeedBalancing == false) &&
1054  (pBalancingInstance->oddCellsNeedBalancing == false)) {
1055  if (((c % 2u) != 0u) && (pBalancingInstance->evenCellsBalancingProcessed == false)) {
1056  pBalancingInstance->evenCellsNeedBalancing = true;
1057  } else if (((c % 2u) == 0u) && (pBalancingInstance->oddCellsBalancingProcessed == false)) {
1058  pBalancingInstance->oddCellsNeedBalancing = true;
1059  } else {
1060  /* nothing to do */
1061  }
1062  }
1063  if ((pBalancingInstance->evenCellsNeedBalancing == true) && ((c % 2u) != 0u) &&
1064  /* If the even cells need to be balanced */
1065  (pBalancingInstance->evenCellsBalancingProcessed == false)) {
1066  pBalancingInstance->cellsToBalance |= ((uint16_t)0x01u << c);
1067  } else if (
1068  /* If the odd cells need to be balanced */
1069  (pBalancingInstance->oddCellsNeedBalancing == true) && ((c % 2u) == 0u) &&
1070  (pBalancingInstance->oddCellsBalancingProcessed == false)) {
1071  pBalancingInstance->cellsToBalance |= ((uint16_t)0x01u << c);
1072  } else {
1073  /* nothing to do */
1074  }
1075  }
1076  }
1077  } else {
1078  retval = STD_NOT_OK;
1079  }
1080  return retval;
1081 }
1082 
1084  FAS_ASSERT(kpkInstance != NULL_PTR);
1085  FAS_ASSERT(kpkInstance->pCellVoltages_table != NULL_PTR);
1086  FAS_ASSERT(kpkInstance->pCellTemperatures_table != NULL_PTR);
1088 
1089  uint16_t numberValidVoltageMeasurements[BS_NR_OF_STRINGS] = {0};
1090  /* voltages */
1091  for (uint8_t i_mod = 0; i_mod < (BS_NR_OF_MODULES_PER_STRING * BS_NR_OF_STRINGS); i_mod++) {
1092  const bool moduleIsConnected = MXM_CheckIfADeviceIsConnected(kpkInstance, i_mod);
1093  uint8_t stringNumber = 0u;
1094  uint16_t moduleNumber = 0u;
1095  MXM_ConvertModuleToString(i_mod, &stringNumber, &moduleNumber);
1096  FAS_ASSERT(stringNumber < BS_NR_OF_STRINGS);
1097  FAS_ASSERT(moduleNumber < BS_NR_OF_MODULES_PER_STRING);
1098  kpkInstance->pCellVoltages_table->moduleVoltage_mV[stringNumber][moduleNumber] =
1099  kpkInstance->localVoltages.blockVoltages[i_mod];
1100  /* every iteration that we hit a string first (module 0), we reset the packvoltage counter */
1101  if (moduleNumber == 0u) {
1102  kpkInstance->pCellVoltages_table->stringVoltage_mV[stringNumber] = 0;
1103  }
1104  kpkInstance->pCellVoltages_table->stringVoltage_mV[stringNumber] +=
1105  (int32_t)kpkInstance->localVoltages.blockVoltages[i_mod];
1106  FAS_ASSERT(
1107  BS_NR_OF_CELL_BLOCKS_PER_MODULE <= MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE); /*!< invalid configuration! */
1108  for (uint8_t cb = 0u; cb < BS_NR_OF_CELL_BLOCKS_PER_MODULE; cb++) {
1109  uint16_t cell_counter_max = ((uint16_t)i_mod * MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE) + cb;
1110  const uint16_t cellVoltageLocal_mV = kpkInstance->localVoltages.cellVoltages_mV[cell_counter_max];
1111  if ((int32_t)cellVoltageLocal_mV > INT16_MAX) {
1112  kpkInstance->pCellVoltages_table->cellVoltage_mV[stringNumber][i_mod][cb] = INT16_MAX;
1113  } else {
1114  kpkInstance->pCellVoltages_table->cellVoltage_mV[stringNumber][i_mod][cb] =
1115  (int16_t)cellVoltageLocal_mV;
1116  }
1118  kpkInstance->pCellVoltages_table->cellVoltage_mV[stringNumber][i_mod][cb], mxm_plausibleCellVoltages);
1119  if ((valueIsPlausible == STD_OK) && moduleIsConnected) {
1120  numberValidVoltageMeasurements[stringNumber]++;
1121  } else {
1122  /* Invalidate cell voltage measurement */
1123  kpkInstance->pCellVoltages_table->invalidCellVoltage[stringNumber][moduleNumber] |=
1124  ((uint64_t)1u << cb);
1125  }
1126  }
1127  }
1128 
1129  /* temperatures */
1130  uint16_t numberValidTemperatureMeasurements[BS_NR_OF_STRINGS] = {0};
1131  for (uint8_t i_mod = 0; i_mod < (BS_NR_OF_MODULES_PER_STRING * BS_NR_OF_STRINGS); i_mod++) {
1132  const bool moduleIsConnected = MXM_CheckIfADeviceIsConnected(kpkInstance, i_mod);
1133  uint8_t stringNumber = 0u;
1134  uint16_t moduleNumber = 0u;
1135  MXM_ConvertModuleToString(i_mod, &stringNumber, &moduleNumber);
1136  FAS_ASSERT(stringNumber < BS_NR_OF_STRINGS);
1137  FAS_ASSERT(moduleNumber < BS_NR_OF_MODULES_PER_STRING);
1138 
1139  /* store aux measurement from AUX2 (MUX0) */
1140  if (kpkInstance->muxCounter < BS_NR_OF_TEMP_SENSORS_PER_MODULE) {
1141  const uint16_t temperatureIndexDb = kpkInstance->muxCounter;
1142  const uint16_t temperatureIndexMxm = ((uint16_t)i_mod * MXM_MAXIMUM_NR_OF_AUX_PER_MODULE) + 2u;
1143  const uint16_t auxVoltage_mV = kpkInstance->localVoltages.auxVoltages_mV[temperatureIndexMxm];
1144  /* const uint16_t temporaryVoltage = (auxVoltage_mV / ((float_t)3300 - auxVoltage_mV)) * 1000; */
1145  const int16_t temperature_ddegC = TSI_GetTemperature(auxVoltage_mV);
1146  kpkInstance->pCellTemperatures_table
1147  ->cellTemperature_ddegC[stringNumber][moduleNumber][temperatureIndexDb] = temperature_ddegC;
1148  const STD_RETURN_TYPE_e valueIsPlausible = AFE_PlausibilityCheckTempMinMax(temperature_ddegC);
1149  if ((valueIsPlausible == STD_OK) && moduleIsConnected) {
1150  numberValidTemperatureMeasurements[stringNumber]++;
1151  } else {
1152  /* Invalidate temperature measurement */
1153  kpkInstance->pCellTemperatures_table->invalidCellTemperature[stringNumber][moduleNumber] |=
1154  ((uint16_t)1u << kpkInstance->muxCounter);
1155  }
1156  }
1157  }
1158 
1159  for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) {
1160  kpkInstance->pCellVoltages_table->nrValidCellVoltages[s] = numberValidVoltageMeasurements[s];
1161  kpkInstance->pCellTemperatures_table->nrValidTemperatures[s] = numberValidTemperatureMeasurements[s];
1162  }
1163 
1165 
1166  return retval;
1167 }
1168 
1170  MXM_BALANCING_STATE_s *pBalancingInstance,
1171  MXM_MONITORING_INSTANCE_s *pMonitoringInstance) {
1172  FAS_ASSERT(pBalancingInstance != NULL_PTR);
1173  FAS_ASSERT(pMonitoringInstance != NULL_PTR);
1174 
1175  pBalancingInstance->moduleBalancingIndex = 0u;
1176  pBalancingInstance->evenCellsNeedBalancing = false;
1177  pBalancingInstance->oddCellsNeedBalancing = false;
1178  pBalancingInstance->evenCellsBalancingProcessed = false;
1179  pBalancingInstance->oddCellsBalancingProcessed = false;
1180  pBalancingInstance->cellsToBalance = 0u;
1181  pBalancingInstance->previousTimeStamp = 0u;
1182  pBalancingInstance->currentTimeStamp = 0u;
1183 
1184  pMonitoringInstance->resetNecessary = false;
1185  pMonitoringInstance->errorCounter = 0u;
1186  pMonitoringInstance->timestampLastError = 0u;
1187  pMonitoringInstance->timestampInit = 0u;
1188  pMonitoringInstance->state = MXM_STATEMACHINE_STATES_UNINITIALIZED;
1189  pMonitoringInstance->operationSubstate = MXM_INIT_ENTRY;
1190  pMonitoringInstance->allowStartup = false;
1191  pMonitoringInstance->operationRequested = false;
1192  pMonitoringInstance->firstMeasurementDone = false;
1193  pMonitoringInstance->stopRequested = false;
1194  pMonitoringInstance->openWireRequested = false;
1195  pMonitoringInstance->undervoltageAlert = false;
1196  pMonitoringInstance->muxCounter = 0u;
1198  pMonitoringInstance->dcByte = MXM_DC_EMPTY;
1199  pMonitoringInstance->mxmVoltageCellCounter = 0u;
1200  pMonitoringInstance->highest5xDevice = 0u;
1201  pMonitoringInstance->requestStatus5x = MXM_5X_STATE_UNSENT;
1202  pMonitoringInstance->batteryCmdBuffer.regAddress = MXM_REG_VERSION;
1203  pMonitoringInstance->batteryCmdBuffer.lsb = 0u;
1204  pMonitoringInstance->batteryCmdBuffer.msb = 0u;
1205  pMonitoringInstance->batteryCmdBuffer.blocksize = 0u;
1206  pMonitoringInstance->batteryCmdBuffer.deviceAddress = 0u;
1207  pMonitoringInstance->batteryCmdBuffer.model = MXM_GetModelIdOfDaisyChain();
1208  pMonitoringInstance->resultSelfCheck = STD_NOT_OK;
1209  /* for the "static" pre-init self-checks: do not reset if the result has passed; it will not change; FMEA can change */
1210  pMonitoringInstance->selfCheck.fmeaStatusASCI = STD_NOT_OK;
1211 
1212  for (uint32_t i = 0u; i < (MXM_MAXIMUM_NR_OF_MODULES * MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE); i++) {
1213  pMonitoringInstance->localVoltages.cellVoltages_mV[i] = 0u;
1214  }
1215 
1216  for (uint32_t i = 0u; i < (MXM_MAXIMUM_NR_OF_MODULES * MXM_MAXIMUM_NR_OF_AUX_PER_MODULE); i++) {
1217  pMonitoringInstance->localVoltages.auxVoltages_mV[i] = 0u;
1218  }
1219 
1220  for (uint32_t i = 0u; i < MXM_MAXIMUM_NR_OF_MODULES; i++) {
1221  pMonitoringInstance->localVoltages.blockVoltages[i] = 0u;
1222  }
1223 
1224  for (uint32_t i = 0u; i < MXM_MAXIMUM_NR_OF_MODULES; i++) {
1225  pMonitoringInstance->registry[i].connected = false;
1226  pMonitoringInstance->registry[i].deviceAddress = 0u;
1227  pMonitoringInstance->registry[i].model = MXM_MODEL_ID_NONE;
1228  pMonitoringInstance->registry[i].siliconVersion = MXM_SILICON_VERSION_INVALID;
1229  pMonitoringInstance->registry[i].deviceID = 0u;
1230  pMonitoringInstance->registry[i].registerStatus1 = 0u;
1231  pMonitoringInstance->registry[i].registerStatus2 = 0u;
1232  pMonitoringInstance->registry[i].registerStatus3 = 0u;
1233  pMonitoringInstance->registry[i].registerFmea1 = 0u;
1234  pMonitoringInstance->registry[i].registerFmea2 = 0u;
1235  }
1236 
1237  for (uint32_t i = 0u; i < MXM_RX_BUFFER_LENGTH; i++) {
1238  pMonitoringInstance->rxBuffer[i] = 0u;
1239  }
1240 }
1241 
1243  FAS_ASSERT(pState != NULL_PTR);
1244  STD_RETURN_TYPE_e retval = STD_OK;
1245  MXM_SELFCHECK_s *selfCheck = &pState->selfCheck;
1246  FAS_ASSERT(selfCheck != NULL_PTR);
1247  if (selfCheck->crc == STD_NOT_OK) {
1248  selfCheck->crc = MXM_CRC8SelfTest();
1249  }
1250  if (selfCheck->conv == STD_NOT_OK) {
1251  selfCheck->conv = MXM_ConvertTest();
1252  }
1253  if (selfCheck->firstSetBit == STD_NOT_OK) {
1254  selfCheck->firstSetBit = MXM_FirstSetBitTest();
1255  }
1256  if (selfCheck->extractValueFromRegister == STD_NOT_OK) {
1258  }
1259  if (selfCheck->parseVoltageReadall == STD_NOT_OK) {
1260  selfCheck->parseVoltageReadall = MXM_ParseVoltageReadallTest(pState);
1261  }
1262  if (selfCheck->addressSpaceChecker == STD_NOT_OK) {
1264  }
1265 
1266  if ((selfCheck->crc == STD_OK) && (selfCheck->addressSpaceChecker == STD_OK) && (selfCheck->conv == STD_OK) &&
1267  (selfCheck->firstSetBit == STD_OK) && (selfCheck->extractValueFromRegister == STD_OK) &&
1268  (selfCheck->parseVoltageReadall == STD_OK)) {
1269  /* check has passed, return value already set */
1270  } else {
1271  retval = STD_NOT_OK;
1272  }
1273  /* report to diag module, Maxim driver reports always to string 0 (current implementation just has one interface) */
1274  (void)DIAG_CheckEvent(retval, DIAG_ID_AFE_CONFIG, DIAG_SYSTEM, 0u);
1275 
1276  return retval;
1277 }
1278 
1281  FAS_ASSERT(pState != NULL_PTR);
1283  if (pState->requestStatus5x == MXM_5X_STATE_UNSENT) {
1284  pState->batteryCmdBuffer.regAddress = regAddress;
1285  const STD_RETURN_TYPE_e setStateRequestReturn = MXM_5XSetStateRequest(
1287  FAS_ASSERT(setStateRequestReturn == STD_OK);
1288  } else if (pState->requestStatus5x == MXM_5X_STATE_PROCESSED) {
1290  uint8_t temp_len = BATTERY_MANAGEMENT_TX_LENGTH_READALL +
1291  (2u * MXM_5XGetNumberOfSatellites(pState->pInstance5X));
1292  /* AXIVION Next Codeline Style FaultDetection-UnusedAssignments: default value is set as a safety measure */
1293  STD_RETURN_TYPE_e readallReturn = STD_NOT_OK;
1294  if (regAddress == MXM_REG_BLOCK) {
1295  readallReturn = MXM_ParseVoltageReadall(
1296  pState->rxBuffer, temp_len, &pState->localVoltages, MXM_CONVERSION_BLOCK_VOLTAGE);
1297  } else {
1298  readallReturn =
1300  }
1301  if (readallReturn == STD_NOT_OK) {
1302  MXM_ErrorHandlerReset(pState, false);
1303  }
1305  retval = MXM_MONITORING_STATE_PASS;
1306  } else if (pState->requestStatus5x == MXM_5X_STATE_UNPROCESSED) {
1307  /* do nothing */
1308  } else if (pState->requestStatus5x == MXM_5X_STATE_ERROR) {
1309  /* try to reset state */
1311  MXM_ErrorHandlerReset(pState, false);
1312  } else {
1313  /* invalid state */
1315  }
1316  return retval;
1317 }
1318 
1320  FAS_ASSERT(pInstance != NULL_PTR);
1321 
1322  if (pInstance->state == MXM_STATEMACHINE_STATES_UNINITIALIZED) {
1323  pInstance->requestStatus5x = MXM_5X_STATE_UNSENT;
1324  pInstance->timestampInit = OS_GetTickCount();
1325  MXM_MonRegistryInit(pInstance);
1327  }
1328 
1329  switch (pInstance->state) {
1331  pInstance->resultSelfCheck = MXM_PreInitSelfCheck(pInstance);
1332  if (pInstance->resultSelfCheck == STD_OK) {
1333  pInstance->requestStatus5x = MXM_5X_STATE_UNSENT;
1334  pInstance->state = MXM_STATEMACHINE_STATES_INIT;
1335  } else {
1336  /* software is broken by configuration/design */
1338  }
1339  break;
1341  if (pInstance->requestStatus5x == MXM_5X_STATE_UNSENT) {
1342  const STD_RETURN_TYPE_e setStateRequestReturn = MXM_5XSetStateRequest(
1343  pInstance->pInstance5X,
1345  pInstance->batteryCmdBuffer,
1346  &pInstance->requestStatus5x);
1347  FAS_ASSERT(setStateRequestReturn == STD_OK);
1348  } else if (pInstance->requestStatus5x == MXM_5X_STATE_UNPROCESSED) {
1349  /* just wait */
1350  } else if (pInstance->requestStatus5x == MXM_5X_STATE_ERROR) {
1351  /* do not reset state machine, but count error */
1352  MXM_ErrorHandlerReset(pInstance, false);
1353  } else if (pInstance->allowStartup == false) {
1354  /* do not start yet, just wait */
1355 
1356  } else if ((pInstance->requestStatus5x == MXM_5X_STATE_PROCESSED) && (pInstance->allowStartup == true)) {
1357  /* update registry */
1358  STD_RETURN_TYPE_e ConnectResult =
1360  FAS_ASSERT(ConnectResult == STD_OK);
1361  pInstance->requestStatus5x = MXM_5X_STATE_UNSENT;
1363  } else {
1365  }
1366 
1367  break;
1369  /* TODO more checks */
1370  pInstance->selfCheck.fmeaStatusASCI = STD_NOT_OK;
1371  if (pInstance->requestStatus5x == MXM_5X_STATE_UNSENT) {
1372  const STD_RETURN_TYPE_e stateRequestReturn = MXM_5XSetStateRequest(
1373  pInstance->pInstance5X,
1375  pInstance->batteryCmdBuffer,
1376  &pInstance->requestStatus5x);
1377  FAS_ASSERT(stateRequestReturn == STD_OK);
1378  } else if (pInstance->requestStatus5x == MXM_5X_STATE_UNPROCESSED) {
1379  /* just wait */
1380  } else if (pInstance->requestStatus5x == MXM_5X_STATE_ERROR) {
1381  /* this is a configuration or hardware failure */
1382  pInstance->selfCheck.fmeaStatusASCI = STD_NOT_OK;
1383  pInstance->resultSelfCheck = STD_NOT_OK;
1384  MXM_ErrorHandlerReset(pInstance, false);
1385  } else if (pInstance->requestStatus5x == MXM_5X_STATE_PROCESSED) {
1386  pInstance->selfCheck.fmeaStatusASCI = STD_OK;
1387  const STD_RETURN_TYPE_e resultNumberOfSatellitesGood =
1389  /* report to diag module, Maxim driver reports always to string 0 (current implementation just has one interface) */
1390  (void)DIAG_CheckEvent(resultNumberOfSatellitesGood, DIAG_ID_AFE_CONFIG, DIAG_STRING, 0u);
1391  if ((pInstance->resultSelfCheck == STD_OK) && (pInstance->selfCheck.fmeaStatusASCI == STD_OK) &&
1392  (resultNumberOfSatellitesGood == STD_OK)) {
1393  pInstance->resultSelfCheck = STD_OK;
1394  pInstance->requestStatus5x = MXM_5X_STATE_UNSENT;
1395  pInstance->state = MXM_STATEMACHINE_STATES_IDLE;
1396  } else if (mxm_allowSkippingPostInitSelfCheck == true) {
1397  pInstance->resultSelfCheck = STD_NOT_OK;
1398  pInstance->requestStatus5x = MXM_5X_STATE_UNSENT;
1399  pInstance->state = MXM_STATEMACHINE_STATES_IDLE;
1400  } else {
1401  /* skipping the self-check is not allowed and it failed, try to reset */
1402  pInstance->resetNecessary = true;
1403  }
1404  } else {
1406  }
1407  break;
1409  pInstance->stopRequested = false;
1410  if (pInstance->operationRequested == true) {
1412  pInstance->operationSubstate = MXM_INIT_ENTRY;
1413  } else {
1414  /* Do nothing */
1415  }
1416  break;
1418  MXM_StateMachineOperation(pInstance);
1419  break;
1420  default:
1422  break; /* LCOV_EXCL_LINE */
1423  }
1424 }
1425 
1426 /*========== Externalized Static Function Implementations (Unit Test) =======*/
1427 #ifdef UNITY_UNIT_TEST
1428 extern STD_RETURN_TYPE_e TEST_MXM_ParseVoltageReadallTest(MXM_MONITORING_INSTANCE_s *pInstance) {
1429  return MXM_ParseVoltageReadallTest(pInstance);
1430 }
1431 extern STD_RETURN_TYPE_e TEST_MXM_ParseVoltagesIntoDB(MXM_MONITORING_INSTANCE_s *pInstance) {
1432  return MXM_ParseVoltagesIntoDB(pInstance);
1433 }
1434 extern STD_RETURN_TYPE_e TEST_MXM_ParseVoltageReadall(
1435  uint8_t *voltRxBuffer,
1436  uint16_t voltRxBufferLength,
1437  MXM_DATA_STORAGE_s *datastorage,
1438  MXM_CONVERSION_TYPE_e conversionType) {
1439  return MXM_ParseVoltageReadall(voltRxBuffer, voltRxBufferLength, datastorage, conversionType);
1440 }
1441 #endif
STD_RETURN_TYPE_e AFE_PlausibilityCheckTempMinMax(const int16_t cellTemperature_ddegC)
Cell temperature plausibility check.
STD_RETURN_TYPE_e AFE_PlausibilityCheckVoltageMeasurementRange(const int16_t cellVoltage_mV, const AFE_PLAUSIBILITY_VALUES_s plausibleValues)
Cell voltage measurement range plausibility check.
plausibility checks for cell voltage and cell temperatures
#define BS_NR_OF_CELL_BLOCKS_PER_MODULE
number of cells per module
#define BS_NR_OF_STRINGS
Number of parallel strings in the battery pack.
#define BS_NR_OF_TEMP_SENSORS_PER_MODULE
number of temperature sensors per battery module
#define BS_NR_OF_MODULES_PER_STRING
number of modules in a string
Database module header.
#define DATA_WRITE_DATA(...)
Definition: database.h:96
STD_RETURN_TYPE_e DIAG_CheckEvent(STD_RETURN_TYPE_e cond, DIAG_ID_e diagId, DIAG_IMPACT_LEVEL_e impact, uint32_t data)
DIAG_CheckEvent provides a simple interface to check an event for STD_OK.
Definition: diag.c:374
Diagnosis driver header.
@ DIAG_SYSTEM
Definition: diag_cfg.h:280
@ DIAG_STRING
Definition: diag_cfg.h:281
@ DIAG_ID_AFE_CONFIG
Definition: diag_cfg.h:183
Assert macro implementation.
#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
#define FAS_STATIC_ASSERT(cond, msg)
Definition: fassert.h:285
Definition of foxBMS standard types.
STD_RETURN_TYPE_e
Definition: fstd_types.h:82
@ 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
General macros and definitions for the whole platform.
#define GEN_MUST_CHECK_RETURN
Allows functions to generate warnings in GCC for unused returns.
Definition: general.h:87
void MXM_CheckIfErrorCounterCanBeReset(MXM_MONITORING_INSTANCE_s *pInstance)
Function that checks if the error counter can be reset.
Definition: mxm_1785x.c:896
#define MXM_OFFSET_AUX0
Definition: mxm_1785x.c:94
#define MXM_TEST_BUFFER_MAXIMUM_LENGTH
Definition: mxm_1785x.c:106
STD_RETURN_TYPE_e MXM_PreInitSelfCheck(MXM_MONITORING_INSTANCE_s *pState)
Execute all preinit selfchecks.
Definition: mxm_1785x.c:1242
#define MXM_OFFSET_CELL_13
Definition: mxm_1785x.c:92
void MXM_ErrorHandlerReset(MXM_MONITORING_INSTANCE_s *pInstance, bool immediateReset)
This error handler is used as a last resort and tries a reset of the complete driver.
Definition: mxm_1785x.c:909
static STD_RETURN_TYPE_e MXM_ParseVoltageReadall(const uint8_t *const kpkVoltageRxBuffer, uint16_t voltageRxBufferLength, MXM_DATA_STORAGE_s *datastorage, MXM_CONVERSION_TYPE_e conversionType)
Parse a RX buffer containing voltage values.
Definition: mxm_1785x.c:278
bool GEN_MUST_CHECK_RETURN MXM_HandleStateReadall(MXM_MONITORING_INSTANCE_s *pInstance, MXM_REG_NAME_e registerName, MXM_STATEMACHINE_OPERATION_STATES_e nextState)
Handle the state machine-transactions for a READALL.
Definition: mxm_1785x.c:948
static const AFE_PLAUSIBILITY_VALUES_s mxm_plausibleCellVoltages
Definition: mxm_1785x.c:109
#define MXM_OFFSET_CELL_11
Definition: mxm_1785x.c:90
#define MXM_OFFSET_CELL_6
Definition: mxm_1785x.c:85
STD_RETURN_TYPE_e MXM_ProcessOpenWire(const MXM_MONITORING_INSTANCE_s *const kpkInstance)
Processes the retrieved information on open wire.
Definition: mxm_1785x.c:979
#define MXM_OFFSET_CELL_1
Definition: mxm_1785x.c:80
#define MXM_OFFSET_CELL_7
Definition: mxm_1785x.c:86
#define MXM_OFFSET_CELL_10
Definition: mxm_1785x.c:89
STD_RETURN_TYPE_e MXM_ParseVoltagesIntoDB(const MXM_MONITORING_INSTANCE_s *const kpkInstance)
Copies measured voltage data into the database.
Definition: mxm_1785x.c:1083
#define MXM_OFFSET_CELL_14
Definition: mxm_1785x.c:93
#define MXM_OFFSET_BLOCK
Definition: mxm_1785x.c:97
#define MXM_OFFSET_CELL_8
Definition: mxm_1785x.c:87
#define MXM_OFFSET_CELL_5
Definition: mxm_1785x.c:84
#define MXM_OFFSET_CELL_4
Definition: mxm_1785x.c:83
static void MXM_GetDataFrom5XStateMachine(MXM_MONITORING_INSTANCE_s *pInstance)
Retrieves data from lower state machine and writes it to the rx buffer.
Definition: mxm_1785x.c:199
STD_RETURN_TYPE_e MXM_ConstructBalancingBuffer(MXM_BALANCING_STATE_s *pBalancingInstance)
Fill the balancing data structure.
Definition: mxm_1785x.c:1024
#define MXM_OFFSET_AUX2
Definition: mxm_1785x.c:95
#define MXM_OFFSET_CELL_9
Definition: mxm_1785x.c:88
#define MXM_OFFSET_CELL_2
Definition: mxm_1785x.c:81
static void MXM_ParseVoltageLineReadall(const uint8_t *const kpkVoltRxBuffer, uint16_t voltRxBufferLength, uint8_t measurementOffset, MXM_CONVERSION_TYPE_e conversionType, uint16_t *pVoltagesTarget, MXM_MEASURE_TYPE_e measurementType, uint32_t fullScaleReference_mV)
Parse voltage values from a READALL receive buffer into an array.
Definition: mxm_1785x.c:207
void MXM_StateMachine(MXM_MONITORING_INSTANCE_s *pInstance)
Main state-machine implementation.
Definition: mxm_1785x.c:1319
#define MXM_MAXIMUM_ERROR_COUNT
Definition: mxm_1785x.c:100
static STD_RETURN_TYPE_e GEN_MUST_CHECK_RETURN MXM_ParseVoltageReadallTest(MXM_MONITORING_INSTANCE_s *pInstance)
Test the MXM_ParseVoltageReadall()-function.
Definition: mxm_1785x.c:493
#define MXM_REF_VAA_mV
VAA reference voltage (3.3V)
Definition: mxm_1785x.c:116
void MXM_InitializeStateStruct(MXM_BALANCING_STATE_s *pBalancingInstance, MXM_MONITORING_INSTANCE_s *pMonitoringInstance)
Initializes the state structs with default values.
Definition: mxm_1785x.c:1169
#define MXM_OFFSET_AUX3
Definition: mxm_1785x.c:96
#define MXM_TIMEOUT_RESET_ERROR_COUNTER_ms
Definition: mxm_1785x.c:103
MXM_MONITORING_STATE_e GEN_MUST_CHECK_RETURN MXM_MonGetVoltages(MXM_MONITORING_INSTANCE_s *pState, MXM_REG_NAME_e regAddress)
Encapsulation for reading voltages from a register.
Definition: mxm_1785x.c:1280
void MXM_HandleStateWriteall(MXM_MONITORING_INSTANCE_s *pInstance, MXM_STATEMACHINE_OPERATION_STATES_e nextState)
Handle the state machine-transactions for a WRITEALL.
Definition: mxm_1785x.c:920
#define MXM_OFFSET_CELL_3
Definition: mxm_1785x.c:82
#define MXM_OFFSET_CELL_12
Definition: mxm_1785x.c:91
Headers for the driver for the MAX17841B ASCI and MAX1785x analog front-end.
#define MXM_REF_UNIPOLAR_CELL_mV
Definition: mxm_1785x.h:111
MXM_MODEL_ID_e MXM_GetModelIdOfDaisyChain(void)
returns the model ID of the daisy chain
Definition: mxm_17852.c:96
#define MXM_CELLS_IN_LSB
Definition: mxm_1785x.h:108
void MXM_StateMachineOperation(MXM_MONITORING_INSTANCE_s *pState)
State-Machine implementation for operation state.
Definition: mxm_17852.c:100
#define MXM_THRESHOLD_DIAGNOSTIC_AFTER_CYCLES
Battery monitoring driver for MAX1785x battery monitoring ICs.
Definition: mxm_1785x.h:102
void MXM_ConvertModuleToString(const uint16_t moduleNumber, uint8_t *pStringNumber, uint16_t *pModuleNumberInString)
Get the string and module number from a global module number.
STD_RETURN_TYPE_e GEN_MUST_CHECK_RETURN MXM_ConvertTest(void)
Test the MXM_Convert()-function.
STD_RETURN_TYPE_e GEN_MUST_CHECK_RETURN MXM_ExtractValueFromRegisterTest(void)
Test MXM_ExtractValueFromRegister().
void MXM_Convert(uint8_t lsb, uint8_t msb, uint16_t *pTarget, MXM_CONVERSION_TYPE_e convType, uint32_t fullScaleReference_mV)
Convert a measurement value to a voltage value.
STD_RETURN_TYPE_e GEN_MUST_CHECK_RETURN MXM_FirstSetBitTest(void)
Test MXM_FirstSetBit().
This is a collection of helper functions for the MAX1785x ICs.
MXM_MONITORING_STATE_e
@ MXM_MONITORING_STATE_PASS
@ MXM_MONITORING_STATE_PENDING
MXM_STATEMACHINE_OPERATION_STATES_e
@ MXM_INIT_ENTRY
@ MXM_STATEMACHINE_STATES_OPERATION
@ MXM_STATEMACHINE_STATES_INIT
@ MXM_STATEMACHINE_STATES_SELFCHECK_POST_INIT
@ MXM_STATEMACHINE_STATES_UNINITIALIZED
@ MXM_STATEMACHINE_STATES_IDLE
@ MXM_STATEMACHINE_STATES_SELFCHECK_PRE_INIT
#define MXM_RX_BUFFER_LENGTH
Length of RX buffer.
@ MXM_SILICON_VERSION_INVALID
@ MXM_MODEL_ID_NONE
#define MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE
Maximum number of cells per module.
#define MXM_MAXIMUM_NR_OF_AUX_PER_MODULE
Maximum number of AUX ports per module.
@ MXM_DC_EMPTY
MXM_MEASURE_TYPE_e
@ MXM_MEASURE_CELL_VOLTAGE
@ MXM_MEASURE_BLOCK_VOLTAGE
@ MXM_MEASURE_TEMP
MXM_CONVERSION_TYPE_e
@ MXM_CONVERSION_BIPOLAR
@ MXM_CONVERSION_UNIPOLAR
@ MXM_CONVERSION_BLOCK_VOLTAGE
#define MXM_MAXIMUM_NR_OF_MODULES
Maximum number of modules.
STD_RETURN_TYPE_e GEN_MUST_CHECK_RETURN MXM_5XUserAccessibleAddressSpaceCheckerSelfCheck(void)
runs a selfcheck for the address space check
STD_RETURN_TYPE_e MXM_5XGetRXBuffer(const MXM_5X_INSTANCE_s *const kpkInstance, uint8_t *rxBuffer, uint16_t rxBufferLength)
Copy RX buffer into variable.
STD_RETURN_TYPE_e MXM_5XSetStateRequest(MXM_5X_INSTANCE_s *pInstance5x, MXM_STATEMACHINE_5X_e state, MXM_5X_COMMAND_PAYLOAD_s commandPayload, MXM_5X_STATE_REQUEST_STATUS_e *processed)
Set state request for the Battery Management Statemachine.
STD_RETURN_TYPE_e MXM_5XGetNumberOfSatellitesGood(const MXM_5X_INSTANCE_s *const kpkInstance)
Get the value of MXM_5X_INSTANCE_s::numberOfSatellitesIsGood.
MXM_DC_BYTE_e MXM_5XGetLastDCByte(const MXM_5X_INSTANCE_s *const kpkInstance)
Returns the last received DC byte.
uint8_t MXM_5XGetNumberOfSatellites(const MXM_5X_INSTANCE_s *const kpkInstance)
Get number of satellites.
Headers for the driver for the MAX17841B ASCI and MAX1785x analog front-end.
@ MXM_STATEMACH_5X_INIT
@ MXM_STATEMACH_5X_READALL
@ MXM_STATEMACH_5X_WRITEALL
@ MXM_STATEMACH_5X_41B_FMEA_CHECK
@ MXM_5X_STATE_UNSENT
@ MXM_5X_STATE_PROCESSED
@ MXM_5X_STATE_UNPROCESSED
@ MXM_5X_STATE_ERROR
#define BATTERY_MANAGEMENT_HELLOALL
HELLOALL message.
#define BATTERY_MANAGEMENT_READALL
READALL message (read single register of all daisy-chain devices)
#define BATTERY_MANAGEMENT_TX_LENGTH_READALL
Battery Management Protocol lengths of TX buffer.
const bool mxm_allowSkippingPostInitSelfCheck
Definition: mxm_cfg.c:69
STD_RETURN_TYPE_e GEN_MUST_CHECK_RETURN MXM_CRC8SelfTest(void)
Test the CRC8-algorithm with a known pattern.
Definition: mxm_crc8.c:147
MXM_REG_NAME_e
MAX1785x register names.
@ MXM_REG_CELL1
@ MXM_REG_CELL4
@ MXM_REG_AUX0
@ MXM_REG_CELL10
@ MXM_REG_AUX3
@ MXM_REG_VERSION
@ MXM_REG_CELL9
@ MXM_REG_BLOCK
@ MXM_REG_CELL3
@ MXM_REG_CELL14
@ MXM_REG_CELL6
@ MXM_REG_CELL2
@ MXM_REG_CELL11
@ MXM_REG_CELL5
@ MXM_REG_CELL13
@ MXM_REG_AUX2
@ MXM_REG_CELL7
@ MXM_REG_CELL8
@ MXM_REG_CELL12
bool MXM_CheckIfADeviceIsConnected(const MXM_MONITORING_INSTANCE_s *const kpkState, uint8_t device)
check if a device is connected
Definition: mxm_registry.c:266
void MXM_MonRegistryInit(MXM_MONITORING_INSTANCE_s *pState)
Initialize monitoring registry.
Definition: mxm_registry.c:83
STD_RETURN_TYPE_e MXM_MonRegistryConnectDevices(MXM_MONITORING_INSTANCE_s *pState, uint8_t numberOfDevices)
Mark devices as connected in the registry and set the address.
Definition: mxm_registry.c:100
Functions in order to have a registry of monitoring ICs.
bool OS_CheckTimeHasPassed(uint32_t oldTimeStamp_ms, uint32_t timeToPass_ms)
This function checks if timeToPass has passed since the last timestamp to now.
Definition: os.c:150
Declaration of the OS wrapper interface.
uint32_t OS_GetTickCount(void)
Returns OS based system tick value.
Definition: os_freertos.c:158
struct definition for plausibility values of an AFE
const int16_t maximumPlausibleVoltage_mV
uint8_t balancingState[BS_NR_OF_STRINGS][BS_NR_OF_CELL_BLOCKS_PER_STRING]
Definition: database_cfg.h:260
int16_t cellTemperature_ddegC[BS_NR_OF_STRINGS][BS_NR_OF_MODULES_PER_STRING][BS_NR_OF_TEMP_SENSORS_PER_MODULE]
Definition: database_cfg.h:156
uint16_t nrValidTemperatures[BS_NR_OF_STRINGS]
Definition: database_cfg.h:159
uint16_t invalidCellTemperature[BS_NR_OF_STRINGS][BS_NR_OF_MODULES_PER_STRING]
Definition: database_cfg.h:158
int16_t cellVoltage_mV[BS_NR_OF_STRINGS][BS_NR_OF_MODULES_PER_STRING][BS_NR_OF_CELL_BLOCKS_PER_MODULE]
Definition: database_cfg.h:139
uint64_t invalidCellVoltage[BS_NR_OF_STRINGS][BS_NR_OF_MODULES_PER_STRING]
Definition: database_cfg.h:142
uint16_t nrValidCellVoltages[BS_NR_OF_STRINGS]
Definition: database_cfg.h:143
uint32_t moduleVoltage_mV[BS_NR_OF_STRINGS][BS_NR_OF_MODULES_PER_STRING]
Definition: database_cfg.h:144
int32_t stringVoltage_mV[BS_NR_OF_STRINGS]
Definition: database_cfg.h:137
uint8_t openWire[BS_NR_OF_STRINGS][BS_NR_OF_MODULES_PER_STRING *(BS_NR_OF_CELL_BLOCKS_PER_MODULE+1u)]
Definition: database_cfg.h:315
DATA_BLOCK_BALANCING_CONTROL_s *const pBalancingControl_table
uint16_t blockVoltages[MXM_MAXIMUM_NR_OF_MODULES]
uint16_t auxVoltages_mV[MXM_MAXIMUM_NR_OF_MODULES *MXM_MAXIMUM_NR_OF_AUX_PER_MODULE]
uint16_t cellVoltages_mV[MXM_MAXIMUM_NR_OF_MODULES *MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE]
MXM_5X_COMMAND_PAYLOAD_s batteryCmdBuffer
STD_RETURN_TYPE_e resultSelfCheck
DATA_BLOCK_OPEN_WIRE_s *const pOpenWire_table
MXM_STATEMACHINE_OPERATION_STATES_e operationSubstate
uint8_t rxBuffer[MXM_RX_BUFFER_LENGTH]
MXM_REGISTRY_ENTRY_s registry[MXM_MAXIMUM_NR_OF_MODULES]
MXM_STATEMACHINE_STATES_e state
MXM_5X_INSTANCE_s *const pInstance5X
MXM_5X_STATE_REQUEST_STATUS_e requestStatus5x
MXM_DATA_STORAGE_s localVoltages
Local storage for cell-voltages.
DATA_BLOCK_CELL_VOLTAGE_s *const pCellVoltages_table
DATA_BLOCK_CELL_TEMPERATURE_s *const pCellTemperatures_table
MXM_SILICON_VERSION_e siliconVersion
uint16_t registerStatus2
uint16_t registerStatus3
uint32_t deviceID
uint16_t registerFmea2
uint8_t deviceAddress
MXM_MODEL_ID_e model
uint16_t registerStatus1
uint16_t registerFmea1
bool connected
STD_RETURN_TYPE_e firstSetBit
STD_RETURN_TYPE_e parseVoltageReadall
STD_RETURN_TYPE_e fmeaStatusASCI
STD_RETURN_TYPE_e crc
STD_RETURN_TYPE_e extractValueFromRegister
STD_RETURN_TYPE_e addressSpaceChecker
STD_RETURN_TYPE_e conv
Temperature Sensor Interface on Slave Unit driver header.
int16_t TSI_GetTemperature(uint16_t adcVoltage_mV)
translate a voltage to a temperature