foxBMS  1.6.0
The foxBMS Battery Management System API Documentation
nxp_mc33775a.c
Go to the documentation of this file.
1 /**
2  *
3  * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright notice, this
12  * list of conditions and the following disclaimer.
13  *
14  * 2. Redistributions in binary form must reproduce the above copyright notice,
15  * this list of conditions and the following disclaimer in the documentation
16  * and/or other materials provided with the distribution.
17  *
18  * 3. Neither the name of the copyright holder nor the names of its
19  * contributors may be used to endorse or promote products derived from
20  * this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  *
33  * We kindly request you to use one or more of the following phrases to refer to
34  * foxBMS in your hardware, software, documentation or advertising materials:
35  *
36  * - ″This product uses parts of foxBMS®″
37  * - ″This product includes parts of foxBMS®″
38  * - ″This product is derived from foxBMS®″
39  *
40  */
41 
42 /**
43  * @file nxp_mc33775a.c
44  * @author foxBMS Team
45  * @date 2020-05-08 (date of creation)
46  * @updated 2023-10-12 (date of last update)
47  * @version v1.6.0
48  * @ingroup DRIVERS
49  * @prefix N775
50  *
51  * @brief Driver for the MC33775A analog front-end.
52  *
53  */
54 
55 /*========== Includes =======================================================*/
56 #include "nxp_mc33775a.h"
57 /* clang-format off */
58 #include "nxp_mc33775a-ll.h"
59 /* clang-format on */
60 
61 #pragma diag_push
62 #pragma diag_suppress 232
63 #include "MC33775A.h"
64 #pragma diag_pop
65 
66 #include "afe.h"
67 #include "afe_dma.h"
68 #include "database.h"
69 #include "fassert.h"
70 #include "fstd_types.h"
71 #include "ftask.h"
72 #include "mcu.h"
73 #include "os.h"
74 #include "spi.h"
75 
76 #include <math.h>
77 #include <stdbool.h>
78 #include <stdint.h>
79 
80 /*========== Macros and Definitions =========================================*/
81 
82 /*========== Static Constant and Variable Definitions =======================*/
83 /** local copies of database tables */
84 /**@{*/
94 /**@}*/
97 
98 /*========== Extern Constant and Variable Definitions =======================*/
99 
101  .firstMeasurementMade = false,
102  .currentString = 0u,
103  .pSpiTxSequenceStart = NULL_PTR,
104  .pSpiTxSequence = NULL_PTR,
105  .pSpiRxSequenceStart = NULL_PTR,
106  .pSpiRxSequence = NULL_PTR,
107  .currentMux = {0},
108  .pMuxSequenceStart = {0},
109  .pMuxSequence = {0},
110  .n775Data.cellVoltage = &n775_cellVoltage,
111  .n775Data.cellTemperature = &n775_cellTemperature,
112  .n775Data.allGpioVoltage = &n775_allGpioVoltage,
113  .n775Data.minMax = &n775_minMax,
114  .n775Data.balancingFeedback = &n775_balancingFeedback,
115  .n775Data.balancingControl = &n775_balancingControl,
116  .n775Data.slaveControl = &n775_slaveControl,
117  .n775Data.openWire = &n775_openWire,
118  .n775Data.supplyCurrent = &n775_supplyCurrent,
119  .n775Data.errorTable = &n775_errorTable,
120 };
121 
122 /*========== Static Function Prototypes =====================================*/
123 /**
124  * @brief manages balancing.
125  * @details Reads balancing order from database and balances the corresponding
126  * cells.
127  * @param pState state of the NXP MC33775A driver
128  */
129 static void N775_BalanceControl(N775_STATE_s *pState);
130 
131 /**
132  * @brief setups balancing.
133  * @details Sets all balancing timer to max to allow for software balancing
134  * control.
135  * @param pState state of the NXP MC33775A driver
136  */
137 static void N775_BalanceSetup(N775_STATE_s *pState);
138 
139 /**
140  * @brief captures the measurement.
141  * @details The MC33775A measures continuously.
142  * This function takes a snapshot on all slaves in the daisy-chain.
143  * @param pState state of the NXP MC33775A driver
144  */
145 static void N775_CaptureMeasurement(N775_STATE_s *pState);
146 
147 /**
148  * @brief enumerates the N775 slaves.
149  * @details This function gives the slaves in the daisy-chain an address.
150  * @param pState state of the NXP MC33775A driver
151  */
153 /**
154  * @brief handles error when doing measurements.
155  * @details This function is used in the measurement function.
156  * It sets the errors flags in the error table according to the value
157  * returned by the communication function.
158  * @param pState state of the NXP MC33775A driver
159  * @param returnedValue status of the low-level communication
160  * @param module number of module addressed
161  */
162 static void N775_ErrorHandling(N775_STATE_s *pState, N775_COMMUNICATION_STATUS_e returnedValue, uint8_t module);
163 
164 /**
165  * @brief updates index in mux sequence.
166  * @param pState state of the NXP MC33775A driver
167  */
168 static void N775_IncrementMuxIndex(N775_STATE_s *pState);
169 
170 /**
171  * @brief increments index in string sequence.
172  * @param pState state of the NXP MC33775A driver
173  */
174 static void N775_IncrementStringSequence(N775_STATE_s *pState);
175 
176 /**
177  * @brief initializes the N775 driver.
178  * @details This function enumerates the slaves and starts the measurement.
179  * @param pState state of the NXP MC33775A driver
180  */
181 static void N775_Initialize(N775_STATE_s *pState);
182 
183 /**
184  * @brief in the database, initializes the fields related to the N775 driver.
185  * @details This function loops through all the N775-related data fields in the
186  * database and sets them to 0.
187  * It shall be called in the initialization or re-initialization
188  * routine of the N775 driver.
189  * @param pState state of the NXP MC33775A driver
190  *
191  */
192 static void N775_InitializeDatabase(N775_STATE_s *pState);
193 
194 /**
195  * @brief init I2C for the N775 slaves.
196  * @details This function makes slaves ready for I2C transactions with on-slave
197  * devices.
198  * @param pState state of the NXP MC33775A driver
199  */
200 static void N775_InitializeI2c(N775_STATE_s *pState);
201 
202 /**
203  * @brief reset index in string sequence.
204  * @param pState state of the NXP MC33775A driver
205  */
206 static void N775_ResetStringSequence(N775_STATE_s *pState);
207 
208 /**
209  * @brief resets index in mux sequence.
210  * @param pState state of the NXP MC33775A driver
211  */
212 static void N775_ResetMuxIndex(N775_STATE_s *pState);
213 
214 /**
215  * @brief sets the measurement initialization status.
216  * @param pState state of the NXP MC33775A driver
217  */
219 
220 /**
221  * @brief sets mux channel.
222  * @details This function uses I2C to set the mux channel.
223  * @param pState state of the NXP MC33775A driver
224  */
226 
227 /**
228  * @brief starts the measurement.
229  * @details The MC33775A measures continuously.
230  * This function starts the measurement.
231  * @param pState state of the NXP MC33775A driver
232  */
233 static void N775_StartMeasurement(N775_STATE_s *pState);
234 
235 /**
236  * @brief transmit over I2C on NXP slave.
237  * @param pState state of the NXP MC33775A driver
238  */
240 
241 /**
242  * @brief waits for a definite amount of time in ms.
243  * @details This function uses FreeRTOS. It blocks the tasks for the given
244  * amount of milliseconds.
245  * @param milliseconds time to wait in ms
246  */
247 static void N775_Wait(uint32_t milliseconds);
248 
249 /*========== Static Function Implementations ================================*/
250 
251 static void N775_BalanceControl(N775_STATE_s *pState) {
252  FAS_ASSERT(pState != NULL_PTR);
253 
254  N775_BalanceSetup(pState);
255 
257 
258  for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) {
259  uint8_t deviceAddress = m + 1u;
260  uint16_t balancingState = 0u;
261  for (uint16_t c = 0u; c < BS_NR_OF_CELL_BLOCKS_PER_MODULE; c++) {
262  if (pState->n775Data.balancingControl
263  ->balancingState[pState->currentString][c + (m * BS_NR_OF_CELL_BLOCKS_PER_MODULE)] != 0u) {
264  balancingState |= 1u << c;
265  }
266  }
267  /* All channels active --> 14 bits set to 1 --> 0x3FFF */
268  FAS_ASSERT(balancingState <= 0x3FFFu);
269  /* Enable channels, one written to a channels means balancing active */
270  N775_CommunicationWrite(deviceAddress, MC33775_BAL_CH_CFG_OFFSET, balancingState, pState->pSpiTxSequence);
271  }
272 }
273 
274 static void N775_BalanceSetup(N775_STATE_s *pState) {
275  FAS_ASSERT(pState != NULL_PTR);
276 
277  /* Set global timeout counter to max value */
279  N775_BROADCAST_ADDRESS, MC33775_BAL_GLOB_TO_TMR_OFFSET, N775_GLOBAL_BALANCING_TIMER, pState->pSpiTxSequence);
280 
281  /* Disable pre-balancing timer by setting it to zero */
283  N775_BROADCAST_ADDRESS, MC33775_BAL_PRE_TMR_OFFSET, N775_PRE_BALANCING_TIMER, pState->pSpiTxSequence);
284 
285  /* Set PWM value for all channels to 100%, set balancing timer for all channels to maximum value */
288  MC33775_BAL_TMR_CH_ALL_OFFSET,
289  (MC33775_BAL_TMR_CH_ALL_PWM_PWM100_ENUM_VAL << MC33775_BAL_TMR_CH_ALL_PWM_POS) |
290  (N775_ALL_CHANNEL_BALANCING_TIMER << MC33775_BAL_TMR_CH_ALL_BALTIME_POS),
291  pState->pSpiTxSequence);
292 
293  /* Select timer based balancing and enable balancing */
296  MC33775_BAL_GLOB_CFG_OFFSET,
297  (MC33775_BAL_GLOB_CFG_BALEN_ENABLED_ENUM_VAL << MC33775_BAL_GLOB_CFG_BALEN_POS) |
298  (MC33775_BAL_GLOB_CFG_TMRBALEN_STOP_ENUM_VAL << MC33775_BAL_GLOB_CFG_TMRBALEN_POS),
299  pState->pSpiTxSequence);
300 }
301 
302 static void N775_CaptureMeasurement(N775_STATE_s *pState) {
303  FAS_ASSERT(pState != NULL_PTR);
304 
305  uint16_t primaryRawValues[20] = {0u};
306  uint16_t secondaryRawValues[4] = {0u};
307  uint16_t currentRawValue = 0u;
308  int16_t primaryValues[20] = {0u};
309  int16_t secondaryValues[4] = {0u};
310  int16_t currentValue = 0u;
314  uint16_t error = 0u;
315  bool gpio03Error = false;
316  bool gpio47Error = false;
317 
318  /* Send capture command. This ends the last cycle and starts a new one */
321  MC33775_ALLM_APP_CTRL_OFFSET,
322  (1u << MC33775_ALLM_APP_CTRL_PAUSEBAL_POS) | (0x3FFu << MC33775_PRMM_APP_CTRL_CAPVC_POS) |
323  (MC33775_PRMM_APP_CTRL_VCOLNUM_DISABLED_ENUM_VAL << MC33775_PRMM_APP_CTRL_VCOLNUM_POS),
324  pState->pSpiTxSequence);
325  /* Wait for measurements to take place */
327  /* Send capture command. This ends the last cycle and starts a new one */
330  MC33775_ALLM_APP_CTRL_OFFSET,
331  (0u << MC33775_ALLM_APP_CTRL_PAUSEBAL_POS) | (0x3FFu << MC33775_PRMM_APP_CTRL_CAPVC_POS) |
332  (MC33775_PRMM_APP_CTRL_VCOLNUM_DISABLED_ENUM_VAL << MC33775_PRMM_APP_CTRL_VCOLNUM_POS),
333  pState->pSpiTxSequence);
334  /* Wait for measurements to be ready */
336 
337  for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) {
338  uint8_t deviceAddress = m + 1u;
339  retValPrimary = N775_CommunicationReadMultiple(
340  deviceAddress, 20, 4u, MC33775_PRMM_APP_VC_CNT_OFFSET, primaryRawValues, pState);
341  retValSecondary = N775_CommunicationReadMultiple(
342  deviceAddress, 4, 4u, MC33775_SECM_APP_AIN4_OFFSET, secondaryRawValues, pState);
343  if (N775_CHECK_SUPPLY_CURRENT == true) {
344  retValSupplyCurrent =
345  N775_CommunicationRead(deviceAddress, MC33775_SECM_PER_NPNISENSE_OFFSET, &currentRawValue, pState);
346  }
347 
348  N775_ErrorHandling(pState, retValPrimary, m);
349  if (retValPrimary == N775_COMMUNICATION_OK) {
350  for (uint8_t cb = 0u; cb < BS_NR_OF_CELL_BLOCKS_PER_MODULE; cb++) {
351  /* Store cell voltages */
352  if (N775_INVALID_REGISTER_VALUE != primaryRawValues[cb + 1u]) {
353  primaryValues[cb + 1u] = (int16_t)primaryRawValues[cb + 1u];
354  pState->n775Data.cellVoltage->cellVoltage_mV[pState->currentString][m][cb] =
355  (((float_t)primaryValues[cb + 1u]) * 154.0e-6f * 1000.0f);
356  } else {
357  error++;
358  }
359  }
360  for (uint8_t g = 0u; g < 4u; g++) {
361  /* Store GPIO voltages */
362  if (N775_INVALID_REGISTER_VALUE != primaryRawValues[g + 16u]) {
363  primaryValues[g + 16u] = (int16_t)primaryRawValues[g + 16u];
364  pState->n775Data.allGpioVoltage
366  (((float_t)primaryValues[g + 16u]) * 154.0e-6f * 1000.0f);
367  } else {
368  gpio03Error = true;
369  error++;
370  }
371  }
372  /* Store module voltage */
373  if (N775_INVALID_REGISTER_VALUE != primaryRawValues[15u]) {
374  primaryValues[15u] = (int16_t)primaryRawValues[15u];
375  pState->n775Data.cellVoltage->moduleVoltage_mV[pState->currentString][m] =
376  (((float_t)primaryValues[15u]) * 2.58e-3f * 1000.0f);
377  } else {
378  error++;
379  }
380  }
381 
382  N775_ErrorHandling(pState, retValSecondary, m);
383  if (retValSecondary == N775_COMMUNICATION_OK) {
384  for (uint8_t g = 4u; g < 8u; g++) {
385  if (N775_INVALID_REGISTER_VALUE != secondaryRawValues[g - 4u]) {
386  secondaryValues[g - 4u] = (int16_t)secondaryRawValues[g - 4u];
387  pState->n775Data.allGpioVoltage
389  (((float_t)secondaryValues[g - 4u]) * 154.0e-6f * 1000.0f);
390  } else {
391  gpio47Error = true;
392  error++;
393  }
394  }
395  }
396 
397  /* Set temperature values */
398  if (N775_USE_MUX_FOR_TEMP == true) {
399  /* Mux case */
400  if (gpio03Error == false) {
401  pState->n775Data.cellTemperature
402  ->cellTemperature_ddegC[pState->currentString][m][pState->currentMux[pState->currentString]] =
404  pState->n775Data.allGpioVoltage
405  ->gpioVoltages_mV[pState->currentString]
407  }
408  } else if (N775_USE_MUX_FOR_TEMP == false) {
409  /* No mux case */
410  if ((gpio03Error == false) && (gpio47Error == false)) {
411  for (uint8_t ts = 0u; ts < BS_NR_OF_TEMP_SENSORS_PER_MODULE; ts++) {
414  pState->n775Data.allGpioVoltage
416  }
417  }
418  } else {
419  /* Invalid value for switch case */
421  }
422 
423  if (N775_CHECK_SUPPLY_CURRENT == true) {
424  N775_ErrorHandling(pState, retValSupplyCurrent, m);
425  if (retValSupplyCurrent == N775_COMMUNICATION_OK) {
426  if (N775_INVALID_REGISTER_VALUE != currentRawValue) {
427  currentValue = (int16_t)currentRawValue;
428  pState->n775Data.supplyCurrent->current[pState->currentString][m] =
429  (((float_t)currentValue) * 7.69e-6f * 1000.0f);
430  } else {
431  error++;
432  }
433  }
434  }
435  }
436 
438 }
439 
441  FAS_ASSERT(pState != NULL_PTR);
442  uint16_t readValue = 0u;
443  uint16_t uid[3u] = {0};
445  STD_RETURN_TYPE_e retVal = STD_NOT_OK;
446 
447  /** Parse all slaves in the daisy-chain */
448  for (uint8_t i = 1; i <= BS_NR_OF_MODULES_PER_STRING; i++) {
449  /* First send slave to deep sleep to reset message counter */
451  i,
452  MC33775_SYS_MODE_OFFSET,
453  (MC33775_SYS_MODE_TARGETMODE_DEEPSLEEP_ENUM_VAL << MC33775_SYS_MODE_TARGETMODE_POS),
454  pState->pSpiTxSequence);
455  N775_Wait(1u);
456 
457  /* Wake up slave */
458  returnedValue = N775_CommunicationRead(i, MC33775_SYS_COM_CFG_OFFSET, &readValue, pState);
459  /* If slave is not enumerated */
460  if (returnedValue != N775_COMMUNICATION_OK) {
461  /* Wait until the slave has woken up */
463 
464  returnedValue = N775_CommunicationRead(i, MC33775_SYS_COM_CFG_OFFSET, &readValue, pState);
465  /* If slave is not enumerated */
466  if (returnedValue != N775_COMMUNICATION_OK) {
467  /* Enumerate slave */
469  (0u << 6u) + 0u,
470  MC33775_SYS_COM_CFG_OFFSET,
471  i + (N775_DEFAULT_CHAIN_ADDRESS << 6) +
472  (MC33775_SYS_COM_CFG_BUSFW_ENABLED_ENUM_VAL << MC33775_SYS_COM_CFG_BUSFW_POS),
473  pState->pSpiTxSequence);
474  }
475 
476  /* Reset the message counter of the driver */
478  /* Check that the device has been enumerated */
479  returnedValue = N775_CommunicationRead(i, MC33775_SYS_VERSION_OFFSET, &readValue, pState);
480  if (returnedValue == N775_COMMUNICATION_OK) {
481  retVal = STD_OK;
482  }
483  } else {
484  /* Slave already has an address */
485  retVal = STD_OK;
486  }
487 
488  /* Set timeout, enable/disable timeout */
490  i,
491  MC33775_SYS_COM_TO_CFG_OFFSET,
492  (N775_TIMEOUT_SWITCH << MC33775_SYS_COM_TO_CFG_COMTODISABLE_POS) |
493  (N775_TIMEOUT_TO_SLEEP_10MS << MC33775_SYS_COM_TO_CFG_COMTO_POS),
494  pState->pSpiTxSequence);
495 
496  /* read uid of each device */
497  returnedValue = N775_CommunicationReadMultiple(i, 3u, 3u, MC33775_SYS_UID_LOW_OFFSET, uid, pState);
498  if (returnedValue == N775_COMMUNICATION_OK) {
499  pState->n775Data.uid[pState->currentString][i - 1u] = 0u;
500  for (uint8_t j = 0u; j <= 3u; j++) {
501  pState->n775Data.uid[pState->currentString][i - 1u] |= ((uint64_t)uid[j]) << (16u * j);
502  }
503  }
504  }
505 
506  return retVal;
507 }
508 
509 static void N775_ErrorHandling(N775_STATE_s *pState, N775_COMMUNICATION_STATUS_e returnedValue, uint8_t module) {
510  FAS_ASSERT(pState != NULL_PTR);
511 
512  if (returnedValue == N775_COMMUNICATION_OK) {
513  pState->n775Data.errorTable->communicationOk[pState->currentString][module] = true;
514  pState->n775Data.errorTable->noCommunicationTimeout[pState->currentString][module] = true;
515  pState->n775Data.errorTable->crcIsValid[pState->currentString][module] = true;
516  } else {
517  pState->n775Data.errorTable->communicationOk[pState->currentString][module] = false;
518  switch (returnedValue) {
520  pState->n775Data.errorTable->noCommunicationTimeout[pState->currentString][module] = false;
521  break;
523  pState->n775Data.errorTable->crcIsValid[pState->currentString][module] = false;
524  break;
525  default:
526  pState->n775Data.errorTable->communicationOk[pState->currentString][module] = false;
527  break;
528  }
529  }
530 }
531 
532 static void N775_IncrementMuxIndex(N775_STATE_s *pState) {
533  FAS_ASSERT(pState != NULL_PTR);
534 
535  pState->currentMux[pState->currentString]++;
536  if (pState->currentMux[pState->currentString] >= N775_MUX_SEQUENCE_LENGTH) {
537  pState->currentMux[pState->currentString] = 0u;
538  }
539  pState->pMuxSequence[pState->currentString] = pState->pMuxSequenceStart[pState->currentString] +
540  pState->currentMux[pState->currentString];
541 }
542 
544  FAS_ASSERT(pState != NULL_PTR);
545 
546  pState->currentString++;
547  pState->pSpiTxSequence = pState->pSpiTxSequenceStart + pState->currentString;
548  pState->pSpiRxSequence = pState->pSpiRxSequenceStart + pState->currentString;
549 }
550 
551 static void N775_Initialize(N775_STATE_s *pState) {
552  FAS_ASSERT(pState != NULL_PTR);
553 
554  /* Reset mux sequence */
555  N775_ResetMuxIndex(pState);
556 
557  /* Initialize daisy-chain */
558  if (STD_OK != N775_Enumerate(pState)) {
559  /* error handling */}
560  N775_StartMeasurement(pState);
561  N775_InitializeI2c(pState);
562  N775_BalanceSetup(pState);
563 }
564 
565 static void N775_InitializeDatabase(N775_STATE_s *pState) {
566  FAS_ASSERT(pState != NULL_PTR);
567  uint16_t iterator = 0;
568 
569  for (uint8_t stringNumber = 0u; stringNumber < BS_NR_OF_STRINGS; stringNumber++) {
570  pState->n775Data.cellVoltage->state = 0;
571  pState->n775Data.minMax->minimumCellVoltage_mV[stringNumber] = 0;
572  pState->n775Data.minMax->maximumCellVoltage_mV[stringNumber] = 0;
573  pState->n775Data.minMax->nrModuleMinimumCellVoltage[stringNumber] = 0;
574  pState->n775Data.minMax->nrModuleMaximumCellVoltage[stringNumber] = 0;
575  pState->n775Data.minMax->nrCellMinimumCellVoltage[stringNumber] = 0;
576  pState->n775Data.minMax->nrCellMaximumCellVoltage[stringNumber] = 0;
577  for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) {
578  for (uint8_t cb = 0u; cb < BS_NR_OF_CELL_BLOCKS_PER_STRING; cb++) {
579  pState->n775Data.cellVoltage->cellVoltage_mV[stringNumber][m][cb] = 0;
580  }
581  }
582 
583  pState->n775Data.cellTemperature->state = 0;
584  pState->n775Data.minMax->minimumTemperature_ddegC[stringNumber] = 0;
585  pState->n775Data.minMax->maximumTemperature_ddegC[stringNumber] = 0;
586  pState->n775Data.minMax->nrModuleMinimumTemperature[stringNumber] = 0;
587  pState->n775Data.minMax->nrModuleMaximumTemperature[stringNumber] = 0;
588  pState->n775Data.minMax->nrSensorMinimumTemperature[stringNumber] = 0;
589  pState->n775Data.minMax->nrSensorMaximumTemperature[stringNumber] = 0;
590 
591  for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) {
592  for (uint8_t ts = 0u; ts < BS_NR_OF_TEMP_SENSORS_PER_MODULE; ts++) {
593  pState->n775Data.cellTemperature->cellTemperature_ddegC[stringNumber][m][ts] = 0;
594  }
595  }
596 
597  for (iterator = 0u; iterator < BS_NR_OF_CELL_BLOCKS_PER_STRING; iterator++) {
598  pState->n775Data.balancingControl->balancingState[stringNumber][iterator] = 0;
599  }
600  for (iterator = 0u; iterator < BS_NR_OF_MODULES_PER_STRING; iterator++) {
601  pState->n775Data.errorTable->communicationOk[stringNumber][iterator] = false;
602  pState->n775Data.errorTable->noCommunicationTimeout[stringNumber][iterator] = false;
603  pState->n775Data.errorTable->crcIsValid[stringNumber][iterator] = false;
604  pState->n775Data.errorTable->mux0IsOk[stringNumber][iterator] = false;
605  pState->n775Data.errorTable->mux1IsOK[stringNumber][iterator] = false;
606  pState->n775Data.errorTable->mux2IsOK[stringNumber][iterator] = false;
607  pState->n775Data.errorTable->mux3IsOK[stringNumber][iterator] = false;
608  }
609  for (iterator = 0u; iterator < BS_NR_OF_MODULES_PER_STRING; iterator++) {
610  pState->n775Data.uid[stringNumber][iterator] = 0;
611  }
612  }
613 
618 }
619 
620 static void N775_InitializeI2c(N775_STATE_s *pState) {
621  FAS_ASSERT(pState != NULL_PTR);
622 
623  /* Enable the I2C module and select 400 kHz */
626  MC33775_I2C_CFG_OFFSET,
627  (MC33775_I2C_CFG_EN_ENABLED_ENUM_VAL << MC33775_I2C_CFG_EN_POS) +
628  (MC33775_I2C_CFG_CLKSEL_F_400K_ENUM_VAL << MC33775_I2C_CFG_CLKSEL_POS),
629  pState->pSpiTxSequence);
630 }
631 
633  FAS_ASSERT(pState != NULL_PTR);
634 
635  pState->currentString = 0u;
636  pState->pSpiTxSequence = pState->pSpiTxSequenceStart + pState->currentString;
637  pState->pSpiRxSequence = pState->pSpiRxSequenceStart + pState->currentString;
638 }
639 
640 static void N775_ResetMuxIndex(N775_STATE_s *pState) {
641  FAS_ASSERT(pState != NULL_PTR);
642 
643  pState->currentMux[pState->currentString] = 0u;
644  pState->pMuxSequence[pState->currentString] = pState->pMuxSequenceStart[pState->currentString];
645 }
646 
648  FAS_ASSERT(pState != NULL_PTR);
649 
651  pState->firstMeasurementMade = true;
653 }
654 
656  FAS_ASSERT(pState != NULL_PTR);
657  FAS_ASSERT(pState->pMuxSequence[pState->currentString]->muxId < 4u);
658  FAS_ASSERT(pState->pMuxSequence[pState->currentString]->muxChannel <= 0xFFu);
659 
660  uint16_t readValue = 0u;
661  uint8_t dataI2c = 0u;
662  uint8_t addressI2c_write = N775_ADG728_ADDRESS_UPPERBITS;
663  uint8_t addressI2c_read = N775_ADG728_ADDRESS_UPPERBITS;
664  uint16_t tries = 0u;
665  STD_RETURN_TYPE_e retVAL = STD_OK;
667 
668  /* First set channel */
669 
670  /* Set bit1 and bit0 with mux address, write to mux */
671  addressI2c_write |= ((pState->pMuxSequence[pState->currentString]->muxId) << 1u) | N775_I2C_WRITE;
672  /* Set bit1 and bit0 with mux address, read from mux */
673  addressI2c_read |= ((pState->pMuxSequence[pState->currentString]->muxId) << 1u) | N775_I2C_READ;
674 
675  /**
676  * Set data to send, contains channel bit (8 channels)
677  * 1 means channel active, 0 means channel inactive
678  */
679  if (pState->pMuxSequence[pState->currentString]->muxChannel == 0xFF) {
680  /* 0xFF in mux sequence means disable all channels */
681  dataI2c = 0u;
682  } else {
683  dataI2c = (uint8_t)(1u << (pState->pMuxSequence[pState->currentString]->muxChannel));
684  }
685 
686  /* Write data to send on I2C bus in registers */
689  MC33775_I2C_DATA0_OFFSET,
690  (addressI2c_write << MC33775_I2C_DATA0_BYTE0_POS) | (dataI2c << MC33775_I2C_DATA0_BYTE1_POS),
691  pState->pSpiTxSequence);
692 
693  /* Read with a repeated start directly after write */
696  MC33775_I2C_DATA1_OFFSET,
697  (addressI2c_read << MC33775_I2C_DATA1_BYTE2_POS) | (N775_I2C_DUMMY_BYTE << MC33775_I2C_DATA1_BYTE3_POS),
698  pState->pSpiTxSequence);
699 
700  /* Write into the control register to start transaction */
703  MC33775_I2C_CTRL_OFFSET,
704  (N775_I2C_NR_BYTES_FOR_MUX_WRITE << MC33775_I2C_CTRL_START_POS) |
705  ((MC33775_I2C_CTRL_STPAFTER_STOP_ENUM_VAL << MC33775_I2C_CTRL_STPAFTER_POS) +
706  (N775_I2C_NR_BYTES_TO_SWITCH_TO_READ_FOR_UX_READ << MC33775_I2C_CTRL_RDAFTER_POS)),
707  pState->pSpiTxSequence);
708 
709  /**
710  * Wait util transaction ends, test on last device in daisy-chain
711  * So device address = number of modules
712  */
713  tries = N775_FLAG_READY_TRIES;
714  do {
715  returnedValue =
716  N775_CommunicationRead(BS_NR_OF_MODULES_PER_STRING, MC33775_I2C_STAT_OFFSET, &readValue, pState);
717  tries--;
718  N775_Wait(2u);
719  } while ((readValue & MC33775_I2C_STAT_PENDING_MSK) && (returnedValue == N775_COMMUNICATION_OK) && (tries > 0u));
720 
721  if ((returnedValue == N775_COMMUNICATION_OK) && (tries > 0u)) {
722  /**
723  * Get I2C read data, on last device in daisy-chain
724  * Use result to set error state for all slaves to avoid
725  * reading all slaves in daisy-chain.
726  */
727  returnedValue =
728  N775_CommunicationRead(BS_NR_OF_MODULES_PER_STRING, MC33775_I2C_DATA1_OFFSET, &readValue, pState);
729  readValue = readValue >> MC33775_I2C_DATA1_BYTE3_POS;
730 
731  if (returnedValue == N775_COMMUNICATION_OK) {
732  if (N775_CHECK_MUX_STATE == true) {
733  if (readValue == dataI2c) {
734  /* OK */
735  for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) {
736  pState->n775Data.errorTable->mux0IsOk[pState->currentString][m] = true;
737  }
738  } else {
739  /* Not OK */
740  for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) {
741  pState->n775Data.errorTable->mux0IsOk[pState->currentString][m] = false;
742  }
743  }
744  } else {
745  retVAL = STD_NOT_OK;
746  }
747  }
748  } else {
749  retVAL = STD_NOT_OK;
750  }
751 
752  return retVAL;
753 }
754 
755 static void N775_StartMeasurement(N775_STATE_s *pState) {
756  FAS_ASSERT(pState != NULL_PTR);
757 
758  /* Enable cell voltage measurements */
759  N775_CommunicationWrite(N775_BROADCAST_ADDRESS, MC33775_ALLM_VCVB_CFG_OFFSET, 0x3FFF, pState->pSpiTxSequence);
760  /* Enable analog inputs 0-3 and module voltage measurement */
761  N775_CommunicationWrite(N775_BROADCAST_ADDRESS, MC33775_PRMM_AIN_CFG_OFFSET, 0x1F, pState->pSpiTxSequence);
762  /* Enable analog inputs 4-7 measurement */
763  N775_CommunicationWrite(N775_BROADCAST_ADDRESS, MC33775_SECM_AIN_CFG_OFFSET, 0x0F, pState->pSpiTxSequence);
764  /* Set pause of balancing before measurement start, enable the measurement units simultaneously */
767  MC33775_ALLM_CFG_OFFSET,
768  (N775_BALPAUSELEN_10US << MC33775_ALLM_CFG_BALPAUSELEN_POS) | (1 << MC33775_ALLM_CFG_MEASEN_POS),
769  pState->pSpiTxSequence);
770 
772 }
773 
775  FAS_ASSERT(pState != NULL_PTR);
776  uint8_t i2cAddressByte = 0u;
777  uint16_t readValue = 0u;
778  uint16_t tries = 0u;
779  STD_RETURN_TYPE_e retVal = STD_OK;
781  AFE_I2C_QUEUE_s transactionData;
782 
783  if (ftsk_allQueuesCreated == true) {
784  if (OS_ReceiveFromQueue(ftsk_afeToI2cQueue, (void *)&transactionData, 0u) == OS_SUCCESS) {
785  /* Queue was not empty */
786  i2cAddressByte = (transactionData.deviceAddress << 1u) & 0xFEu; /* I2C address has only 7 bits */
787  uint8_t nack = 0u;
788  uint8_t registerIncrement = 0u;
789  uint16_t registerStartAddress = 0u;
790  uint16_t dataToWrite = 0u;
791  uint8_t byteIndex = 0u;
792  uint8_t bytesWritten = 0u;
793  uint8_t msbIndex = 1u;
794  uint8_t lsbIndex = 1u;
795 
796  switch (transactionData.transferType) {
798  transactionData.transferType = AFE_I2C_TRANSFER_TYPE_WRITE_FAIL;
799  /* First prepare data to send on I2C bus in registers */
800  i2cAddressByte |= N775_I2C_WRITE;
801  /* Set I2C device address for write access followed by first byte of data */
803  transactionData.module + 1u,
804  MC33775_I2C_DATA0_OFFSET,
805  (i2cAddressByte << MC33775_I2C_DATA0_BYTE0_POS) |
806  (transactionData.writeData[0u] << MC33775_I2C_DATA0_BYTE1_POS),
807  pState->pSpiTxSequence);
808 
809  if (transactionData.writeDataLength > 1u) {
810  /* Now set data to be written to I2C device */
811  registerStartAddress = MC33775_I2C_DATA1_OFFSET;
812  registerIncrement = 0u;
813  byteIndex = 1u;
814  dataToWrite = 0u;
815  while (byteIndex < transactionData.writeDataLength) {
816  /* Each subsequent data register contains two bytes of read data */
817 
818  if ((byteIndex % 2u) != 0u) {
819  dataToWrite |= (uint16_t)(transactionData.writeData[byteIndex]) & 0xFFu;
820  bytesWritten++;
821  } else {
822  dataToWrite |= ((uint16_t)(transactionData.writeData[byteIndex]) << 8u) & 0xFF00u;
823  bytesWritten++;
824  }
825  byteIndex++;
826  if ((bytesWritten == 2u) || (byteIndex == transactionData.writeDataLength)) {
828  transactionData.module + 1u,
829  registerStartAddress + registerIncrement,
830  dataToWrite,
831  pState->pSpiTxSequence);
832  registerIncrement++;
833  bytesWritten = 0u;
834  dataToWrite = 0u;
835  }
836  }
837  }
838  /* Data to write ready, now start transmission */
839  /* Write into the control register to start transaction */
841  transactionData.module + 1u,
842  MC33775_I2C_CTRL_OFFSET,
843  /* transactionData.writeDataLength + 1u: data + I2C device address byte */
844  ((transactionData.writeDataLength + 1u) << MC33775_I2C_CTRL_START_POS) |
845  ((MC33775_I2C_CTRL_STPAFTER_STOP_ENUM_VAL << MC33775_I2C_CTRL_STPAFTER_POS) +
846  (0u << MC33775_I2C_CTRL_RDAFTER_POS)),
847  pState->pSpiTxSequence);
848  /* Wait until transaction ends */
849  tries = N775_FLAG_READY_TRIES;
850  do {
851  returnedValue = N775_CommunicationRead(
852  transactionData.module + 1u, MC33775_I2C_STAT_OFFSET, &readValue, pState);
853  tries--;
854  N775_Wait(2u);
855  } while ((readValue & MC33775_I2C_STAT_PENDING_MSK) && (returnedValue == N775_COMMUNICATION_OK) &&
856  (tries > 0u));
857 
858  if ((returnedValue == N775_COMMUNICATION_OK) && (tries > 0u)) {
859  retVal = STD_OK;
860  transactionData.transferType = AFE_I2C_TRANSFER_TYPE_WRITE_SUCCESS;
861  }
862  if (OS_SendToBackOfQueue(ftsk_afeFromI2cQueue, (void *)&transactionData, 0u) == OS_SUCCESS) {
863  /* Queue is not full */
864  } else {
865  /* Queue is full */
866  retVal = STD_NOT_OK;
867  }
868  break;
869 
871  transactionData.transferType = AFE_I2C_TRANSFER_TYPE_READ_FAIL;
872  i2cAddressByte |= N775_I2C_READ;
873  /* First prepare address to send on I2C bus in registers */
875  transactionData.module + 1u,
876  MC33775_I2C_DATA0_OFFSET,
877  i2cAddressByte << MC33775_I2C_DATA0_BYTE0_POS,
878  pState->pSpiTxSequence);
879  /* Write into the control register to start transaction */
880  /* Stop condition after transfer, no repeated start */
882  transactionData.module + 1u,
883  MC33775_I2C_CTRL_OFFSET,
884  /* transactionData.dataLength + 1u: data + I2C device address byte */
885  ((transactionData.readDataLength + 1u) << MC33775_I2C_CTRL_START_POS) |
886  ((1u << MC33775_I2C_CTRL_STPAFTER_POS) + (0u << MC33775_I2C_CTRL_RDAFTER_POS)),
887  pState->pSpiTxSequence);
888  /* Wait until transaction ends */
889  tries = N775_FLAG_READY_TRIES;
890  do {
891  returnedValue = N775_CommunicationRead(
892  transactionData.module + 1u, MC33775_I2C_STAT_OFFSET, &readValue, pState);
893  tries--;
894  N775_Wait(2u);
895  } while ((readValue & MC33775_I2C_STAT_PENDING_MSK) && (returnedValue == N775_COMMUNICATION_OK) &&
896  (tries > 0u));
897  /* Now retrieve read data */
898  nack = readValue & MC33775_I2C_STAT_NACKRCV_MSK;
899  if ((returnedValue == N775_COMMUNICATION_OK) && (tries > 0u) && (nack == 0u)) {
900  uint16_t readData[13u] = {0u};
901  /* In data registers, bytes0 contains the address, read data begins at byte1 */
902  /* First data register contains byte1, second data register byte2 and byte3, ... */
903  uint16_t nrOfRegisterToRead = (transactionData.readDataLength / 2u) + 1u;
904  returnedValue = N775_CommunicationReadMultiple(
905  transactionData.module + 1u,
906  nrOfRegisterToRead,
907  4u,
908  MC33775_I2C_DATA0_OFFSET,
909  readData,
910  pState);
911 
912  /* First data register only contains one byte of the read data */
913  transactionData.readData[0u] = (uint8_t)((readData[0u] & 0xFF00) >> 8u);
914  byteIndex = 1u;
915  msbIndex = 1u;
916  lsbIndex = 1u;
917  while (byteIndex < transactionData.readDataLength) {
918  /* Each subsequent data register contains two bytes of read data */
919  if ((byteIndex % 2u) != 0u) {
920  transactionData.readData[byteIndex] = (uint8_t)(readData[lsbIndex] & 0xFFu);
921  lsbIndex++;
922  } else {
923  transactionData.readData[byteIndex] = (uint8_t)((readData[msbIndex] & 0xFF00u) >> 8u);
924  msbIndex++;
925  }
926  byteIndex++;
927  }
928  retVal = STD_OK;
929  transactionData.transferType = AFE_I2C_TRANSFER_TYPE_READ_SUCCESS;
930  }
931  if (OS_SendToBackOfQueue(ftsk_afeFromI2cQueue, (void *)&transactionData, 0u) == OS_SUCCESS) {
932  /* Queue is not full */
933  } else {
934  /* Queue is full */
935  retVal = STD_NOT_OK;
936  }
937  break;
938 
940  transactionData.transferType = AFE_I2C_TRANSFER_TYPE_READ_FAIL;
941  /* First prepare address to send on I2C bus in registers */
943  transactionData.module + 1u,
944  MC33775_I2C_DATA0_OFFSET,
945  ((i2cAddressByte | N775_I2C_WRITE) << MC33775_I2C_DATA0_BYTE0_POS) |
946  (transactionData.writeData[0u] << MC33775_I2C_DATA0_BYTE1_POS),
947  pState->pSpiTxSequence);
948 
949  if (transactionData.writeDataLength > 1u) {
950  /* Now set data to be written to I2C device */
951  registerStartAddress = MC33775_I2C_DATA1_OFFSET;
952  registerIncrement = 0u;
953  byteIndex = 1u;
954  dataToWrite = 0u;
955  transactionData.writeData[transactionData.writeDataLength] = i2cAddressByte | N775_I2C_READ;
956  while (byteIndex < (transactionData.writeDataLength + 1)) {
957  /* Each subsequent data register contains two bytes of read data */
958 
959  if ((byteIndex % 2u) != 0u) {
960  dataToWrite |= (uint16_t)(transactionData.writeData[byteIndex]) & 0xFFu;
961  bytesWritten++;
962  } else {
963  dataToWrite |= ((uint16_t)(transactionData.writeData[byteIndex]) << 8u) & 0xFF00u;
964  bytesWritten++;
965  }
966  byteIndex++;
967  if ((bytesWritten == 2u) || (byteIndex == (transactionData.writeDataLength + 1))) {
969  transactionData.module + 1u,
970  registerStartAddress + registerIncrement,
971  dataToWrite,
972  pState->pSpiTxSequence);
973  registerIncrement++;
974  bytesWritten = 0u;
975  dataToWrite = 0u;
976  }
977  }
978  } else {
980  transactionData.module + 1u,
981  MC33775_I2C_DATA1_OFFSET,
982  ((i2cAddressByte | N775_I2C_READ) << MC33775_I2C_DATA1_BYTE2_POS),
983  pState->pSpiTxSequence);
984  }
985 
986  /* Write into the control register to start transaction */
987  /* Stop condition after transfer, repeated start */
989  transactionData.module + 1u,
990  MC33775_I2C_CTRL_OFFSET,
991  /* transaction length: I2C device address byte for write + data to write
992  + I2C device address byte for read + data to read */
993  ((transactionData.writeDataLength + transactionData.readDataLength + 2u)
994  << MC33775_I2C_CTRL_START_POS) |
995  ((1u << MC33775_I2C_CTRL_STPAFTER_POS) +
996  ((1u + transactionData.writeDataLength) << MC33775_I2C_CTRL_RDAFTER_POS)),
997  pState->pSpiTxSequence);
998  /* Wait until transaction ends */
999  tries = N775_FLAG_READY_TRIES;
1000  do {
1001  returnedValue = N775_CommunicationRead(
1002  transactionData.module + 1u, MC33775_I2C_STAT_OFFSET, &readValue, pState);
1003  tries--;
1004  N775_Wait(2u);
1005  } while ((readValue & MC33775_I2C_STAT_PENDING_MSK) && (returnedValue == N775_COMMUNICATION_OK) &&
1006  (tries > 0u));
1007  /* Now retrieve read data */
1008  nack = readValue & MC33775_I2C_STAT_NACKRCV_MSK;
1009  if ((returnedValue == N775_COMMUNICATION_OK) && (tries > 0u) && (nack == 0u)) {
1010  uint16_t readData[13u] = {0u};
1011  /* First data to read is at least in this register */
1012  uint16_t registerOffset = MC33775_I2C_DATA0_OFFSET;
1013  /* Find offset of first register to read */
1014  registerOffset += (transactionData.writeDataLength + 2u) / 2u;
1015  /* In data registers, byte0 contains the device address, byte1 the first byte written */
1016  /* I2C device address byte for read is present before the first read byte */
1017  uint16_t nrOfRegisterToRead = 0u;
1018  if ((transactionData.writeDataLength % 2u) == 0u) {
1019  nrOfRegisterToRead = (transactionData.readDataLength + 1u) / 2u;
1020  } else {
1021  nrOfRegisterToRead = (transactionData.readDataLength / 2u) + 1u;
1022  }
1023 
1024  returnedValue = N775_CommunicationReadMultiple(
1025  transactionData.module + 1u, nrOfRegisterToRead, 4u, registerOffset, readData, pState);
1026 
1027  /* Second data register only contains one byte of the read data (byte3)
1028  Read data starts at second register because:
1029  byte0: I2C device address for write access
1030  byte1: first byte written
1031  I2C device address byte for read is present before the first read byte
1032  */
1033  if (((transactionData.writeDataLength + 1) % 2u) != 0u) {
1034  byteIndex = 0u;
1035  msbIndex = 0u;
1036  lsbIndex = 0u;
1037  while (byteIndex < transactionData.readDataLength) {
1038  /* Each subsequent data register contains two bytes of read data */
1039  if ((byteIndex % 2u) == 0u) {
1040  transactionData.readData[byteIndex] = (uint8_t)(readData[lsbIndex] & 0xFFu);
1041  lsbIndex++;
1042  } else {
1043  transactionData.readData[byteIndex] =
1044  (uint8_t)((readData[msbIndex] & 0xFF00u) >> 8u);
1045  msbIndex++;
1046  }
1047  byteIndex++;
1048  }
1049  } else {
1050  byteIndex = 0u;
1051  msbIndex = 0u;
1052  lsbIndex = 1u;
1053  while (byteIndex < transactionData.readDataLength) {
1054  /* Each subsequent data register contains two bytes of read data */
1055  if ((byteIndex % 2u) != 0u) {
1056  transactionData.readData[byteIndex] = (uint8_t)(readData[lsbIndex] & 0xFFu);
1057  lsbIndex++;
1058  } else {
1059  transactionData.readData[byteIndex] =
1060  (uint8_t)((readData[msbIndex] & 0xFF00u) >> 8u);
1061  msbIndex++;
1062  }
1063  byteIndex++;
1064  }
1065  }
1066  retVal = STD_OK;
1067  transactionData.transferType = AFE_I2C_TRANSFER_TYPE_READ_SUCCESS;
1068  }
1069  if (OS_SendToBackOfQueue(ftsk_afeFromI2cQueue, (void *)&transactionData, 0u) == OS_SUCCESS) {
1070  /* Queue is not full */
1071  } else {
1072  /* Queue is full */
1073  retVal = STD_NOT_OK;
1074  }
1075  break;
1076 
1077  default:
1078  /* Invalid value transfer type */
1080  break;
1081  }
1082  }
1083  }
1084 
1085  return retVal;
1086 }
1087 
1088 static void N775_Wait(uint32_t milliseconds) {
1089  uint32_t current_time = OS_GetTickCount();
1090  /* Block task without possibility to wake up */
1091  OS_DelayTaskUntil(&current_time, milliseconds);
1092 }
1093 
1094 /*========== Extern Function Implementations ================================*/
1095 
1096 extern STD_RETURN_TYPE_e N775_I2cRead(uint8_t module, uint8_t deviceAddress, uint8_t *pData, uint8_t dataLength) {
1097  FAS_ASSERT(pData != NULL_PTR);
1098  FAS_ASSERT((dataLength > 0u) && (dataLength <= 13u));
1099  STD_RETURN_TYPE_e retVal = STD_NOT_OK;
1100  AFE_I2C_QUEUE_s transactionData;
1101 
1102  transactionData.module = module;
1103  transactionData.deviceAddress = deviceAddress;
1104  transactionData.readDataLength = dataLength;
1105  transactionData.transferType = AFE_I2C_TRANSFER_TYPE_READ;
1106  if (OS_SendToBackOfQueue(ftsk_afeToI2cQueue, (void *)&transactionData, 0u) == OS_SUCCESS) {
1107  /* queue is not full */
1108  /* waiting for transfer to finish */
1109  if (OS_ReceiveFromQueue(ftsk_afeFromI2cQueue, (void *)&transactionData, N775_I2C_FINISHED_TIMEOUT_ms) ==
1110  OS_SUCCESS) {
1111  if (transactionData.transferType == AFE_I2C_TRANSFER_TYPE_READ_SUCCESS) {
1112  for (uint8_t i = 0u; i < dataLength; i++) {
1113  pData[i] = transactionData.readData[i];
1114  }
1115  retVal = STD_OK;
1116  }
1117  }
1118  } else {
1119  /* queue is full */
1120  }
1121 
1122  return retVal;
1123 }
1124 
1125 extern STD_RETURN_TYPE_e N775_I2cWrite(uint8_t module, uint8_t deviceAddress, uint8_t *pData, uint8_t dataLength) {
1126  FAS_ASSERT(pData != NULL_PTR);
1127  FAS_ASSERT((dataLength > 0u) && (dataLength <= 13u));
1128  STD_RETURN_TYPE_e retVal = STD_NOT_OK;
1129  AFE_I2C_QUEUE_s transactionData;
1130 
1131  transactionData.module = module;
1132  transactionData.deviceAddress = deviceAddress;
1133  transactionData.writeDataLength = dataLength;
1134  transactionData.transferType = AFE_I2C_TRANSFER_TYPE_WRITE;
1135  for (uint8_t i = 0u; i < dataLength; i++) {
1136  transactionData.writeData[i] = pData[i];
1137  }
1138  if (OS_SendToBackOfQueue(ftsk_afeToI2cQueue, (void *)&transactionData, 0u) == OS_SUCCESS) {
1139  /* queue is not full */
1140  /* waiting for transfer to finish */
1141  if (OS_ReceiveFromQueue(ftsk_afeFromI2cQueue, (void *)&transactionData, N775_I2C_FINISHED_TIMEOUT_ms) ==
1142  OS_SUCCESS) {
1143  if (transactionData.transferType == AFE_I2C_TRANSFER_TYPE_WRITE_SUCCESS) {
1144  retVal = STD_OK;
1145  }
1146  }
1147  } else {
1148  /* queue is full */
1149  }
1150 
1151  return retVal;
1152 }
1153 
1155  uint8_t module,
1156  uint8_t deviceAddress,
1157  uint8_t *pDataWrite,
1158  uint8_t writeDataLength,
1159  uint8_t *pDataRead,
1160  uint8_t readDataLength) {
1161  FAS_ASSERT(pDataWrite != NULL_PTR);
1162  FAS_ASSERT(pDataRead != NULL_PTR);
1163  FAS_ASSERT(writeDataLength > 0u);
1164  FAS_ASSERT(readDataLength > 0u);
1165  FAS_ASSERT((uint16_t)(writeDataLength + readDataLength) <= 12u);
1166  STD_RETURN_TYPE_e retVal = STD_NOT_OK;
1167  AFE_I2C_QUEUE_s transactionData;
1168 
1169  transactionData.module = module;
1170  transactionData.deviceAddress = deviceAddress;
1171  transactionData.writeDataLength = writeDataLength;
1172  transactionData.readDataLength = readDataLength;
1174  for (uint8_t i = 0u; i < writeDataLength; i++) {
1175  transactionData.writeData[i] = pDataWrite[i];
1176  }
1177  if (OS_SendToBackOfQueue(ftsk_afeToI2cQueue, (void *)&transactionData, 0u) == OS_SUCCESS) {
1178  /* queue is not full */
1179  /* waiting for transfer to finish */
1180  if (OS_ReceiveFromQueue(ftsk_afeFromI2cQueue, (void *)&transactionData, N775_I2C_FINISHED_TIMEOUT_ms) ==
1181  OS_SUCCESS) {
1182  if (transactionData.transferType == AFE_I2C_TRANSFER_TYPE_READ_SUCCESS) {
1183  for (uint8_t i = 0u; i < readDataLength; i++) {
1184  pDataRead[i] = transactionData.readData[i];
1185  }
1186  retVal = STD_OK;
1187  }
1188  }
1189  } else {
1190  /* queue is full */
1191  }
1192 
1193  return retVal;
1194 }
1195 
1197  FAS_ASSERT(pState != NULL_PTR);
1198  bool retval = false;
1199 
1201  retval = pState->firstMeasurementMade;
1203 
1204  return retval;
1205 }
1206 
1207 extern void N775_Measure(N775_STATE_s *pState) {
1208  FAS_ASSERT(pState != NULL_PTR);
1209 
1210  N775_InitializeDatabase(pState);
1211  /* Initialize SPI sequence pointers */
1214 
1215  /* Initialize each string */
1216  N775_ResetStringSequence(pState);
1217  while (pState->currentString < BS_NR_OF_STRINGS) {
1218  /* Initialize mux sequence pointers */
1220  N775_Initialize(pState);
1222  }
1223 
1224  while (1) {
1225  N775_ResetStringSequence(pState);
1226 
1227  while (pState->currentString < BS_NR_OF_STRINGS) {
1228  if (N775_USE_MUX_FOR_TEMP == true) {
1229  /* Set mux channel according to mux sequence */
1230  N775_SetMuxChannel(pState);
1231  }
1232  N775_CaptureMeasurement(pState);
1233  if (N775_USE_MUX_FOR_TEMP == true) {
1234  /* Update index in mux sequence */
1235  N775_IncrementMuxIndex(pState);
1236  }
1237  N775_BalanceControl(pState);
1238 
1239  N775_TransmitI2c(pState);
1240 
1241  for (uint8_t m = 0u; m < BS_NR_OF_MODULES_PER_STRING; m++) {
1242  if (N775_IsFirstMeasurementCycleFinished(pState) == true) {
1243  if (pState->n775Data.errorTable->noCommunicationTimeout[pState->currentString][m] == 0u) {
1244  /* Daisy-chain does not answer: initialize it again */
1246  N775_Initialize(pState);
1247  /* Daisy-chain re-initialized: no need to check further slaves */
1248  break;
1249  }
1250  }
1251  }
1252 
1254  }
1255 
1256  /* Set flag when all strings have been measured */
1257  if ((pState->currentString == BS_NR_OF_STRINGS) && (N775_IsFirstMeasurementCycleFinished(pState) == 0u)) {
1259  }
1260  }
1261 }
1262 
1263 /*========== Externalized Static Function Implementations (Unit Test) =======*/
1264 #ifdef UNITY_UNIT_TEST
1265 extern void TEST_N775_BalanceControl(N775_STATE_s *pState) {
1266  N775_BalanceControl(pState);
1267 }
1268 extern void TEST_N775_BalanceSetup(N775_STATE_s *pState) {
1269  N775_BalanceSetup(pState);
1270 }
1271 extern void TEST_N775_CaptureMeasurement(N775_STATE_s *pState) {
1272  N775_CaptureMeasurement(pState);
1273 }
1274 extern STD_RETURN_TYPE_e TEST_N775_Enumerate(N775_STATE_s *pState) {
1275  return N775_Enumerate(pState);
1276 }
1277 extern void TEST_N775_ErrorHandling(N775_STATE_s *pState, N775_COMMUNICATION_STATUS_e returnedValue, uint8_t module) {
1278  N775_ErrorHandling(pState, returnedValue, module);
1279 }
1280 extern void TEST_N775_IncrementMuxIndex(N775_STATE_s *pState) {
1281  N775_IncrementMuxIndex(pState);
1282 }
1283 extern void TEST_N775_IncrementStringSequence(N775_STATE_s *pState) {
1285 }
1286 extern void TEST_N775_Initialize(N775_STATE_s *pState) {
1287  N775_Initialize(pState);
1288 }
1289 extern void TEST_N775_InitializeDatabase(N775_STATE_s *pState) {
1290  N775_InitializeDatabase(pState);
1291 }
1292 extern void TEST_N775_InitializeI2c(N775_STATE_s *pState) {
1293  N775_InitializeI2c(pState);
1294 }
1295 extern void TEST_N775_ResetStringSequence(N775_STATE_s *pState) {
1296  N775_ResetStringSequence(pState);
1297 }
1298 extern void TEST_N775_ResetMuxIndex(N775_STATE_s *pState) {
1299  N775_ResetMuxIndex(pState);
1300 }
1301 extern void TEST_N775_SetFirstMeasurementCycleFinished(N775_STATE_s *pState) {
1303 }
1304 extern STD_RETURN_TYPE_e TEST_N775_SetMuxChannel(N775_STATE_s *pState) {
1305  return N775_SetMuxChannel(pState);
1306 }
1307 extern void TEST_N775_StartMeasurement(N775_STATE_s *pState) {
1308  N775_StartMeasurement(pState);
1309 }
1310 extern STD_RETURN_TYPE_e TEST_N775_TransmitI2c(N775_STATE_s *pState) {
1311  return N775_TransmitI2c(pState);
1312 }
1313 extern void TEST_N775_Wait(uint32_t milliseconds) {
1314  N775_Wait(milliseconds);
1315 }
1316 #endif
AFE driver header.
@ AFE_I2C_TRANSFER_TYPE_WRITE
Definition: afe.h:82
@ AFE_I2C_TRANSFER_TYPE_WRITEREAD
Definition: afe.h:79
@ AFE_I2C_TRANSFER_TYPE_READ_SUCCESS
Definition: afe.h:80
@ AFE_I2C_TRANSFER_TYPE_WRITE_FAIL
Definition: afe.h:84
@ AFE_I2C_TRANSFER_TYPE_READ
Definition: afe.h:78
@ AFE_I2C_TRANSFER_TYPE_WRITE_SUCCESS
Definition: afe.h:83
@ AFE_I2C_TRANSFER_TYPE_READ_FAIL
Definition: afe.h:81
Headers for the driver for the general DMA module of monitoring ICs.
#define BS_NR_OF_CELL_BLOCKS_PER_MODULE
number of cells per module
#define BS_NR_OF_STRINGS
Number of parallel strings in the battery pack.
#define BS_NR_OF_TEMP_SENSORS_PER_MODULE
number of temperature sensors per battery module
#define BS_NR_OF_GPIOS_PER_MODULE
Defines the number of GPIOs.
#define BS_NR_OF_CELL_BLOCKS_PER_STRING
#define BS_NR_OF_MODULES_PER_STRING
number of modules in a string
Database module header.
#define DATA_READ_DATA(...)
Definition: database.h:86
#define DATA_WRITE_DATA(...)
Definition: database.h:96
@ DATA_BLOCK_ID_BALANCING_CONTROL
Definition: database_cfg.h:83
@ DATA_BLOCK_ID_MIN_MAX
Definition: database_cfg.h:99
@ DATA_BLOCK_ID_CELL_TEMPERATURE_BASE
Definition: database_cfg.h:87
@ DATA_BLOCK_ID_OPEN_WIRE_BASE
Definition: database_cfg.h:103
@ DATA_BLOCK_ID_SLAVE_CONTROL
Definition: database_cfg.h:107
@ DATA_BLOCK_ID_CELL_VOLTAGE_BASE
Definition: database_cfg.h:90
@ DATA_BLOCK_ID_ALL_GPIO_VOLTAGES_BASE
Definition: database_cfg.h:81
@ DATA_BLOCK_ID_BALANCING_FEEDBACK_BASE
Definition: database_cfg.h:84
Assert macro implementation.
#define FAS_ASSERT(x)
Assertion macro that asserts that x is true.
Definition: fassert.h:255
#define FAS_TRAP
Define that evaluates to essential boolean false thus tripping an assert.
Definition: fassert.h:129
Definition of foxBMS standard types.
STD_RETURN_TYPE_e
Definition: fstd_types.h:82
@ STD_NOT_OK
Definition: fstd_types.h:84
@ STD_OK
Definition: fstd_types.h:83
#define NULL_PTR
Null pointer.
Definition: fstd_types.h:77
Header of task driver implementation.
OS_QUEUE ftsk_afeFromI2cQueue
volatile bool ftsk_allQueuesCreated
OS_QUEUE ftsk_afeToI2cQueue
Headers for the driver for the MCU module.
N775_COMMUNICATION_STATUS_e N775_CommunicationRead(uint16_t deviceAddress, uint16_t registerAddress, uint16_t *pValue, N775_STATE_s *pState)
Read a value from a specific register in a specific device.
N775_COMMUNICATION_STATUS_e N775_CommunicationReadMultiple(uint16_t deviceAddress, uint16_t numberOfItems, uint16_t responseLength, uint16_t registerAddress, uint16_t *pValues, N775_STATE_s *pState)
Read multiple values from specific registers in a specific device.
void N775_ResetMessageCounter(uint16_t deviceAddress, uint8_t string)
Reset the message counter for one or all devices.
void N775_CommunicationWrite(uint16_t deviceAddress, uint16_t registerAddress, uint16_t value, SPI_INTERFACE_CONFIG_s *pSpiInterface)
Write a value into a specific register in a specific device.
Header for the low level driver for the MC33775A.
enum N775_COMMUNICATION_STATUS N775_COMMUNICATION_STATUS_e
@ N775_COMMUNICATION_OK
@ N775_COMMUNICATION_ERROR_WRONG_CRC
@ N775_COMMUNICATION_ERROR_TIMEOUT
static DATA_BLOCK_SLAVE_CONTROL_s n775_slaveControl
Definition: nxp_mc33775a.c:92
STD_RETURN_TYPE_e N775_I2cWriteRead(uint8_t module, uint8_t deviceAddress, uint8_t *pDataWrite, uint8_t writeDataLength, uint8_t *pDataRead, uint8_t readDataLength)
trigger a read on the I2C bus of the slave, first write address of register to read.
bool N775_IsFirstMeasurementCycleFinished(N775_STATE_s *pState)
gets the measurement initialization status.
static void N775_StartMeasurement(N775_STATE_s *pState)
starts the measurement.
Definition: nxp_mc33775a.c:755
static N775_ERROR_TABLE_s n775_errorTable
Definition: nxp_mc33775a.c:96
static STD_RETURN_TYPE_e N775_TransmitI2c(N775_STATE_s *pState)
transmit over I2C on NXP slave.
Definition: nxp_mc33775a.c:774
N775_STATE_s n775_stateBase
Definition: nxp_mc33775a.c:100
static DATA_BLOCK_ALL_GPIO_VOLTAGES_s n775_allGpioVoltage
Definition: nxp_mc33775a.c:89
static void N775_SetFirstMeasurementCycleFinished(N775_STATE_s *pState)
sets the measurement initialization status.
Definition: nxp_mc33775a.c:647
static DATA_BLOCK_MIN_MAX_s n775_minMax
Definition: nxp_mc33775a.c:87
static void N775_ResetStringSequence(N775_STATE_s *pState)
reset index in string sequence.
Definition: nxp_mc33775a.c:632
static DATA_BLOCK_CELL_TEMPERATURE_s n775_cellTemperature
Definition: nxp_mc33775a.c:86
static void N775_InitializeDatabase(N775_STATE_s *pState)
in the database, initializes the fields related to the N775 driver.
Definition: nxp_mc33775a.c:565
static void N775_ResetMuxIndex(N775_STATE_s *pState)
resets index in mux sequence.
Definition: nxp_mc33775a.c:640
static DATA_BLOCK_CELL_VOLTAGE_s n775_cellVoltage
Definition: nxp_mc33775a.c:85
static void N775_BalanceSetup(N775_STATE_s *pState)
setups balancing.
Definition: nxp_mc33775a.c:274
static void N775_IncrementStringSequence(N775_STATE_s *pState)
increments index in string sequence.
Definition: nxp_mc33775a.c:543
static void N775_CaptureMeasurement(N775_STATE_s *pState)
captures the measurement.
Definition: nxp_mc33775a.c:302
void N775_Measure(N775_STATE_s *pState)
trigger function for the N775 driver state machine.
static void N775_IncrementMuxIndex(N775_STATE_s *pState)
updates index in mux sequence.
Definition: nxp_mc33775a.c:532
static DATA_BLOCK_BALANCING_CONTROL_s n775_balancingControl
Definition: nxp_mc33775a.c:88
static DATA_BLOCK_OPEN_WIRE_s n775_openWire
Definition: nxp_mc33775a.c:93
static void N775_ErrorHandling(N775_STATE_s *pState, N775_COMMUNICATION_STATUS_e returnedValue, uint8_t module)
handles error when doing measurements.
Definition: nxp_mc33775a.c:509
static N775_SUPPLY_CURRENT_s n775_supplyCurrent
Definition: nxp_mc33775a.c:95
STD_RETURN_TYPE_e N775_I2cRead(uint8_t module, uint8_t deviceAddress, uint8_t *pData, uint8_t dataLength)
trigger a read on the I2C bus of the slave.
static void N775_Wait(uint32_t milliseconds)
waits for a definite amount of time in ms.
static void N775_InitializeI2c(N775_STATE_s *pState)
init I2C for the N775 slaves.
Definition: nxp_mc33775a.c:620
static STD_RETURN_TYPE_e N775_Enumerate(N775_STATE_s *pState)
enumerates the N775 slaves.
Definition: nxp_mc33775a.c:440
static void N775_BalanceControl(N775_STATE_s *pState)
manages balancing.
Definition: nxp_mc33775a.c:251
STD_RETURN_TYPE_e N775_I2cWrite(uint8_t module, uint8_t deviceAddress, uint8_t *pData, uint8_t dataLength)
trigger a write on the I2C bus of the slave.
static STD_RETURN_TYPE_e N775_SetMuxChannel(N775_STATE_s *pState)
sets mux channel.
Definition: nxp_mc33775a.c:655
static void N775_Initialize(N775_STATE_s *pState)
initializes the N775 driver.
Definition: nxp_mc33775a.c:551
static DATA_BLOCK_BALANCING_FEEDBACK_s n775_balancingFeedback
Definition: nxp_mc33775a.c:90
Headers for the driver for the MC33775A analog front-end.
N775_MUX_CH_CFG_s n775_muxSequence[N775_MUX_SEQUENCE_LENGTH]
int16_t N775_ConvertVoltagesToTemperatures(uint16_t adcVoltage_mV)
converts a raw voltage from multiplexer to a temperature value in deci °C.
#define N775_I2C_NR_BYTES_FOR_MUX_WRITE
#define N775_I2C_NR_BYTES_TO_SWITCH_TO_READ_FOR_UX_READ
#define N775_MEASUREMENT_CAPTURE_TIME_MS
#define N775_INVALID_REGISTER_VALUE
#define N775_I2C_DUMMY_BYTE
#define N775_CHECK_SUPPLY_CURRENT
#define N775_TIMEOUT_SWITCH
#define N775_TIMEOUT_TO_SLEEP_10MS
#define N775_CHECK_MUX_STATE
#define N775_DEFAULT_CHAIN_ADDRESS
#define N775_I2C_READ
#define N775_MUXED_TEMP_GPIO_POSITION
#define N775_MEASUREMENT_READY_TIME_MS
#define N775_MUX_SEQUENCE_LENGTH
#define N775_I2C_WRITE
#define N775_I2C_FINISHED_TIMEOUT_ms
#define N775_ADG728_ADDRESS_UPPERBITS
#define N775_BROADCAST_ADDRESS
#define N775_USE_MUX_FOR_TEMP
#define N775_PRE_BALANCING_TIMER
#define N775_BALPAUSELEN_10US
#define N775_GLOBAL_BALANCING_TIMER
#define N775_WAKEUP_TIME_MS
#define N775_TIME_AFTER_MEASUREMENT_START_MS
#define N775_ALL_CHANNEL_BALANCING_TIMER
#define N775_FLAG_READY_TRIES
Declaration of the OS wrapper interface.
@ OS_SUCCESS
Definition: os.h:86
OS_STD_RETURN_e OS_ReceiveFromQueue(OS_QUEUE xQueue, void *const pvBuffer, uint32_t ticksToWait)
Receive an item from a queue.
Definition: os_freertos.c:264
void OS_DelayTaskUntil(uint32_t *pPreviousWakeTime, uint32_t milliseconds)
Delay a task until a specified time.
Definition: os_freertos.c:162
void OS_ExitTaskCritical(void)
Exit Critical interface function for use in FreeRTOS-Tasks and FreeRTOS-ISR.
Definition: os_freertos.c:154
void OS_EnterTaskCritical(void)
Enter Critical interface function for use in FreeRTOS-Tasks and FreeRTOS-ISR.
Definition: os_freertos.c:150
OS_STD_RETURN_e OS_SendToBackOfQueue(OS_QUEUE xQueue, const void *const pvItemToQueue, uint32_t ticksToWait)
Post an item to the back the provided queue.
Definition: os_freertos.c:277
uint32_t OS_GetTickCount(void)
Returns OS based system tick value.
Definition: os_freertos.c:158
Headers for the driver for the SPI module.
SPI_INTERFACE_CONFIG_s spi_nxp775InterfaceTx[BS_NR_OF_STRINGS]
Definition: spi_cfg.c:215
SPI_INTERFACE_CONFIG_s spi_nxp775InterfaceRx[BS_NR_OF_STRINGS]
Definition: spi_cfg.c:226
uint8_t module
Definition: afe.h:89
uint8_t writeData[13u]
Definition: afe.h:95
AFE_I2C_TRANSFER_TYPE_e transferType
Definition: afe.h:90
uint8_t deviceAddress
Definition: afe.h:91
uint8_t readDataLength
Definition: afe.h:94
uint8_t writeDataLength
Definition: afe.h:96
int16_t gpioVoltages_mV[BS_NR_OF_STRINGS][BS_NR_OF_MODULES_PER_STRING *BS_NR_OF_GPIOS_PER_MODULE]
Definition: database_cfg.h:325
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:323
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:255
uint8_t balancingState[BS_NR_OF_STRINGS][BS_NR_OF_CELL_BLOCKS_PER_STRING]
Definition: database_cfg.h:260
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:290
int16_t cellTemperature_ddegC[BS_NR_OF_STRINGS][BS_NR_OF_MODULES_PER_STRING][BS_NR_OF_TEMP_SENSORS_PER_MODULE]
Definition: database_cfg.h:156
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:153
int16_t cellVoltage_mV[BS_NR_OF_STRINGS][BS_NR_OF_MODULES_PER_STRING][BS_NR_OF_CELL_BLOCKS_PER_MODULE]
Definition: database_cfg.h:139
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:135
uint32_t moduleVoltage_mV[BS_NR_OF_STRINGS][BS_NR_OF_MODULES_PER_STRING]
Definition: database_cfg.h:144
DATA_BLOCK_ID_e uniqueId
Definition: database_cfg.h:125
int16_t minimumTemperature_ddegC[BS_NR_OF_STRINGS]
Definition: database_cfg.h:180
uint16_t nrSensorMinimumTemperature[BS_NR_OF_STRINGS]
Definition: database_cfg.h:182
uint16_t nrModuleMinimumTemperature[BS_NR_OF_STRINGS]
Definition: database_cfg.h:181
uint16_t nrModuleMaximumTemperature[BS_NR_OF_STRINGS]
Definition: database_cfg.h:184
int16_t maximumTemperature_ddegC[BS_NR_OF_STRINGS]
Definition: database_cfg.h:183
uint16_t nrSensorMaximumTemperature[BS_NR_OF_STRINGS]
Definition: database_cfg.h:185
uint16_t nrCellMaximumCellVoltage[BS_NR_OF_STRINGS]
Definition: database_cfg.h:177
uint16_t nrCellMinimumCellVoltage[BS_NR_OF_STRINGS]
Definition: database_cfg.h:175
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:167
uint16_t nrModuleMinimumCellVoltage[BS_NR_OF_STRINGS]
Definition: database_cfg.h:174
uint16_t nrModuleMaximumCellVoltage[BS_NR_OF_STRINGS]
Definition: database_cfg.h:176
int16_t maximumCellVoltage_mV[BS_NR_OF_STRINGS]
Definition: database_cfg.h:172
int16_t minimumCellVoltage_mV[BS_NR_OF_STRINGS]
Definition: database_cfg.h:170
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:310
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:271
DATA_BLOCK_BALANCING_CONTROL_s * balancingControl
uint64_t uid[BS_NR_OF_STRINGS][BS_NR_OF_MODULES_PER_STRING]
N775_ERROR_TABLE_s * errorTable
DATA_BLOCK_CELL_TEMPERATURE_s * cellTemperature
DATA_BLOCK_ALL_GPIO_VOLTAGES_s * allGpioVoltage
N775_SUPPLY_CURRENT_s * supplyCurrent
DATA_BLOCK_MIN_MAX_s * minMax
DATA_BLOCK_CELL_VOLTAGE_s * cellVoltage
bool mux1IsOK[BS_NR_OF_STRINGS][BS_NR_OF_MODULES_PER_STRING]
bool crcIsValid[BS_NR_OF_STRINGS][BS_NR_OF_MODULES_PER_STRING]
bool mux0IsOk[BS_NR_OF_STRINGS][BS_NR_OF_MODULES_PER_STRING]
bool communicationOk[BS_NR_OF_STRINGS][BS_NR_OF_MODULES_PER_STRING]
bool noCommunicationTimeout[BS_NR_OF_STRINGS][BS_NR_OF_MODULES_PER_STRING]
bool mux2IsOK[BS_NR_OF_STRINGS][BS_NR_OF_MODULES_PER_STRING]
bool mux3IsOK[BS_NR_OF_STRINGS][BS_NR_OF_MODULES_PER_STRING]
SPI_INTERFACE_CONFIG_s * pSpiRxSequenceStart
SPI_INTERFACE_CONFIG_s * pSpiTxSequenceStart
N775_MUX_CH_CFG_s * pMuxSequence[BS_NR_OF_STRINGS]
SPI_INTERFACE_CONFIG_s * pSpiTxSequence
SPI_INTERFACE_CONFIG_s * pSpiRxSequence
N775_DATAPTR_s n775Data
uint8_t currentMux[BS_NR_OF_STRINGS]
N775_MUX_CH_CFG_s * pMuxSequenceStart[BS_NR_OF_STRINGS]
uint16_t current[BS_NR_OF_STRINGS][BS_NR_OF_MODULES_PER_STRING]