foxBMS  1.3.0
The foxBMS Battery Management System API Documentation
mxm_1785x.c
Go to the documentation of this file.
1 /**
2  *
3  * @copyright © 2010 - 2022, 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 2022-05-30 (date of last update)
47  * @version v1.3.0
48  * @ingroup DRIVERS
49  * @prefix MXM
50  *
51  * @brief Driver for the MAX17841B ASCI and MAX1785x monitoring chip
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 "mxm_1785x.h"
60 
61 #include "afe_plausibility.h"
62 #include "database.h"
63 #include "diag.h"
64 #include "mxm_1785x_tools.h"
65 #include "mxm_battery_management.h"
66 #include "mxm_registry.h"
67 #include "os.h"
68 #include "tsi.h"
69 
70 /*========== Macros and Definitions =========================================*/
71 
72 #define MXM_OFFSET_CELL_1 (0u) /*!< storage offset for cell 1 */
73 #define MXM_OFFSET_CELL_2 (1u) /*!< storage offset for cell 2 */
74 #define MXM_OFFSET_CELL_3 (2u) /*!< storage offset for cell 3 */
75 #define MXM_OFFSET_CELL_4 (3u) /*!< storage offset for cell 4 */
76 #define MXM_OFFSET_CELL_5 (4u) /*!< storage offset for cell 5 */
77 #define MXM_OFFSET_CELL_6 (5u) /*!< storage offset for cell 6 */
78 #define MXM_OFFSET_CELL_7 (6u) /*!< storage offset for cell 7 */
79 #define MXM_OFFSET_CELL_8 (7u) /*!< storage offset for cell 8 */
80 #define MXM_OFFSET_CELL_9 (8u) /*!< storage offset for cell 9 */
81 #define MXM_OFFSET_CELL_10 (9u) /*!< storage offset for cell 10 */
82 #define MXM_OFFSET_CELL_11 (10u) /*!< storage offset for cell 11 */
83 #define MXM_OFFSET_CELL_12 (11u) /*!< storage offset for cell 12 */
84 #define MXM_OFFSET_CELL_13 (12u) /*!< storage offset for cell 13 */
85 #define MXM_OFFSET_CELL_14 (13u) /*!< storage offset for cell 14 */
86 #define MXM_OFFSET_AUX0 (0u) /*!< storage offset for AUX0 */
87 #define MXM_OFFSET_AUX2 (2u) /*!< storage offset for AUX2 */
88 #define MXM_OFFSET_AUX3 (3u) /*!< storage offset for AUX3 */
89 #define MXM_OFFSET_BLOCK (0u) /*!< storage offset for block voltage */
90 
91 /** maximum number of errors that may occur before the next error triggers a reset */
92 #define MXM_MAXIMUM_ERROR_COUNT (10u)
93 
94 /** timeout after which the error counter will be reset */
95 #define MXM_TIMEOUT_RESET_ERROR_COUNTER_ms (500)
96 
97 /** maximum length of a test buffer */
98 #define MXM_TEST_BUFFER_MAXIMUM_LENGTH (120u)
99 
100 /** local definition of plausible cell voltage values */
103  .minimumPlausibleVoltage_mV = -2500,
104 };
105 
106 /*========== Static Constant and Variable Definitions =======================*/
107 /** @brief VAA reference voltage (3.3V) */
108 #define MXM_REF_VAA_mV (3300u)
109 
110 /*========== Extern Constant and Variable Definitions =======================*/
111 
112 /*========== Static Function Prototypes =====================================*/
113 
114 /** @brief Retrieves data from lower statemachine and writes it to the rx buffer. */
116 
117 /**
118  * @brief Parse voltage values from a READALL receive buffer into an
119  * array.
120  * @details This function expects a preprocessed RX buffer with an answer
121  * to a READALL command. It will parse the data bytes from this
122  * message into an array structured like mxm_local_cellvoltages.
123  * The offset of the measured cell has to be defined. For example
124  * cell 1 has an offset of 0 and cell 4 has an offset of 3. The
125  * offset for the READALL command is always defined in reference
126  * to module 0.
127  *
128  * If is_temperature_measurement is set to true, the function
129  * expects an auxiliary measurement (e.g. temperatures).
130  * @param[in] kpkVoltRxBuffer array-pointer to the RX buffer
131  * @param[in] voltRxBufferLength length of the RX buffer
132  * @param[in] measurementOffset offset of the data in the cell voltage
133  * array (target)
134  * @param[in] conversionType type of conversion that has been used
135  * for the measured data
136  * @param[out] pVoltagesTarget array-pointer to the cell voltages
137  * array
138  * @param[in] measurementType whether the measurement is temperature
139  * or cell
140  * @param[in] fullScaleReference_mV reference voltage of full scale
141  */
142 static void MXM_ParseVoltageLineReadall(
143  const uint8_t *const kpkVoltRxBuffer,
144  uint16_t voltRxBufferLength,
145  uint8_t measurementOffset,
146  MXM_CONVERSION_TYPE_e conversionType,
147  uint16_t *pVoltagesTarget,
148  MXM_MEASURE_TYPE_e measurementType,
149  uint32_t fullScaleReference_mV);
150 
151 /**
152  * @brief Parse a RX buffer containing voltage values.
153  * @details This function parses a RX buffer containing the answer to a
154  * READALL command. It will check whether the message contains a
155  * READALL command and whether a supported register has been
156  * queried.
157  * Depending on the queried register, it will pass the proper
158  * parameters to #MXM_ParseVoltageLineReadall(). The contained
159  * data from this message will be parsed into a struct structured
160  * like #MXM_MONITORING_INSTANCE_s::localVoltages.
161  * @param[in] kpkVoltageRxBuffer array-pointer to the RX buffer
162  * @param[in] voltageRxBufferLength length of the RX buffer
163  * @param[out] datastorage contains all measured voltages for local
164  * consumption in the module
165  * @param[in] conversionType type of conversion that has been used for
166  * the measured data
167  * @return #STD_NOT_OK in the case that the RX buffer does not contain a
168  * valid message or the conversion-type is unknown,
169  * otherwise #STD_OK
170  */
172  const uint8_t *const kpkVoltageRxBuffer,
173  uint16_t voltageRxBufferLength,
174  MXM_DATA_STORAGE_s *datastorage,
175  MXM_CONVERSION_TYPE_e conversionType);
176 
177 /**
178  * @brief Test the #MXM_ParseVoltageReadall()-function
179  * @details Test the function #MXM_ParseVoltageReadall() by passing predefined
180  * RX buffer to it and checking the outcome. This function writes to
181  * the variable #MXM_MONITORING_INSTANCE_s::localVoltages and nulls it
182  * completely after execution. It is intended as a self-check that can
183  * be performed during startup of the driver.
184  * @return #STD_OK if the self-check has been performed successfully,
185  * otherwise #STD_NOT_OK
186  */
188 
189 /*========== Static Function Implementations ================================*/
190 
192  FAS_ASSERT(pInstance != NULL_PTR);
193  STD_RETURN_TYPE_e getBufferResult =
195  FAS_ASSERT(getBufferResult == STD_OK);
196  pInstance->dcByte = MXM_5XGetLastDCByte(pInstance->pInstance5X);
197 }
198 
200  const uint8_t *const kpkVoltRxBuffer,
201  uint16_t voltRxBufferLength,
202  uint8_t measurementOffset,
203  MXM_CONVERSION_TYPE_e conversionType,
204  uint16_t *pVoltagesTarget,
205  MXM_MEASURE_TYPE_e measurementType,
206  uint32_t fullScaleReference_mV) {
207  FAS_ASSERT(kpkVoltRxBuffer != NULL_PTR);
208  FAS_ASSERT(pVoltagesTarget != NULL_PTR);
209  /* AXIVION Routine Generic-MissingParameterAssert: voltRxBufferLength: parameter accepts whole range */
210  /* AXIVION Routine Generic-MissingParameterAssert: measurementOffset: parameter accepts whole range */
211  /* AXIVION Routine Generic-MissingParameterAssert: conversionType: parameter accepts whole range */
212  /* AXIVION Routine Generic-MissingParameterAssert: measurementType: parameter accepts whole range */
213  /* AXIVION Routine Generic-MissingParameterAssert: fullScaleReference_mV: parameter accepts whole range */
214 
215  /* assert that assumptions behind computation of numberOfConnectedDevices
216  are correct */
217  FAS_ASSERT(voltRxBufferLength >= (2u + 2u));
218  FAS_ASSERT(((voltRxBufferLength - 2u - 2u) / 2u) <= (uint16_t)UINT8_MAX);
219  /* buffer-length - length of start - length of end divided by two (LSB and MSB) */
220  const uint8_t numberOfConnectedDevices = (uint8_t)(((voltRxBufferLength - 2u - 2u) / 2u) & (uint8_t)UINT8_MAX);
221  /* TODO impact of alive counter on rxBufferLength
222  * otherwise offset at the end of message is currently 2 (DATACHECKBYTE and CRC) */
223  for (uint8_t i = 2u; i < (voltRxBufferLength - 2u); i = i + 2u) {
224  const uint8_t calculatedModuleNumber = numberOfConnectedDevices - ((i / 2u) - 1u) - 1u;
225  uint16_t calculatedModulePosition = 0u;
226  switch (measurementType) {
227  case MXM_MEASURE_TEMP:
228  calculatedModulePosition = (uint16_t)calculatedModuleNumber * MXM_MAXIMUM_NR_OF_AUX_PER_MODULE;
229  break;
231  calculatedModulePosition = (uint16_t)calculatedModuleNumber * MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE;
232  break;
234  calculatedModulePosition = calculatedModuleNumber;
235  break;
236  default:
238  break;
239  }
240  FAS_ASSERT((calculatedModulePosition + measurementOffset) <= (uint16_t)UINT16_MAX);
241  uint16_t calculatedArrayPosition = calculatedModulePosition + measurementOffset;
242 
243  /* check calculated array position */
244  switch (measurementType) {
245  case MXM_MEASURE_TEMP:
247  break;
250  break;
252  FAS_ASSERT(calculatedArrayPosition < (MXM_MAXIMUM_NR_OF_MODULES));
253  break;
254  default:
256  break;
257  }
258 
259  FAS_ASSERT(i <= voltRxBufferLength);
260  FAS_ASSERT((i + (uint16_t)1u) <= voltRxBufferLength);
261  MXM_Convert(
262  kpkVoltRxBuffer[i],
263  kpkVoltRxBuffer[i + 1u],
264  &pVoltagesTarget[calculatedArrayPosition],
265  conversionType,
266  fullScaleReference_mV);
267  }
268 }
269 
271  const uint8_t *const kpkVoltageRxBuffer,
272  uint16_t voltageRxBufferLength,
273  MXM_DATA_STORAGE_s *datastorage,
274  MXM_CONVERSION_TYPE_e conversionType) {
275  STD_RETURN_TYPE_e retval = STD_OK;
276  FAS_ASSERT(kpkVoltageRxBuffer != NULL_PTR);
277  FAS_ASSERT(datastorage != NULL_PTR);
278  /* AXIVION Routine Generic-MissingParameterAssert: voltageRxBufferLength: parameter accepts whole range */
279  /* AXIVION Routine Generic-MissingParameterAssert: conversionType: parameter accepts whole range */
280 
281  if (kpkVoltageRxBuffer[0] != BATTERY_MANAGEMENT_READALL) {
282  /* rxBuffer does not contain a READALL command */
283  retval = STD_NOT_OK;
284  } else if ((voltageRxBufferLength % 2u) != 0u) {
285  /* without alive counter rx-buffer always should be of even length */
286  /* TODO impact of alive-counter-byte */
287  retval = STD_NOT_OK;
288  } else if (
289  (conversionType != MXM_CONVERSION_UNIPOLAR) && (conversionType != MXM_CONVERSION_BIPOLAR) &&
290  (conversionType != MXM_CONVERSION_BLOCK_VOLTAGE)) {
291  /* conversion type is not supported */
292  retval = STD_NOT_OK;
293  } else {
294  switch (kpkVoltageRxBuffer[1]) {
295  case (uint8_t)MXM_REG_CELL1:
297  kpkVoltageRxBuffer,
298  voltageRxBufferLength,
300  conversionType,
301  datastorage->cellVoltages_mV,
304  break;
305  case (uint8_t)MXM_REG_CELL2:
307  kpkVoltageRxBuffer,
308  voltageRxBufferLength,
310  conversionType,
311  datastorage->cellVoltages_mV,
314  break;
315  case (uint8_t)MXM_REG_CELL3:
317  kpkVoltageRxBuffer,
318  voltageRxBufferLength,
320  conversionType,
321  datastorage->cellVoltages_mV,
324  break;
325  case (uint8_t)MXM_REG_CELL4:
327  kpkVoltageRxBuffer,
328  voltageRxBufferLength,
330  conversionType,
331  datastorage->cellVoltages_mV,
334  break;
335  case (uint8_t)MXM_REG_CELL5:
337  kpkVoltageRxBuffer,
338  voltageRxBufferLength,
340  conversionType,
341  datastorage->cellVoltages_mV,
344  break;
345  case (uint8_t)MXM_REG_CELL6:
347  kpkVoltageRxBuffer,
348  voltageRxBufferLength,
350  conversionType,
351  datastorage->cellVoltages_mV,
354  break;
355  case (uint8_t)MXM_REG_CELL7:
357  kpkVoltageRxBuffer,
358  voltageRxBufferLength,
360  conversionType,
361  datastorage->cellVoltages_mV,
364  break;
365  case (uint8_t)MXM_REG_CELL8:
367  kpkVoltageRxBuffer,
368  voltageRxBufferLength,
370  conversionType,
371  datastorage->cellVoltages_mV,
374  break;
375  case (uint8_t)MXM_REG_CELL9:
377  kpkVoltageRxBuffer,
378  voltageRxBufferLength,
380  conversionType,
381  datastorage->cellVoltages_mV,
384  break;
385  case (uint8_t)MXM_REG_CELL10:
387  kpkVoltageRxBuffer,
388  voltageRxBufferLength,
390  conversionType,
391  datastorage->cellVoltages_mV,
394  break;
395  case (uint8_t)MXM_REG_CELL11:
397  kpkVoltageRxBuffer,
398  voltageRxBufferLength,
400  conversionType,
401  datastorage->cellVoltages_mV,
404  break;
405  case (uint8_t)MXM_REG_CELL12:
407  kpkVoltageRxBuffer,
408  voltageRxBufferLength,
410  conversionType,
411  datastorage->cellVoltages_mV,
414  break;
415  case (uint8_t)MXM_REG_CELL13:
417  kpkVoltageRxBuffer,
418  voltageRxBufferLength,
420  conversionType,
421  datastorage->cellVoltages_mV,
424  break;
425  case (uint8_t)MXM_REG_CELL14:
427  kpkVoltageRxBuffer,
428  voltageRxBufferLength,
430  conversionType,
431  datastorage->cellVoltages_mV,
434  break;
435  case (uint8_t)MXM_REG_AUX0:
437  kpkVoltageRxBuffer,
438  voltageRxBufferLength,
440  conversionType,
441  datastorage->auxVoltages_mV,
444  break;
445  case (uint8_t)MXM_REG_AUX2:
447  kpkVoltageRxBuffer,
448  voltageRxBufferLength,
450  conversionType,
451  datastorage->auxVoltages_mV,
454  break;
455  case (uint8_t)MXM_REG_AUX3:
457  kpkVoltageRxBuffer,
458  voltageRxBufferLength,
460  conversionType,
461  datastorage->auxVoltages_mV,
464  break;
465  case (uint8_t)MXM_REG_BLOCK:
467  kpkVoltageRxBuffer,
468  voltageRxBufferLength,
470  conversionType,
471  datastorage->blockVoltages,
473  65000u);
474  /* TODO scaling and variable size (65000)*/
475  break;
476  default:
477  /* the read register is not a valid cell register */
478  retval = STD_NOT_OK;
479  break;
480  }
481  }
482  return retval;
483 }
484 
486  FAS_ASSERT(pInstance != NULL_PTR);
487  STD_RETURN_TYPE_e retval = STD_OK;
488 
489  /* AXIVION Disable Style Generic-NoMagicNumbers: This test function uses magic numbers to test predefined values. */
490 
491  uint8_t testBuffer[MXM_TEST_BUFFER_MAXIMUM_LENGTH] = {0};
492  uint16_t testBufferLength = MXM_TEST_BUFFER_MAXIMUM_LENGTH;
493  /* init test buffer */
494  for (uint8_t i = 0u; i < MXM_TEST_BUFFER_MAXIMUM_LENGTH; i++) {
495  testBuffer[i] = 0u;
496  }
497 
498  /* not a readall buffer */
499  testBuffer[0] = BATTERY_MANAGEMENT_HELLOALL;
500  if (MXM_ParseVoltageReadall(testBuffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
501  STD_NOT_OK) {
502  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
503  retval = STD_NOT_OK;
504  }
505 
506  /* not a cell voltage register */
507  testBuffer[0] = BATTERY_MANAGEMENT_READALL;
508  testBuffer[1] = (uint8_t)MXM_REG_VERSION;
509  if (MXM_ParseVoltageReadall(testBuffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
510  STD_NOT_OK) {
511  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
512  retval = STD_NOT_OK;
513  }
514 
515  /* bogus conversion type */
516  testBuffer[0] = BATTERY_MANAGEMENT_READALL;
517  testBuffer[1] = (uint8_t)MXM_REG_CELL1;
518  /* AXIVION Next Line Style MisraC2012Directive-4.1 MisraC2012-10.5: explicitely invalid value in order to provoke error response */
519  if (MXM_ParseVoltageReadall(testBuffer, testBufferLength, &pInstance->localVoltages, (MXM_CONVERSION_TYPE_e)42) !=
520  STD_NOT_OK) {
521  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
522  retval = STD_NOT_OK;
523  }
524 
525  /* not an even length of rxBuffer */
526  testBuffer[0] = BATTERY_MANAGEMENT_READALL;
527  testBuffer[1] = (uint8_t)MXM_REG_CELL1;
528  testBufferLength = 5;
529  if (MXM_ParseVoltageReadall(testBuffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
530  STD_NOT_OK) {
531  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
532  retval = STD_NOT_OK;
533  }
534 
535  /* test data for CELL1REG */
536  testBuffer[0] = BATTERY_MANAGEMENT_READALL;
537  testBuffer[1] = (uint8_t)MXM_REG_CELL1;
538  testBuffer[2] = 0xFCu;
539  testBuffer[3] = 0xFFu;
540  testBuffer[4] = 0x00u;
541  testBuffer[5] = 0x00u;
542  testBuffer[6] = 0xFCu;
543  testBuffer[7] = 0xFFu;
544  testBuffer[8] = 0x42u; /* DATACHECKBYTE, irrelevant for function, filled with dummy bytes */
545  testBuffer[9] = 0x44u; /* CRCBYTE, irrelevant for function, filled with dummy bytes */
546  testBufferLength = 10u;
547  if (MXM_ParseVoltageReadall(testBuffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
548  STD_OK) {
549  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
550  retval = STD_NOT_OK;
551  } else {
552  if ((pInstance->localVoltages.cellVoltages_mV[0] != MXM_REF_UNIPOLAR_CELL_mV) ||
553  (pInstance->localVoltages.cellVoltages_mV[14] != 0u) ||
555  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
556  retval = STD_NOT_OK;
557  }
558  }
559 
560  /* null mxm_local_cellvoltages */
561  for (uint16_t i_0 = 0; i_0 < (MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE * MXM_MAXIMUM_NR_OF_MODULES); i_0++) {
562  pInstance->localVoltages.cellVoltages_mV[i_0] = 0;
563  }
564 
565  /* test data for CELL2REG */
566  testBuffer[0] = BATTERY_MANAGEMENT_READALL;
567  testBuffer[1] = (uint8_t)MXM_REG_CELL2;
568  testBuffer[2] = 0xFCu;
569  testBuffer[3] = 0xFFu;
570  testBuffer[4] = 0x00u;
571  testBuffer[5] = 0x00u;
572  testBuffer[6] = 0xFCu;
573  testBuffer[7] = 0xFFu;
574  testBuffer[8] = 0x42u; /* DATACHECKBYTE, irrelevant for function, filled with dummy bytes */
575  testBuffer[9] = 0x44u; /* CRCBYTE, irrelevant for function, filled with dummy bytes */
576  testBufferLength = 10;
577  if (MXM_ParseVoltageReadall(testBuffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
578  STD_OK) {
579  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
580  retval = STD_NOT_OK;
581  } else {
582  if ((pInstance->localVoltages.cellVoltages_mV[1] != MXM_REF_UNIPOLAR_CELL_mV) ||
583  (pInstance->localVoltages.cellVoltages_mV[15] != 0u) ||
585  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
586  retval = STD_NOT_OK;
587  }
588  }
589 
590  /* null mxm_local_cellvoltages */
591  for (uint16_t i_1 = 0; i_1 < (MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE * MXM_MAXIMUM_NR_OF_MODULES); i_1++) {
592  pInstance->localVoltages.cellVoltages_mV[i_1] = 0;
593  }
594 
595  /* test data for CELL3REG */
596  testBuffer[0] = BATTERY_MANAGEMENT_READALL;
597  testBuffer[1] = (uint8_t)MXM_REG_CELL3;
598  testBuffer[2] = 0xFCu;
599  testBuffer[3] = 0xFFu;
600  testBuffer[4] = 0x42u; /* DATACHECKBYTE, irrelevant for function, filled with dummy bytes */
601  testBuffer[5] = 0x44u; /* CRCBYTE, irrelevant for function, filled with dummy bytes */
602  testBufferLength = 6;
603  if (MXM_ParseVoltageReadall(testBuffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
604  STD_OK) {
605  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
606  retval = STD_NOT_OK;
607  } else {
609  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
610  retval = STD_NOT_OK;
611  }
612  }
613 
614  /* null mxm_local_cellvoltages */
615  for (uint16_t i_2 = 0; i_2 < (MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE * MXM_MAXIMUM_NR_OF_MODULES); i_2++) {
616  pInstance->localVoltages.cellVoltages_mV[i_2] = 0;
617  }
618 
619  /* test data for CELL4REG */
620  testBuffer[0] = BATTERY_MANAGEMENT_READALL;
621  testBuffer[1] = (uint8_t)MXM_REG_CELL4;
622  testBuffer[2] = 0xFCu;
623  testBuffer[3] = 0xFFu;
624  testBuffer[4] = 0x42u; /* DATACHECKBYTE, irrelevant for function, filled with dummy bytes */
625  testBuffer[5] = 0x44u; /* CRCBYTE, irrelevant for function, filled with dummy bytes */
626  testBufferLength = 6;
627  if (MXM_ParseVoltageReadall(testBuffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
628  STD_OK) {
629  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
630  retval = STD_NOT_OK;
631  } else {
633  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
634  retval = STD_NOT_OK;
635  }
636  }
637 
638  /* null mxm_local_cellvoltages */
639  for (uint16_t i_3 = 0; i_3 < (MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE * MXM_MAXIMUM_NR_OF_MODULES); i_3++) {
640  pInstance->localVoltages.cellVoltages_mV[i_3] = 0;
641  }
642 
643  /* test data for CELL5REG */
644  testBuffer[0] = BATTERY_MANAGEMENT_READALL;
645  testBuffer[1] = (uint8_t)MXM_REG_CELL5;
646  testBuffer[2] = 0xFCu;
647  testBuffer[3] = 0xFFu;
648  testBuffer[4] = 0x42u; /* DATACHECKBYTE, irrelevant for function, filled with dummy bytes */
649  testBuffer[5] = 0x44u; /* CRCBYTE, irrelevant for function, filled with dummy bytes */
650  testBufferLength = 6;
651  if (MXM_ParseVoltageReadall(testBuffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
652  STD_OK) {
653  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
654  retval = STD_NOT_OK;
655  } else {
657  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
658  retval = STD_NOT_OK;
659  }
660  }
661 
662  /* null mxm_local_cellvoltages */
663  for (uint16_t i_4 = 0; i_4 < (MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE * MXM_MAXIMUM_NR_OF_MODULES); i_4++) {
664  pInstance->localVoltages.cellVoltages_mV[i_4] = 0;
665  }
666 
667  /* test data for CELL6REG */
668  testBuffer[0] = BATTERY_MANAGEMENT_READALL;
669  testBuffer[1] = (uint8_t)MXM_REG_CELL6;
670  testBuffer[2] = 0xFCu;
671  testBuffer[3] = 0xFFu;
672  testBuffer[4] = 0x42u; /* DATACHECKBYTE, irrelevant for function, filled with dummy bytes */
673  testBuffer[5] = 0x44u; /* CRCBYTE, irrelevant for function, filled with dummy bytes */
674  testBufferLength = 6;
675  if (MXM_ParseVoltageReadall(testBuffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
676  STD_OK) {
677  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
678  retval = STD_NOT_OK;
679  } else {
681  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
682  retval = STD_NOT_OK;
683  }
684  }
685 
686  /* null mxm_local_cellvoltages */
687  for (uint16_t i_5 = 0; i_5 < (MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE * MXM_MAXIMUM_NR_OF_MODULES); i_5++) {
688  pInstance->localVoltages.cellVoltages_mV[i_5] = 0;
689  }
690 
691  /* test data for CELL7REG */
692  testBuffer[0] = BATTERY_MANAGEMENT_READALL;
693  testBuffer[1] = (uint8_t)MXM_REG_CELL7;
694  testBuffer[2] = 0xFCu;
695  testBuffer[3] = 0xFFu;
696  testBuffer[4] = 0x42u; /* DATACHECKBYTE, irrelevant for function, filled with dummy bytes */
697  testBuffer[5] = 0x44u; /* CRCBYTE, irrelevant for function, filled with dummy bytes */
698  testBufferLength = 6;
699  if (MXM_ParseVoltageReadall(testBuffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
700  STD_OK) {
701  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
702  retval = STD_NOT_OK;
703  } else {
705  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
706  retval = STD_NOT_OK;
707  }
708  }
709 
710  /* null mxm_local_cellvoltages */
711  for (uint16_t i_6 = 0; i_6 < (MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE * MXM_MAXIMUM_NR_OF_MODULES); i_6++) {
712  pInstance->localVoltages.cellVoltages_mV[i_6] = 0;
713  }
714 
715  /* test data for CELL8REG */
716  testBuffer[0] = BATTERY_MANAGEMENT_READALL;
717  testBuffer[1] = (uint8_t)MXM_REG_CELL8;
718  testBuffer[2] = 0xFCu;
719  testBuffer[3] = 0xFFu;
720  testBuffer[4] = 0x42u; /* DATACHECKBYTE, irrelevant for function, filled with dummy bytes */
721  testBuffer[5] = 0x44u; /* CRCBYTE, irrelevant for function, filled with dummy bytes */
722  testBufferLength = 6;
723  if (MXM_ParseVoltageReadall(testBuffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
724  STD_OK) {
725  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
726  retval = STD_NOT_OK;
727  } else {
729  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
730  retval = STD_NOT_OK;
731  }
732  }
733 
734  /* null mxm_local_cellvoltages */
735  for (uint16_t i_7 = 0; i_7 < (MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE * MXM_MAXIMUM_NR_OF_MODULES); i_7++) {
736  pInstance->localVoltages.cellVoltages_mV[i_7] = 0;
737  }
738 
739  /* test data for CELL9REG */
740  testBuffer[0] = BATTERY_MANAGEMENT_READALL;
741  testBuffer[1] = (uint8_t)MXM_REG_CELL9;
742  testBuffer[2] = 0xFCu;
743  testBuffer[3] = 0xFFu;
744  testBuffer[4] = 0x42u; /* DATACHECKBYTE, irrelevant for function, filled with dummy bytes */
745  testBuffer[5] = 0x44u; /* CRCBYTE, irrelevant for function, filled with dummy bytes */
746  testBufferLength = 6;
747  if (MXM_ParseVoltageReadall(testBuffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
748  STD_OK) {
749  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
750  retval = STD_NOT_OK;
751  } else {
753  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
754  retval = STD_NOT_OK;
755  }
756  }
757 
758  /* null mxm_local_cellvoltages */
759  for (uint16_t i_8 = 0; i_8 < (MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE * MXM_MAXIMUM_NR_OF_MODULES); i_8++) {
760  pInstance->localVoltages.cellVoltages_mV[i_8] = 0;
761  }
762 
763  /* test data for CELL10REG */
764  testBuffer[0] = BATTERY_MANAGEMENT_READALL;
765  testBuffer[1] = (uint8_t)MXM_REG_CELL10;
766  testBuffer[2] = 0xFCu;
767  testBuffer[3] = 0xFFu;
768  testBuffer[4] = 0x42u; /* DATACHECKBYTE, irrelevant for function, filled with dummy bytes */
769  testBuffer[5] = 0x44u; /* CRCBYTE, irrelevant for function, filled with dummy bytes */
770  testBufferLength = 6;
771  if (MXM_ParseVoltageReadall(testBuffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
772  STD_OK) {
773  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
774  retval = STD_NOT_OK;
775  } else {
777  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
778  retval = STD_NOT_OK;
779  }
780  }
781 
782  /* null mxm_local_cellvoltages */
783  for (uint16_t i_9 = 0; i_9 < (MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE * MXM_MAXIMUM_NR_OF_MODULES); i_9++) {
784  pInstance->localVoltages.cellVoltages_mV[i_9] = 0;
785  }
786 
787  /* test data for CELL11REG */
788  testBuffer[0] = BATTERY_MANAGEMENT_READALL;
789  testBuffer[1] = (uint8_t)MXM_REG_CELL11;
790  testBuffer[2] = 0xFCu;
791  testBuffer[3] = 0xFFu;
792  testBuffer[4] = 0x42u; /* DATACHECKBYTE, irrelevant for function, filled with dummy bytes */
793  testBuffer[5] = 0x44u; /* CRCBYTE, irrelevant for function, filled with dummy bytes */
794  testBufferLength = 6;
795  if (MXM_ParseVoltageReadall(testBuffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
796  STD_OK) {
797  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
798  retval = STD_NOT_OK;
799  } else {
801  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
802  retval = STD_NOT_OK;
803  }
804  }
805 
806  /* null mxm_local_cellvoltages */
807  for (uint16_t i_10 = 0; i_10 < (MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE * MXM_MAXIMUM_NR_OF_MODULES); i_10++) {
808  pInstance->localVoltages.cellVoltages_mV[i_10] = 0;
809  }
810 
811  /* test data for CELL12REG */
812  testBuffer[0] = BATTERY_MANAGEMENT_READALL;
813  testBuffer[1] = (uint8_t)MXM_REG_CELL12;
814  testBuffer[2] = 0xFCu;
815  testBuffer[3] = 0xFFu;
816  testBuffer[4] = 0x42u; /* DATACHECKBYTE, irrelevant for function, filled with dummy bytes */
817  testBuffer[5] = 0x44u; /* CRCBYTE, irrelevant for function, filled with dummy bytes */
818  testBufferLength = 6;
819  if (MXM_ParseVoltageReadall(testBuffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
820  STD_OK) {
821  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
822  retval = STD_NOT_OK;
823  } else {
825  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
826  retval = STD_NOT_OK;
827  }
828  }
829 
830  /* null mxm_local_cellvoltages */
831  for (uint16_t i_11 = 0; i_11 < (MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE * MXM_MAXIMUM_NR_OF_MODULES); i_11++) {
832  pInstance->localVoltages.cellVoltages_mV[i_11] = 0;
833  }
834 
835  /* test data for CELL13REG */
836  testBuffer[0] = BATTERY_MANAGEMENT_READALL;
837  testBuffer[1] = (uint8_t)MXM_REG_CELL13;
838  testBuffer[2] = 0xFCu;
839  testBuffer[3] = 0xFFu;
840  testBuffer[4] = 0x42u; /* DATACHECKBYTE, irrelevant for function, filled with dummy bytes */
841  testBuffer[5] = 0x44u; /* CRCBYTE, irrelevant for function, filled with dummy bytes */
842  testBufferLength = 6;
843  if (MXM_ParseVoltageReadall(testBuffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
844  STD_OK) {
845  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
846  retval = STD_NOT_OK;
847  } else {
849  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
850  retval = STD_NOT_OK;
851  }
852  }
853 
854  /* null mxm_local_cellvoltages */
855  for (uint16_t i_12 = 0; i_12 < (MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE * MXM_MAXIMUM_NR_OF_MODULES); i_12++) {
856  pInstance->localVoltages.cellVoltages_mV[i_12] = 0;
857  }
858 
859  /* test data for CELL14REG */
860  testBuffer[0] = BATTERY_MANAGEMENT_READALL;
861  testBuffer[1] = (uint8_t)MXM_REG_CELL14;
862  testBuffer[2] = 0xFCu;
863  testBuffer[3] = 0xFFu;
864  testBuffer[4] = 0x42u; /* DATACHECKBYTE, irrelevant for function, filled with dummy bytes */
865  testBuffer[5] = 0x44u; /* CRCBYTE, irrelevant for function, filled with dummy bytes */
866  testBufferLength = 6;
867  if (MXM_ParseVoltageReadall(testBuffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
868  STD_OK) {
869  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
870  retval = STD_NOT_OK;
871  } else {
873  retval = STD_NOT_OK;
874  }
875  }
876 
877  /* null mxm_local_cellvoltages */
878  for (uint16_t i_13 = 0; i_13 < (MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE * MXM_MAXIMUM_NR_OF_MODULES); i_13++) {
879  pInstance->localVoltages.cellVoltages_mV[i_13] = 0;
880  }
881 
882  /* AXIVION Enable Style Generic-NoMagicNumbers: */
883 
884  return retval;
885 }
886 
887 /*========== Extern Function Implementations ================================*/
889  FAS_ASSERT(pInstance != NULL_PTR);
890 
891  if (pInstance->errorCounter != 0u) {
892  const bool counterCanBeReset =
894  if (counterCanBeReset == true) {
895  pInstance->errorCounter = 0u;
896  pInstance->timestampLastError = 0u;
897  }
898  }
899 }
900 
901 extern void MXM_ErrorHandlerReset(MXM_MONITORING_INSTANCE_s *pInstance, bool immediateReset) {
902  FAS_ASSERT(pInstance != NULL_PTR);
903 
904  pInstance->timestampLastError = OS_GetTickCount();
905  pInstance->errorCounter++;
906 
907  if ((pInstance->errorCounter > MXM_MAXIMUM_ERROR_COUNT) || (immediateReset == true)) {
908  pInstance->resetNecessary = true;
909  }
910 }
911 
913  MXM_MONITORING_INSTANCE_s *pInstance,
915  FAS_ASSERT(pInstance != NULL_PTR);
916 
917  if (pInstance->requestStatus5x == MXM_5X_STATE_UNSENT) {
918  const STD_RETURN_TYPE_e setStateRequestReturn = MXM_5XSetStateRequest(
919  pInstance->pInstance5X,
921  pInstance->batteryCmdBuffer,
922  &pInstance->requestStatus5x);
923  FAS_ASSERT(setStateRequestReturn == STD_OK);
924  } else if (pInstance->requestStatus5x == MXM_5X_STATE_UNPROCESSED) {
925  /* wait for processing */
926  } else if (pInstance->requestStatus5x == MXM_5X_STATE_PROCESSED) {
927  /* continue to the substate specified by the request */
928  pInstance->operationSubstate = nextState;
930  } else if (pInstance->requestStatus5x == MXM_5X_STATE_ERROR) {
931  /* default-behavior: retry */
933  MXM_ErrorHandlerReset(pInstance, false);
934  } else {
935  /* invalid value, trap */
937  }
938 }
939 
941  MXM_MONITORING_INSTANCE_s *pInstance,
942  MXM_REG_NAME_e registerName,
944  FAS_ASSERT(pInstance != NULL_PTR);
945 
946  bool retval = false;
947  if (pInstance->requestStatus5x == MXM_5X_STATE_UNSENT) {
948  pInstance->batteryCmdBuffer.regAddress = registerName;
949  const STD_RETURN_TYPE_e setStateRequestReturn = MXM_5XSetStateRequest(
950  pInstance->pInstance5X, MXM_STATEMACH_5X_READALL, pInstance->batteryCmdBuffer, &pInstance->requestStatus5x);
951  FAS_ASSERT(setStateRequestReturn == STD_OK);
952  } else if (pInstance->requestStatus5x == MXM_5X_STATE_PROCESSED) {
954  pInstance->operationSubstate = nextState;
956  retval = true;
957  } else if (pInstance->requestStatus5x == MXM_5X_STATE_UNPROCESSED) {
958  /* wait for processing */
959  } else if (pInstance->requestStatus5x == MXM_5X_STATE_ERROR) {
960  /* try to reset state */
962  MXM_ErrorHandlerReset(pInstance, false);
963  } else {
964  /* invalid state */
966  }
967 
968  return retval;
969 }
970 
972  FAS_ASSERT(kpkInstance != NULL_PTR);
973  FAS_ASSERT(kpkInstance->pOpenwire_table != NULL_PTR);
974 
975  const uint8_t numberOfSatellites = MXM_5XGetNumberOfSatellites(kpkInstance->pInstance5X);
977  (((uint16_t)BATTERY_MANAGEMENT_TX_LENGTH_READALL + (2u * MXM_MAXIMUM_NR_OF_MODULES)) <= (uint8_t)UINT8_MAX),
978  "please check assumptions: code cannot handle number of modules");
979  const uint8_t messageLength = BATTERY_MANAGEMENT_TX_LENGTH_READALL + (2u * numberOfSatellites);
980  /* step over every byte-tuple in the RX-buffer */
981  for (uint8_t i = 2u; i < (messageLength - 2u); i = i + 2u) {
982  /* calculate current module number (first in RX-buffer is last in line) */
983  const uint8_t calculatedModuleNumberInDaisyChain = numberOfSatellites - ((i / 2u) - 1u) - 1u;
984  uint8_t stringNumber = 0u;
985  uint16_t moduleNumber = 0u;
986  MXM_ConvertModuleToString(calculatedModuleNumberInDaisyChain, &stringNumber, &moduleNumber);
987  const uint16_t calculatedModulePosition = moduleNumber * MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE;
988 
989  /* step over every cell in the module and update the openwire struct accordingly */
990  for (uint8_t c = 0u; c < MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE; c++) {
991  if (c < MXM_CELLS_IN_LSB) {
992  /* cell numbers under 8 can be found in the LSB */
993  const uint8_t mask = 1u << c;
994  if ((uint8_t)(mask & kpkInstance->rxBuffer[i]) > 0u) {
995  kpkInstance->pOpenwire_table->openwire[stringNumber][calculatedModulePosition + c] = 1;
996  } else {
997  kpkInstance->pOpenwire_table->openwire[stringNumber][calculatedModulePosition + c] = 0;
998  }
999  } else {
1000  /* cell numbers over or equal 8 can be found in the MSB */
1001  const uint8_t mask = 1u << (c - MXM_CELLS_IN_LSB);
1002  if ((uint8_t)(mask & kpkInstance->rxBuffer[i + 1u]) > 0u) {
1003  kpkInstance->pOpenwire_table->openwire[stringNumber][calculatedModulePosition + c] = 1;
1004  } else {
1005  kpkInstance->pOpenwire_table->openwire[stringNumber][calculatedModulePosition + c] = 0;
1006  }
1007  }
1008  }
1009  }
1010 
1011  /* write database block */
1012  const STD_RETURN_TYPE_e dataReturn = DATA_WRITE_DATA(kpkInstance->pOpenwire_table);
1013  return dataReturn;
1014 }
1015 
1017  FAS_ASSERT(pBalancingInstance != NULL_PTR);
1018  FAS_ASSERT(pBalancingInstance->pBalancingControl_table != NULL_PTR);
1019  /* check for impossible configuration */
1021  STD_RETURN_TYPE_e retval = STD_OK;
1022 
1023  /* Re-Initialize the cells to balance at each iteration */
1024  pBalancingInstance->cellsToBalance = 0u;
1025 
1026  /* /!\ WARNING
1027  In this function, EVEN cells refer to the even cells IN THE REAL MODULE, and NOT in the database index.
1028  --> EVEN cells in a module = ODD database index
1029  --> ODD cells in a module = EVEN database index
1030  e.g. : Cell 2 in the module corresponds to index 1 in the database
1031  the cell index is even, but the database index is odd. */
1032 
1033  /* Iterate over all the cells of the module 'moduleBalancingIndex' in a daisy-chain */
1034  if (pBalancingInstance->moduleBalancingIndex < MXM_MAXIMUM_NR_OF_MODULES) {
1035  for (uint8_t c = 0; c < BS_NR_OF_CELL_BLOCKS_PER_MODULE; c++) {
1036  /* Determine the position of the cell 'c' of module 'moduleBalancingIndex' in the DB */
1037  uint8_t stringNumber = 0u;
1038  uint16_t moduleNumber = 0u;
1039  MXM_ConvertModuleToString(pBalancingInstance->moduleBalancingIndex, &stringNumber, &moduleNumber);
1040  const uint16_t dBIndex = (moduleNumber * BS_NR_OF_CELL_BLOCKS_PER_MODULE) + c;
1041  if (pBalancingInstance->pBalancingControl_table->balancingState[stringNumber][dBIndex] == 1u) {
1042  /* Cell 'c' of module '::moduleBalancingIndex' needs to be balanced.
1043  Need to determine the balancing order --> even or odd cells?
1044  If the balancing order has not been determined before, need to do it. */
1045  if ((pBalancingInstance->evenCellsNeedBalancing == false) &&
1046  (pBalancingInstance->oddCellsNeedBalancing == false)) {
1047  if (((c % 2u) != 0u) && (pBalancingInstance->evenCellsBalancingProcessed == false)) {
1048  pBalancingInstance->evenCellsNeedBalancing = true;
1049  } else if (((c % 2u) == 0u) && (pBalancingInstance->oddCellsBalancingProcessed == false)) {
1050  pBalancingInstance->oddCellsNeedBalancing = true;
1051  } else {
1052  /* nothing to do */
1053  }
1054  }
1055  if ((pBalancingInstance->evenCellsNeedBalancing == true) && ((c % 2u) != 0u) &&
1056  /* If the even cells need to be balanced */
1057  (pBalancingInstance->evenCellsBalancingProcessed == false)) {
1058  pBalancingInstance->cellsToBalance |= ((uint16_t)0x01u << c);
1059  } else if (
1060  /* If the odd cells need to be balanced */
1061  (pBalancingInstance->oddCellsNeedBalancing == true) && ((c % 2u) == 0u) &&
1062  (pBalancingInstance->oddCellsBalancingProcessed == false)) {
1063  pBalancingInstance->cellsToBalance |= ((uint16_t)0x01u << c);
1064  } else {
1065  /* nothing to do */
1066  }
1067  }
1068  }
1069  } else {
1070  retval = STD_NOT_OK;
1071  }
1072  return retval;
1073 }
1074 
1076  FAS_ASSERT(kpkInstance != NULL_PTR);
1077  FAS_ASSERT(kpkInstance->pCellVoltages_table != NULL_PTR);
1078  FAS_ASSERT(kpkInstance->pCellTemperatures_table != NULL_PTR);
1080 
1081  uint16_t numberValidVoltageMeasurements[BS_NR_OF_STRINGS] = {0};
1082  /* voltages */
1083  for (uint8_t i_mod = 0; i_mod < (BS_NR_OF_MODULES_PER_STRING * BS_NR_OF_STRINGS); i_mod++) {
1084  const bool moduleIsConnected = MXM_CheckIfADeviceIsConnected(kpkInstance, i_mod);
1085  uint8_t stringNumber = 0u;
1086  uint16_t moduleNumber = 0u;
1087  MXM_ConvertModuleToString(i_mod, &stringNumber, &moduleNumber);
1088  FAS_ASSERT(stringNumber < BS_NR_OF_STRINGS);
1089  FAS_ASSERT(moduleNumber < BS_NR_OF_MODULES_PER_STRING);
1090  kpkInstance->pCellVoltages_table->moduleVoltage_mV[stringNumber][moduleNumber] =
1091  kpkInstance->localVoltages.blockVoltages[i_mod];
1092  /* every iteration that we hit a string first (module 0), we reset the packvoltage counter */
1093  if (moduleNumber == 0u) {
1094  kpkInstance->pCellVoltages_table->packVoltage_mV[stringNumber] = 0;
1095  }
1096  kpkInstance->pCellVoltages_table->packVoltage_mV[stringNumber] +=
1097  (int32_t)kpkInstance->localVoltages.blockVoltages[i_mod];
1098  FAS_ASSERT(
1099  BS_NR_OF_CELL_BLOCKS_PER_MODULE <= MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE); /*!< invalid configuration! */
1100  for (uint8_t i_bat = 0; i_bat < BS_NR_OF_CELL_BLOCKS_PER_MODULE; i_bat++) {
1101  uint16_t cell_counter_db = (moduleNumber * BS_NR_OF_CELL_BLOCKS_PER_MODULE) + i_bat;
1102  uint16_t cell_counter_max = ((uint16_t)i_mod * MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE) + i_bat;
1103  const uint16_t cellVoltageLocal_mV = kpkInstance->localVoltages.cellVoltages_mV[cell_counter_max];
1104  if ((int32_t)cellVoltageLocal_mV > INT16_MAX) {
1105  kpkInstance->pCellVoltages_table->cellVoltage_mV[stringNumber][cell_counter_db] = INT16_MAX;
1106  } else {
1107  kpkInstance->pCellVoltages_table->cellVoltage_mV[stringNumber][cell_counter_db] =
1108  (int16_t)cellVoltageLocal_mV;
1109  }
1111  kpkInstance->pCellVoltages_table->cellVoltage_mV[stringNumber][cell_counter_db],
1113  if ((valueIsPlausible == STD_OK) && moduleIsConnected) {
1114  numberValidVoltageMeasurements[stringNumber]++;
1115  } else {
1116  /* Invalidate cell voltage measurement */
1117  kpkInstance->pCellVoltages_table->invalidCellVoltage[stringNumber][moduleNumber] |=
1118  ((uint64_t)1u << i_bat);
1119  }
1120  }
1121  }
1122 
1123  /* temperatures */
1124  uint16_t numberValidTemperatureMeasurements[BS_NR_OF_STRINGS] = {0};
1125  for (uint8_t i_mod = 0; i_mod < (BS_NR_OF_MODULES_PER_STRING * BS_NR_OF_STRINGS); i_mod++) {
1126  const bool moduleIsConnected = MXM_CheckIfADeviceIsConnected(kpkInstance, i_mod);
1127  uint8_t stringNumber = 0u;
1128  uint16_t moduleNumber = 0u;
1129  MXM_ConvertModuleToString(i_mod, &stringNumber, &moduleNumber);
1130  FAS_ASSERT(stringNumber < BS_NR_OF_STRINGS);
1131  FAS_ASSERT(moduleNumber < BS_NR_OF_MODULES_PER_STRING);
1132 
1133  /* store aux measurement from AUX2 (MUX0) */
1134  if (kpkInstance->muxCounter < BS_NR_OF_TEMP_SENSORS_PER_MODULE) {
1135  const uint16_t temperatureIndexDb = (moduleNumber * BS_NR_OF_TEMP_SENSORS_PER_MODULE) +
1136  kpkInstance->muxCounter;
1137  const uint16_t temperatureIndexMxm = ((uint16_t)i_mod * MXM_MAXIMUM_NR_OF_AUX_PER_MODULE) + 2u;
1138  const uint16_t auxVoltage_mV = kpkInstance->localVoltages.auxVoltages_mV[temperatureIndexMxm];
1139  /* const uint16_t temporaryVoltage = (auxVoltage_mV / ((float)3300 - auxVoltage_mV)) * 1000; */
1140  const int16_t temperature_ddegC = TSI_GetTemperature(auxVoltage_mV);
1141  kpkInstance->pCellTemperatures_table->cellTemperature_ddegC[stringNumber][temperatureIndexDb] =
1142  temperature_ddegC;
1143  const STD_RETURN_TYPE_e valueIsPlausible = AFE_PlausibilityCheckTempMinMax(temperature_ddegC);
1144  if ((valueIsPlausible == STD_OK) && moduleIsConnected) {
1145  numberValidTemperatureMeasurements[stringNumber]++;
1146  } else {
1147  /* Invalidate temperature measurement */
1148  kpkInstance->pCellTemperatures_table->invalidCellTemperature[stringNumber][moduleNumber] |=
1149  ((uint16_t)1u << kpkInstance->muxCounter);
1150  }
1151  }
1152  }
1153 
1154  for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) {
1155  kpkInstance->pCellVoltages_table->nrValidCellVoltages[s] = numberValidVoltageMeasurements[s];
1156  kpkInstance->pCellTemperatures_table->nrValidTemperatures[s] = numberValidTemperatureMeasurements[s];
1157  }
1158 
1160 
1161  return retval;
1162 }
1163 
1165  MXM_BALANCING_STATE_s *pBalancingInstance,
1166  MXM_MONITORING_INSTANCE_s *pMonitoringInstance) {
1167  FAS_ASSERT(pBalancingInstance != NULL_PTR);
1168  FAS_ASSERT(pMonitoringInstance != NULL_PTR);
1169 
1170  pBalancingInstance->moduleBalancingIndex = 0u;
1171  pBalancingInstance->evenCellsNeedBalancing = false;
1172  pBalancingInstance->oddCellsNeedBalancing = false;
1173  pBalancingInstance->evenCellsBalancingProcessed = false;
1174  pBalancingInstance->oddCellsBalancingProcessed = false;
1175  pBalancingInstance->cellsToBalance = 0u;
1176  pBalancingInstance->previousTimeStamp = 0u;
1177  pBalancingInstance->currentTimeStamp = 0u;
1178 
1179  pMonitoringInstance->resetNecessary = false;
1180  pMonitoringInstance->errorCounter = 0u;
1181  pMonitoringInstance->timestampLastError = 0u;
1182  pMonitoringInstance->timestampInit = 0u;
1183  pMonitoringInstance->state = MXM_STATEMACHINE_STATES_UNINITIALIZED;
1184  pMonitoringInstance->operationSubstate = MXM_INIT_ENTRY;
1185  pMonitoringInstance->allowStartup = false;
1186  pMonitoringInstance->operationRequested = false;
1187  pMonitoringInstance->firstMeasurementDone = false;
1188  pMonitoringInstance->stopRequested = false;
1189  pMonitoringInstance->openwireRequested = false;
1190  pMonitoringInstance->undervoltageAlert = false;
1191  pMonitoringInstance->muxCounter = 0u;
1193  pMonitoringInstance->dcByte = MXM_DC_EMPTY;
1194  pMonitoringInstance->mxmVoltageCellCounter = 0u;
1195  pMonitoringInstance->highest5xDevice = 0u;
1196  pMonitoringInstance->requestStatus5x = MXM_5X_STATE_UNSENT;
1197  pMonitoringInstance->batteryCmdBuffer.regAddress = MXM_REG_VERSION;
1198  pMonitoringInstance->batteryCmdBuffer.lsb = 0u;
1199  pMonitoringInstance->batteryCmdBuffer.msb = 0u;
1200  pMonitoringInstance->batteryCmdBuffer.blocksize = 0u;
1201  pMonitoringInstance->batteryCmdBuffer.deviceAddress = 0u;
1202  pMonitoringInstance->batteryCmdBuffer.model = MXM_GetModelIdOfDaisyChain();
1203  pMonitoringInstance->resultSelfCheck = STD_NOT_OK;
1204  /* for the "static" pre-init self-checks: do not reset if the result has passed; it will not change; FMEA can change */
1205  pMonitoringInstance->selfCheck.fmeaStatusASCI = STD_NOT_OK;
1206 
1207  for (uint32_t i = 0u; i < (MXM_MAXIMUM_NR_OF_MODULES * MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE); i++) {
1208  pMonitoringInstance->localVoltages.cellVoltages_mV[i] = 0u;
1209  }
1210 
1211  for (uint32_t i = 0u; i < (MXM_MAXIMUM_NR_OF_MODULES * MXM_MAXIMUM_NR_OF_AUX_PER_MODULE); i++) {
1212  pMonitoringInstance->localVoltages.auxVoltages_mV[i] = 0u;
1213  }
1214 
1215  for (uint32_t i = 0u; i < MXM_MAXIMUM_NR_OF_MODULES; i++) {
1216  pMonitoringInstance->localVoltages.blockVoltages[i] = 0u;
1217  }
1218 
1219  for (uint32_t i = 0u; i < MXM_MAXIMUM_NR_OF_MODULES; i++) {
1220  pMonitoringInstance->registry[i].connected = false;
1221  pMonitoringInstance->registry[i].deviceAddress = 0u;
1222  pMonitoringInstance->registry[i].model = MXM_MODEL_ID_NONE;
1223  pMonitoringInstance->registry[i].siliconVersion = MXM_SILICON_VERSION_INVALID;
1224  pMonitoringInstance->registry[i].deviceID = 0u;
1225  pMonitoringInstance->registry[i].registerStatus1 = 0u;
1226  pMonitoringInstance->registry[i].registerStatus2 = 0u;
1227  pMonitoringInstance->registry[i].registerStatus3 = 0u;
1228  pMonitoringInstance->registry[i].registerFmea1 = 0u;
1229  pMonitoringInstance->registry[i].registerFmea2 = 0u;
1230  }
1231 
1232  for (uint32_t i = 0u; i < MXM_RX_BUFFER_LENGTH; i++) {
1233  pMonitoringInstance->rxBuffer[i] = 0u;
1234  }
1235 }
1236 
1238  FAS_ASSERT(pState != NULL_PTR);
1239  STD_RETURN_TYPE_e retval = STD_OK;
1240  MXM_SELFCHECK_s *selfCheck = &pState->selfCheck;
1241  FAS_ASSERT(selfCheck != NULL_PTR);
1242  if (selfCheck->crc == STD_NOT_OK) {
1243  selfCheck->crc = MXM_CRC8SelfTest();
1244  }
1245  if (selfCheck->conv == STD_NOT_OK) {
1246  selfCheck->conv = MXM_ConvertTest();
1247  }
1248  if (selfCheck->firstSetBit == STD_NOT_OK) {
1249  selfCheck->firstSetBit = MXM_FirstSetBitTest();
1250  }
1251  if (selfCheck->extractValueFromRegister == STD_NOT_OK) {
1253  }
1254  if (selfCheck->parseVoltageReadall == STD_NOT_OK) {
1255  selfCheck->parseVoltageReadall = MXM_ParseVoltageReadallTest(pState);
1256  }
1257  if (selfCheck->addressSpaceChecker == STD_NOT_OK) {
1259  }
1260 
1261  if ((selfCheck->crc == STD_OK) && (selfCheck->addressSpaceChecker == STD_OK) && (selfCheck->conv == STD_OK) &&
1262  (selfCheck->firstSetBit == STD_OK) && (selfCheck->extractValueFromRegister == STD_OK) &&
1263  (selfCheck->parseVoltageReadall == STD_OK)) {
1264  /* check has passed, return value already set */
1265  } else {
1266  retval = STD_NOT_OK;
1267  }
1268  /* report to diag module, Maxim driver reports always to string 0 (current implementation just has one interface) */
1269  (void)DIAG_CheckEvent(retval, DIAG_ID_AFE_CONFIG, DIAG_SYSTEM, 0u);
1270 
1271  return retval;
1272 }
1273 
1276  FAS_ASSERT(pState != NULL_PTR);
1278  if (pState->requestStatus5x == MXM_5X_STATE_UNSENT) {
1279  pState->batteryCmdBuffer.regAddress = regAddress;
1280  const STD_RETURN_TYPE_e setStateRequestReturn = MXM_5XSetStateRequest(
1282  FAS_ASSERT(setStateRequestReturn == STD_OK);
1283  } else if (pState->requestStatus5x == MXM_5X_STATE_PROCESSED) {
1285  uint8_t temp_len = BATTERY_MANAGEMENT_TX_LENGTH_READALL +
1286  (2u * MXM_5XGetNumberOfSatellites(pState->pInstance5X));
1287  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: default value is set as a safety measure */
1288  STD_RETURN_TYPE_e readallReturn = STD_NOT_OK;
1289  if (regAddress == MXM_REG_BLOCK) {
1290  readallReturn = MXM_ParseVoltageReadall(
1291  pState->rxBuffer, temp_len, &pState->localVoltages, MXM_CONVERSION_BLOCK_VOLTAGE);
1292  } else {
1293  readallReturn =
1295  }
1296  if (readallReturn == STD_NOT_OK) {
1297  MXM_ErrorHandlerReset(pState, false);
1298  }
1300  retval = MXM_MONITORING_STATE_PASS;
1301  } else if (pState->requestStatus5x == MXM_5X_STATE_UNPROCESSED) {
1302  /* do nothing */
1303  } else if (pState->requestStatus5x == MXM_5X_STATE_ERROR) {
1304  /* try to reset state */
1306  MXM_ErrorHandlerReset(pState, false);
1307  } else {
1308  /* invalid state */
1310  }
1311  return retval;
1312 }
1313 
1315  FAS_ASSERT(pInstance != NULL_PTR);
1316 
1317  if (pInstance->state == MXM_STATEMACHINE_STATES_UNINITIALIZED) {
1318  pInstance->requestStatus5x = MXM_5X_STATE_UNSENT;
1319  pInstance->timestampInit = OS_GetTickCount();
1320  MXM_MonRegistryInit(pInstance);
1322  }
1323 
1324  switch (pInstance->state) {
1326  pInstance->resultSelfCheck = MXM_PreInitSelfCheck(pInstance);
1327  if (pInstance->resultSelfCheck == STD_OK) {
1328  pInstance->requestStatus5x = MXM_5X_STATE_UNSENT;
1329  pInstance->state = MXM_STATEMACHINE_STATES_INIT;
1330  } else {
1331  /* software is broken by configuration/design */
1333  }
1334  break;
1336  if (pInstance->requestStatus5x == MXM_5X_STATE_UNSENT) {
1337  const STD_RETURN_TYPE_e setStateRequestReturn = MXM_5XSetStateRequest(
1338  pInstance->pInstance5X,
1340  pInstance->batteryCmdBuffer,
1341  &pInstance->requestStatus5x);
1342  FAS_ASSERT(setStateRequestReturn == STD_OK);
1343  } else if (pInstance->requestStatus5x == MXM_5X_STATE_UNPROCESSED) {
1344  /* just wait */
1345  } else if (pInstance->requestStatus5x == MXM_5X_STATE_ERROR) {
1346  /* do not reset state machine, but count error */
1347  MXM_ErrorHandlerReset(pInstance, false);
1348  } else if (pInstance->allowStartup == false) {
1349  /* do not start yet, just wait */
1350 
1351  } else if ((pInstance->requestStatus5x == MXM_5X_STATE_PROCESSED) && (pInstance->allowStartup == true)) {
1352  /* update registry */
1353  STD_RETURN_TYPE_e ConnectResult =
1355  FAS_ASSERT(ConnectResult == STD_OK);
1356  pInstance->requestStatus5x = MXM_5X_STATE_UNSENT;
1358  } else {
1360  }
1361 
1362  break;
1364  /* TODO more checks */
1365  pInstance->selfCheck.fmeaStatusASCI = STD_NOT_OK;
1366  if (pInstance->requestStatus5x == MXM_5X_STATE_UNSENT) {
1367  const STD_RETURN_TYPE_e stateRequestReturn = MXM_5XSetStateRequest(
1368  pInstance->pInstance5X,
1370  pInstance->batteryCmdBuffer,
1371  &pInstance->requestStatus5x);
1372  FAS_ASSERT(stateRequestReturn == STD_OK);
1373  } else if (pInstance->requestStatus5x == MXM_5X_STATE_UNPROCESSED) {
1374  /* just wait */
1375  } else if (pInstance->requestStatus5x == MXM_5X_STATE_ERROR) {
1376  /* this is a configuration or hardware failure */
1377  pInstance->selfCheck.fmeaStatusASCI = STD_NOT_OK;
1378  pInstance->resultSelfCheck = STD_NOT_OK;
1379  MXM_ErrorHandlerReset(pInstance, false);
1380  } else if (pInstance->requestStatus5x == MXM_5X_STATE_PROCESSED) {
1381  pInstance->selfCheck.fmeaStatusASCI = STD_OK;
1382  const STD_RETURN_TYPE_e resultNumberOfSatellitesGood =
1384  /* report to diag module, Maxim driver reports always to string 0 (current implementation just has one interface) */
1385  (void)DIAG_CheckEvent(resultNumberOfSatellitesGood, DIAG_ID_AFE_CONFIG, DIAG_STRING, 0u);
1386  if ((pInstance->resultSelfCheck == STD_OK) && (pInstance->selfCheck.fmeaStatusASCI == STD_OK) &&
1387  (resultNumberOfSatellitesGood == STD_OK)) {
1388  pInstance->resultSelfCheck = STD_OK;
1389  pInstance->requestStatus5x = MXM_5X_STATE_UNSENT;
1390  pInstance->state = MXM_STATEMACHINE_STATES_IDLE;
1391  } else if (mxm_allowSkippingPostInitSelfCheck == true) {
1392  pInstance->resultSelfCheck = STD_NOT_OK;
1393  pInstance->requestStatus5x = MXM_5X_STATE_UNSENT;
1394  pInstance->state = MXM_STATEMACHINE_STATES_IDLE;
1395  } else {
1396  /* skipping the self-check is not allowed and it failed, try to reset */
1397  pInstance->resetNecessary = true;
1398  }
1399  } else {
1401  }
1402  break;
1404  pInstance->stopRequested = false;
1405  if (pInstance->operationRequested == true) {
1407  pInstance->operationSubstate = MXM_INIT_ENTRY;
1408  } else {
1409  /* Do nothing */
1410  }
1411  break;
1413  MXM_StateMachineOperation(pInstance);
1414  break;
1415  default:
1417  break;
1418  }
1419 }
1420 
1421 /*========== Externalized Static Function Implementations (Unit Test) =======*/
1422 #ifdef UNITY_UNIT_TEST
1423 extern STD_RETURN_TYPE_e TEST_MXM_ParseVoltageReadallTest(MXM_MONITORING_INSTANCE_s *pInstance) {
1424  return MXM_ParseVoltageReadallTest(pInstance);
1425 }
1426 extern STD_RETURN_TYPE_e TEST_MXM_ParseVoltagesIntoDB(MXM_MONITORING_INSTANCE_s *pInstance) {
1427  return MXM_ParseVoltagesIntoDB(pInstance);
1428 }
1429 extern STD_RETURN_TYPE_e TEST_MXM_ParseVoltageReadall(
1430  uint8_t *voltRxBuffer,
1431  uint16_t voltRxBufferLength,
1432  MXM_DATA_STORAGE_s *datastorage,
1433  MXM_CONVERSION_TYPE_e conversionType) {
1434  return MXM_ParseVoltageReadall(voltRxBuffer, voltRxBufferLength, datastorage, conversionType);
1435 }
1436 #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:93
STD_RETURN_TYPE_e DIAG_CheckEvent(STD_RETURN_TYPE_e cond, DIAG_ID_e diag_id, DIAG_IMPACT_LEVEL_e impact, uint32_t data)
DIAG_CheckEvent provides a simple interface to check an event for STD_OK.
Definition: diag.c:356
Diagnosis driver header.
@ DIAG_SYSTEM
Definition: diag_cfg.h:251
@ DIAG_STRING
Definition: diag_cfg.h:252
@ DIAG_ID_AFE_CONFIG
Definition: diag_cfg.h:164
#define FAS_ASSERT(x)
Assertion macro that asserts that x is true.
Definition: fassert.h:241
#define FAS_TRAP
Define that evaluates to essential boolean false thus tripping an assert.
Definition: fassert.h:115
#define f_static_assert(cond, msg)
Definition: fassert.h:271
STD_RETURN_TYPE_e
Definition: fstd_types.h:81
@ STD_NOT_OK
Definition: fstd_types.h:83
@ STD_OK
Definition: fstd_types.h:82
#define NULL_PTR
Null pointer.
Definition: fstd_types.h:76
#define must_check_return
Allows functions to generate warnings in GCC for unused returns.
Definition: general.h:88
void MXM_CheckIfErrorCounterCanBeReset(MXM_MONITORING_INSTANCE_s *pInstance)
Function that checks if the error counter can be reset.
Definition: mxm_1785x.c:888
#define MXM_OFFSET_AUX0
Definition: mxm_1785x.c:86
#define MXM_TEST_BUFFER_MAXIMUM_LENGTH
Definition: mxm_1785x.c:98
STD_RETURN_TYPE_e MXM_PreInitSelfCheck(MXM_MONITORING_INSTANCE_s *pState)
Execute all preinit selfchecks.
Definition: mxm_1785x.c:1237
#define MXM_OFFSET_CELL_13
Definition: mxm_1785x.c:84
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:901
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:270
static const AFE_PLAUSIBILITY_VALUES_s mxm_plausibleCellVoltages
Definition: mxm_1785x.c:101
#define MXM_OFFSET_CELL_11
Definition: mxm_1785x.c:82
#define MXM_OFFSET_CELL_6
Definition: mxm_1785x.c:77
STD_RETURN_TYPE_e MXM_ProcessOpenWire(const MXM_MONITORING_INSTANCE_s *const kpkInstance)
Processes the retrieved information on openwire.
Definition: mxm_1785x.c:971
bool must_check_return MXM_HandleStateReadall(MXM_MONITORING_INSTANCE_s *pInstance, MXM_REG_NAME_e registerName, MXM_STATEMACHINE_OPERATION_STATES_e nextState)
Handle the statemachine-transactions for a READALL.
Definition: mxm_1785x.c:940
#define MXM_OFFSET_CELL_1
Definition: mxm_1785x.c:72
#define MXM_OFFSET_CELL_7
Definition: mxm_1785x.c:78
#define MXM_OFFSET_CELL_10
Definition: mxm_1785x.c:81
STD_RETURN_TYPE_e MXM_ParseVoltagesIntoDB(const MXM_MONITORING_INSTANCE_s *const kpkInstance)
Copies measured voltage data into the database.
Definition: mxm_1785x.c:1075
#define MXM_OFFSET_CELL_14
Definition: mxm_1785x.c:85
#define MXM_OFFSET_BLOCK
Definition: mxm_1785x.c:89
#define MXM_OFFSET_CELL_8
Definition: mxm_1785x.c:79
#define MXM_OFFSET_CELL_5
Definition: mxm_1785x.c:76
#define MXM_OFFSET_CELL_4
Definition: mxm_1785x.c:75
static void MXM_GetDataFrom5XStateMachine(MXM_MONITORING_INSTANCE_s *pInstance)
Retrieves data from lower statemachine and writes it to the rx buffer.
Definition: mxm_1785x.c:191
STD_RETURN_TYPE_e MXM_ConstructBalancingBuffer(MXM_BALANCING_STATE_s *pBalancingInstance)
Fill the balancing datastructure.
Definition: mxm_1785x.c:1016
MXM_MONITORING_STATE_e 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:1275
#define MXM_OFFSET_AUX2
Definition: mxm_1785x.c:87
#define MXM_OFFSET_CELL_9
Definition: mxm_1785x.c:80
#define MXM_OFFSET_CELL_2
Definition: mxm_1785x.c:73
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:199
void MXM_StateMachine(MXM_MONITORING_INSTANCE_s *pInstance)
Main state-machine implementation.
Definition: mxm_1785x.c:1314
#define MXM_MAXIMUM_ERROR_COUNT
Definition: mxm_1785x.c:92
#define MXM_REF_VAA_mV
VAA reference voltage (3.3V)
Definition: mxm_1785x.c:108
void MXM_InitializeStateStruct(MXM_BALANCING_STATE_s *pBalancingInstance, MXM_MONITORING_INSTANCE_s *pMonitoringInstance)
Initializes the state structs with default values.
Definition: mxm_1785x.c:1164
#define MXM_OFFSET_AUX3
Definition: mxm_1785x.c:88
#define MXM_TIMEOUT_RESET_ERROR_COUNTER_ms
Definition: mxm_1785x.c:95
static STD_RETURN_TYPE_e must_check_return MXM_ParseVoltageReadallTest(MXM_MONITORING_INSTANCE_s *pInstance)
Test the MXM_ParseVoltageReadall()-function.
Definition: mxm_1785x.c:485
void MXM_HandleStateWriteall(MXM_MONITORING_INSTANCE_s *pInstance, MXM_STATEMACHINE_OPERATION_STATES_e nextState)
Handle the statemachine-transactions for a WRITEALL.
Definition: mxm_1785x.c:912
#define MXM_OFFSET_CELL_3
Definition: mxm_1785x.c:74
#define MXM_OFFSET_CELL_12
Definition: mxm_1785x.c:83
Headers for the driver for the MAX17841B ASCI and MAX1785x monitoring chip.
#define MXM_REF_UNIPOLAR_CELL_mV
Definition: mxm_1785x.h:104
MXM_MODEL_ID_e MXM_GetModelIdOfDaisyChain(void)
returns the model ID of the daisy chain
Definition: mxm_17852.c:91
#define MXM_CELLS_IN_LSB
Definition: mxm_1785x.h:101
void MXM_StateMachineOperation(MXM_MONITORING_INSTANCE_s *pState)
State-Machine implementation for operation state.
Definition: mxm_17852.c:95
#define MXM_THRESHOLD_DIAGNOSTIC_AFTER_CYCLES
Battery monitoring driver for MAX1785x battery monitoring ICs.
Definition: mxm_1785x.h:95
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 must_check_return MXM_ConvertTest(void)
Test the MXM_Convert()-function.
STD_RETURN_TYPE_e must_check_return MXM_FirstSetBitTest(void)
Test MXM_FirstSetBit().
STD_RETURN_TYPE_e 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.
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 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 monitoring chip.
@ 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:67
STD_RETURN_TYPE_e must_check_return MXM_CRC8SelfTest(void)
Test the CRC8-algorithm with a known pattern.
Definition: mxm_crc8.c:140
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:262
void MXM_MonRegistryInit(MXM_MONITORING_INSTANCE_s *pState)
Initialize monitoring registry.
Definition: mxm_registry.c:79
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:96
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:144
Declaration of the OS wrapper interface.
uint32_t OS_GetTickCount(void)
Returns OS based system tick value.
Definition: os_freertos.c:139
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:252
int16_t cellTemperature_ddegC[BS_NR_OF_STRINGS][BS_NR_OF_TEMP_SENSORS_PER_STRING]
Definition: database_cfg.h:148
uint16_t nrValidTemperatures[BS_NR_OF_STRINGS]
Definition: database_cfg.h:151
uint16_t invalidCellTemperature[BS_NR_OF_STRINGS][BS_NR_OF_MODULES_PER_STRING]
Definition: database_cfg.h:150
int32_t packVoltage_mV[BS_NR_OF_STRINGS]
Definition: database_cfg.h:131
uint64_t invalidCellVoltage[BS_NR_OF_STRINGS][BS_NR_OF_MODULES_PER_STRING]
Definition: database_cfg.h:135
uint16_t nrValidCellVoltages[BS_NR_OF_STRINGS]
Definition: database_cfg.h:136
uint32_t moduleVoltage_mV[BS_NR_OF_STRINGS][BS_NR_OF_MODULES_PER_STRING]
Definition: database_cfg.h:137
int16_t cellVoltage_mV[BS_NR_OF_STRINGS][BS_NR_OF_CELL_BLOCKS_PER_STRING]
Definition: database_cfg.h:132
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:307
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
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_OPEN_WIRE_s *const pOpenwire_table
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