foxBMS  1.1.1
The foxBMS Battery Management System 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-07-14 (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 "database.h"
61 #include "diag.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 /** length of voltage-read array */
71 #define MXM_VOLTAGE_READ_ARRAY_LENGTH (MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE + 3u)
72 
73 /*========== Static Constant and Variable Definitions =======================*/
74 /**
75  * @brief Mapping of voltage registers
76  *
77  * This array maps registers of the monitoring IC onto cell-numbers. The
78  * register values are defined in the #MXM_REG_NAME_e enum.
79  * For now the length of this array is #MXM_VOLTAGE_READ_ARRAY_LENGTH
80  * as it is enabled for the measurement of all cells, two AUX-voltages and
81  * one block voltage. This has to be adapted once this driver is enabled for
82  * general operation.
83  */
100  MXM_REG_AUX3,
102 };
103 
104 /**
105  * @brief Local cell voltage data block
106  *
107  * This local instance stores the measured cell voltages. In contrast to
108  * #MXM_MONITORING_INSTANCE::localVoltages, the layout of this structure
109  * changes with the defined battery-system as it is described by the
110  * database_cfg.h. Mapping the values from
111  * #MXM_MONITORING_INSTANCE::localVoltages to #mxm_cellVoltages and copying
112  * these entries into the database is handled by #MXM_ParseVoltagesIntoDB().
113  */
115 
116 /**
117  * @brief Local cell temperature data block
118  * @details This local instance stores the measured cell temperatures.
119  */
121 
122 /** @brief Local data structure for openwire results. */
124 
125 /**
126  * @brief Balancing control
127  * @details This variable stores information about which cells need balancing
128  */
130 
131 /**
132  * @brief Module index in the daisy chain
133  * @details Used for balancing
134  */
135 static uint8_t mxm_moduleBalancingIndex = {0};
136 
137 /**
138  * @brief Even cells group needs to be balanced
139  * @details Even and odd cells can't be balanced at the same time
140  */
141 static uint8_t mxm_evenCellsNeedBalancing = {0};
142 
143 /**
144  * @brief Odd cells group needs to be balanced
145  * @details Even and odd cells can't be balanced at the same time
146  */
147 static uint8_t mxm_oddCellsNeedBalancing = {0};
148 
149 /**
150  * @brief Even cells group balancing done
151  * @details Odd cells can be balanced now
152  */
153 static uint8_t mxm_evenCellsBalancingProcessed = {0};
154 
155 /**
156  * @brief Odd cells group balancing done
157  * @details Even cells can be balanced now
158  */
159 static uint8_t mxm_oddCellsBalancingProcessed = {0};
160 
161 /**
162  * @brief Mask to control balacing
163  * @details Bitfield masked with register BALSWCTRL, 16 bits => up to 14 cells
164  */
165 uint16_t mxm_cellsToBalance = 0x00;
166 
167 /** @brief Timers used to guarantee that balancing is performed periodically @{*/
168 static uint32_t mxm_previousTime = {0};
169 static uint32_t mxm_currentTime = {0};
170 /**@}*/
171 
172 /** @brief Delay in milliseconds before the balancing status is updated */
173 #define MXM_DELAY_BALANCING 10000u
174 
175 /** @brief VAA reference voltage (3.3V) */
176 #define MXM_REF_VAA_mV (3300u)
177 
178 /** @defgroup MXM_I2C_IMPLEMENTATION symbols and settings pertaining to the I2C implementation in MXM
179  * @{
180  */
181 /** @brief address of MUX0 */
182 #define MXM_I2C_MUX0_ADDRESS (0x4Cu)
183 /** @brief address of MUX1 */
184 #define MXM_I2C_MUX1_ADDRESS (0x4Du)
185 /**@}*/
186 
187 /*========== Extern Constant and Variable Definitions =======================*/
188 
189 /*========== Static Function Prototypes =====================================*/
190 
191 /** @brief Retrieves data from lower statemachine and writes it to the rx buffer. */
193 
194 /**
195  * @brief Parse voltage values from a READALL receive buffer into an
196  * array.
197  * @details This function expects a preprocessed RX buffer with an answer
198  * to a READALL command. It will parse the data bytes from this
199  * message into an array structured like mxm_local_cellvoltages.
200  * The offset of the measured cell has to be defined. For example
201  * cell 1 has an offset of 0 and cell 4 has an offset of 3. The
202  * offset for the READALL command is always defined in reference
203  * to module 0.
204  *
205  * If is_temperature_measurement is set to true, the function
206  * expects an auxiliary measurement (e.g. temperatures).
207  * @param[in] kpkVoltRxBuffer array-pointer to the RX buffer
208  * @param[in] voltRxBufferLength length of the RX buffer
209  * @param[in] measurementOffset offset of the data in the cell voltage
210  * array (target)
211  * @param[in] conversionType type of conversion that has been used
212  * for the measured data
213  * @param[out] pVoltagesTarget array-pointer to the cell voltages
214  * array
215  * @param[in] meas_type whether the measurement is temperature
216  * or cell
217  * @param[in] full_scale_reference_mV reference voltage of full scale
218  */
219 static void MXM_ParseVoltageLineReadall(
220  const uint8_t *const kpkVoltRxBuffer,
221  uint16_t voltRxBufferLength,
222  uint8_t measurementOffset,
223  MXM_CONVERSION_TYPE_e conversionType,
224  uint16_t *pVoltagesTarget,
225  MXM_MEASURE_TYPE_e meas_type,
226  uint32_t full_scale_reference_mV);
227 
228 /**
229  * @brief Parse a RX buffer containing voltage values.
230  * @details This function parses a RX buffer containing the answer to a
231  * READALL command. It will check whether the message contains a
232  * READALL command and whether a supported register has been
233  * queried.
234  * Depending on the queried register, it will pass the proper
235  * parameters to #MXM_ParseVoltageLineReadall(). The contained
236  * data from this message will be parsed into a struct structured
237  * like #MXM_MONITORING_INSTANCE::localVoltages.
238  * @param[in] kpkVoltageRxBuffer array-pointer to the RX buffer
239  * @param[in] voltageRxBufferLength length of the RX buffer
240  * @param[out] datastorage contains all measured voltages for local
241  * consumption in the module
242  * @param[in] conversionType type of conversion that has been used for
243  * the measured data
244  * @return #STD_NOT_OK in the case that the RX buffer does not contain a
245  * valid message or the conversion-type is unknown,
246  * otherwise #STD_OK
247  */
249  const uint8_t *const kpkVoltageRxBuffer,
250  uint16_t voltageRxBufferLength,
251  MXM_DATA_STORAGE_s *datastorage,
252  MXM_CONVERSION_TYPE_e conversionType);
253 
254 /**
255  * @brief Test the #MXM_ParseVoltageReadall()-function
256  * @details Test the function #MXM_ParseVoltageReadall() by passing predefined
257  * RX buffer to it and checking the outcome. This function writes to
258  * the variable #MXM_MONITORING_INSTANCE::localVoltages and nulls it
259  * completely after execution. It is intended as a self-check that can
260  * be performed during startup of the driver.
261  * @return #STD_OK if the self-check has been performed successfully,
262  * otherwise #STD_NOT_OK
263  */
265 
266 /**
267  * @brief Encapsulation for reading voltages from a register
268  * @details This function encapsulates the request of state-changes and
269  * following conversion for the reading of an arbitrary
270  * measurement voltage of the daisy-chain. Its parameters are
271  * a variable for tracking the state of the underlying
272  * state-machines and the register address that has to be
273  * queried. It returns whether the action has been successful
274  * or not.
275  * In order to obtain all cell voltages this function has to
276  * be called for every relevant register address.
277  * @param[in,out] pState pointer to the state-machine struct
278  * @param[in] regAddress register address that shall be queried
279  * @return current state of the action:
280  * - MXM_MON_STATE_PASS upon completion
281  * - MXM_MON_STATE_PENDING as long as the action is
282  * ongoing
283  * - MXM_MON_STATE_FAIL if the function failed and could
284  * not recover on its own
285  */
288 
289 /**
290  * @brief Copies measured voltage data into the database.
291  * @details This function copies the acquired voltage data from
292  * #MXM_MONITORING_INSTANCE::localVoltages into the database-struct mxm_cellVoltages and
293  * copies this struct into the database. This action is required due
294  * to different data layouts. This driver always stores its
295  * cell-voltages in an array with 14*32 = 448 cells in order to reduce
296  * the amount of different configurations and variants.
297  *
298  * This function maps these values into the database-struct which
299  * scales with the number of connected cells and monitoring ICs.
300  * @param[in] kpkInstance pointer to the #MXM_MONITORING_INSTANCE_s struct
301  * @return #STD_OK if the action was successful or #STD_NOT_OK otherwise
302  */
304 
305 /**
306  * @brief Execute all preinit selfchecks.
307  * @details Executes the following self-checks:
308  * - #MXM_CRC8SelfTest()
309  * - #MXM_ConvertTest()
310  * - #MXM_FirstSetBitTest()
311  * - #MXM_ExtractValueFromRegisterTest()
312  * - #MXM_ParseVoltageReadallTest()
313  * - #MXM_5XUserAccessibleAddressSpaceCheckerSelfCheck()
314  *
315  * These self-checks do not need an initialized daisy-chain
316  * and can therefore be executed at startup of the
317  * state-machine.
318  *
319  * After execution of each test, the return value is stored in
320  * the supplied state-struct. The function returns whether the
321  * self-check has successfully passed.
322  * @param[in,out] pState pointer to the state-struct, will write status into
323  * @return #STD_OK on success, #STD_NOT_OK on failure,
324  * return value has to be used
325  */
327 
328 /**
329  * @brief State-Machine implementation for operation state
330  * @details This state-machine contains the "program" with which the
331  * connected monitoring satellites are controlled. It is
332  * entered by #MXM_StateMachine() once the daisy-chain has
333  * been initialized and is in operation state.
334  * @param[in,out] pState used as both input and output (stores
335  * state-information, requests and intermediate values)
336  */
338 
339 /**
340  * @brief Fill the balancing datastructure
341  * @details This function fills the data-structure that describes
342  * which balancing channels of the monitoring ICs should be
343  * activated.
344  * @return #STD_NOT_OK in case of invalid access
345  */
347 
348 /**
349  * @brief Handle the statemachine-transactions for a WRITEALL
350  * @details Before calling this function, update the command buffer of
351  * the state-variable. Then call this function and pass on the
352  * state-variable and the next state. The function will
353  * handle the communication with the lower state-machine and
354  * will transition into the next state, if the command has
355  * been sent successfully.
356  * @param[in,out] pInstance pointer to instance of the mxm
357  * monitoring state-machine
358  * @param[in] nextState state that should be entered upon successful
359  * completion
360  */
361 static void MXM_HandleStateWriteall(
362  MXM_MONITORING_INSTANCE_s *pInstance,
364 
365 /**
366  * @brief Handle the statemachine-transactions for a READALL
367  * @details Call this function and pass on the state-variable, the
368  * register to be read and the next state. The function will
369  * handle the communication with the lower state-machine and
370  * will transition into the next state, if the command has
371  * been sent successfully. Moreover it will return true when
372  * transitioning. The return value has to be checked and used
373  * to execute additional code if necessary.
374  * @param[in,out] pInstance pointer to instance of the mxm
375  * monitoring state-machine
376  * @param[in] registerName register that should be read
377  * @param[in] nextState state that should be entered upon successful
378  * completion
379  * @return true when the state has been handled, false otherwise, use
380  * this to execute additional code when the message has been
381  * read.
382  */
384  MXM_MONITORING_INSTANCE_s *pInstance,
385  MXM_REG_NAME_e registerName,
387 
388 /**
389  * @brief Processes the retrieved information on openwire
390  * @details Parses through a retrieved RX buffer and writes into the
391  * database.
392  * @param[in,out] kpkInstance pointer to instance of the Maxim monitoring
393  * state-machine
394  * @param[in,out] pDataOpenWire pointer to the local copy of the data-base
395  * entry
396  */
397 static void MXM_ProcessOpenWire(
398  const MXM_MONITORING_INSTANCE_s *const kpkInstance,
399  DATA_BLOCK_OPEN_WIRE_s *pDataOpenWire);
400 
401 /*========== Static Function Implementations ================================*/
404  pInstance->dcByte = MXM_5XGetLastDCByte(pInstance->pInstance5X);
405 }
406 
408  MXM_MONITORING_INSTANCE_s *pInstance,
410  FAS_ASSERT(pInstance != NULL_PTR);
411 
412  if (pInstance->requestStatus5x == MXM_5X_STATE_UNSENT) {
414  pInstance->pInstance5X,
416  pInstance->batteryCmdBuffer,
417  &pInstance->requestStatus5x);
418  } else if (pInstance->requestStatus5x == MXM_5X_STATE_UNPROCESSED) {
419  /* wait for processing */
420  } else if (pInstance->requestStatus5x == MXM_5X_STATE_PROCESSED) {
421  /* continue to the substate specified by the request */
422  pInstance->operationSubstate = nextState;
424  } else if (pInstance->requestStatus5x == MXM_5X_STATE_ERROR) {
425  /* default-behavior: retry */
427  } else {
428  /* invalid value, trap */
430  }
431 }
432 
434  MXM_MONITORING_INSTANCE_s *pInstance,
435  MXM_REG_NAME_e registerName,
437  FAS_ASSERT(pInstance != NULL_PTR);
438 
439  bool retval = false;
440  if (pInstance->requestStatus5x == MXM_5X_STATE_UNSENT) {
441  pInstance->batteryCmdBuffer.regAddress = registerName;
443  pInstance->pInstance5X, MXM_STATEMACH_5X_READALL, pInstance->batteryCmdBuffer, &pInstance->requestStatus5x);
444  } else if (pInstance->requestStatus5x == MXM_5X_STATE_PROCESSED) {
446  pInstance->operationSubstate = nextState;
448  retval = true;
449  } else if (pInstance->requestStatus5x == MXM_5X_STATE_UNPROCESSED) {
450  /* do nothing */
451  } else if (pInstance->requestStatus5x == MXM_5X_STATE_ERROR) {
452  /* try to reset state */
454  } else {
455  /* invalid state */
457  }
458 
459  return retval;
460 }
461 
463  const MXM_MONITORING_INSTANCE_s *const kpkInstance,
464  DATA_BLOCK_OPEN_WIRE_s *pDataOpenWire) {
465  FAS_ASSERT(kpkInstance != NULL_PTR);
466  FAS_ASSERT(pDataOpenWire != NULL_PTR);
467 
468  uint8_t numberOfSatellites = MXM_5XGetNumberOfSatellites(kpkInstance->pInstance5X);
469  uint8_t msg_len = BATTERY_MANAGEMENT_TX_LENGTH_READALL + (2u * numberOfSatellites);
470  /* step over every byte-tuple in the RX-buffer */
471  for (uint8_t i_po = 2u; i_po < (msg_len - 2u); i_po = i_po + 2u) {
472  /* calculate current module number (first in RX-buffer is last in line) */
473  uint8_t calculatedModuleNumberInDaisyChain = numberOfSatellites - ((uint16_t)(i_po / 2u) - 1u) - 1u;
474  uint8_t stringNumber = 0u;
475  uint16_t moduleNumber = 0u;
476  MXM_ConvertModuleToString(calculatedModuleNumberInDaisyChain, &stringNumber, &moduleNumber);
477  uint16_t calculated_module_position = moduleNumber * MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE;
478 
479  /* step over every cell in the module and update the openwire struct accordingly */
480  for (uint8_t c = 0u; c < MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE; c++) {
481  if (c < 8u) {
482  /* cell numbers under 8 can be found in the LSB */
483  uint8_t mask = 1u << c;
484  if ((uint8_t)(mask & kpkInstance->rxBuffer[i_po]) > 0u) {
485  pDataOpenWire->openwire[stringNumber][calculated_module_position + c] = 1;
486  } else {
487  pDataOpenWire->openwire[stringNumber][calculated_module_position + c] = 0;
488  }
489  } else {
490  /* cell numbers over or equal 8 can be found in the MSB */
491  uint8_t mask = 1u << (c - 8u);
492  if ((uint8_t)(mask & kpkInstance->rxBuffer[i_po + 1u]) > 0u) {
493  pDataOpenWire->openwire[stringNumber][calculated_module_position + c] = 1;
494  } else {
495  pDataOpenWire->openwire[stringNumber][calculated_module_position + c] = 0;
496  }
497  }
498  }
499  }
500 
501  /* write database block */
502  DATA_WRITE_DATA(pDataOpenWire);
503 }
504 
506  STD_RETURN_TYPE_e retval = STD_OK;
507 
508  /* Re-Initialize the cells to balance at each iteration */
509  mxm_cellsToBalance = 0u;
510 
511  /* /!\ WARNING
512  In this function, EVEN cells refer to the even cells IN THE REAL MODULE, and NOT in the database index.
513  --> EVEN cells in a module = ODD database index
514  --> ODD cells in a module = EVEN database index
515  e.g. : Cell 2 in the module corresponds to index 1 in the database
516  the cell index is even, but the database index is odd. */
517 
518  /* Iterate over all the cells of the module 'mxm_moduleBalancingIndex' in a daisy-chain */
520  for (uint8_t cell_index = 0; cell_index < BS_NR_OF_CELLS_PER_MODULE; cell_index++) {
521  if (cell_index < MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE) {
522  /* Determine the position of the cell 'cell_index' of module 'mxm_moduleBalancingIndex' in the DB */
523  uint8_t stringNumber = 0u;
524  uint16_t moduleNumber = 0u;
525  MXM_ConvertModuleToString(mxm_moduleBalancingIndex, &stringNumber, &moduleNumber);
526  uint16_t db_index = (moduleNumber * BS_NR_OF_CELLS_PER_MODULE) + cell_index;
527  if (mxm_balancingControl.balancingState[stringNumber][db_index] == 1u) {
528  /* Cell 'cell_index' of module 'mxm_moduleBalancingIndex' needs to be balanced.
529  Need to determine the balancing order --> even or odd cells?
530  If the balancing order has not been determined before, need to do it. */
531  if ((mxm_evenCellsNeedBalancing == 0u) && (mxm_oddCellsNeedBalancing == 0u)) {
532  if (((cell_index % 2u) != 0u) && (mxm_evenCellsBalancingProcessed == 0u)) {
534  } else if (((cell_index % 2u) == 0u) && (mxm_oddCellsBalancingProcessed == 0u)) {
536  }
537  }
538  /* If the even cells need to be balanced */
539  if ((mxm_evenCellsNeedBalancing == 1u) && ((cell_index % 2u) != 0u) &&
541  mxm_cellsToBalance |= (0x01u << cell_index);
542  }
543  /* If the odd cells need to be balanced */
544  else if (
545  (mxm_oddCellsNeedBalancing == 1u) && ((cell_index % 2u) == 0u) &&
547  mxm_cellsToBalance |= (0x01u << cell_index);
548  }
549  }
550  } else {
551  retval = STD_NOT_OK;
552  }
553  }
554  } else {
555  retval = STD_NOT_OK;
556  }
557  return retval;
558 }
559 
561  const uint8_t *const kpkVoltRxBuffer,
562  uint16_t voltRxBufferLength,
563  uint8_t measurementOffset,
564  MXM_CONVERSION_TYPE_e conversionType,
565  uint16_t *pVoltagesTarget,
566  MXM_MEASURE_TYPE_e meas_type,
567  uint32_t full_scale_reference_mV) {
568  uint8_t number_of_connected_devices =
569  (voltRxBufferLength - 2u - 2u) /
570  2u; /*!< buffer-length - length of start - length of end divided by two (LSB and MSB) */
571  /* TODO impact of alive counter on rxBufferLength
572  * otherwise offset at the end of message is currently 2 (DATACHECKBYTE and CRC) */
573  for (uint8_t i = 2u; i < (voltRxBufferLength - 2u); i = i + 2u) {
574  uint8_t calculated_module_number = number_of_connected_devices - ((uint16_t)(i / 2u) - 1u) - 1u;
575  uint16_t calculated_module_position = 0u;
576  switch (meas_type) {
577  case MXM_MEASURE_TEMP:
578  calculated_module_position = calculated_module_number * MXM_MAXIMUM_NR_OF_AUX_PER_MODULE;
579  break;
581  calculated_module_position = calculated_module_number * MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE;
582  break;
584  calculated_module_position = calculated_module_number;
585  break;
586  default:
588  break;
589  }
590  uint16_t calculated_array_position = calculated_module_position + measurementOffset;
591 
592  /* check calculated array position */
593  switch (meas_type) {
594  case MXM_MEASURE_TEMP:
596  break;
598  FAS_ASSERT(
599  calculated_array_position < (MXM_MAXIMUM_NR_OF_MODULES * MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE));
600  break;
602  FAS_ASSERT(calculated_array_position < (MXM_MAXIMUM_NR_OF_MODULES));
603  break;
604  default:
606  break;
607  }
608 
609  MXM_Convert(
610  kpkVoltRxBuffer[i],
611  kpkVoltRxBuffer[i + 1u],
612  &pVoltagesTarget[calculated_array_position],
613  conversionType,
614  full_scale_reference_mV);
615  }
616 }
617 
619  const uint8_t *const kpkVoltageRxBuffer,
620  uint16_t voltageRxBufferLength,
621  MXM_DATA_STORAGE_s *datastorage,
622  MXM_CONVERSION_TYPE_e conversionType) {
623  STD_RETURN_TYPE_e retval = STD_OK;
624  FAS_ASSERT(kpkVoltageRxBuffer != NULL_PTR);
625  FAS_ASSERT(datastorage != NULL_PTR);
626 
627  uint8_t cell_offset = 0;
628  if (kpkVoltageRxBuffer[0] != BATTERY_MANAGEMENT_READALL) {
629  /* rxBuffer does not contain a READALL command */
630  retval = STD_NOT_OK;
631  } else if ((voltageRxBufferLength % 2u) != 0u) {
632  /* without alive counter rx-buffer always should be of even length */
633  /* TODO impact of alive-counter-byte */
634  retval = STD_NOT_OK;
635  } else if (
636  (conversionType != MXM_CONVERSION_UNIPOLAR) && (conversionType != MXM_CONVERSION_BIPOLAR) &&
637  (conversionType != MXM_CONVERSION_BLOCK_VOLTAGE)) {
638  /* conversion type is not supported */
639  retval = STD_NOT_OK;
640  } else {
641  switch ((MXM_REG_NAME_e)kpkVoltageRxBuffer[1]) {
642  case MXM_REG_CELL1:
643  cell_offset = 0u;
645  kpkVoltageRxBuffer,
646  voltageRxBufferLength,
647  cell_offset,
648  conversionType,
649  datastorage->cellVoltages_mV,
651  5000u);
652  break;
653  case MXM_REG_CELL2:
654  cell_offset = 1u;
656  kpkVoltageRxBuffer,
657  voltageRxBufferLength,
658  cell_offset,
659  conversionType,
660  datastorage->cellVoltages_mV,
662  5000u);
663  break;
664  case MXM_REG_CELL3:
665  cell_offset = 2u;
667  kpkVoltageRxBuffer,
668  voltageRxBufferLength,
669  cell_offset,
670  conversionType,
671  datastorage->cellVoltages_mV,
673  5000u);
674  break;
675  case MXM_REG_CELL4:
676  cell_offset = 3u;
678  kpkVoltageRxBuffer,
679  voltageRxBufferLength,
680  cell_offset,
681  conversionType,
682  datastorage->cellVoltages_mV,
684  5000u);
685  break;
686  case MXM_REG_CELL5:
687  cell_offset = 4u;
689  kpkVoltageRxBuffer,
690  voltageRxBufferLength,
691  cell_offset,
692  conversionType,
693  datastorage->cellVoltages_mV,
695  5000u);
696  break;
697  case MXM_REG_CELL6:
698  cell_offset = 5u;
700  kpkVoltageRxBuffer,
701  voltageRxBufferLength,
702  cell_offset,
703  conversionType,
704  datastorage->cellVoltages_mV,
706  5000u);
707  break;
708  case MXM_REG_CELL7:
709  cell_offset = 6u;
711  kpkVoltageRxBuffer,
712  voltageRxBufferLength,
713  cell_offset,
714  conversionType,
715  datastorage->cellVoltages_mV,
717  5000u);
718  break;
719  case MXM_REG_CELL8:
720  cell_offset = 7u;
722  kpkVoltageRxBuffer,
723  voltageRxBufferLength,
724  cell_offset,
725  conversionType,
726  datastorage->cellVoltages_mV,
728  5000u);
729  break;
730  case MXM_REG_CELL9:
731  cell_offset = 8u;
733  kpkVoltageRxBuffer,
734  voltageRxBufferLength,
735  cell_offset,
736  conversionType,
737  datastorage->cellVoltages_mV,
739  5000u);
740  break;
741  case MXM_REG_CELL10:
742  cell_offset = 9u;
744  kpkVoltageRxBuffer,
745  voltageRxBufferLength,
746  cell_offset,
747  conversionType,
748  datastorage->cellVoltages_mV,
750  5000u);
751  break;
752  case MXM_REG_CELL11:
753  cell_offset = 10u;
755  kpkVoltageRxBuffer,
756  voltageRxBufferLength,
757  cell_offset,
758  conversionType,
759  datastorage->cellVoltages_mV,
761  5000u);
762  break;
763  case MXM_REG_CELL12:
764  cell_offset = 11u;
766  kpkVoltageRxBuffer,
767  voltageRxBufferLength,
768  cell_offset,
769  conversionType,
770  datastorage->cellVoltages_mV,
772  5000u);
773  break;
774  case MXM_REG_CELL13:
775  cell_offset = 12u;
777  kpkVoltageRxBuffer,
778  voltageRxBufferLength,
779  cell_offset,
780  conversionType,
781  datastorage->cellVoltages_mV,
783  5000u);
784  break;
785  case MXM_REG_CELL14:
786  cell_offset = 13u;
788  kpkVoltageRxBuffer,
789  voltageRxBufferLength,
790  cell_offset,
791  conversionType,
792  datastorage->cellVoltages_mV,
794  5000u);
795  break;
796  case MXM_REG_AUX0:
797  cell_offset = 0u;
799  kpkVoltageRxBuffer,
800  voltageRxBufferLength,
801  cell_offset,
802  conversionType,
803  datastorage->auxVoltages_mV,
806  break;
807  case MXM_REG_AUX2:
808  cell_offset = 2u;
810  kpkVoltageRxBuffer,
811  voltageRxBufferLength,
812  cell_offset,
813  conversionType,
814  datastorage->auxVoltages_mV,
817  break;
818  case MXM_REG_AUX3:
819  cell_offset = 3u;
821  kpkVoltageRxBuffer,
822  voltageRxBufferLength,
823  cell_offset,
824  conversionType,
825  datastorage->auxVoltages_mV,
828  break;
829  case MXM_REG_BLOCK:
830  cell_offset = 0u;
832  kpkVoltageRxBuffer,
833  voltageRxBufferLength,
834  cell_offset,
835  conversionType,
836  datastorage->blockVoltages,
838  65000u);
839  /* TODO scaling and variable size (65000)*/
840  break;
841  default:
842  /* the read register is not a valid cell register */
843  retval = STD_NOT_OK;
844  break;
845  }
846  }
847  return retval;
848 }
849 
851  FAS_ASSERT(pInstance != NULL_PTR);
852  STD_RETURN_TYPE_e retval = STD_OK;
853 
854  uint8_t test_buffer[100] = {0};
855  uint16_t testBufferLength = 100;
856 
857  /* not a readall buffer */
858  test_buffer[0] = BATTERY_MANAGEMENT_HELLOALL;
859  if (MXM_ParseVoltageReadall(test_buffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
860  STD_NOT_OK) {
861  retval = STD_NOT_OK;
862  }
863 
864  /* not a cell voltage register */
865  test_buffer[0] = BATTERY_MANAGEMENT_READALL;
866  test_buffer[1] = MXM_REG_VERSION;
867  if (MXM_ParseVoltageReadall(test_buffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
868  STD_NOT_OK) {
869  retval = STD_NOT_OK;
870  }
871 
872  /* bogus conversion type */
873  test_buffer[0] = BATTERY_MANAGEMENT_READALL;
874  test_buffer[1] = MXM_REG_CELL1;
875  if (MXM_ParseVoltageReadall(test_buffer, testBufferLength, &pInstance->localVoltages, (MXM_CONVERSION_TYPE_e)42) !=
876  STD_NOT_OK) {
877  retval = STD_NOT_OK;
878  }
879 
880  /* not an even length of rxBuffer */
881  test_buffer[0] = BATTERY_MANAGEMENT_READALL;
882  test_buffer[1] = MXM_REG_CELL1;
883  testBufferLength = 5;
884  if (MXM_ParseVoltageReadall(test_buffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
885  STD_NOT_OK) {
886  retval = STD_NOT_OK;
887  }
888 
889  /* test data for CELL1REG */
890  test_buffer[0] = BATTERY_MANAGEMENT_READALL;
891  test_buffer[1] = MXM_REG_CELL1;
892  test_buffer[2] = 0xFCu;
893  test_buffer[3] = 0xFFu;
894  test_buffer[4] = 0x00u;
895  test_buffer[5] = 0x00u;
896  test_buffer[6] = 0xFCu;
897  test_buffer[7] = 0xFFu;
898  test_buffer[8] = 0x42u; /* DATACHECKBYTE, irrelevant for function, filled with dummy bytes */
899  test_buffer[9] = 0x44u; /* CRCBYTE, irrelevant for function, filled with dummy bytes */
900  testBufferLength = 10u;
901  if (MXM_ParseVoltageReadall(test_buffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
902  STD_OK) {
903  retval = STD_NOT_OK;
904  } else {
905  if ((pInstance->localVoltages.cellVoltages_mV[0] != 5000u) ||
906  (pInstance->localVoltages.cellVoltages_mV[14] != 0u) ||
907  (pInstance->localVoltages.cellVoltages_mV[28] != 5000u)) {
908  retval = STD_NOT_OK;
909  }
910  }
911 
912  /* null mxm_local_cellvoltages */
913  for (uint16_t i_0 = 0; i_0 < (MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE * MXM_MAXIMUM_NR_OF_MODULES); i_0++) {
914  pInstance->localVoltages.cellVoltages_mV[i_0] = 0;
915  }
916 
917  /* test data for CELL2REG */
918  test_buffer[0] = BATTERY_MANAGEMENT_READALL;
919  test_buffer[1] = MXM_REG_CELL2;
920  test_buffer[2] = 0xFCu;
921  test_buffer[3] = 0xFFu;
922  test_buffer[4] = 0x00u;
923  test_buffer[5] = 0x00u;
924  test_buffer[6] = 0xFCu;
925  test_buffer[7] = 0xFFu;
926  test_buffer[8] = 0x42u; /* DATACHECKBYTE, irrelevant for function, filled with dummy bytes */
927  test_buffer[9] = 0x44u; /* CRCBYTE, irrelevant for function, filled with dummy bytes */
928  testBufferLength = 10;
929  if (MXM_ParseVoltageReadall(test_buffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
930  STD_OK) {
931  retval = STD_NOT_OK;
932  } else {
933  if ((pInstance->localVoltages.cellVoltages_mV[1] != 5000u) ||
934  (pInstance->localVoltages.cellVoltages_mV[15] != 0u) ||
935  (pInstance->localVoltages.cellVoltages_mV[29] != 5000u)) {
936  retval = STD_NOT_OK;
937  }
938  }
939 
940  /* null mxm_local_cellvoltages */
941  for (uint16_t i_1 = 0; i_1 < (MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE * MXM_MAXIMUM_NR_OF_MODULES); i_1++) {
942  pInstance->localVoltages.cellVoltages_mV[i_1] = 0;
943  }
944 
945  /* test data for CELL3REG */
946  test_buffer[0] = BATTERY_MANAGEMENT_READALL;
947  test_buffer[1] = MXM_REG_CELL3;
948  test_buffer[2] = 0xFCu;
949  test_buffer[3] = 0xFFu;
950  test_buffer[4] = 0x42u; /* DATACHECKBYTE, irrelevant for function, filled with dummy bytes */
951  test_buffer[5] = 0x44u; /* CRCBYTE, irrelevant for function, filled with dummy bytes */
952  testBufferLength = 6;
953  if (MXM_ParseVoltageReadall(test_buffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
954  STD_OK) {
955  retval = STD_NOT_OK;
956  } else {
957  if (pInstance->localVoltages.cellVoltages_mV[2] != 5000u) {
958  retval = STD_NOT_OK;
959  }
960  }
961 
962  /* null mxm_local_cellvoltages */
963  for (uint16_t i_2 = 0; i_2 < (MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE * MXM_MAXIMUM_NR_OF_MODULES); i_2++) {
964  pInstance->localVoltages.cellVoltages_mV[i_2] = 0;
965  }
966 
967  /* test data for CELL4REG */
968  test_buffer[0] = BATTERY_MANAGEMENT_READALL;
969  test_buffer[1] = MXM_REG_CELL4;
970  test_buffer[2] = 0xFCu;
971  test_buffer[3] = 0xFFu;
972  test_buffer[4] = 0x42u; /* DATACHECKBYTE, irrelevant for function, filled with dummy bytes */
973  test_buffer[5] = 0x44u; /* CRCBYTE, irrelevant for function, filled with dummy bytes */
974  testBufferLength = 6;
975  if (MXM_ParseVoltageReadall(test_buffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
976  STD_OK) {
977  retval = STD_NOT_OK;
978  } else {
979  if (pInstance->localVoltages.cellVoltages_mV[3] != 5000u) {
980  retval = STD_NOT_OK;
981  }
982  }
983 
984  /* null mxm_local_cellvoltages */
985  for (uint16_t i_3 = 0; i_3 < (MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE * MXM_MAXIMUM_NR_OF_MODULES); i_3++) {
986  pInstance->localVoltages.cellVoltages_mV[i_3] = 0;
987  }
988 
989  /* test data for CELL5REG */
990  test_buffer[0] = BATTERY_MANAGEMENT_READALL;
991  test_buffer[1] = MXM_REG_CELL5;
992  test_buffer[2] = 0xFCu;
993  test_buffer[3] = 0xFFu;
994  test_buffer[4] = 0x42u; /* DATACHECKBYTE, irrelevant for function, filled with dummy bytes */
995  test_buffer[5] = 0x44u; /* CRCBYTE, irrelevant for function, filled with dummy bytes */
996  testBufferLength = 6;
997  if (MXM_ParseVoltageReadall(test_buffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
998  STD_OK) {
999  retval = STD_NOT_OK;
1000  } else {
1001  if (pInstance->localVoltages.cellVoltages_mV[4] != 5000u) {
1002  retval = STD_NOT_OK;
1003  }
1004  }
1005 
1006  /* null mxm_local_cellvoltages */
1007  for (uint16_t i_4 = 0; i_4 < (MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE * MXM_MAXIMUM_NR_OF_MODULES); i_4++) {
1008  pInstance->localVoltages.cellVoltages_mV[i_4] = 0;
1009  }
1010 
1011  /* test data for CELL6REG */
1012  test_buffer[0] = BATTERY_MANAGEMENT_READALL;
1013  test_buffer[1] = MXM_REG_CELL6;
1014  test_buffer[2] = 0xFCu;
1015  test_buffer[3] = 0xFFu;
1016  test_buffer[4] = 0x42u; /* DATACHECKBYTE, irrelevant for function, filled with dummy bytes */
1017  test_buffer[5] = 0x44u; /* CRCBYTE, irrelevant for function, filled with dummy bytes */
1018  testBufferLength = 6;
1019  if (MXM_ParseVoltageReadall(test_buffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
1020  STD_OK) {
1021  retval = STD_NOT_OK;
1022  } else {
1023  if (pInstance->localVoltages.cellVoltages_mV[5] != 5000u) {
1024  retval = STD_NOT_OK;
1025  }
1026  }
1027 
1028  /* null mxm_local_cellvoltages */
1029  for (uint16_t i_5 = 0; i_5 < (MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE * MXM_MAXIMUM_NR_OF_MODULES); i_5++) {
1030  pInstance->localVoltages.cellVoltages_mV[i_5] = 0;
1031  }
1032 
1033  /* test data for CELL7REG */
1034  test_buffer[0] = BATTERY_MANAGEMENT_READALL;
1035  test_buffer[1] = MXM_REG_CELL7;
1036  test_buffer[2] = 0xFCu;
1037  test_buffer[3] = 0xFFu;
1038  test_buffer[4] = 0x42u; /* DATACHECKBYTE, irrelevant for function, filled with dummy bytes */
1039  test_buffer[5] = 0x44u; /* CRCBYTE, irrelevant for function, filled with dummy bytes */
1040  testBufferLength = 6;
1041  if (MXM_ParseVoltageReadall(test_buffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
1042  STD_OK) {
1043  retval = STD_NOT_OK;
1044  } else {
1045  if (pInstance->localVoltages.cellVoltages_mV[6] != 5000u) {
1046  retval = STD_NOT_OK;
1047  }
1048  }
1049 
1050  /* null mxm_local_cellvoltages */
1051  for (uint16_t i_6 = 0; i_6 < (MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE * MXM_MAXIMUM_NR_OF_MODULES); i_6++) {
1052  pInstance->localVoltages.cellVoltages_mV[i_6] = 0;
1053  }
1054 
1055  /* test data for CELL8REG */
1056  test_buffer[0] = BATTERY_MANAGEMENT_READALL;
1057  test_buffer[1] = MXM_REG_CELL8;
1058  test_buffer[2] = 0xFCu;
1059  test_buffer[3] = 0xFFu;
1060  test_buffer[4] = 0x42u; /* DATACHECKBYTE, irrelevant for function, filled with dummy bytes */
1061  test_buffer[5] = 0x44u; /* CRCBYTE, irrelevant for function, filled with dummy bytes */
1062  testBufferLength = 6;
1063  if (MXM_ParseVoltageReadall(test_buffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
1064  STD_OK) {
1065  retval = STD_NOT_OK;
1066  } else {
1067  if (pInstance->localVoltages.cellVoltages_mV[7] != 5000u) {
1068  retval = STD_NOT_OK;
1069  }
1070  }
1071 
1072  /* null mxm_local_cellvoltages */
1073  for (uint16_t i_7 = 0; i_7 < (MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE * MXM_MAXIMUM_NR_OF_MODULES); i_7++) {
1074  pInstance->localVoltages.cellVoltages_mV[i_7] = 0;
1075  }
1076 
1077  /* test data for CELL9REG */
1078  test_buffer[0] = BATTERY_MANAGEMENT_READALL;
1079  test_buffer[1] = MXM_REG_CELL9;
1080  test_buffer[2] = 0xFCu;
1081  test_buffer[3] = 0xFFu;
1082  test_buffer[4] = 0x42u; /* DATACHECKBYTE, irrelevant for function, filled with dummy bytes */
1083  test_buffer[5] = 0x44u; /* CRCBYTE, irrelevant for function, filled with dummy bytes */
1084  testBufferLength = 6;
1085  if (MXM_ParseVoltageReadall(test_buffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
1086  STD_OK) {
1087  retval = STD_NOT_OK;
1088  } else {
1089  if (pInstance->localVoltages.cellVoltages_mV[8] != 5000u) {
1090  retval = STD_NOT_OK;
1091  }
1092  }
1093 
1094  /* null mxm_local_cellvoltages */
1095  for (uint16_t i_8 = 0; i_8 < (MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE * MXM_MAXIMUM_NR_OF_MODULES); i_8++) {
1096  pInstance->localVoltages.cellVoltages_mV[i_8] = 0;
1097  }
1098 
1099  /* test data for CELL10REG */
1100  test_buffer[0] = BATTERY_MANAGEMENT_READALL;
1101  test_buffer[1] = MXM_REG_CELL10;
1102  test_buffer[2] = 0xFCu;
1103  test_buffer[3] = 0xFFu;
1104  test_buffer[4] = 0x42u; /* DATACHECKBYTE, irrelevant for function, filled with dummy bytes */
1105  test_buffer[5] = 0x44u; /* CRCBYTE, irrelevant for function, filled with dummy bytes */
1106  testBufferLength = 6;
1107  if (MXM_ParseVoltageReadall(test_buffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
1108  STD_OK) {
1109  retval = STD_NOT_OK;
1110  } else {
1111  if (pInstance->localVoltages.cellVoltages_mV[9] != 5000u) {
1112  retval = STD_NOT_OK;
1113  }
1114  }
1115 
1116  /* null mxm_local_cellvoltages */
1117  for (uint16_t i_9 = 0; i_9 < (MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE * MXM_MAXIMUM_NR_OF_MODULES); i_9++) {
1118  pInstance->localVoltages.cellVoltages_mV[i_9] = 0;
1119  }
1120 
1121  /* test data for CELL11REG */
1122  test_buffer[0] = BATTERY_MANAGEMENT_READALL;
1123  test_buffer[1] = MXM_REG_CELL11;
1124  test_buffer[2] = 0xFCu;
1125  test_buffer[3] = 0xFFu;
1126  test_buffer[4] = 0x42u; /* DATACHECKBYTE, irrelevant for function, filled with dummy bytes */
1127  test_buffer[5] = 0x44u; /* CRCBYTE, irrelevant for function, filled with dummy bytes */
1128  testBufferLength = 6;
1129  if (MXM_ParseVoltageReadall(test_buffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
1130  STD_OK) {
1131  retval = STD_NOT_OK;
1132  } else {
1133  if (pInstance->localVoltages.cellVoltages_mV[10] != 5000u) {
1134  retval = STD_NOT_OK;
1135  }
1136  }
1137 
1138  /* null mxm_local_cellvoltages */
1139  for (uint16_t i_10 = 0; i_10 < (MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE * MXM_MAXIMUM_NR_OF_MODULES); i_10++) {
1140  pInstance->localVoltages.cellVoltages_mV[i_10] = 0;
1141  }
1142 
1143  /* test data for CELL12REG */
1144  test_buffer[0] = BATTERY_MANAGEMENT_READALL;
1145  test_buffer[1] = MXM_REG_CELL12;
1146  test_buffer[2] = 0xFCu;
1147  test_buffer[3] = 0xFFu;
1148  test_buffer[4] = 0x42u; /* DATACHECKBYTE, irrelevant for function, filled with dummy bytes */
1149  test_buffer[5] = 0x44u; /* CRCBYTE, irrelevant for function, filled with dummy bytes */
1150  testBufferLength = 6;
1151  if (MXM_ParseVoltageReadall(test_buffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
1152  STD_OK) {
1153  retval = STD_NOT_OK;
1154  } else {
1155  if (pInstance->localVoltages.cellVoltages_mV[11] != 5000u) {
1156  retval = STD_NOT_OK;
1157  }
1158  }
1159 
1160  /* null mxm_local_cellvoltages */
1161  for (uint16_t i_11 = 0; i_11 < (MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE * MXM_MAXIMUM_NR_OF_MODULES); i_11++) {
1162  pInstance->localVoltages.cellVoltages_mV[i_11] = 0;
1163  }
1164 
1165  /* test data for CELL13REG */
1166  test_buffer[0] = BATTERY_MANAGEMENT_READALL;
1167  test_buffer[1] = MXM_REG_CELL13;
1168  test_buffer[2] = 0xFCu;
1169  test_buffer[3] = 0xFFu;
1170  test_buffer[4] = 0x42u; /* DATACHECKBYTE, irrelevant for function, filled with dummy bytes */
1171  test_buffer[5] = 0x44u; /* CRCBYTE, irrelevant for function, filled with dummy bytes */
1172  testBufferLength = 6;
1173  if (MXM_ParseVoltageReadall(test_buffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
1174  STD_OK) {
1175  retval = STD_NOT_OK;
1176  } else {
1177  if (pInstance->localVoltages.cellVoltages_mV[12] != 5000u) {
1178  retval = STD_NOT_OK;
1179  }
1180  }
1181 
1182  /* null mxm_local_cellvoltages */
1183  for (uint16_t i_12 = 0; i_12 < (MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE * MXM_MAXIMUM_NR_OF_MODULES); i_12++) {
1184  pInstance->localVoltages.cellVoltages_mV[i_12] = 0;
1185  }
1186 
1187  /* test data for CELL14REG */
1188  test_buffer[0] = BATTERY_MANAGEMENT_READALL;
1189  test_buffer[1] = MXM_REG_CELL14;
1190  test_buffer[2] = 0xFCu;
1191  test_buffer[3] = 0xFFu;
1192  test_buffer[4] = 0x42u; /* DATACHECKBYTE, irrelevant for function, filled with dummy bytes */
1193  test_buffer[5] = 0x44u; /* CRCBYTE, irrelevant for function, filled with dummy bytes */
1194  testBufferLength = 6;
1195  if (MXM_ParseVoltageReadall(test_buffer, testBufferLength, &pInstance->localVoltages, MXM_CONVERSION_UNIPOLAR) !=
1196  STD_OK) {
1197  retval = STD_NOT_OK;
1198  } else {
1199  if (pInstance->localVoltages.cellVoltages_mV[13] != 5000u) {
1200  retval = STD_NOT_OK;
1201  }
1202  }
1203 
1204  /* null mxm_local_cellvoltages */
1205  for (uint16_t i_13 = 0; i_13 < (MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE * MXM_MAXIMUM_NR_OF_MODULES); i_13++) {
1206  pInstance->localVoltages.cellVoltages_mV[i_13] = 0;
1207  }
1208 
1209  return retval;
1210 }
1211 
1214  FAS_ASSERT(pState != NULL_PTR);
1216  if (pState->requestStatus5x == MXM_5X_STATE_UNSENT) {
1217  pState->batteryCmdBuffer.regAddress = regAddress;
1220  } else if (pState->requestStatus5x == MXM_5X_STATE_PROCESSED) {
1222  uint8_t temp_len = BATTERY_MANAGEMENT_TX_LENGTH_READALL +
1223  (2u * MXM_5XGetNumberOfSatellites(pState->pInstance5X));
1224  if (regAddress == MXM_REG_BLOCK) {
1226  } else {
1228  }
1230  retval = MXM_MONITORING_STATE_PASS;
1231  } else if (pState->requestStatus5x == MXM_5X_STATE_UNPROCESSED) {
1232  /* do nothing */
1233  } else if (pState->requestStatus5x == MXM_5X_STATE_ERROR) {
1234  /* try to reset state */
1236  } else {
1237  /* invalid state */
1239  }
1240  return retval;
1241 }
1242 
1244  FAS_ASSERT(kpkInstance != NULL_PTR);
1245  STD_RETURN_TYPE_e retval = STD_OK;
1246 
1247  /* voltages */
1248  for (uint8_t i_mod = 0; i_mod < (BS_NR_OF_MODULES * BS_NR_OF_STRINGS); i_mod++) {
1249  if (i_mod < MXM_MAXIMUM_NR_OF_MODULES) {
1250  uint8_t stringNumber = 0u;
1251  uint16_t moduleNumber = 0u;
1252  MXM_ConvertModuleToString(i_mod, &stringNumber, &moduleNumber);
1253  mxm_cellVoltages.moduleVoltage_mV[stringNumber][moduleNumber] =
1254  kpkInstance->localVoltages.blockVoltages[i_mod];
1255  /* every iteration that we hit a string first (module 0), we reset the packvoltage counter */
1256  if (moduleNumber == 0u) {
1257  mxm_cellVoltages.packVoltage_mV[stringNumber] = 0;
1258  }
1259  mxm_cellVoltages.packVoltage_mV[stringNumber] += kpkInstance->localVoltages.blockVoltages[i_mod];
1260  for (uint8_t i_bat = 0; i_bat < BS_NR_OF_CELLS_PER_MODULE; i_bat++) {
1261  if (i_bat < MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE) {
1262  uint16_t cell_counter_db = (moduleNumber * BS_NR_OF_CELLS_PER_MODULE) + i_bat;
1263  uint16_t cell_counter_max = (i_mod * MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE) + i_bat;
1264  mxm_cellVoltages.cellVoltage_mV[stringNumber][cell_counter_db] =
1265  kpkInstance->localVoltages.cellVoltages_mV[cell_counter_max];
1266  }
1267  }
1268  } else {
1269  retval = STD_NOT_OK;
1270  }
1271  }
1272 
1273  /* temperatures */
1274  for (uint8_t i_mod = 0; i_mod < (BS_NR_OF_MODULES * BS_NR_OF_STRINGS); i_mod++) {
1275  if (i_mod < MXM_MAXIMUM_NR_OF_MODULES) {
1276  uint8_t stringNumber = 0u;
1277  uint16_t moduleNumber = 0u;
1278  MXM_ConvertModuleToString(i_mod, &stringNumber, &moduleNumber);
1279 
1280  /* store aux measurement from AUX2 (MUX0) */
1281  if (kpkInstance->muxCounter < BS_NR_OF_TEMP_SENSORS_PER_MODULE) {
1282  const uint16_t temperatureIndexDb = (moduleNumber * BS_NR_OF_TEMP_SENSORS_PER_MODULE) +
1283  kpkInstance->muxCounter;
1284  const uint16_t temperatureIndexMxm = (i_mod * MXM_MAXIMUM_NR_OF_AUX_PER_MODULE) + 2u;
1285  const uint16_t auxVoltage_mV = kpkInstance->localVoltages.auxVoltages_mV[temperatureIndexMxm];
1286  /* const uint16_t temporaryVoltage = (auxVoltage_mV / ((float)3300 - auxVoltage_mV)) * 1000; */
1287  const int16_t temperature_ddegC = TSI_GetTemperature(auxVoltage_mV);
1288  mxm_cellTemperatures.cellTemperature_ddegC[stringNumber][temperatureIndexDb] = temperature_ddegC;
1289  }
1290  } else {
1291  retval = STD_NOT_OK;
1292  }
1293  }
1294 
1296 
1297  return retval;
1298 }
1299 
1301  FAS_ASSERT(pState != NULL_PTR);
1302  STD_RETURN_TYPE_e retval = STD_OK;
1303  pState->selfCheck.crc = MXM_CRC8SelfTest();
1304  pState->selfCheck.conv = MXM_ConvertTest();
1309 
1310  if ((pState->selfCheck.crc == STD_OK) && (pState->selfCheck.addressSpaceChecker == STD_OK) &&
1311  (pState->selfCheck.conv == STD_OK) && (pState->selfCheck.firstSetBit == STD_OK) &&
1313  retval = STD_OK;
1314  } else {
1315  retval = STD_NOT_OK;
1316  }
1317 
1318  return retval;
1319 }
1320 
1322  pState->operationRequested = false;
1323  /* TODO handle transition to measurement states properly with dedicated state-machine */
1324  /* TODO parse DATACHECKBYTE where available */
1325 
1327 
1328  switch (pState->operationSubstate) {
1329  case MXM_OP_ENTRY_STATE:
1331  break;
1333  /* configure I2CPNTR to channel number corresponding to mux counter*/
1335  pState->batteryCmdBuffer.lsb = (0x01u << pState->muxCounter);
1336  pState->batteryCmdBuffer.msb = 0x00u;
1338  break;
1339  case MXM_OP_WRITE_MUX0:
1340  /* send configuration to MUX0 for channel 0 (PNTR configured to 1u) */
1342  pState->batteryCmdBuffer.lsb = (MXM_I2C_MUX0_ADDRESS << 1u);
1343  pState->batteryCmdBuffer.msb = 0x40u;
1345  break;
1346  case MXM_OP_WRITE_MUX1:
1347  /* send configuration to MUX1 for channel 0 (PNTR configured to 1u) */
1349  pState->batteryCmdBuffer.lsb = (MXM_I2C_MUX1_ADDRESS << 1u);
1350  pState->batteryCmdBuffer.msb = 0x40u;
1352  break;
1355  /* set SCANSTROBE, enable 4x OVERSAMPL */
1356  pState->batteryCmdBuffer.lsb = 0x09u;
1357  /* enable AUTOBALSWDIS */
1358  pState->batteryCmdBuffer.msb = 0x10u;
1360  break;
1363  /* no additional handling needed */
1364  }
1365  break;
1366  case MXM_OP_GET_VOLTAGES:
1367  temp_mon_state = MXM_MonGetVoltages(pState, mxm_voltageCellAddresses[pState->mxmVoltageCellCounter]);
1368 
1369  if (temp_mon_state == MXM_MONITORING_STATE_PASS) {
1370  pState->mxmVoltageCellCounter++;
1371  /* modified: read one additional aux entry */
1373  pState->mxmVoltageCellCounter = 0;
1375  }
1376  } else if (temp_mon_state == MXM_MONITORING_STATE_FAIL) {
1377  /* reinitialize */
1379  }
1380  break;
1381  case MXM_OP_GET_ALRTSUM:
1383  /* no additional handling needed */
1384  }
1385  break;
1387  if (MXM_ParseVoltagesIntoDB(pState) == STD_OK) {
1389  pState->firstMeasurementDone = true;
1390  }
1391  if (pState->stopRequested == true) {
1393  } else {
1394  /* do nothing */
1395  }
1396  break;
1397  case MXM_OP_PINOPEN_ENTRY:
1398  if (pState->openwireRequested == true) {
1400  pState->openwireRequested = false;
1401  } else {
1403  }
1404  break;
1405  case MXM_OP_PINOPEN_EXIT:
1407  break;
1409  if (pState->requestStatus5x == MXM_5X_STATE_UNSENT) {
1411  pState->batteryCmdBuffer.lsb = 0xFFu;
1412  pState->batteryCmdBuffer.msb = 0xFFu; /* execute diagnostic on every cell */
1413  }
1415  break;
1417  if (pState->requestStatus5x == MXM_5X_STATE_UNSENT) {
1419  pState->batteryCmdBuffer.lsb = 0x81u;
1420  pState->batteryCmdBuffer.msb = 0x00u; /* request comp scan */
1421  }
1423  break;
1426  /* no additional handling needed */
1427  }
1428  break;
1431  /* no additional handling needed */
1432  }
1433  break;
1437  break;
1439  if (pState->requestStatus5x == MXM_5X_STATE_UNSENT) {
1441  pState->batteryCmdBuffer.lsb = 0x00u;
1442  pState->batteryCmdBuffer.msb = 0x00u;
1443  }
1445  break;
1446  case MXM_OP_BAL_ENTRY:
1447  /* Get the current time */
1449 
1450  /* NOTE: The overflow of the timer (coded on 32bits) is handled by the CPU
1451  Wait 'MXM_DELAY_BALANCING' milliseconds before processing the balancing */
1453  /* nothing to do, exit balancing state chain */
1455  } else {
1456  /* Balancing needs to be processed */
1458  /* First reset the balancing switches, and THEN
1459  set the balancing switches according to the database */
1461 
1462  /* Change the parity of cells to balance */
1463  if (mxm_evenCellsBalancingProcessed == 1u) {
1466  }
1467  /* Same for odd cells */
1468  if (mxm_oddCellsBalancingProcessed == 1u) {
1471  }
1472  }
1473  break;
1475  /* Send a WRITEALL command to open all balancing switches */
1476  if (pState->requestStatus5x == MXM_5X_STATE_UNSENT) {
1478  /* CBRESTART is not reset to 0, not needed. */
1479  pState->batteryCmdBuffer.lsb = 0x00U;
1480  pState->batteryCmdBuffer.msb = 0x00U;
1481  }
1483  break;
1485  /* Send a WRITEDEVICE command to each module in a daisy-chain
1486  to close appropriate balancing switches */
1487  if (pState->requestStatus5x == MXM_5X_STATE_UNSENT) {
1490 
1492  if (STD_OK == database_retval) {
1493  /* Construct the balancing buffer */
1495 
1496  if (retval == STD_OK) {
1497  if (mxm_cellsToBalance > 0u) {
1498  /* Some cells need to be balanced */
1501  pState->batteryCmdBuffer.lsb = (uint8_t)mxm_cellsToBalance;
1502  pState->batteryCmdBuffer.msb = (uint8_t)(mxm_cellsToBalance >> 8u);
1504  pState->pInstance5X,
1506  pState->batteryCmdBuffer,
1507  &pState->requestStatus5x);
1508  } else {
1509  /* It is not necessary to re-send 0 to the device, because it has been done previously
1510  in the BALANCING_CONTROL_RESET_ALL sub-state */
1512  }
1513 
1514  } else {
1515  /* this should not happen if the software works as expected */
1516  /* TODO review this trap */
1517  /* FAS_ASSERT(FAS_TRAP); */
1519  }
1520  } else {
1521  /* database read not successful, retry */
1523  }
1524  } else if (pState->requestStatus5x == MXM_5X_STATE_UNPROCESSED) {
1525  /* wait for processing */
1526  } else if (pState->requestStatus5x == MXM_5X_STATE_PROCESSED) {
1527  if (mxm_moduleBalancingIndex < pState->highest5xDevice) {
1528  /* Not all modules have been treated. Repeat this state with the next module */
1531  } else {
1532  /* Finished the iteration of all modules in a daisy chain, continue */
1534 
1535  /* Update flags for the end of balancing */
1536  if (mxm_evenCellsNeedBalancing == 1u) {
1538  } else if (mxm_oddCellsNeedBalancing == 1u) {
1540  }
1541  }
1542 
1543  /* Re-set the status to UNSENT to repeat the WRITE operation */
1546  } else if (pState->requestStatus5x == MXM_5X_STATE_ERROR) {
1548  }
1549  break;
1550  case MXM_OP_BAL_START:
1551  /* Initiate balancing for all devices in a daisy chain */
1552  if (pState->requestStatus5x == MXM_5X_STATE_UNSENT) {
1554  /* Manual ON MODE + Balancing halt in case of High temperature
1555  + Alert when cell balancing is finished */
1556  pState->batteryCmdBuffer.lsb = 0x0EU;
1557  pState->batteryCmdBuffer.msb = 0x18U;
1558  }
1560  break;
1561  case MXM_OP_BAL_EXIT:
1563  break;
1565  /* actions that should be taken at the end of a measurement cycle */
1567  break;
1569  if (pState->muxCounter < (8u - 1u)) {
1570  pState->muxCounter++;
1571  } else {
1572  pState->muxCounter = 0u;
1573  }
1575  break;
1576  case MXM_OP_CYCLE_END_EXIT:
1578  break;
1579  /* "initialization" from here on */
1580  case MXM_INIT_DEVCFG1:
1581  /* switch to single UART with external loopback */
1582  if (pState->requestStatus5x == MXM_5X_STATE_UNSENT) {
1584  pState->batteryCmdBuffer.lsb = 0x02u;
1585  pState->batteryCmdBuffer.msb = 0x01u;
1586  }
1588  break;
1589  case MXM_INIT_SET_FMEA2:
1590  if (pState->requestStatus5x == MXM_5X_STATE_UNSENT) {
1592  pState->batteryCmdBuffer.lsb = 0x00u;
1593  pState->batteryCmdBuffer.msb = 0x00u;
1594  }
1596  break;
1597  case MXM_INIT_STATUS1:
1598  /* clear ALRTRST */
1599  if (pState->requestStatus5x == MXM_5X_STATE_UNSENT) {
1601  pState->batteryCmdBuffer.lsb = 0x00u;
1602  pState->batteryCmdBuffer.msb = 0x00u;
1603  }
1605  break;
1606  case MXM_INIT_GET_VERSION:
1607  /* add version information to registry */
1609  uint8_t temp_len = BATTERY_MANAGEMENT_TX_LENGTH_READALL +
1610  (2u * MXM_5XGetNumberOfSatellites(pState->pInstance5X));
1611  MXM_MonRegistryParseVersionIntoDevices(pState, temp_len);
1612  }
1613  break;
1614  case MXM_INIT_GET_ID1:
1615  /* add ID1 to registry */
1616  if (true == MXM_HandleStateReadall(pState, MXM_REG_ID1, MXM_INIT_GET_ID2)) {
1617  uint8_t temp_len = BATTERY_MANAGEMENT_TX_LENGTH_READALL +
1618  (2u * MXM_5XGetNumberOfSatellites(pState->pInstance5X));
1620  }
1621  break;
1622  case MXM_INIT_GET_ID2:
1623  /* add ID2 to registry */
1624  if (true == MXM_HandleStateReadall(pState, MXM_REG_ID2, MXM_INIT_MEASUREEN1)) {
1625  uint8_t temp_len = BATTERY_MANAGEMENT_TX_LENGTH_READALL +
1626  (2u * MXM_5XGetNumberOfSatellites(pState->pInstance5X));
1628  }
1629  break;
1630  case MXM_INIT_MEASUREEN1:
1631  /* enable all 14 cells */
1632  if (pState->requestStatus5x == MXM_5X_STATE_UNSENT) {
1634  pState->batteryCmdBuffer.lsb = 0xFFu;
1635  pState->batteryCmdBuffer.msb = 0x7Fu; /* TODO this also enables block measurement */
1636  }
1638  break;
1639  case MXM_INIT_MEASUREEN2:
1640  /* enable AUX2 and AUX3 */
1641  if (pState->requestStatus5x == MXM_5X_STATE_UNSENT) {
1643  pState->batteryCmdBuffer.lsb = 0x0Cu; /* AUX2 and AUX3 */
1644  pState->batteryCmdBuffer.msb = 0x00u;
1645  }
1647  break;
1648  case MXM_INIT_AUXGPIOCFG:
1649  /* switch GPIO2 and GPIO3 to AUX, enable I2C */
1650  if (pState->requestStatus5x == MXM_5X_STATE_UNSENT) {
1652  pState->batteryCmdBuffer.lsb = 0x00u;
1653  /* pState->batteryCmdBuffer.msb = 0x3Eu; */ /* conf for MAX17853 */
1654  /* pState->batteryCmdBuffer.msb = 0x8Eu; */ /* conf for MAX17852, I2C enable */
1655  /* I2C enable, AUX2 and AUX3 */
1656  pState->batteryCmdBuffer.msb = 0x80u;
1657  }
1659  break;
1660  case MXM_INIT_AUXTIMEREG:
1661  /* configure settling time that NTC network takes for measurement to 500us */
1662  /* WARNING: reevaluate this value if thermistor supply is switched
1663  during sampling */
1664  if (pState->requestStatus5x == MXM_5X_STATE_UNSENT) {
1666  pState->batteryCmdBuffer.lsb = 0x53u;
1667  pState->batteryCmdBuffer.msb = 0x00u;
1668  }
1670  break;
1671  case MXM_INIT_ACQCFG:
1672  /* set ACQGFC */
1673  if (pState->requestStatus5x == MXM_5X_STATE_UNSENT) {
1675  /* default values */
1676  pState->batteryCmdBuffer.lsb = 0x00u;
1677  /* we have to turn thrm switch manually on, as charging the
1678  network takes to long */
1679  pState->batteryCmdBuffer.msb = 0x06u;
1680  }
1682  break;
1683  case MXM_INIT_UVTHSETREG:
1684  /* configure UVTHSETREG */
1685  if (pState->requestStatus5x == MXM_5X_STATE_UNSENT) {
1688  MXM_VoltageIntoUnipolar14Bit(1700u, 5000u),
1689  &pState->batteryCmdBuffer.lsb,
1690  &pState->batteryCmdBuffer.msb);
1691  }
1693  break;
1694  case MXM_INIT_OVTHSETREG:
1695  /* configure OVTHSETREG */
1696  if (pState->requestStatus5x == MXM_5X_STATE_UNSENT) {
1699  MXM_VoltageIntoUnipolar14Bit(3300u, 5000u),
1700  &pState->batteryCmdBuffer.lsb,
1701  &pState->batteryCmdBuffer.msb);
1702  }
1704  break;
1705  case MXM_INIT_BALEXP1:
1706  /* set BALEXP1 to have 1 minute timeout in manual balancing */
1707  if (pState->requestStatus5x == MXM_5X_STATE_UNSENT) {
1709  pState->batteryCmdBuffer.lsb = 0x01u;
1710  pState->batteryCmdBuffer.msb = 0x00u;
1711  }
1713  break;
1714  case MXM_INIT_BALEXP2:
1715  /* set BALEXP2 to have 1 minute timeout in manual balancing */
1716  if (pState->requestStatus5x == MXM_5X_STATE_UNSENT) {
1718  pState->batteryCmdBuffer.lsb = 0x01u;
1719  pState->batteryCmdBuffer.msb = 0x00u;
1720  }
1722  break;
1723  case MXM_INIT_BALEXP3:
1724  /* set BALEXP3 to have 1 minute timeout in manual balancing */
1725  if (pState->requestStatus5x == MXM_5X_STATE_UNSENT) {
1727  pState->batteryCmdBuffer.lsb = 0x01u;
1728  pState->batteryCmdBuffer.msb = 0x00u;
1729  }
1731  break;
1732  case MXM_INIT_BALEXP4:
1733  /* set BALEXP4 to have 1 minute timeout in manual balancing */
1734  if (pState->requestStatus5x == MXM_5X_STATE_UNSENT) {
1736  pState->batteryCmdBuffer.lsb = 0x01u;
1737  pState->batteryCmdBuffer.msb = 0x00u;
1738  }
1740  break;
1741  case MXM_INIT_BALEXP5:
1742  /* set BALEXP5 to have 1 minute timeout in manual balancing */
1743  if (pState->requestStatus5x == MXM_5X_STATE_UNSENT) {
1745  pState->batteryCmdBuffer.lsb = 0x01u;
1746  pState->batteryCmdBuffer.msb = 0x00u;
1747  }
1749  break;
1750  case MXM_INIT_BALEXP6:
1751  /* set BALEXP6 to have 1 minute timeout in manual balancing */
1752  if (pState->requestStatus5x == MXM_5X_STATE_UNSENT) {
1754  pState->batteryCmdBuffer.lsb = 0x01u;
1755  pState->batteryCmdBuffer.msb = 0x00u;
1756  }
1758  break;
1759  case MXM_INIT_BALEXP7:
1760  /* set BALEXP7 to have 1 minute timeout in manual balancing */
1761  if (pState->requestStatus5x == MXM_5X_STATE_UNSENT) {
1763  pState->batteryCmdBuffer.lsb = 0x01u;
1764  pState->batteryCmdBuffer.msb = 0x00u;
1765  }
1767  break;
1768  case MXM_INIT_BALEXP8:
1769  /* set BALEXP8 to have 1 minute timeout in manual balancing */
1770  if (pState->requestStatus5x == MXM_5X_STATE_UNSENT) {
1772  pState->batteryCmdBuffer.lsb = 0x01u;
1773  pState->batteryCmdBuffer.msb = 0x00u;
1774  }
1776  break;
1777  case MXM_INIT_BALEXP9:
1778  /* set BALEXP9 to have 1 minute timeout in manual balancing */
1779  if (pState->requestStatus5x == MXM_5X_STATE_UNSENT) {
1781  pState->batteryCmdBuffer.lsb = 0x01u;
1782  pState->batteryCmdBuffer.msb = 0x00u;
1783  }
1785  break;
1786  case MXM_INIT_BALEXP10:
1787  /* set BALEXP10 to have 1 minute timeout in manual balancing */
1788  if (pState->requestStatus5x == MXM_5X_STATE_UNSENT) {
1790  pState->batteryCmdBuffer.lsb = 0x01u;
1791  pState->batteryCmdBuffer.msb = 0x00u;
1792  }
1794  break;
1795  case MXM_INIT_BALEXP11:
1796  /* set BALEXP11 to have 1 minute timeout in manual balancing */
1797  if (pState->requestStatus5x == MXM_5X_STATE_UNSENT) {
1799  pState->batteryCmdBuffer.lsb = 0x01u;
1800  pState->batteryCmdBuffer.msb = 0x00u;
1801  }
1803  break;
1804  case MXM_INIT_BALEXP12:
1805  /* set BALEXP12 to have 1 minute timeout in manual balancing */
1806  if (pState->requestStatus5x == MXM_5X_STATE_UNSENT) {
1808  pState->batteryCmdBuffer.lsb = 0x01u;
1809  pState->batteryCmdBuffer.msb = 0x00u;
1810  }
1812  break;
1813  case MXM_INIT_BALEXP13:
1814  /* set BALEXP13 to have 1 minute timeout in manual balancing */
1815  if (pState->requestStatus5x == MXM_5X_STATE_UNSENT) {
1817  pState->batteryCmdBuffer.lsb = 0x01u;
1818  pState->batteryCmdBuffer.msb = 0x00u;
1819  }
1821  break;
1822  case MXM_INIT_BALEXP14:
1823  /* set BALEXP14 to have 1 minute timeout in manual balancing */
1824  if (pState->requestStatus5x == MXM_5X_STATE_UNSENT) {
1826  pState->batteryCmdBuffer.lsb = 0x01u;
1827  pState->batteryCmdBuffer.msb = 0x00u;
1828  }
1830  break;
1831  case MXM_INIT_BALSWDLY:
1832  /* set BALSWDLY to 2 ms settling time after balancing */
1833  if (pState->requestStatus5x == MXM_5X_STATE_UNSENT) {
1835  /* CELLDLY = 1920us (~2ms) --> 20*96us
1836  CELLDLY corresponds to the time to relax the cell before voltage measurement */
1837  pState->batteryCmdBuffer.lsb = 0x00u;
1838  pState->batteryCmdBuffer.msb = 0x14u;
1839  }
1841  break;
1842  case MXM_INIT_ALRTOVEN:
1843  /* enable ALRTOVEN */
1844  if (pState->requestStatus5x == MXM_5X_STATE_UNSENT) {
1846  pState->batteryCmdBuffer.lsb = 0xFFu;
1847  pState->batteryCmdBuffer.msb = 0x3Fu;
1848  }
1850  break;
1851  case MXM_INIT_ALRTUVEN:
1852  /* enable ALRTUVEN */
1853  if (pState->requestStatus5x == MXM_5X_STATE_UNSENT) {
1855  pState->batteryCmdBuffer.lsb = 0xFFu;
1856  pState->batteryCmdBuffer.msb = 0x3Fu;
1857  }
1859  break;
1860  case MXM_INIT_COMPOPNTHREG:
1861  /* configure COMPOPNTHREG */
1862  if (pState->requestStatus5x == MXM_5X_STATE_UNSENT) {
1864  /* TODO 0.5V */
1866  MXM_VoltageIntoUnipolar14Bit(500u, 5000u),
1867  &pState->batteryCmdBuffer.lsb,
1868  &pState->batteryCmdBuffer.msb);
1869  }
1871  break;
1874  /* no additional handling needed */
1875  }
1876  break;
1877  case MXM_INIT_I2C_CFG:
1878  /* configure I2CCFG to
1879  * 400kHz
1880  * Alternate write Mode (just a pointer without data)
1881  * Combined Format
1882  * 7 Bit addressing
1883  * one byte pointer length
1884  * default
1885  */
1886  if (pState->requestStatus5x == MXM_5X_STATE_UNSENT) {
1888  pState->batteryCmdBuffer.lsb = 0x00u;
1889  pState->batteryCmdBuffer.msb = 0xE0u;
1890  }
1892  break;
1893  case MXM_INIT_I2C_PNTR:
1894  /* configure I2CPNTR */
1895  if (pState->requestStatus5x == MXM_5X_STATE_UNSENT) {
1897  pState->batteryCmdBuffer.lsb = 0x01u;
1898  pState->batteryCmdBuffer.msb = 0x00u;
1899  }
1901  break;
1903  /* send configuration to MUX0 for channel 0 (PNTR configured to 1u) */
1904  if (pState->requestStatus5x == MXM_5X_STATE_UNSENT) {
1906  pState->batteryCmdBuffer.lsb = (MXM_I2C_MUX0_ADDRESS << 1u);
1907  pState->batteryCmdBuffer.msb = 0x40u;
1908  }
1910  break;
1912  /* send configuration to MUX1 for channel 0 (PNTR configured to 1u) */
1913  if (pState->requestStatus5x == MXM_5X_STATE_UNSENT) {
1915  pState->batteryCmdBuffer.lsb = (MXM_I2C_MUX1_ADDRESS << 1u);
1916  pState->batteryCmdBuffer.msb = 0x40u;
1917  }
1919  break;
1922  /* no additional handling needed */
1923  }
1924  break;
1925  default:
1926  /* invalid state */
1928  break;
1929  }
1930 }
1931 
1932 /*========== Extern Function Implementations ================================*/
1933 
1935  FAS_ASSERT(pInstance != NULL_PTR);
1936 
1937  if (pInstance->state == MXM_STATEMACHINE_STATES_UNINITIALIZED) {
1938  pInstance->requestStatus5x = MXM_5X_STATE_UNSENT;
1939  MXM_MonRegistryInit(pInstance);
1941  }
1942 
1943  switch (pInstance->state) {
1945  /* TODO proper selfchecks, that are only executed during IBIT, CBIT and PBIT */
1946  pInstance->resultSelfCheck = MXM_PreInitSelfCheck(pInstance);
1947  if (pInstance->resultSelfCheck == STD_OK) {
1948  pInstance->requestStatus5x = MXM_5X_STATE_UNSENT;
1949  pInstance->state = MXM_STATEMACHINE_STATES_INIT;
1950  } else {
1951  /* software is broken by configuration/design */
1953  }
1954  break;
1956  if (pInstance->requestStatus5x == MXM_5X_STATE_UNSENT) {
1958  pInstance->pInstance5X,
1960  pInstance->batteryCmdBuffer,
1961  &pInstance->requestStatus5x);
1962  } else if (pInstance->requestStatus5x == MXM_5X_STATE_UNPROCESSED) {
1963  /* just wait */
1964  /* TODO timeout? */
1965  } else if (pInstance->requestStatus5x == MXM_5X_STATE_ERROR) {
1966  /* TODO error handling */
1967  } else if (pInstance->allowStartup == false) {
1968  /* do not start yet, just wait */
1969 
1970  } else if ((pInstance->requestStatus5x == MXM_5X_STATE_PROCESSED) && (pInstance->allowStartup == true)) {
1971  /* update registry */
1972  /* TODO handle return value of this function */
1974  pInstance->requestStatus5x = MXM_5X_STATE_UNSENT;
1976  } else {
1978  }
1979 
1980  break;
1982  /* TODO more checks */
1983  pInstance->selfCheck.fmeaStatusASCI = STD_NOT_OK;
1984  if (pInstance->requestStatus5x == MXM_5X_STATE_UNSENT) {
1986  pInstance->pInstance5X,
1988  pInstance->batteryCmdBuffer,
1989  &pInstance->requestStatus5x);
1990  } else if (pInstance->requestStatus5x == MXM_5X_STATE_UNPROCESSED) {
1991  /* just wait */
1992  /* TODO timeout? */
1993  } else if (pInstance->requestStatus5x == MXM_5X_STATE_ERROR) {
1994  pInstance->selfCheck.fmeaStatusASCI = STD_NOT_OK;
1995  /* TODO configuration or hardware failure */
1996  pInstance->resultSelfCheck = STD_NOT_OK;
1998  } else if (pInstance->requestStatus5x == MXM_5X_STATE_PROCESSED) {
1999  pInstance->selfCheck.fmeaStatusASCI = STD_OK;
2000  if ((pInstance->resultSelfCheck == STD_OK) && (pInstance->selfCheck.fmeaStatusASCI == STD_OK) &&
2002  pInstance->resultSelfCheck = STD_OK;
2003  pInstance->requestStatus5x = MXM_5X_STATE_UNSENT;
2004  pInstance->state = MXM_STATEMACHINE_STATES_IDLE;
2005  }
2006  } else {
2008  }
2009  break;
2011  pInstance->stopRequested = false;
2012  if (pInstance->operationRequested == true) {
2014  } else {
2015  /* Do nothing */
2016  }
2017  break;
2019  MXM_StateMachineOperation(pInstance);
2020  break;
2021  default:
2023  break;
2024  }
2025 }
2026 
2027 /*========== Externalized Static Function Implementations (Unit Test) =======*/
2028 #ifdef UNITY_UNIT_TEST
2029 extern STD_RETURN_TYPE_e TEST_MXM_ParseVoltageReadallTest(MXM_MONITORING_INSTANCE_s *pInstance) {
2030  return MXM_ParseVoltageReadallTest(pInstance);
2031 }
2032 extern STD_RETURN_TYPE_e TEST_MXM_ParseVoltagesIntoDB(MXM_MONITORING_INSTANCE_s *pInstance) {
2033  return MXM_ParseVoltagesIntoDB(pInstance);
2034 }
2035 extern MXM_MONINTORING_STATE_e TEST_MXM_MonGetVoltages(
2036  MXM_MONITORING_INSTANCE_s *pInstance,
2037  MXM_REG_NAME_e regAddress) {
2038  return MXM_MonGetVoltages(pInstance, regAddress);
2039 }
2040 extern void TEST_MXM_HandleStateWriteall(
2041  MXM_MONITORING_INSTANCE_s *pInstance,
2043  MXM_HandleStateWriteall(pInstance, nextState);
2044 }
2045 extern bool TEST_MXM_HandleStateReadall(
2046  MXM_MONITORING_INSTANCE_s *pInstance,
2047  MXM_REG_NAME_e registerName,
2049  return MXM_HandleStateReadall(pInstance, registerName, nextState);
2050 }
2051 extern STD_RETURN_TYPE_e TEST_MXM_ParseVoltageReadall(
2052  uint8_t *volt_rx_buffer,
2053  uint16_t volt_rx_buffer_len,
2054  MXM_DATA_STORAGE_s *datastorage,
2055  MXM_CONVERSION_TYPE_e conversionType) {
2056  return MXM_ParseVoltageReadall(volt_rx_buffer, volt_rx_buffer_len, datastorage, conversionType);
2057 }
2058 extern void TEST_MXM_ProcessOpenWire(MXM_MONITORING_INSTANCE_s *pInstance, DATA_BLOCK_OPEN_WIRE_s *pDataOpenWire) {
2059  MXM_ProcessOpenWire(pInstance, pDataOpenWire);
2060 }
2061 #endif
#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_READ_DATA(...)
Definition: database.h:76
#define DATA_WRITE_DATA(...)
Definition: database.h:86
@ DATA_BLOCK_ID_BALANCING_CONTROL
Definition: database_cfg.h:77
@ DATA_BLOCK_ID_CELL_TEMPERATURE_BASE
Definition: database_cfg.h:95
@ DATA_BLOCK_ID_OPEN_WIRE_BASE
Definition: database_cfg.h:81
@ DATA_BLOCK_ID_CELL_VOLTAGE_BASE
Definition: database_cfg.h:94
Diagnosis driver header.
#define FAS_ASSERT(x)
Assertion macro that asserts that x is true.
Definition: fassert.h:237
#define FAS_TRAP
Define that evaluates to essential boolean false thus tripping an assert.
Definition: fassert.h:108
@ STD_NOT_OK
Definition: fstd_types.h:73
@ STD_OK
Definition: fstd_types.h:72
#define NULL_PTR
Null pointer.
Definition: fstd_types.h:66
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:95
#define MXM_I2C_MUX0_ADDRESS
address of MUX0
Definition: mxm_1785x.c:182
#define MXM_I2C_MUX1_ADDRESS
address of MUX1
Definition: mxm_1785x.c:184
static STD_RETURN_TYPE_e MXM_ParseVoltagesIntoDB(const MXM_MONITORING_INSTANCE_s *const kpkInstance)
Copies measured voltage data into the database.
Definition: mxm_1785x.c:1243
static uint8_t mxm_evenCellsNeedBalancing
Even cells group needs to be balanced.
Definition: mxm_1785x.c:141
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:618
static uint8_t mxm_oddCellsNeedBalancing
Odd cells group needs to be balanced.
Definition: mxm_1785x.c:147
static DATA_BLOCK_CELL_TEMPERATURE_s mxm_cellTemperatures
Local cell temperature data block.
Definition: mxm_1785x.c:120
static DATA_BLOCK_BALANCING_CONTROL_s mxm_balancingControl
Balancing control.
Definition: mxm_1785x.c:129
#define MXM_DELAY_BALANCING
Delay in milliseconds before the balancing status is updated.
Definition: mxm_1785x.c:173
static 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:433
static uint8_t mxm_oddCellsBalancingProcessed
Odd cells group balancing done.
Definition: mxm_1785x.c:159
static uint8_t mxm_evenCellsBalancingProcessed
Even cells group balancing done.
Definition: mxm_1785x.c:153
static uint8_t mxm_moduleBalancingIndex
Module index in the daisy chain.
Definition: mxm_1785x.c:135
static void MXM_StateMachineOperation(MXM_MONITORING_INSTANCE_s *pState)
State-Machine implementation for operation state.
Definition: mxm_1785x.c:1321
static uint32_t mxm_currentTime
Timers used to guarantee that balancing is performed periodically.
Definition: mxm_1785x.c:169
static DATA_BLOCK_OPEN_WIRE_s mxm_openwire
Local data structure for openwire results.
Definition: mxm_1785x.c:123
static 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:407
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:402
static STD_RETURN_TYPE_e MXM_ConstructBalancingBuffer(void)
Fill the balancing datastructure.
Definition: mxm_1785x.c:505
uint16_t mxm_cellsToBalance
Mask to control balacing.
Definition: mxm_1785x.c:165
static const MXM_REG_NAME_e mxm_voltageCellAddresses[MXM_VOLTAGE_READ_ARRAY_LENGTH]
Mapping of voltage registers.
Definition: mxm_1785x.c:84
static uint32_t mxm_previousTime
Timers used to guarantee that balancing is performed periodically.
Definition: mxm_1785x.c:168
void MXM_StateMachine(MXM_MONITORING_INSTANCE_s *pInstance)
Battery monitoring driver for MAX1785x battery monitoring ICs.
Definition: mxm_1785x.c:1934
#define MXM_REF_VAA_mV
VAA reference voltage (3.3V)
Definition: mxm_1785x.c:176
#define MXM_VOLTAGE_READ_ARRAY_LENGTH
Definition: mxm_1785x.c:71
static STD_RETURN_TYPE_e must_check_return MXM_ParseVoltageReadallTest(MXM_MONITORING_INSTANCE_s *pInstance)
Test the MXM_ParseVoltageReadall()-function.
Definition: mxm_1785x.c:850
static void MXM_ProcessOpenWire(const MXM_MONITORING_INSTANCE_s *const kpkInstance, DATA_BLOCK_OPEN_WIRE_s *pDataOpenWire)
Processes the retrieved information on openwire.
Definition: mxm_1785x.c:462
static MXM_MONINTORING_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:1213
static DATA_BLOCK_CELL_VOLTAGE_s mxm_cellVoltages
Local cell voltage data block.
Definition: mxm_1785x.c:114
static STD_RETURN_TYPE_e must_check_return MXM_PreInitSelfCheck(MXM_MONITORING_INSTANCE_s *pState)
Execute all preinit selfchecks.
Definition: mxm_1785x.c:1300
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 meas_type, uint32_t full_scale_reference_mV)
Parse voltage values from a READALL receive buffer into an array.
Definition: mxm_1785x.c:560
Headers for the driver for the MAX17841B ASCI and MAX1785x monitoring chip.
void MXM_Unipolar14BitInto16Bit(uint16_t inputValue, uint8_t *lsb, uint8_t *msb)
convert a unipolar 14bit-value and shifts it into the 16bit-format
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().
uint16_t MXM_VoltageIntoUnipolar14Bit(uint16_t voltage_mV, uint16_t fullscaleReference_mV)
convert a voltage value into a unipolar 14bit value
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_PASS
@ MXM_MONITORING_STATE_PENDING
@ MXM_MONITORING_STATE_FAIL
MXM_STATEMACHINE_OPERATION_STATES_e
@ MXM_INIT_I2C_GET_STAT1
@ MXM_INIT_BALEXP5
@ MXM_OP_WRITE_MUX0
@ MXM_INIT_BALEXP6
@ MXM_INIT_STATUS1
@ MXM_INIT_BALEXP13
@ MXM_INIT_OVTHSETREG
@ MXM_INIT_BALEXP1
@ MXM_INIT_BALEXP9
@ MXM_OP_PINOPEN_RESTORE_CURRENT_SOURCE_CONF
@ MXM_INIT_I2C_SEND_MUX1
@ MXM_INIT_MEASUREEN1
@ MXM_OP_PINOPEN_SET_CURRENT_SOURCES
@ MXM_INIT_GET_ID2
@ MXM_INIT_MEASUREEN2
@ MXM_OP_PINOPEN_GET_SCAN_STROBE
@ MXM_INIT_I2C_PNTR
@ MXM_OP_BAL_START
@ MXM_INIT_BALEXP8
@ MXM_INIT_UVTHSETREG
@ MXM_OP_PINOPEN_COMPSCAN
@ MXM_INIT_SET_FMEA2
@ MXM_INIT_I2C_SEND_MUX0
@ MXM_INIT_BALSWDLY
@ MXM_INIT_GET_VERSION
@ MXM_OP_BAL_CONTROL_SET_ALL
@ MXM_INIT_GET_ID1
@ MXM_INIT_GET_I2C_STAT2
@ MXM_OP_PINOPEN_EXIT
@ MXM_OP_PINOPEN_ENTRY
@ MXM_OP_PINOPEN_PROCESS_OPENWIRE
@ MXM_INIT_BALEXP10
@ MXM_INIT_BALEXP14
@ MXM_INIT_BALEXP12
@ MXM_OP_INCREMENT_MUX_COUNTER
@ MXM_OP_BAL_EXIT
@ MXM_OP_PARSE_VOLTAGES_INTO_DB
@ MXM_INIT_I2C_CFG
@ MXM_INIT_ALRTUVEN
@ MXM_INIT_BALEXP3
@ MXM_OP_SELECT_MUX_CHANNEL
@ MXM_INIT_BALEXP2
@ MXM_OP_WRITE_MUX1
@ MXM_INIT_ALRTOVEN
@ MXM_OP_ENTRY_STATE
@ MXM_INIT_BALEXP7
@ MXM_OP_CYCLE_END_EXIT
@ MXM_OP_GET_VOLTAGES
@ MXM_OP_GET_ALRTSUM
@ MXM_OP_CYCLE_END_ENTRY
@ MXM_OP_BAL_CONTROL_RESET_ALL
@ MXM_OP_BAL_ENTRY
@ MXM_INIT_ACQCFG
@ MXM_INIT_COMPOPNTHREG
@ MXM_OP_PINOPEN_GET_ALRT
@ MXM_INIT_BALEXP4
@ MXM_OP_SET_SCAN_STROBE
@ MXM_OP_GET_SCAN_STROBE
@ MXM_INIT_DEVCFG1
@ MXM_INIT_BALEXP11
@ MXM_INIT_AUXTIMEREG
@ MXM_INIT_AUXGPIOCFG
enum MXM_MONITORING_STATE MXM_MONINTORING_STATE_e
@ 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.
#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_CONVERSION_BIPOLAR
@ MXM_CONVERSION_UNIPOLAR
@ MXM_CONVERSION_BLOCK_VOLTAGE
enum MXM_MEASURE_TYPE MXM_MEASURE_TYPE_e
enum MXM_CONVERSION_TYPE MXM_CONVERSION_TYPE_e
#define MXM_MAXIMUM_NR_OF_MODULES
Maximum number of modules.
@ MXM_MEASURE_CELL_VOLTAGE
@ MXM_MEASURE_BLOCK_VOLTAGE
@ MXM_MEASURE_TEMP
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::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_WRITE_DEVICE
@ 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.
STD_RETURN_TYPE_e must_check_return MXM_CRC8SelfTest(void)
Test the CRC8-algorithm with a known pattern.
Definition: mxm_crc8.c:124
enum MXM_REG_NAME MXM_REG_NAME_e
MAX1785x register names.
@ MXM_REG_CTSTCFG
@ MXM_REG_CELL1
@ MXM_REG_CELL4
@ MXM_REG_BALEXP11
@ MXM_REG_STATUS1
@ MXM_REG_BALEXP6
@ MXM_REG_BALEXP2
@ MXM_REG_AUX0
@ MXM_REG_ALRTSUM
@ MXM_REG_CELL10
@ MXM_REG_BALEXP13
@ MXM_REG_I2CCFG
@ MXM_REG_BALEXP5
@ MXM_REG_UVTHSET
@ MXM_REG_BALEXP10
@ MXM_REG_AUX3
@ MXM_REG_BALEXP1
@ MXM_REG_SCANCTRL
@ MXM_REG_VERSION
@ MXM_REG_MEASUREEN2
@ MXM_REG_I2CSTAT
@ MXM_REG_ID1
@ MXM_REG_BALEXP14
@ MXM_REG_I2CPNTR
@ MXM_REG_CELL9
@ MXM_REG_AUXTIME
@ MXM_REG_BLOCK
@ MXM_REG_COMPOPNTH
@ MXM_REG_AUXGPIOCFG
@ MXM_REG_CELL3
@ MXM_REG_BALEXP8
@ MXM_REG_ID2
@ MXM_REG_BALEXP9
@ MXM_REG_CELL14
@ MXM_REG_CELL6
@ MXM_REG_I2CSEND
@ MXM_REG_ACQCFG
@ MXM_REG_BALCTRL
@ MXM_REG_CELL2
@ MXM_REG_BALEXP7
@ MXM_REG_ALRTUVEN
@ MXM_REG_BALEXP3
@ MXM_REG_CELL11
@ MXM_REG_MEASUREEN1
@ MXM_REG_BALSWDLY
@ MXM_REG_CELL5
@ MXM_REG_CELL13
@ MXM_REG_OVTHSET
@ MXM_REG_AUX2
@ MXM_REG_BALSWCTRL
@ MXM_REG_FMEA2
@ MXM_REG_CELL7
@ MXM_REG_BALEXP12
@ MXM_REG_ALRTCOMPUV
@ MXM_REG_DEVCFG1
@ MXM_REG_ALRTOVEN
@ MXM_REG_CELL8
@ MXM_REG_CELL12
@ MXM_REG_BALEXP4
void MXM_MonRegistryParseIdIntoDevices(MXM_MONITORING_INSTANCE_s *pState, uint8_t rxBufferLength, MXM_REG_NAME_e type)
Parse ID (1 or 2) into the registry.
Definition: mxm_registry.c:104
void MXM_MonRegistryInit(MXM_MONITORING_INSTANCE_s *pState)
Initialize monitoring registry.
Definition: mxm_registry.c:70
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:82
void MXM_MonRegistryParseVersionIntoDevices(MXM_MONITORING_INSTANCE_s *pState, uint8_t rxBufferLength)
Parse Version into the registry.
Definition: mxm_registry.c:133
Functions in order to have a registry of monitoring ICs.
uint32_t OS_GetTickCount(void)
Returns OS based system tick value.
Definition: os.c:182
Implementation of the tasks used by the system, headers.
DATA_BLOCK_ID_e uniqueId
Definition: database_cfg.h:110
uint8_t balancingState[BS_NR_OF_STRINGS][BS_NR_OF_BAT_CELLS]
Definition: database_cfg.h:255
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:251
int16_t cellTemperature_ddegC[BS_NR_OF_STRINGS][BS_NR_OF_TEMP_SENSORS_PER_STRING]
Definition: database_cfg.h:138
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:136
uint32_t moduleVoltage_mV[BS_NR_OF_STRINGS][BS_NR_OF_MODULES]
Definition: database_cfg.h:127
int16_t cellVoltage_mV[BS_NR_OF_STRINGS][BS_NR_OF_BAT_CELLS]
Definition: database_cfg.h:123
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:120
int32_t packVoltage_mV[BS_NR_OF_STRINGS]
Definition: database_cfg.h:122
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:303
uint8_t openwire[BS_NR_OF_STRINGS][BS_NR_OF_MODULES *(BS_NR_OF_CELLS_PER_MODULE+1)]
Definition: database_cfg.h:307
uint16_t blockVoltages[MXM_MAXIMUM_NR_OF_MODULES]
uint16_t cellVoltages_mV[MXM_MAXIMUM_NR_OF_MODULES *MXM_MAXIMUM_NR_OF_CELLS_PER_MODULE]
uint16_t auxVoltages_mV[MXM_MAXIMUM_NR_OF_MODULES *MXM_MAXIMUM_NR_OF_AUX_PER_MODULE]
uint8_t rxBuffer[MXM_RX_BUFFER_LENGTH]
STD_RETURN_TYPE_e resultSelfCheck
MXM_STATEMACHINE_OPERATION_STATES_e operationSubstate
MXM_SELFCHECK_s selfCheck
MXM_DATA_STORAGE_s localVoltages
Local storage for cell-voltages.
MXM_5X_COMMAND_PAYLOAD_s batteryCmdBuffer
MXM_5X_INSTANCE_s * pInstance5X
MXM_STATEMACHINE_STATES_e state
MXM_5X_STATE_REQUEST_STATUS_e requestStatus5x
STD_RETURN_TYPE_e parseVoltageReadall
STD_RETURN_TYPE_e extractValueFromRegister
STD_RETURN_TYPE_e conv
STD_RETURN_TYPE_e fmeaStatusASCI
STD_RETURN_TYPE_e firstSetBit
STD_RETURN_TYPE_e addressSpaceChecker
STD_RETURN_TYPE_e crc
Temperature Sensor Interface on Slave Unit driver header.
int16_t TSI_GetTemperature(uint16_t adcVoltage_mV)
translate a voltage to a temperature