foxBMS - Unit Tests  1.2.1
The foxBMS Unit Tests API Documentation
mxm_1785x.c
Go to the documentation of this file.
1 /**
2  *
3  * @copyright © 2010 - 2021, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright notice, this
12  * list of conditions and the following disclaimer.
13  *
14  * 2. Redistributions in binary form must reproduce the above copyright notice,
15  * this list of conditions and the following disclaimer in the documentation
16  * and/or other materials provided with the distribution.
17  *
18  * 3. Neither the name of the copyright holder nor the names of its
19  * contributors may be used to endorse or promote products derived from
20  * this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  *
33  * We kindly request you to use one or more of the following phrases to refer to
34  * foxBMS in your hardware, software, documentation or advertising materials:
35  *
36  * - ″This product uses parts of foxBMS®″
37  * - ″This product includes parts of foxBMS®″
38  * - ″This product is derived from foxBMS®″
39  *
40  */
41 
42 /**
43  * @file mxm_1785x.c
44  * @author foxBMS Team
45  * @date 2019-01-15 (date of creation)
46  * @updated 2021-12-06 (date of last update)
47  * @ingroup DRIVERS
48  * @prefix MXM
49  *
50  * @brief Driver for the MAX17841B ASCI and MAX1785x monitoring chip
51  *
52  * @details This file contains the main-state-machine that drives the
53  * monitoring ICs of the MAX1785x family by Maxim Integrated.
54  *
55  */
56 
57 /*========== Includes =======================================================*/
58 #include "mxm_1785x.h"
59 
60 #include "afe_plausibility.h"
61 #include "database.h"
62 #include "mxm_1785x_tools.h"
63 #include "mxm_battery_management.h"
64 #include "mxm_registry.h"
65 #include "os.h"
66 #include "tsi.h"
67 
68 /*========== Macros and Definitions =========================================*/
69 
70 #define MXM_OFFSET_CELL_1 (0u) /*!< storage offset for cell 1 */
71 #define MXM_OFFSET_CELL_2 (1u) /*!< storage offset for cell 2 */
72 #define MXM_OFFSET_CELL_3 (2u) /*!< storage offset for cell 3 */
73 #define MXM_OFFSET_CELL_4 (3u) /*!< storage offset for cell 4 */
74 #define MXM_OFFSET_CELL_5 (4u) /*!< storage offset for cell 5 */
75 #define MXM_OFFSET_CELL_6 (5u) /*!< storage offset for cell 6 */
76 #define MXM_OFFSET_CELL_7 (6u) /*!< storage offset for cell 7 */
77 #define MXM_OFFSET_CELL_8 (7u) /*!< storage offset for cell 8 */
78 #define MXM_OFFSET_CELL_9 (8u) /*!< storage offset for cell 9 */
79 #define MXM_OFFSET_CELL_10 (9u) /*!< storage offset for cell 10 */
80 #define MXM_OFFSET_CELL_11 (10u) /*!< storage offset for cell 11 */
81 #define MXM_OFFSET_CELL_12 (11u) /*!< storage offset for cell 12 */
82 #define MXM_OFFSET_CELL_13 (12u) /*!< storage offset for cell 13 */
83 #define MXM_OFFSET_CELL_14 (13u) /*!< storage offset for cell 14 */
84 #define MXM_OFFSET_AUX0 (0u) /*!< storage offset for AUX0 */
85 #define MXM_OFFSET_AUX2 (2u) /*!< storage offset for AUX2 */
86 #define MXM_OFFSET_AUX3 (3u) /*!< storage offset for AUX3 */
87 #define MXM_OFFSET_BLOCK (0u) /*!< storage offset for block voltage */
88 
89 /** maximum number of errors that may occur before the next error triggers a reset */
90 #define MXM_MAXIMUM_ERROR_COUNT (10u)
91 
92 /** timeout after which the error counter will be reset */
93 #define MXM_TIMEOUT_RESET_ERROR_COUNTER_ms (500)
94 
95 /** maximum length of a test buffer */
96 #define MXM_TEST_BUFFER_MAXIMUM_LENGTH (120u)
97 
98 /** local definition of plausible cell voltage values */
101  .minimumPlausibleVoltage_mV = -2500,
102 };
103 
104 /*========== Static Constant and Variable Definitions =======================*/
105 /** @brief VAA reference voltage (3.3V) */
106 #define MXM_REF_VAA_mV (3300u)
107 
108 /*========== Extern Constant and Variable Definitions =======================*/
109 
110 /*========== Static Function Prototypes =====================================*/
111 
112 /** @brief Retrieves data from lower statemachine and writes it to the rx buffer. */
114 
115 /**
116  * @brief Parse voltage values from a READALL receive buffer into an
117  * array.
118  * @details This function expects a preprocessed RX buffer with an answer
119  * to a READALL command. It will parse the data bytes from this
120  * message into an array structured like mxm_local_cellvoltages.
121  * The offset of the measured cell has to be defined. For example
122  * cell 1 has an offset of 0 and cell 4 has an offset of 3. The
123  * offset for the READALL command is always defined in reference
124  * to module 0.
125  *
126  * If is_temperature_measurement is set to true, the function
127  * expects an auxiliary measurement (e.g. temperatures).
128  * @param[in] kpkVoltRxBuffer array-pointer to the RX buffer
129  * @param[in] voltRxBufferLength length of the RX buffer
130  * @param[in] measurementOffset offset of the data in the cell voltage
131  * array (target)
132  * @param[in] conversionType type of conversion that has been used
133  * for the measured data
134  * @param[out] pVoltagesTarget array-pointer to the cell voltages
135  * array
136  * @param[in] measurementType whether the measurement is temperature
137  * or cell
138  * @param[in] fullScaleReference_mV reference voltage of full scale
139  */
140 static void MXM_ParseVoltageLineReadall(
141  const uint8_t *const kpkVoltRxBuffer,
142  uint16_t voltRxBufferLength,
143  uint8_t measurementOffset,
144  MXM_CONVERSION_TYPE_e conversionType,
145  uint16_t *pVoltagesTarget,
146  MXM_MEASURE_TYPE_e measurementType,
147  uint32_t fullScaleReference_mV);
148 
149 /**
150  * @brief Parse a RX buffer containing voltage values.
151  * @details This function parses a RX buffer containing the answer to a
152  * READALL command. It will check whether the message contains a
153  * READALL command and whether a supported register has been
154  * queried.
155  * Depending on the queried register, it will pass the proper
156  * parameters to #MXM_ParseVoltageLineReadall(). The contained
157  * data from this message will be parsed into a struct structured
158  * like #MXM_MONITORING_INSTANCE_s::localVoltages.
159  * @param[in] kpkVoltageRxBuffer array-pointer to the RX buffer
160  * @param[in] voltageRxBufferLength length of the RX buffer
161  * @param[out] datastorage contains all measured voltages for local
162  * consumption in the module
163  * @param[in] conversionType type of conversion that has been used for
164  * the measured data
165  * @return #STD_NOT_OK in the case that the RX buffer does not contain a
166  * valid message or the conversion-type is unknown,
167  * otherwise #STD_OK
168  */
170  const uint8_t *const kpkVoltageRxBuffer,
171  uint16_t voltageRxBufferLength,
172  MXM_DATA_STORAGE_s *datastorage,
173  MXM_CONVERSION_TYPE_e conversionType);
174 
175 /**
176  * @brief Test the #MXM_ParseVoltageReadall()-function
177  * @details Test the function #MXM_ParseVoltageReadall() by passing predefined
178  * RX buffer to it and checking the outcome. This function writes to
179  * the variable #MXM_MONITORING_INSTANCE_s::localVoltages and nulls it
180  * completely after execution. It is intended as a self-check that can
181  * be performed during startup of the driver.
182  * @return #STD_OK if the self-check has been performed successfully,
183  * otherwise #STD_NOT_OK
184  */
186 
187 /**
188  * @brief Execute all preinit selfchecks.
189  * @details Executes the following self-checks:
190  * - #MXM_CRC8SelfTest()
191  * - #MXM_ConvertTest()
192  * - #MXM_FirstSetBitTest()
193  * - #MXM_ExtractValueFromRegisterTest()
194  * - #MXM_ParseVoltageReadallTest()
195  * - #MXM_5XUserAccessibleAddressSpaceCheckerSelfCheck()
196  *
197  * These self-checks do not need an initialized daisy-chain
198  * and can therefore be executed at startup of the
199  * state-machine.
200  *
201  * After execution of each test, the return value is stored in
202  * the supplied state-struct. The function returns whether the
203  * self-check has successfully passed.
204  * @param[in,out] pState pointer to the state-struct, will write status into
205  * @return #STD_OK on success, #STD_NOT_OK on failure,
206  * return value has to be used
207  */
209 
210 /*========== Static Function Implementations ================================*/
211 
213  FAS_ASSERT(pInstance != NULL_PTR);
214  STD_RETURN_TYPE_e getBufferResult =
216  FAS_ASSERT(getBufferResult == STD_OK);
217  pInstance->dcByte = MXM_5XGetLastDCByte(pInstance->pInstance5X);
218 }
219 
221  const uint8_t *const kpkVoltRxBuffer,
222  uint16_t voltRxBufferLength,
223  uint8_t measurementOffset,
224  MXM_CONVERSION_TYPE_e conversionType,
225  uint16_t *pVoltagesTarget,
226  MXM_MEASURE_TYPE_e measurementType,
227  uint32_t fullScaleReference_mV) {
228  FAS_ASSERT(kpkVoltRxBuffer != NULL_PTR);
229  FAS_ASSERT(pVoltagesTarget != NULL_PTR);
230 
231  /* assert that assumptions behind computation of numberOfConnectedDevices
232  are correct */
233  FAS_ASSERT(voltRxBufferLength >= (2u + 2u));
234  FAS_ASSERT(((voltRxBufferLength - 2u - 2u) / 2u) <= (uint16_t)UINT8_MAX);
235  /* buffer-length - length of start - length of end divided by two (LSB and MSB) */
236  const uint8_t numberOfConnectedDevices = (uint8_t)(((voltRxBufferLength - 2u - 2u) / 2u) & (uint8_t)UINT8_MAX);
237  /* TODO impact of alive counter on rxBufferLength
238  * otherwise offset at the end of message is currently 2 (DATACHECKBYTE and CRC) */
239  for (uint8_t i = 2u; i < (voltRxBufferLength - 2u); i = i + 2u) {
240  const uint8_t calculatedModuleNumber = numberOfConnectedDevices - ((i / 2u) - 1u) - 1u;
241  uint16_t calculatedModulePosition = 0u;
242  switch (measurementType) {
243  case MXM_MEASURE_TEMP:
244  calculatedModulePosition = (uint16_t)calculatedModuleNumber * MXM_MAXIMUM_NR_OF_AUX_PER_MODULE;
245  break;
247  calculatedModulePosition = (uint16_t)calculatedModuleNumber * MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE;
248  break;
250  calculatedModulePosition = calculatedModuleNumber;
251  break;
252  default:
254  break;
255  }
256  FAS_ASSERT((calculatedModulePosition + measurementOffset) <= (uint16_t)UINT16_MAX);
257  uint16_t calculatedArrayPosition = calculatedModulePosition + measurementOffset;
258 
259  /* check calculated array position */
260  switch (measurementType) {
261  case MXM_MEASURE_TEMP:
263  break;
266  break;
268  FAS_ASSERT(calculatedArrayPosition < (MXM_MAXIMUM_NR_OF_MODULES));
269  break;
270  default:
272  break;
273  }
274 
275  FAS_ASSERT(i <= voltRxBufferLength);
276  FAS_ASSERT((i + (uint16_t)1u) <= voltRxBufferLength);
277  MXM_Convert(
278  kpkVoltRxBuffer[i],
279  kpkVoltRxBuffer[i + 1u],
280  &pVoltagesTarget[calculatedArrayPosition],
281  conversionType,
282  fullScaleReference_mV);
283  }
284 }
285 
287  const uint8_t *const kpkVoltageRxBuffer,
288  uint16_t voltageRxBufferLength,
289  MXM_DATA_STORAGE_s *datastorage,
290  MXM_CONVERSION_TYPE_e conversionType) {
291  STD_RETURN_TYPE_e retval = STD_OK;
292  FAS_ASSERT(kpkVoltageRxBuffer != NULL_PTR);
293  FAS_ASSERT(datastorage != NULL_PTR);
294 
295  if (kpkVoltageRxBuffer[0] != BATTERY_MANAGEMENT_READALL) {
296  /* rxBuffer does not contain a READALL command */
297  retval = STD_NOT_OK;
298  } else if ((voltageRxBufferLength % 2u) != 0u) {
299  /* without alive counter rx-buffer always should be of even length */
300  /* TODO impact of alive-counter-byte */
301  retval = STD_NOT_OK;
302  } else if (
303  (conversionType != MXM_CONVERSION_UNIPOLAR) && (conversionType != MXM_CONVERSION_BIPOLAR) &&
304  (conversionType != MXM_CONVERSION_BLOCK_VOLTAGE)) {
305  /* conversion type is not supported */
306  retval = STD_NOT_OK;
307  } else {
308  switch (kpkVoltageRxBuffer[1]) {
309  case (uint8_t)MXM_REG_CELL1:
311  kpkVoltageRxBuffer,
312  voltageRxBufferLength,
314  conversionType,
315  datastorage->cellVoltages_mV,
318  break;
319  case (uint8_t)MXM_REG_CELL2:
321  kpkVoltageRxBuffer,
322  voltageRxBufferLength,
324  conversionType,
325  datastorage->cellVoltages_mV,
328  break;
329  case (uint8_t)MXM_REG_CELL3:
331  kpkVoltageRxBuffer,
332  voltageRxBufferLength,
334  conversionType,
335  datastorage->cellVoltages_mV,
338  break;
339  case (uint8_t)MXM_REG_CELL4:
341  kpkVoltageRxBuffer,
342  voltageRxBufferLength,
344  conversionType,
345  datastorage->cellVoltages_mV,
348  break;
349  case (uint8_t)MXM_REG_CELL5:
351  kpkVoltageRxBuffer,
352  voltageRxBufferLength,
354  conversionType,
355  datastorage->cellVoltages_mV,
358  break;
359  case (uint8_t)MXM_REG_CELL6:
361  kpkVoltageRxBuffer,
362  voltageRxBufferLength,
364  conversionType,
365  datastorage->cellVoltages_mV,
368  break;
369  case (uint8_t)MXM_REG_CELL7:
371  kpkVoltageRxBuffer,
372  voltageRxBufferLength,
374  conversionType,
375  datastorage->cellVoltages_mV,
378  break;
379  case (uint8_t)MXM_REG_CELL8:
381  kpkVoltageRxBuffer,
382  voltageRxBufferLength,
384  conversionType,
385  datastorage->cellVoltages_mV,
388  break;
389  case (uint8_t)MXM_REG_CELL9:
391  kpkVoltageRxBuffer,
392  voltageRxBufferLength,
394  conversionType,
395  datastorage->cellVoltages_mV,
398  break;
399  case (uint8_t)MXM_REG_CELL10:
401  kpkVoltageRxBuffer,
402  voltageRxBufferLength,
404  conversionType,
405  datastorage->cellVoltages_mV,
408  break;
409  case (uint8_t)MXM_REG_CELL11:
411  kpkVoltageRxBuffer,
412  voltageRxBufferLength,
414  conversionType,
415  datastorage->cellVoltages_mV,
418  break;
419  case (uint8_t)MXM_REG_CELL12:
421  kpkVoltageRxBuffer,
422  voltageRxBufferLength,
424  conversionType,
425  datastorage->cellVoltages_mV,
428  break;
429  case (uint8_t)MXM_REG_CELL13:
431  kpkVoltageRxBuffer,
432  voltageRxBufferLength,
434  conversionType,
435  datastorage->cellVoltages_mV,
438  break;
439  case (uint8_t)MXM_REG_CELL14:
441  kpkVoltageRxBuffer,
442  voltageRxBufferLength,
444  conversionType,
445  datastorage->cellVoltages_mV,
448  break;
449  case (uint8_t)MXM_REG_AUX0:
451  kpkVoltageRxBuffer,
452  voltageRxBufferLength,
454  conversionType,
455  datastorage->auxVoltages_mV,
458  break;
459  case (uint8_t)MXM_REG_AUX2:
461  kpkVoltageRxBuffer,
462  voltageRxBufferLength,
464  conversionType,
465  datastorage->auxVoltages_mV,
468  break;
469  case (uint8_t)MXM_REG_AUX3:
471  kpkVoltageRxBuffer,
472  voltageRxBufferLength,
474  conversionType,
475  datastorage->auxVoltages_mV,
478  break;
479  case (uint8_t)MXM_REG_BLOCK:
481  kpkVoltageRxBuffer,
482  voltageRxBufferLength,
484  conversionType,
485  datastorage->blockVoltages,
487  65000u);
488  /* TODO scaling and variable size (65000)*/
489  break;
490  default:
491  /* the read register is not a valid cell register */
492  retval = STD_NOT_OK;
493  break;
494  }
495  }
496  return retval;
497 }
498 
500  FAS_ASSERT(pInstance != NULL_PTR);
501  STD_RETURN_TYPE_e retval = STD_OK;
502 
503  /* AXIVION Disable Style Generic-NoMagicNumbers: This test function uses magic numbers to test predefined values. */
504 
505  uint8_t testBuffer[MXM_TEST_BUFFER_MAXIMUM_LENGTH] = {0};
506  uint16_t testBufferLength = MXM_TEST_BUFFER_MAXIMUM_LENGTH;
507  /* init test buffer */
508  for (uint8_t i = 0u; i < MXM_TEST_BUFFER_MAXIMUM_LENGTH; i++) {
509  testBuffer[i] = 0u;
510  }
511 
512  /* not a readall buffer */
513  testBuffer[0] = BATTERY_MANAGEMENT_HELLOALL;
514  if (MXM_ParseVoltageReadall(testBuffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
515  STD_NOT_OK) {
516  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
517  retval = STD_NOT_OK;
518  }
519 
520  /* not a cell voltage register */
521  testBuffer[0] = BATTERY_MANAGEMENT_READALL;
522  testBuffer[1] = (uint8_t)MXM_REG_VERSION;
523  if (MXM_ParseVoltageReadall(testBuffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
524  STD_NOT_OK) {
525  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
526  retval = STD_NOT_OK;
527  }
528 
529  /* bogus conversion type */
530  testBuffer[0] = BATTERY_MANAGEMENT_READALL;
531  testBuffer[1] = (uint8_t)MXM_REG_CELL1;
532  /* AXIVION Next Line Style MisraC2012Directive-4.1 MisraC2012-10.5: explicitely invalid value in order to provoke error response */
533  if (MXM_ParseVoltageReadall(testBuffer, testBufferLength, &pInstance->localVoltages, (MXM_CONVERSION_TYPE_e)42) !=
534  STD_NOT_OK) {
535  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
536  retval = STD_NOT_OK;
537  }
538 
539  /* not an even length of rxBuffer */
540  testBuffer[0] = BATTERY_MANAGEMENT_READALL;
541  testBuffer[1] = (uint8_t)MXM_REG_CELL1;
542  testBufferLength = 5;
543  if (MXM_ParseVoltageReadall(testBuffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
544  STD_NOT_OK) {
545  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
546  retval = STD_NOT_OK;
547  }
548 
549  /* test data for CELL1REG */
550  testBuffer[0] = BATTERY_MANAGEMENT_READALL;
551  testBuffer[1] = (uint8_t)MXM_REG_CELL1;
552  testBuffer[2] = 0xFCu;
553  testBuffer[3] = 0xFFu;
554  testBuffer[4] = 0x00u;
555  testBuffer[5] = 0x00u;
556  testBuffer[6] = 0xFCu;
557  testBuffer[7] = 0xFFu;
558  testBuffer[8] = 0x42u; /* DATACHECKBYTE, irrelevant for function, filled with dummy bytes */
559  testBuffer[9] = 0x44u; /* CRCBYTE, irrelevant for function, filled with dummy bytes */
560  testBufferLength = 10u;
561  if (MXM_ParseVoltageReadall(testBuffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
562  STD_OK) {
563  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
564  retval = STD_NOT_OK;
565  } else {
566  if ((pInstance->localVoltages.cellVoltages_mV[0] != MXM_REF_UNIPOLAR_CELL_mV) ||
567  (pInstance->localVoltages.cellVoltages_mV[14] != 0u) ||
569  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
570  retval = STD_NOT_OK;
571  }
572  }
573 
574  /* null mxm_local_cellvoltages */
575  for (uint16_t i_0 = 0; i_0 < (MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE * MXM_MAXIMUM_NR_OF_MODULES); i_0++) {
576  pInstance->localVoltages.cellVoltages_mV[i_0] = 0;
577  }
578 
579  /* test data for CELL2REG */
580  testBuffer[0] = BATTERY_MANAGEMENT_READALL;
581  testBuffer[1] = (uint8_t)MXM_REG_CELL2;
582  testBuffer[2] = 0xFCu;
583  testBuffer[3] = 0xFFu;
584  testBuffer[4] = 0x00u;
585  testBuffer[5] = 0x00u;
586  testBuffer[6] = 0xFCu;
587  testBuffer[7] = 0xFFu;
588  testBuffer[8] = 0x42u; /* DATACHECKBYTE, irrelevant for function, filled with dummy bytes */
589  testBuffer[9] = 0x44u; /* CRCBYTE, irrelevant for function, filled with dummy bytes */
590  testBufferLength = 10;
591  if (MXM_ParseVoltageReadall(testBuffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
592  STD_OK) {
593  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
594  retval = STD_NOT_OK;
595  } else {
596  if ((pInstance->localVoltages.cellVoltages_mV[1] != MXM_REF_UNIPOLAR_CELL_mV) ||
597  (pInstance->localVoltages.cellVoltages_mV[15] != 0u) ||
599  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
600  retval = STD_NOT_OK;
601  }
602  }
603 
604  /* null mxm_local_cellvoltages */
605  for (uint16_t i_1 = 0; i_1 < (MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE * MXM_MAXIMUM_NR_OF_MODULES); i_1++) {
606  pInstance->localVoltages.cellVoltages_mV[i_1] = 0;
607  }
608 
609  /* test data for CELL3REG */
610  testBuffer[0] = BATTERY_MANAGEMENT_READALL;
611  testBuffer[1] = (uint8_t)MXM_REG_CELL3;
612  testBuffer[2] = 0xFCu;
613  testBuffer[3] = 0xFFu;
614  testBuffer[4] = 0x42u; /* DATACHECKBYTE, irrelevant for function, filled with dummy bytes */
615  testBuffer[5] = 0x44u; /* CRCBYTE, irrelevant for function, filled with dummy bytes */
616  testBufferLength = 6;
617  if (MXM_ParseVoltageReadall(testBuffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
618  STD_OK) {
619  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
620  retval = STD_NOT_OK;
621  } else {
623  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
624  retval = STD_NOT_OK;
625  }
626  }
627 
628  /* null mxm_local_cellvoltages */
629  for (uint16_t i_2 = 0; i_2 < (MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE * MXM_MAXIMUM_NR_OF_MODULES); i_2++) {
630  pInstance->localVoltages.cellVoltages_mV[i_2] = 0;
631  }
632 
633  /* test data for CELL4REG */
634  testBuffer[0] = BATTERY_MANAGEMENT_READALL;
635  testBuffer[1] = (uint8_t)MXM_REG_CELL4;
636  testBuffer[2] = 0xFCu;
637  testBuffer[3] = 0xFFu;
638  testBuffer[4] = 0x42u; /* DATACHECKBYTE, irrelevant for function, filled with dummy bytes */
639  testBuffer[5] = 0x44u; /* CRCBYTE, irrelevant for function, filled with dummy bytes */
640  testBufferLength = 6;
641  if (MXM_ParseVoltageReadall(testBuffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
642  STD_OK) {
643  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
644  retval = STD_NOT_OK;
645  } else {
647  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
648  retval = STD_NOT_OK;
649  }
650  }
651 
652  /* null mxm_local_cellvoltages */
653  for (uint16_t i_3 = 0; i_3 < (MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE * MXM_MAXIMUM_NR_OF_MODULES); i_3++) {
654  pInstance->localVoltages.cellVoltages_mV[i_3] = 0;
655  }
656 
657  /* test data for CELL5REG */
658  testBuffer[0] = BATTERY_MANAGEMENT_READALL;
659  testBuffer[1] = (uint8_t)MXM_REG_CELL5;
660  testBuffer[2] = 0xFCu;
661  testBuffer[3] = 0xFFu;
662  testBuffer[4] = 0x42u; /* DATACHECKBYTE, irrelevant for function, filled with dummy bytes */
663  testBuffer[5] = 0x44u; /* CRCBYTE, irrelevant for function, filled with dummy bytes */
664  testBufferLength = 6;
665  if (MXM_ParseVoltageReadall(testBuffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
666  STD_OK) {
667  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
668  retval = STD_NOT_OK;
669  } else {
671  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
672  retval = STD_NOT_OK;
673  }
674  }
675 
676  /* null mxm_local_cellvoltages */
677  for (uint16_t i_4 = 0; i_4 < (MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE * MXM_MAXIMUM_NR_OF_MODULES); i_4++) {
678  pInstance->localVoltages.cellVoltages_mV[i_4] = 0;
679  }
680 
681  /* test data for CELL6REG */
682  testBuffer[0] = BATTERY_MANAGEMENT_READALL;
683  testBuffer[1] = (uint8_t)MXM_REG_CELL6;
684  testBuffer[2] = 0xFCu;
685  testBuffer[3] = 0xFFu;
686  testBuffer[4] = 0x42u; /* DATACHECKBYTE, irrelevant for function, filled with dummy bytes */
687  testBuffer[5] = 0x44u; /* CRCBYTE, irrelevant for function, filled with dummy bytes */
688  testBufferLength = 6;
689  if (MXM_ParseVoltageReadall(testBuffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
690  STD_OK) {
691  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
692  retval = STD_NOT_OK;
693  } else {
695  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
696  retval = STD_NOT_OK;
697  }
698  }
699 
700  /* null mxm_local_cellvoltages */
701  for (uint16_t i_5 = 0; i_5 < (MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE * MXM_MAXIMUM_NR_OF_MODULES); i_5++) {
702  pInstance->localVoltages.cellVoltages_mV[i_5] = 0;
703  }
704 
705  /* test data for CELL7REG */
706  testBuffer[0] = BATTERY_MANAGEMENT_READALL;
707  testBuffer[1] = (uint8_t)MXM_REG_CELL7;
708  testBuffer[2] = 0xFCu;
709  testBuffer[3] = 0xFFu;
710  testBuffer[4] = 0x42u; /* DATACHECKBYTE, irrelevant for function, filled with dummy bytes */
711  testBuffer[5] = 0x44u; /* CRCBYTE, irrelevant for function, filled with dummy bytes */
712  testBufferLength = 6;
713  if (MXM_ParseVoltageReadall(testBuffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
714  STD_OK) {
715  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
716  retval = STD_NOT_OK;
717  } else {
719  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
720  retval = STD_NOT_OK;
721  }
722  }
723 
724  /* null mxm_local_cellvoltages */
725  for (uint16_t i_6 = 0; i_6 < (MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE * MXM_MAXIMUM_NR_OF_MODULES); i_6++) {
726  pInstance->localVoltages.cellVoltages_mV[i_6] = 0;
727  }
728 
729  /* test data for CELL8REG */
730  testBuffer[0] = BATTERY_MANAGEMENT_READALL;
731  testBuffer[1] = (uint8_t)MXM_REG_CELL8;
732  testBuffer[2] = 0xFCu;
733  testBuffer[3] = 0xFFu;
734  testBuffer[4] = 0x42u; /* DATACHECKBYTE, irrelevant for function, filled with dummy bytes */
735  testBuffer[5] = 0x44u; /* CRCBYTE, irrelevant for function, filled with dummy bytes */
736  testBufferLength = 6;
737  if (MXM_ParseVoltageReadall(testBuffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
738  STD_OK) {
739  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
740  retval = STD_NOT_OK;
741  } else {
743  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
744  retval = STD_NOT_OK;
745  }
746  }
747 
748  /* null mxm_local_cellvoltages */
749  for (uint16_t i_7 = 0; i_7 < (MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE * MXM_MAXIMUM_NR_OF_MODULES); i_7++) {
750  pInstance->localVoltages.cellVoltages_mV[i_7] = 0;
751  }
752 
753  /* test data for CELL9REG */
754  testBuffer[0] = BATTERY_MANAGEMENT_READALL;
755  testBuffer[1] = (uint8_t)MXM_REG_CELL9;
756  testBuffer[2] = 0xFCu;
757  testBuffer[3] = 0xFFu;
758  testBuffer[4] = 0x42u; /* DATACHECKBYTE, irrelevant for function, filled with dummy bytes */
759  testBuffer[5] = 0x44u; /* CRCBYTE, irrelevant for function, filled with dummy bytes */
760  testBufferLength = 6;
761  if (MXM_ParseVoltageReadall(testBuffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
762  STD_OK) {
763  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
764  retval = STD_NOT_OK;
765  } else {
767  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
768  retval = STD_NOT_OK;
769  }
770  }
771 
772  /* null mxm_local_cellvoltages */
773  for (uint16_t i_8 = 0; i_8 < (MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE * MXM_MAXIMUM_NR_OF_MODULES); i_8++) {
774  pInstance->localVoltages.cellVoltages_mV[i_8] = 0;
775  }
776 
777  /* test data for CELL10REG */
778  testBuffer[0] = BATTERY_MANAGEMENT_READALL;
779  testBuffer[1] = (uint8_t)MXM_REG_CELL10;
780  testBuffer[2] = 0xFCu;
781  testBuffer[3] = 0xFFu;
782  testBuffer[4] = 0x42u; /* DATACHECKBYTE, irrelevant for function, filled with dummy bytes */
783  testBuffer[5] = 0x44u; /* CRCBYTE, irrelevant for function, filled with dummy bytes */
784  testBufferLength = 6;
785  if (MXM_ParseVoltageReadall(testBuffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
786  STD_OK) {
787  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
788  retval = STD_NOT_OK;
789  } else {
791  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
792  retval = STD_NOT_OK;
793  }
794  }
795 
796  /* null mxm_local_cellvoltages */
797  for (uint16_t i_9 = 0; i_9 < (MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE * MXM_MAXIMUM_NR_OF_MODULES); i_9++) {
798  pInstance->localVoltages.cellVoltages_mV[i_9] = 0;
799  }
800 
801  /* test data for CELL11REG */
802  testBuffer[0] = BATTERY_MANAGEMENT_READALL;
803  testBuffer[1] = (uint8_t)MXM_REG_CELL11;
804  testBuffer[2] = 0xFCu;
805  testBuffer[3] = 0xFFu;
806  testBuffer[4] = 0x42u; /* DATACHECKBYTE, irrelevant for function, filled with dummy bytes */
807  testBuffer[5] = 0x44u; /* CRCBYTE, irrelevant for function, filled with dummy bytes */
808  testBufferLength = 6;
809  if (MXM_ParseVoltageReadall(testBuffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
810  STD_OK) {
811  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
812  retval = STD_NOT_OK;
813  } else {
815  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
816  retval = STD_NOT_OK;
817  }
818  }
819 
820  /* null mxm_local_cellvoltages */
821  for (uint16_t i_10 = 0; i_10 < (MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE * MXM_MAXIMUM_NR_OF_MODULES); i_10++) {
822  pInstance->localVoltages.cellVoltages_mV[i_10] = 0;
823  }
824 
825  /* test data for CELL12REG */
826  testBuffer[0] = BATTERY_MANAGEMENT_READALL;
827  testBuffer[1] = (uint8_t)MXM_REG_CELL12;
828  testBuffer[2] = 0xFCu;
829  testBuffer[3] = 0xFFu;
830  testBuffer[4] = 0x42u; /* DATACHECKBYTE, irrelevant for function, filled with dummy bytes */
831  testBuffer[5] = 0x44u; /* CRCBYTE, irrelevant for function, filled with dummy bytes */
832  testBufferLength = 6;
833  if (MXM_ParseVoltageReadall(testBuffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
834  STD_OK) {
835  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
836  retval = STD_NOT_OK;
837  } else {
839  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
840  retval = STD_NOT_OK;
841  }
842  }
843 
844  /* null mxm_local_cellvoltages */
845  for (uint16_t i_11 = 0; i_11 < (MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE * MXM_MAXIMUM_NR_OF_MODULES); i_11++) {
846  pInstance->localVoltages.cellVoltages_mV[i_11] = 0;
847  }
848 
849  /* test data for CELL13REG */
850  testBuffer[0] = BATTERY_MANAGEMENT_READALL;
851  testBuffer[1] = (uint8_t)MXM_REG_CELL13;
852  testBuffer[2] = 0xFCu;
853  testBuffer[3] = 0xFFu;
854  testBuffer[4] = 0x42u; /* DATACHECKBYTE, irrelevant for function, filled with dummy bytes */
855  testBuffer[5] = 0x44u; /* CRCBYTE, irrelevant for function, filled with dummy bytes */
856  testBufferLength = 6;
857  if (MXM_ParseVoltageReadall(testBuffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
858  STD_OK) {
859  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
860  retval = STD_NOT_OK;
861  } else {
863  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
864  retval = STD_NOT_OK;
865  }
866  }
867 
868  /* null mxm_local_cellvoltages */
869  for (uint16_t i_12 = 0; i_12 < (MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE * MXM_MAXIMUM_NR_OF_MODULES); i_12++) {
870  pInstance->localVoltages.cellVoltages_mV[i_12] = 0;
871  }
872 
873  /* test data for CELL14REG */
874  testBuffer[0] = BATTERY_MANAGEMENT_READALL;
875  testBuffer[1] = (uint8_t)MXM_REG_CELL14;
876  testBuffer[2] = 0xFCu;
877  testBuffer[3] = 0xFFu;
878  testBuffer[4] = 0x42u; /* DATACHECKBYTE, irrelevant for function, filled with dummy bytes */
879  testBuffer[5] = 0x44u; /* CRCBYTE, irrelevant for function, filled with dummy bytes */
880  testBufferLength = 6;
881  if (MXM_ParseVoltageReadall(testBuffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
882  STD_OK) {
883  /* AXIVION Next Line Style FaultDetection-UnusedAssignments: return value collects all negative results. */
884  retval = STD_NOT_OK;
885  } else {
887  retval = STD_NOT_OK;
888  }
889  }
890 
891  /* null mxm_local_cellvoltages */
892  for (uint16_t i_13 = 0; i_13 < (MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE * MXM_MAXIMUM_NR_OF_MODULES); i_13++) {
893  pInstance->localVoltages.cellVoltages_mV[i_13] = 0;
894  }
895 
896  /* AXIVION Enable Style Generic-NoMagicNumbers: */
897 
898  return retval;
899 }
900 
902  FAS_ASSERT(pState != NULL_PTR);
903  STD_RETURN_TYPE_e retval = STD_OK;
904  pState->selfCheck.crc = MXM_CRC8SelfTest();
905  pState->selfCheck.conv = MXM_ConvertTest();
910 
911  if ((pState->selfCheck.crc == STD_OK) && (pState->selfCheck.addressSpaceChecker == STD_OK) &&
912  (pState->selfCheck.conv == STD_OK) && (pState->selfCheck.firstSetBit == STD_OK) &&
914  /* check has passed, return value already set */
915  } else {
916  retval = STD_NOT_OK;
917  }
918 
919  return retval;
920 }
921 
922 /*========== Extern Function Implementations ================================*/
924  FAS_ASSERT(pInstance != NULL_PTR);
925 
926  if (pInstance->errorCounter != 0u) {
927  const bool counterCanBeReset =
929  if (counterCanBeReset == true) {
930  pInstance->errorCounter = 0u;
931  pInstance->timestampLastError = 0u;
932  }
933  }
934 }
935 
936 extern void MXM_ErrorHandlerReset(MXM_MONITORING_INSTANCE_s *pInstance, bool immediateReset) {
937  FAS_ASSERT(pInstance != NULL_PTR);
938 
939  pInstance->timestampLastError = OS_GetTickCount();
940  pInstance->errorCounter++;
941 
942  if ((pInstance->errorCounter > MXM_MAXIMUM_ERROR_COUNT) || (immediateReset == true)) {
943  pInstance->resetNecessary = true;
944  }
945 }
946 
948  MXM_MONITORING_INSTANCE_s *pInstance,
950  FAS_ASSERT(pInstance != NULL_PTR);
951 
952  if (pInstance->requestStatus5x == MXM_5X_STATE_UNSENT) {
953  const STD_RETURN_TYPE_e setStateRequestReturn = MXM_5XSetStateRequest(
954  pInstance->pInstance5X,
956  pInstance->batteryCmdBuffer,
957  &pInstance->requestStatus5x);
958  FAS_ASSERT(setStateRequestReturn == STD_OK);
959  } else if (pInstance->requestStatus5x == MXM_5X_STATE_UNPROCESSED) {
960  /* wait for processing */
961  } else if (pInstance->requestStatus5x == MXM_5X_STATE_PROCESSED) {
962  /* continue to the substate specified by the request */
963  pInstance->operationSubstate = nextState;
965  } else if (pInstance->requestStatus5x == MXM_5X_STATE_ERROR) {
966  /* default-behavior: retry */
968  MXM_ErrorHandlerReset(pInstance, false);
969  } else {
970  /* invalid value, trap */
972  }
973 }
974 
976  MXM_MONITORING_INSTANCE_s *pInstance,
977  MXM_REG_NAME_e registerName,
979  FAS_ASSERT(pInstance != NULL_PTR);
980 
981  bool retval = false;
982  if (pInstance->requestStatus5x == MXM_5X_STATE_UNSENT) {
983  pInstance->batteryCmdBuffer.regAddress = registerName;
984  const STD_RETURN_TYPE_e setStateRequestReturn = MXM_5XSetStateRequest(
985  pInstance->pInstance5X, MXM_STATEMACH_5X_READALL, pInstance->batteryCmdBuffer, &pInstance->requestStatus5x);
986  FAS_ASSERT(setStateRequestReturn == STD_OK);
987  } else if (pInstance->requestStatus5x == MXM_5X_STATE_PROCESSED) {
989  pInstance->operationSubstate = nextState;
991  retval = true;
992  } else if (pInstance->requestStatus5x == MXM_5X_STATE_UNPROCESSED) {
993  /* wait for processing */
994  } else if (pInstance->requestStatus5x == MXM_5X_STATE_ERROR) {
995  /* try to reset state */
997  MXM_ErrorHandlerReset(pInstance, false);
998  } else {
999  /* invalid state */
1001  }
1002 
1003  return retval;
1004 }
1005 
1007  FAS_ASSERT(kpkInstance != NULL_PTR);
1008  FAS_ASSERT(kpkInstance->pOpenwire_table != NULL_PTR);
1009 
1010  const uint8_t numberOfSatellites = MXM_5XGetNumberOfSatellites(kpkInstance->pInstance5X);
1011  static_assert(
1012  (((uint16_t)BATTERY_MANAGEMENT_TX_LENGTH_READALL + (2u * MXM_MAXIMUM_NR_OF_MODULES)) <= (uint8_t)UINT8_MAX),
1013  "please check assumptions: code cannot handle number of modules");
1014  const uint8_t messageLength = BATTERY_MANAGEMENT_TX_LENGTH_READALL + (2u * numberOfSatellites);
1015  /* step over every byte-tuple in the RX-buffer */
1016  for (uint8_t i = 2u; i < (messageLength - 2u); i = i + 2u) {
1017  /* calculate current module number (first in RX-buffer is last in line) */
1018  const uint8_t calculatedModuleNumberInDaisyChain = numberOfSatellites - ((i / 2u) - 1u) - 1u;
1019  uint8_t stringNumber = 0u;
1020  uint16_t moduleNumber = 0u;
1021  MXM_ConvertModuleToString(calculatedModuleNumberInDaisyChain, &stringNumber, &moduleNumber);
1022  const uint16_t calculatedModulePosition = moduleNumber * MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE;
1023 
1024  /* step over every cell in the module and update the openwire struct accordingly */
1025  for (uint8_t c = 0u; c < MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE; c++) {
1026  if (c < MXM_CELLS_IN_LSB) {
1027  /* cell numbers under 8 can be found in the LSB */
1028  const uint8_t mask = 1u << c;
1029  if ((uint8_t)(mask & kpkInstance->rxBuffer[i]) > 0u) {
1030  kpkInstance->pOpenwire_table->openwire[stringNumber][calculatedModulePosition + c] = 1;
1031  } else {
1032  kpkInstance->pOpenwire_table->openwire[stringNumber][calculatedModulePosition + c] = 0;
1033  }
1034  } else {
1035  /* cell numbers over or equal 8 can be found in the MSB */
1036  const uint8_t mask = 1u << (c - MXM_CELLS_IN_LSB);
1037  if ((uint8_t)(mask & kpkInstance->rxBuffer[i + 1u]) > 0u) {
1038  kpkInstance->pOpenwire_table->openwire[stringNumber][calculatedModulePosition + c] = 1;
1039  } else {
1040  kpkInstance->pOpenwire_table->openwire[stringNumber][calculatedModulePosition + c] = 0;
1041  }
1042  }
1043  }
1044  }
1045 
1046  /* write database block */
1047  const STD_RETURN_TYPE_e dataReturn = DATA_WRITE_DATA(kpkInstance->pOpenwire_table);
1048  return dataReturn;
1049 }
1050 
1052  FAS_ASSERT(pBalancingInstance != NULL_PTR);
1053  FAS_ASSERT(pBalancingInstance->pBalancingControl_table != NULL_PTR);
1054  STD_RETURN_TYPE_e retval = STD_OK;
1055 
1056  /* Re-Initialize the cells to balance at each iteration */
1057  pBalancingInstance->cellsToBalance = 0u;
1058 
1059  /* /!\ WARNING
1060  In this function, EVEN cells refer to the even cells IN THE REAL MODULE, and NOT in the database index.
1061  --> EVEN cells in a module = ODD database index
1062  --> ODD cells in a module = EVEN database index
1063  e.g. : Cell 2 in the module corresponds to index 1 in the database
1064  the cell index is even, but the database index is odd. */
1065 
1067  /* Iterate over all the cells of the module 'moduleBalancingIndex' in a daisy-chain */
1068  if (pBalancingInstance->moduleBalancingIndex < MXM_MAXIMUM_NR_OF_MODULES) {
1069  for (uint8_t c = 0; c < BS_NR_OF_CELLS_PER_MODULE; c++) {
1070  /* Determine the position of the cell 'c' of module 'moduleBalancingIndex' in the DB */
1071  uint8_t stringNumber = 0u;
1072  uint16_t moduleNumber = 0u;
1073  MXM_ConvertModuleToString(pBalancingInstance->moduleBalancingIndex, &stringNumber, &moduleNumber);
1074  const uint16_t dBIndex = (moduleNumber * BS_NR_OF_CELLS_PER_MODULE) + c;
1075  if (pBalancingInstance->pBalancingControl_table->balancingState[stringNumber][dBIndex] == 1u) {
1076  /* Cell 'c' of module '::moduleBalancingIndex' needs to be balanced.
1077  Need to determine the balancing order --> even or odd cells?
1078  If the balancing order has not been determined before, need to do it. */
1079  if ((pBalancingInstance->evenCellsNeedBalancing == false) &&
1080  (pBalancingInstance->oddCellsNeedBalancing == false)) {
1081  if (((c % 2u) != 0u) && (pBalancingInstance->evenCellsBalancingProcessed == false)) {
1082  pBalancingInstance->evenCellsNeedBalancing = true;
1083  } else if (((c % 2u) == 0u) && (pBalancingInstance->oddCellsBalancingProcessed == false)) {
1084  pBalancingInstance->oddCellsNeedBalancing = true;
1085  } else {
1086  /* nothing to do */
1087  }
1088  }
1089  if ((pBalancingInstance->evenCellsNeedBalancing == true) && ((c % 2u) != 0u) &&
1090  /* If the even cells need to be balanced */
1091  (pBalancingInstance->evenCellsBalancingProcessed == false)) {
1092  pBalancingInstance->cellsToBalance |= ((uint16_t)0x01u << c);
1093  } else if (
1094  /* If the odd cells need to be balanced */
1095  (pBalancingInstance->oddCellsNeedBalancing == true) && ((c % 2u) == 0u) &&
1096  (pBalancingInstance->oddCellsBalancingProcessed == false)) {
1097  pBalancingInstance->cellsToBalance |= ((uint16_t)0x01u << c);
1098  } else {
1099  /* nothing to do */
1100  }
1101  }
1102  }
1103  } else {
1104  retval = STD_NOT_OK;
1105  }
1106  return retval;
1107 }
1108 
1110  FAS_ASSERT(kpkInstance != NULL_PTR);
1111  FAS_ASSERT(kpkInstance->pCellVoltages_table != NULL_PTR);
1112  FAS_ASSERT(kpkInstance->pCellTemperatures_table != NULL_PTR);
1114 
1115  uint16_t numberValidVoltageMeasurements[BS_NR_OF_STRINGS] = {0};
1116  /* voltages */
1117  for (uint8_t i_mod = 0; i_mod < (BS_NR_OF_MODULES * BS_NR_OF_STRINGS); i_mod++) {
1118  const bool moduleIsConnected = MXM_CheckIfADeviceIsConnected(kpkInstance, i_mod);
1119  uint8_t stringNumber = 0u;
1120  uint16_t moduleNumber = 0u;
1121  MXM_ConvertModuleToString(i_mod, &stringNumber, &moduleNumber);
1122  FAS_ASSERT(stringNumber < BS_NR_OF_STRINGS);
1123  FAS_ASSERT(moduleNumber < BS_NR_OF_MODULES);
1124  kpkInstance->pCellVoltages_table->moduleVoltage_mV[stringNumber][moduleNumber] =
1125  kpkInstance->localVoltages.blockVoltages[i_mod];
1126  /* every iteration that we hit a string first (module 0), we reset the packvoltage counter */
1127  if (moduleNumber == 0u) {
1128  kpkInstance->pCellVoltages_table->packVoltage_mV[stringNumber] = 0;
1129  }
1130  kpkInstance->pCellVoltages_table->packVoltage_mV[stringNumber] +=
1131  (int32_t)kpkInstance->localVoltages.blockVoltages[i_mod];
1132  FAS_ASSERT(BS_NR_OF_CELLS_PER_MODULE <= MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE); /*!< invalid configuration! */
1133  for (uint8_t i_bat = 0; i_bat < BS_NR_OF_CELLS_PER_MODULE; i_bat++) {
1134  uint16_t cell_counter_db = (moduleNumber * BS_NR_OF_CELLS_PER_MODULE) + i_bat;
1135  uint16_t cell_counter_max = ((uint16_t)i_mod * MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE) + i_bat;
1136  const uint16_t cellVoltageLocal_mV = kpkInstance->localVoltages.cellVoltages_mV[cell_counter_max];
1137  if ((int32_t)cellVoltageLocal_mV > INT16_MAX) {
1138  kpkInstance->pCellVoltages_table->cellVoltage_mV[stringNumber][cell_counter_db] = INT16_MAX;
1139  } else {
1140  kpkInstance->pCellVoltages_table->cellVoltage_mV[stringNumber][cell_counter_db] =
1141  (int16_t)cellVoltageLocal_mV;
1142  }
1144  kpkInstance->pCellVoltages_table->cellVoltage_mV[stringNumber][cell_counter_db],
1146  if ((valueIsPlausible == STD_OK) && moduleIsConnected) {
1147  numberValidVoltageMeasurements[stringNumber]++;
1148  } else {
1149  /* Invalidate cell voltage measurement */
1150  kpkInstance->pCellVoltages_table->invalidCellVoltage[stringNumber][moduleNumber] |=
1151  ((uint64_t)1u << i_bat);
1152  }
1153  }
1154  }
1155 
1156  /* temperatures */
1157  uint16_t numberValidTemperatureMeasurements[BS_NR_OF_STRINGS] = {0};
1158  for (uint8_t i_mod = 0; i_mod < (BS_NR_OF_MODULES * BS_NR_OF_STRINGS); i_mod++) {
1159  const bool moduleIsConnected = MXM_CheckIfADeviceIsConnected(kpkInstance, i_mod);
1160  uint8_t stringNumber = 0u;
1161  uint16_t moduleNumber = 0u;
1162  MXM_ConvertModuleToString(i_mod, &stringNumber, &moduleNumber);
1163  FAS_ASSERT(stringNumber < BS_NR_OF_STRINGS);
1164  FAS_ASSERT(moduleNumber < BS_NR_OF_MODULES);
1165 
1166  /* store aux measurement from AUX2 (MUX0) */
1167  if (kpkInstance->muxCounter < BS_NR_OF_TEMP_SENSORS_PER_MODULE) {
1168  const uint16_t temperatureIndexDb = (moduleNumber * BS_NR_OF_TEMP_SENSORS_PER_MODULE) +
1169  kpkInstance->muxCounter;
1170  const uint16_t temperatureIndexMxm = ((uint16_t)i_mod * MXM_MAXIMUM_NR_OF_AUX_PER_MODULE) + 2u;
1171  const uint16_t auxVoltage_mV = kpkInstance->localVoltages.auxVoltages_mV[temperatureIndexMxm];
1172  /* const uint16_t temporaryVoltage = (auxVoltage_mV / ((float)3300 - auxVoltage_mV)) * 1000; */
1173  const int16_t temperature_ddegC = TSI_GetTemperature(auxVoltage_mV);
1174  kpkInstance->pCellTemperatures_table->cellTemperature_ddegC[stringNumber][temperatureIndexDb] =
1175  temperature_ddegC;
1176  const STD_RETURN_TYPE_e valueIsPlausible = AFE_PlausibilityCheckTempMinMax(temperature_ddegC);
1177  if ((valueIsPlausible == STD_OK) && moduleIsConnected) {
1178  numberValidTemperatureMeasurements[stringNumber]++;
1179  } else {
1180  /* Invalidate temperature measurement */
1181  kpkInstance->pCellTemperatures_table->invalidCellTemperature[stringNumber][moduleNumber] |=
1182  ((uint16_t)1u << kpkInstance->muxCounter);
1183  }
1184  }
1185  }
1186 
1187  for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) {
1188  kpkInstance->pCellVoltages_table->nrValidCellVoltages[s] = numberValidVoltageMeasurements[s];
1189  kpkInstance->pCellTemperatures_table->nrValidTemperatures[s] = numberValidTemperatureMeasurements[s];
1190  }
1191 
1193 
1194  return retval;
1195 }
1196 
1198  MXM_BALANCING_STATE_s *pBalancingInstance,
1199  MXM_MONITORING_INSTANCE_s *pMonitoringInstance) {
1200  FAS_ASSERT(pBalancingInstance != NULL_PTR);
1201  FAS_ASSERT(pMonitoringInstance != NULL_PTR);
1202 
1203  pBalancingInstance->moduleBalancingIndex = 0u;
1204  pBalancingInstance->evenCellsNeedBalancing = false;
1205  pBalancingInstance->oddCellsNeedBalancing = false;
1206  pBalancingInstance->evenCellsBalancingProcessed = false;
1207  pBalancingInstance->oddCellsBalancingProcessed = false;
1208  pBalancingInstance->cellsToBalance = 0u;
1209  pBalancingInstance->previousTimeStamp = 0u;
1210  pBalancingInstance->currentTimeStamp = 0u;
1211 
1212  pMonitoringInstance->resetNecessary = false;
1213  pMonitoringInstance->errorCounter = 0u;
1214  pMonitoringInstance->timestampLastError = 0u;
1215  pMonitoringInstance->state = MXM_STATEMACHINE_STATES_UNINITIALIZED;
1216  pMonitoringInstance->operationSubstate = MXM_INIT_ENTRY;
1217  pMonitoringInstance->allowStartup = false;
1218  pMonitoringInstance->operationRequested = false;
1219  pMonitoringInstance->firstMeasurementDone = false;
1220  pMonitoringInstance->stopRequested = false;
1221  pMonitoringInstance->openwireRequested = false;
1222  pMonitoringInstance->undervoltageAlert = false;
1223  pMonitoringInstance->muxCounter = 0u;
1225  pMonitoringInstance->dcByte = MXM_DC_EMPTY;
1226  pMonitoringInstance->mxmVoltageCellCounter = 0u;
1227  pMonitoringInstance->highest5xDevice = 0u;
1228  pMonitoringInstance->requestStatus5x = MXM_5X_STATE_UNSENT;
1229  pMonitoringInstance->batteryCmdBuffer.regAddress = MXM_REG_VERSION;
1230  pMonitoringInstance->batteryCmdBuffer.lsb = 0u;
1231  pMonitoringInstance->batteryCmdBuffer.msb = 0u;
1232  pMonitoringInstance->batteryCmdBuffer.blocksize = 0u;
1233  pMonitoringInstance->batteryCmdBuffer.deviceAddress = 0u;
1234  pMonitoringInstance->batteryCmdBuffer.model = MXM_GetModelIdOfDaisyChain();
1235  pMonitoringInstance->resultSelfCheck = STD_NOT_OK;
1236  pMonitoringInstance->selfCheck.crc = STD_NOT_OK;
1237  pMonitoringInstance->selfCheck.conv = STD_NOT_OK;
1238  pMonitoringInstance->selfCheck.firstSetBit = STD_NOT_OK;
1239  pMonitoringInstance->selfCheck.extractValueFromRegister = STD_NOT_OK;
1240  pMonitoringInstance->selfCheck.parseVoltageReadall = STD_NOT_OK;
1241  pMonitoringInstance->selfCheck.addressSpaceChecker = STD_NOT_OK;
1242  pMonitoringInstance->selfCheck.fmeaStatusASCI = STD_NOT_OK;
1243 
1244  for (uint32_t i = 0u; i < (MXM_MAXIMUM_NR_OF_MODULES * MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE); i++) {
1245  pMonitoringInstance->localVoltages.cellVoltages_mV[i] = 0u;
1246  }
1247 
1248  for (uint32_t i = 0u; i < (MXM_MAXIMUM_NR_OF_MODULES * MXM_MAXIMUM_NR_OF_AUX_PER_MODULE); i++) {
1249  pMonitoringInstance->localVoltages.auxVoltages_mV[i] = 0u;
1250  }
1251 
1252  for (uint32_t i = 0u; i < MXM_MAXIMUM_NR_OF_MODULES; i++) {
1253  pMonitoringInstance->localVoltages.blockVoltages[i] = 0u;
1254  }
1255 
1256  for (uint32_t i = 0u; i < MXM_MAXIMUM_NR_OF_MODULES; i++) {
1257  pMonitoringInstance->registry[i].connected = false;
1258  pMonitoringInstance->registry[i].deviceAddress = 0u;
1259  pMonitoringInstance->registry[i].model = MXM_MODEL_ID_NONE;
1260  pMonitoringInstance->registry[i].siliconVersion = MXM_siliconVersion_invalid;
1261  pMonitoringInstance->registry[i].deviceID = 0u;
1262  pMonitoringInstance->registry[i].registerStatus1 = 0u;
1263  pMonitoringInstance->registry[i].registerStatus2 = 0u;
1264  pMonitoringInstance->registry[i].registerStatus3 = 0u;
1265  pMonitoringInstance->registry[i].registerFmea1 = 0u;
1266  pMonitoringInstance->registry[i].registerFmea2 = 0u;
1267  }
1268 
1269  for (uint32_t i = 0u; i < MXM_RX_BUFFER_LENGTH; i++) {
1270  pMonitoringInstance->rxBuffer[i] = 0u;
1271  }
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  MXM_MonRegistryInit(pInstance);
1321  }
1322 
1323  switch (pInstance->state) {
1325  /* TODO proper selfchecks, that are only executed during IBIT, CBIT and PBIT */
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  if ((pInstance->resultSelfCheck == STD_OK) && (pInstance->selfCheck.fmeaStatusASCI == STD_OK) &&
1385  (resultNumberOfSatellitesGood == STD_OK)) {
1386  pInstance->resultSelfCheck = STD_OK;
1387  pInstance->requestStatus5x = MXM_5X_STATE_UNSENT;
1388  pInstance->state = MXM_STATEMACHINE_STATES_IDLE;
1389  } else if (mxm_allowSkippingPostInitSelfCheck == true) {
1390  pInstance->resultSelfCheck = STD_NOT_OK;
1391  pInstance->requestStatus5x = MXM_5X_STATE_UNSENT;
1392  pInstance->state = MXM_STATEMACHINE_STATES_IDLE;
1393  } else {
1394  /* skipping the self-check is not allowed and it failed, try to reset */
1395  pInstance->resetNecessary = true;
1396  }
1397  } else {
1399  }
1400  break;
1402  pInstance->stopRequested = false;
1403  if (pInstance->operationRequested == true) {
1405  pInstance->operationSubstate = MXM_INIT_ENTRY;
1406  } else {
1407  /* Do nothing */
1408  }
1409  break;
1411  MXM_StateMachineOperation(pInstance);
1412  break;
1413  default:
1415  break;
1416  }
1417 }
1418 
1419 /*========== Externalized Static Function Implementations (Unit Test) =======*/
1420 #ifdef UNITY_UNIT_TEST
1422  return MXM_ParseVoltageReadallTest(pInstance);
1423 }
1425  return MXM_ParseVoltagesIntoDB(pInstance);
1426 }
1428  uint8_t *voltRxBuffer,
1429  uint16_t voltRxBufferLength,
1430  MXM_DATA_STORAGE_s *datastorage,
1431  MXM_CONVERSION_TYPE_e conversionType) {
1432  return MXM_ParseVoltageReadall(voltRxBuffer, voltRxBufferLength, datastorage, conversionType);
1433 }
1434 #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_STRINGS
#define BS_NR_OF_CELLS_PER_MODULE
number of battery cells per battery module (parallel cells are counted as one)
#define BS_NR_OF_MODULES
number of modules in battery pack
#define BS_NR_OF_TEMP_SENSORS_PER_MODULE
number of temperature sensors per battery module
Database module header.
#define DATA_WRITE_DATA(...)
Definition: database.h:86
#define FAS_ASSERT(x)
Assertion macro that asserts that x is true.
Definition: fassert.h:235
#define static_assert(cond, msg)
static assertion macro
Definition: fassert.h:254
#define FAS_TRAP
Define that evaluates to essential boolean false thus tripping an assert.
Definition: fassert.h:110
@ STD_NOT_OK
Definition: fstd_types.h:82
@ STD_OK
Definition: fstd_types.h:81
#define NULL_PTR
Null pointer.
Definition: fstd_types.h:75
enum STD_RETURN_TYPE STD_RETURN_TYPE_e
#define must_check_return
Allows functions to generate warnings in GCC for unused returns.
Definition: general.h:101
void MXM_CheckIfErrorCounterCanBeReset(MXM_MONITORING_INSTANCE_s *pInstance)
Function that checks if the error counter can be reset.
Definition: mxm_1785x.c:923
#define MXM_OFFSET_AUX0
Definition: mxm_1785x.c:84
#define MXM_TEST_BUFFER_MAXIMUM_LENGTH
Definition: mxm_1785x.c:96
#define MXM_OFFSET_CELL_13
Definition: mxm_1785x.c:82
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:936
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:286
static const AFE_PLAUSIBILITY_VALUES_s mxm_plausibleCellVoltages
Definition: mxm_1785x.c:99
#define MXM_OFFSET_CELL_11
Definition: mxm_1785x.c:80
#define MXM_OFFSET_CELL_6
Definition: mxm_1785x.c:75
STD_RETURN_TYPE_e MXM_ProcessOpenWire(const MXM_MONITORING_INSTANCE_s *const kpkInstance)
Processes the retrieved information on openwire.
Definition: mxm_1785x.c:1006
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:975
#define MXM_OFFSET_CELL_1
Definition: mxm_1785x.c:70
#define MXM_OFFSET_CELL_7
Definition: mxm_1785x.c:76
#define MXM_OFFSET_CELL_10
Definition: mxm_1785x.c:79
STD_RETURN_TYPE_e TEST_MXM_ParseVoltagesIntoDB(MXM_MONITORING_INSTANCE_s *pInstance)
Definition: mxm_1785x.c:1424
STD_RETURN_TYPE_e MXM_ParseVoltagesIntoDB(const MXM_MONITORING_INSTANCE_s *const kpkInstance)
Copies measured voltage data into the database.
Definition: mxm_1785x.c:1109
#define MXM_OFFSET_CELL_14
Definition: mxm_1785x.c:83
#define MXM_OFFSET_BLOCK
Definition: mxm_1785x.c:87
#define MXM_OFFSET_CELL_8
Definition: mxm_1785x.c:77
#define MXM_OFFSET_CELL_5
Definition: mxm_1785x.c:74
#define MXM_OFFSET_CELL_4
Definition: mxm_1785x.c:73
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:212
STD_RETURN_TYPE_e MXM_ConstructBalancingBuffer(MXM_BALANCING_STATE_s *pBalancingInstance)
Fill the balancing datastructure.
Definition: mxm_1785x.c:1051
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:85
#define MXM_OFFSET_CELL_9
Definition: mxm_1785x.c:78
#define MXM_OFFSET_CELL_2
Definition: mxm_1785x.c:71
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:220
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:90
#define MXM_REF_VAA_mV
VAA reference voltage (3.3V)
Definition: mxm_1785x.c:106
void MXM_InitializeStateStruct(MXM_BALANCING_STATE_s *pBalancingInstance, MXM_MONITORING_INSTANCE_s *pMonitoringInstance)
Initializes the state structs with default values.
Definition: mxm_1785x.c:1197
#define MXM_OFFSET_AUX3
Definition: mxm_1785x.c:86
#define MXM_TIMEOUT_RESET_ERROR_COUNTER_ms
Definition: mxm_1785x.c:93
static STD_RETURN_TYPE_e must_check_return MXM_ParseVoltageReadallTest(MXM_MONITORING_INSTANCE_s *pInstance)
Test the MXM_ParseVoltageReadall()-function.
Definition: mxm_1785x.c:499
STD_RETURN_TYPE_e TEST_MXM_ParseVoltageReadallTest(MXM_MONITORING_INSTANCE_s *pInstance)
Definition: mxm_1785x.c:1421
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:947
static STD_RETURN_TYPE_e must_check_return MXM_PreInitSelfCheck(MXM_MONITORING_INSTANCE_s *pState)
Execute all preinit selfchecks.
Definition: mxm_1785x.c:901
#define MXM_OFFSET_CELL_3
Definition: mxm_1785x.c:72
STD_RETURN_TYPE_e TEST_MXM_ParseVoltageReadall(uint8_t *voltRxBuffer, uint16_t voltRxBufferLength, MXM_DATA_STORAGE_s *datastorage, MXM_CONVERSION_TYPE_e conversionType)
Definition: mxm_1785x.c:1427
#define MXM_OFFSET_CELL_12
Definition: mxm_1785x.c:81
Headers for the driver for the MAX17841B ASCI and MAX1785x monitoring chip.
#define MXM_REF_UNIPOLAR_CELL_mV
Definition: mxm_1785x.h:103
MXM_MODEL_ID_e MXM_GetModelIdOfDaisyChain(void)
returns the model ID of the daisy chain
Definition: mxm_17852.c:90
#define MXM_CELLS_IN_LSB
Definition: mxm_1785x.h:100
void MXM_StateMachineOperation(MXM_MONITORING_INSTANCE_s *pState)
State-Machine implementation for operation state.
Definition: mxm_17852.c:94
#define MXM_THRESHOLD_DIAGNOSTIC_AFTER_CYCLES
Battery monitoring driver for MAX1785x battery monitoring ICs.
Definition: mxm_1785x.h:94
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_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
@ MXM_siliconVersion_invalid
#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:65
STD_RETURN_TYPE_e must_check_return MXM_CRC8SelfTest(void)
Test the CRC8-algorithm with a known pattern.
Definition: mxm_crc8.c:135
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:256
void MXM_MonRegistryInit(MXM_MONITORING_INSTANCE_s *pState)
Initialize monitoring registry.
Definition: mxm_registry.c:78
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:95
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:140
Declaration of the OS wrapper interface.
uint32_t OS_GetTickCount(void)
Returns OS based system tick value.
Definition: os_freertos.c:129
struct definition for plausibility values of an AFE
const int16_t maximumPlausibleVoltage_mV
uint8_t balancingState[BS_NR_OF_STRINGS][BS_NR_OF_BAT_CELLS]
Definition: database_cfg.h:242
int16_t cellTemperature_ddegC[BS_NR_OF_STRINGS][BS_NR_OF_TEMP_SENSORS_PER_STRING]
Definition: database_cfg.h:139
uint16_t invalidCellTemperature[BS_NR_OF_STRINGS][BS_NR_OF_MODULES]
Definition: database_cfg.h:141
uint16_t nrValidTemperatures[BS_NR_OF_STRINGS]
Definition: database_cfg.h:142
uint16_t nrValidCellVoltages[BS_NR_OF_STRINGS]
Definition: database_cfg.h:127
uint32_t moduleVoltage_mV[BS_NR_OF_STRINGS][BS_NR_OF_MODULES]
Definition: database_cfg.h:128
int16_t cellVoltage_mV[BS_NR_OF_STRINGS][BS_NR_OF_BAT_CELLS]
Definition: database_cfg.h:124
uint64_t invalidCellVoltage[BS_NR_OF_STRINGS][BS_NR_OF_MODULES]
Definition: database_cfg.h:126
int32_t packVoltage_mV[BS_NR_OF_STRINGS]
Definition: database_cfg.h:123
uint8_t openwire[BS_NR_OF_STRINGS][BS_NR_OF_MODULES *(BS_NR_OF_CELLS_PER_MODULE+1u)]
Definition: database_cfg.h:294
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
uint16_t registerStatus2
uint16_t registerStatus3
MXM_siliconVersion_e siliconVersion
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