foxBMS  1.1.1
The foxBMS Battery Management System API Documentation
mxm_17841b.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_17841b.c
44  * @author foxBMS Team
45  * @date 2018-12-14 (date of creation)
46  * @updated 2021-06-16 (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 def
53  *
54  */
55 
56 /*========== Includes =======================================================*/
57 #include "mxm_17841b.h"
58 
59 #include "mxm_41b_register_map.h"
60 #include "mxm_bitextract.h"
61 
62 /*========== Macros and Definitions =========================================*/
63 
64 /*========== Static Constant and Variable Definitions =======================*/
65 /**
66  * @brief Default values for the configuration and interrupt registers
67  * @details This constant array contains the default values to which the
68  * configuration is compared when resetting it.
69  * The array is 7 entries long in order to fit onto the following
70  * registers which are placed in succession in the memory of
71  * MAX17841B:
72  * - RX_Interrupt_Enable
73  * - TX_Interrupt_Enable
74  * - RX_Interrupt_Flags
75  * - TX_Interrupt_Flags
76  * - Configuration_1
77  * - Configuration_2
78  * - Configuration_3
79  */
80 static const uint8_t mxm_41B_reg_default_values[7] = {0, 0, 0, 0x80, 0x60, 0x10, 0x0F};
81 
82 /*========== Extern Constant and Variable Definitions =======================*/
86 
87 /*========== Static Function Prototypes =====================================*/
88 /* static MXM_SPI_STATE_s mxm_proto_enable_keep_alive(void); */
89 /**
90  * @brief Write one or multiple registers of MAX17841B.
91  *
92  * This function puts together a SPI message consisting of command
93  * and payload and writes it to the assigned SPI interface.
94  *
95  * The command should be one of the #MXM_41B_REG_ADD_t commands.
96  * The function checks whether the chosen command is a write command.
97  *
98  * The payload-length has to be consistent with the payload.
99  * Payload-lengths of one will write to one register only. Longer payloads
100  * will write to adjacent registers. Please see the MAX17841B-datasheet
101  * for reference.
102  *
103  * @param[in,out] pInstance pointer to the state of the MAX17841B-state-machine
104  * @param[in] command register command of #MXM_41B_REG_ADD_t
105  * @param[in] kpkPayload pointer to an array of data to be written
106  * @param[in] lengthPayload length of the payload array
107  * @return #STD_NOT_OK for inconsistent input or a blocked SPI interface,
108  * otherwise #STD_OK
109  */
111  MXM_41B_INSTANCE_s *pInstance,
112  MXM_41B_REG_ADD_t command,
113  const uint8_t *const kpkPayload,
114  uint16_t lengthPayload);
115 
116 /**
117  * @brief Read one or multiple registers of MAX17841B.
118  *
119  * This function puts together a SPI message consisting of command
120  * and bit-stuffing and writes it to the assigned SPI-interface.
121  *
122  * The command should be one of the #MXM_41B_REG_ADD_t commands.
123  * The function checks whether the chosen command is a read command.
124  *
125  * The RX buffer length has to be consistent with the RX buffer.
126  * RX buffer lengths of one will read one register only. Longer RX buffers
127  * will read also from adjacent registers. Please see the MAX17841B-datasheet
128  * for reference.
129  *
130  * @param[in,out] pInstance pointer to the state of the MAX17841B-state-machine
131  * @param[in] command register command of #MXM_41B_REG_ADD_t
132  * @param[out] pRxBuffer pointer to an array into which read data will be written
133  * @param[in] length length of the RX buffer array
134  * @return #STD_NOT_OK for inconsistent input or a blocked SPI interface,
135  * otherwise #STD_OK
136  */
138  MXM_41B_INSTANCE_s *pInstance,
139  MXM_41B_REG_ADD_t command,
140  uint16_t *pRxBuffer,
141  uint16_t length);
142 
143 /**
144  * @brief Write the config register of MAX17841B.
145  *
146  * This functions writes the config registers with the values
147  * from the local register copies. It puts together a
148  * buffer from these register values and calls MXM_41BRegisterWrite()
149  * with this data.
150  *
151  * @param[in,out] pInstance state pointer
152  * @return returnvalue of MXM_41BRegisterWrite()
153  */
155 
156 /**
157  * @brief Write a buffer transaction to MAX17841B.
158  *
159  * Writes into the load-queue-buffer.
160  * The supplied-message-length marks the length of the Battery Management
161  * Protocol message without any stuffing-bytes for read-commands.
162  * The extend_message parameter describes with how much bytes the
163  * command shall be stretched. This number will be added to the
164  * length of the command and written into the length field of the
165  * buffer.
166  * After this action the user has to select the next load queue with
167  * the appropriate command in order to mark the load queue as sendable.
168  *
169  * @param[in,out] pInstance pointer to the state of the MAX17841B-state-machine
170  * @param[in] kpkMessage pointer to an array containing the message
171  * @param[in] message_length length of the supplied array
172  * @param[in] extend_message stretch the message by number of bytes
173  * @return #STD_NOT_OK for inconsistent input or a blocked SPI interface,
174  * otherwise #STD_OK
175  */
177  MXM_41B_INSTANCE_s *pInstance,
178  const uint16_t *const kpkMessage,
179  uint16_t message_length,
180  uint8_t extend_message);
181 
182 /*========== Static Function Implementations ================================*/
184  MXM_41B_INSTANCE_s *pInstance,
185  MXM_41B_REG_ADD_t command,
186  const uint8_t *const kpkPayload,
187  uint16_t lengthPayload) {
188  /* sanity check: state-pointer may not be null */
189  FAS_ASSERT(pInstance != NULL_PTR);
190  STD_RETURN_TYPE_e retval = STD_NOT_OK;
191  /* check if command is a write command (write addresses in MAX17841B are even) */
192  if ((command % 2u) == 0u) {
193  /* construct tx buffer */
194  pInstance->spiTXBuffer[0] = command;
195  /* message has payload --> copy into buffer */
196  if (kpkPayload != NULL_PTR) {
197  for (uint16_t i = 0u; i < lengthPayload; i++) {
198  pInstance->spiTXBuffer[i + 1u] = kpkPayload[i];
199  }
200  /* null rest of tx buffer */
201  for (uint16_t i = lengthPayload + 1u; i < MXM_SPI_TX_BUFFER_LENGTH; i++) {
202  pInstance->spiTXBuffer[i] = 0u;
203  }
204  /* send command with payload */
205  retval = MXM_SendData(pInstance->spiTXBuffer, lengthPayload + 1u);
206  } else {
207  /* check if lengthPayload is consistent (should be 0) */
208  if (lengthPayload != 0u) {
209  retval = STD_NOT_OK;
210  } else {
211  /* send command without payload */
212  retval = MXM_SendData(pInstance->spiTXBuffer, 1);
213  }
214  }
215  }
216  return retval;
217 }
218 
220  MXM_41B_INSTANCE_s *pInstance,
221  MXM_41B_REG_ADD_t command,
222  uint16_t *pRxBuffer,
223  uint16_t length) {
224  /* sanity check: state-pointer may not be null */
225  FAS_ASSERT(pInstance != NULL_PTR);
226  /* RX Buffer may not be NULL pointer for this function */
227  FAS_ASSERT(pRxBuffer != NULL_PTR);
228 
229  STD_RETURN_TYPE_e retval = STD_NOT_OK;
230  /* check if command is a read command (read addresses in MAX17841B are odd) */
231  if ((command % 2u) != 0u) {
232  /* construct tx buffer */
233  pInstance->spiTXBuffer[0] = command;
234  /* null rest of tx buffer */
235  for (uint16_t i = 1u; i < MXM_SPI_TX_BUFFER_LENGTH; i++) {
236  pInstance->spiTXBuffer[i] = 0u;
237  }
238  /* send command with payload */
239  retval = MXM_ReceiveData(pInstance->spiTXBuffer, pRxBuffer, length + 1u);
240  }
241  return retval;
242 }
243 
245  /* sanity check: state-pointer may not be null */
246  FAS_ASSERT(pInstance != NULL_PTR);
247  uint8_t mxm_spi_temp_buffer[10] = {0};
248  /* TODO refactor so that int flags are not cleared by this function (because otherwise we would have to read them before every write) */
249  mxm_spi_temp_buffer[0] = pInstance->regRXIntEnable;
250  mxm_spi_temp_buffer[1] = pInstance->regTXIntEnable;
251  mxm_spi_temp_buffer[2] = 0x00; /* TODO add reg_*x_int_flag */
252  mxm_spi_temp_buffer[3] = 0x80;
253  mxm_spi_temp_buffer[4] = pInstance->regConfig1;
254  mxm_spi_temp_buffer[5] = pInstance->regConfig2;
255  mxm_spi_temp_buffer[6] = pInstance->regConfig3;
256 
257  return MXM_41BRegisterWrite(pInstance, MXM_REG_RX_INTERRUPT_ENABLE_W, mxm_spi_temp_buffer, 7);
258 }
259 
261  MXM_41B_INSTANCE_s *pInstance,
262  const uint16_t *const kpkMessage,
263  uint16_t message_length,
264  uint8_t extend_message) {
265  /* sanity check: state-pointer may not be null */
266  FAS_ASSERT(pInstance != NULL_PTR);
267  /* check if message-pointer is valid */
268  FAS_ASSERT(kpkMessage != NULL_PTR);
269  FAS_ASSERT(message_length >= 1u);
270  FAS_ASSERT(message_length <= 6u);
271 
272  /* write address and length to buffer */
273  pInstance->spiTXBuffer[0] = (uint16_t)MXM_BUF_WR_LD_Q_0;
274  pInstance->spiTXBuffer[1] = message_length + extend_message;
275  /* iterate of complete TX buffer and
276  * write into proper fields, null rest
277  */
278  for (uint8_t i = 0; i < (MXM_SPI_TX_BUFFER_LENGTH - 2u); i++) {
279  if (i < message_length) {
280  pInstance->spiTXBuffer[i + 2u] = kpkMessage[i];
281  } else {
282  pInstance->spiTXBuffer[i + 2u] = 0x00u;
283  }
284  }
285 
286  /* send data */
287  return MXM_SendData(pInstance->spiTXBuffer, (message_length + 2u));
288 }
289 
290 /*========== Extern Function Implementations ================================*/
292  MXM_41B_INSTANCE_s *pInstance,
293  MXM_STATEMACH_41B_e state,
294  uint16_t *pPayload,
295  uint16_t payloadLength,
296  uint8_t extendMessageBytes,
297  uint16_t *pRxBuffer,
298  uint16_t rxBufferLength,
299  MXM_41B_STATE_REQUEST_STATUS_e *processed) {
300  /* sanity check: state-pointer may not be null */
301  FAS_ASSERT(pInstance != NULL_PTR);
302 
303  STD_RETURN_TYPE_e retval = STD_OK;
304  /* start by checking for input inconsistency */
305  if (state >= MXM_STATEMACH_41B_MAXSTATE) {
306  retval = STD_NOT_OK;
307  } else if ((pPayload == NULL_PTR) && (payloadLength != 0u)) {
308  retval = STD_NOT_OK;
309  } else if ((payloadLength == 0u) && (pPayload != NULL_PTR)) {
310  retval = STD_NOT_OK;
311  } else if ((pRxBuffer == NULL_PTR) && (rxBufferLength != 0u)) {
312  retval = STD_NOT_OK;
313  } else if ((rxBufferLength == 0u) && (pRxBuffer != NULL_PTR)) {
314  retval = STD_NOT_OK;
315  } else if (processed == NULL_PTR) {
316  retval = STD_NOT_OK;
317  } else if (pInstance->state == MXM_STATEMACH_41B_UNINITIALIZED) {
318  if (state == MXM_STATEMACH_41B_INIT) {
319  pInstance->state = state;
320  pInstance->substate = MXM_41B_ENTRY_SUBSTATE;
321  pInstance->pPayload = pPayload;
322  pInstance->payloadLength = payloadLength;
323  pInstance->extendMessageBytes = extendMessageBytes;
324  pInstance->pRxBuffer = pRxBuffer;
325  pInstance->rxBufferLength = rxBufferLength;
326  pInstance->processed = processed;
327  *pInstance->processed = MXM_41B_STATE_UNPROCESSED;
328  } else {
329  retval = STD_NOT_OK;
330  }
331  } else if (pInstance->state == MXM_STATEMACH_41B_IDLE) {
332  pInstance->state = state;
333  pInstance->substate = MXM_41B_ENTRY_SUBSTATE;
334  pInstance->pPayload = pPayload;
335  pInstance->payloadLength = payloadLength;
336  pInstance->extendMessageBytes = extendMessageBytes;
337  pInstance->pRxBuffer = pRxBuffer;
338  pInstance->rxBufferLength = rxBufferLength;
339  pInstance->processed = processed;
340  *pInstance->processed = MXM_41B_STATE_UNPROCESSED;
341  } else {
342  retval = STD_NOT_OK;
343  }
344  return retval;
345 }
346 
348  MXM_41B_INSTANCE_s *pInstance,
349  MXM_41B_REG_FUNCTION_e registerFunction,
350  MXM_41B_REG_BIT_VALUE value) {
351  /* sanity check: state-pointer may not be null */
352  FAS_ASSERT(pInstance != NULL_PTR);
353 
354  STD_RETURN_TYPE_e retval = STD_OK;
355  /* TODO sanitize value */
356 
357  switch (registerFunction) {
359  pInstance->regConfig2 = mxm_41bWriteValue(
360  value,
361  1,
363  pInstance->regConfig2); /* MXM_41B_TX_PREAMBLES is 5th bit of regConfig2 */
364  break;
366  pInstance->regConfig3 = mxm_41bWriteValue(
367  value, 4, MXM_41B_KEEP_ALIVE, pInstance->regConfig3); /* MXM_41B_KEEP_ALIVE is 0st bit of regConfig3 */
368  break;
370  pInstance->regRXIntEnable = mxm_41bWriteValue(
371  value,
372  1,
374  pInstance->regRXIntEnable); /* MXM_41B_RX_ERROR is 7th bit of regRXIntEnable */
375  break;
377  pInstance->regRXIntEnable = mxm_41bWriteValue(
378  value,
379  1,
381  pInstance->regRXIntEnable); /* MXM_41B_RX_OVERFLOW is 2nd bit of regRXIntEnable */
382  break;
383  default:
384  retval = STD_NOT_OK;
385  break;
386  }
387 
388  return retval;
389 }
390 
392  const MXM_41B_INSTANCE_s *const kpkInstance,
393  MXM_41B_REG_FUNCTION_e registerFunction,
394  MXM_41B_REG_BIT_VALUE *pValue) {
395  /* sanity check: state-pointer may not be null */
396  FAS_ASSERT(kpkInstance != NULL_PTR);
397  /* sanity check: pValue may not be null */
398  FAS_ASSERT(pValue != NULL_PTR);
399  STD_RETURN_TYPE_e retval = STD_OK;
400 
401  switch (registerFunction) {
403  *pValue = mxm_41bReadValue(kpkInstance->regRXStatus, 1, MXM_41B_RX_BUSY_STATUS); /* 5th bit */
404  break;
406  *pValue = mxm_41bReadValue(kpkInstance->regRXStatus, 1, MXM_41B_RX_STOP_STATUS); /* 1st bit */
407  break;
409  *pValue = mxm_41bReadValue(kpkInstance->regRXStatus, 1, MXM_41B_RX_EMPTY_STATUS); /* 0th bit */
410  break;
412  *pValue = mxm_41bReadValue(kpkInstance->regConfig2, 1, MXM_41B_TX_PREAMBLES); /* 5th bit */
413  break;
414  default:
415  *pValue = MXM_41B_REG_FALSE;
416  retval = STD_NOT_OK;
417  break;
418  }
419 
420  return retval;
421 }
422 
423 /* not used currently
424  * extern uint8_t mxm_41b_get_alive_counter(void) {
425  * return pInstance->aliveCounter;
426  * }
427  */
428 
430  /* sanity check: state-pointer may not be null */
431  FAS_ASSERT(pInstance != NULL_PTR);
432 
433  if (pInstance->waitCounter > 200u) {
434  /* error, reset to idle state */
435  pInstance->state = MXM_STATEMACH_41B_IDLE;
436  pInstance->substate = MXM_41B_ENTRY_SUBSTATE;
437  pInstance->waitCounter = 0u;
438  *pInstance->processed = MXM_41B_STATE_ERROR;
439  }
440  STD_RETURN_TYPE_e retval;
441  switch (pInstance->state) {
443 
444  break;
446  if (pInstance->substate == MXM_41B_ENTRY_SUBSTATE) {
447  /* entry of state --> set to first substate */
449  }
450 
451  if (pInstance->substate == MXM_41B_INIT_WRITE_DEFAULT_VALUES) {
452  /* set default register values according to datasheet */
453  /* TODO reset register variables to default values */
454  retval = MXM_41BConfigRegisterWrite(pInstance);
455  if (retval == STD_OK) {
457  }
458  } else if (pInstance->substate == MXM_41B_INIT_READ_CONFIG_REGISTERS) {
459  retval = MXM_41BRegisterRead(pInstance, MXM_REG_RX_INTERRUPT_ENABLE_R, pInstance->spiRXBuffer, 7);
460 
461  if (retval == STD_OK) {
463  }
464  } else if (pInstance->substate == MXM_41B_INIT_CHECK_INITIALIZATION) {
465  retval = STD_OK;
466 
467  if (MXM_GetSPIStateReady() == STD_OK) {
468  for (uint8_t i = 0; i < 7u; i++) {
469  if (pInstance->spiRXBuffer[i + 1u] != mxm_41B_reg_default_values[i]) {
470  retval = STD_NOT_OK;
471  }
472  }
473  } else {
474  retval = STD_NOT_OK;
475  }
476 
477  if (retval == STD_NOT_OK) {
478  /* ERR
479  * TODO could not write config */
480  *pInstance->processed = MXM_41B_STATE_ERROR;
481  } else {
482  /* TODO advance to next state or idle state */
483  pInstance->state = MXM_STATEMACH_41B_IDLE;
484  *pInstance->processed = MXM_41B_STATE_PROCESSED;
485  }
486  } else {
487  /* something is very broken */
488  *pInstance->processed = MXM_41B_STATE_ERROR;
489  }
490  break;
492  /* do nothing in idle state
493  * TODO maybe trigger error checking from here e.g. every 100th cycle */
494  /* clean up substate */
495  pInstance->substate = MXM_41B_ENTRY_SUBSTATE;
496  break;
498  retval = MXM_41BConfigRegisterWrite(pInstance);
499 
500  if (retval == STD_NOT_OK) {
501  /* ERR
502  * TODO could not write config; later on implement retry */
503  *pInstance->processed = MXM_41B_STATE_ERROR;
504  } else {
505  /* TODO advance to next state or idle state */
506  pInstance->state = MXM_STATEMACH_41B_IDLE;
507  *pInstance->processed = MXM_41B_STATE_PROCESSED;
508  }
509  break;
511  /* TODO read status register and parse into static variables */
512  if (pInstance->substate == MXM_41B_ENTRY_SUBSTATE) {
513  /* entry of state --> set to first substate */
515  }
516 
517  if (pInstance->substate == MXM_41B_READ_STATUS_REGISTER_SEND) {
518  /* read rx and tx status register */
519  retval = MXM_41BRegisterRead(pInstance, MXM_REG_RX_STATUS_R, pInstance->spiRXBuffer, 2);
520  if (retval == STD_NOT_OK) {
521  /* TODO error handling and progress to ERROR state */
522  } else {
524  }
525  } else if (pInstance->substate == MXM_41B_READ_STATUS_REGISTER_PROCESS) {
526  pInstance->regRXStatus = (uint8_t)pInstance->spiRXBuffer[1];
527  pInstance->regTXStatus = (uint8_t)pInstance->spiRXBuffer[2];
528  pInstance->state = MXM_STATEMACH_41B_IDLE;
529  *pInstance->processed = MXM_41B_STATE_PROCESSED;
530  } else {
531  /* something is very broken */
532  *pInstance->processed = MXM_41B_STATE_ERROR;
533  }
534  break;
536  if (pInstance->substate == MXM_41B_ENTRY_SUBSTATE) {
537  /* entry of state --> set to first substate */
539  }
540 
541  if (pInstance->substate == MXM_41B_UART_WRITE_LOAD_QUEUE) {
542  /* load queue with message */
543  retval = MXM_41BBufferWrite(
544  pInstance, pInstance->pPayload, pInstance->payloadLength, pInstance->extendMessageBytes);
545 
546  if (retval == STD_NOT_OK) {
547  /* TODO error handling */
548  *pInstance->processed = MXM_41B_STATE_ERROR;
549  } else {
551  }
552  } else if (pInstance->substate == MXM_41B_UART_READ_LOAD_QUEUE) {
553  /* send read load queue */
554  retval = MXM_41BRegisterRead(
555  pInstance, MXM_BUF_RD_LD_Q_0, pInstance->spiRXBuffer, pInstance->payloadLength + 1u);
556 
557  if (retval == STD_NOT_OK) {
558  /* TODO error handling */
559  *pInstance->processed = MXM_41B_STATE_ERROR;
560  } else {
562  }
563  } else if (pInstance->substate == MXM_41B_UART_VERIFY_LOAD_QUEUE_AND_TRANSMIT) {
564  /* verify load queue */
565  retval = STD_OK;
566  /* check message length */
567  if (pInstance->spiRXBuffer[1] != (pInstance->payloadLength + pInstance->extendMessageBytes)) {
568  retval = STD_NOT_OK;
569  }
570  for (uint8_t i = 0; i < pInstance->payloadLength; i++) {
571  if (pInstance->spiRXBuffer[i + 2u] != pInstance->pPayload[i]) {
572  /* message corrupted during SPI transfer */
573  retval = STD_NOT_OK;
574  }
575  }
576  if (retval == STD_NOT_OK) {
577  /* TODO error handling
578  * transfer again? */
579  *pInstance->processed = MXM_41B_STATE_ERROR;
580  } else {
581  /* transmit queue */
582  retval = MXM_41BRegisterWrite(pInstance, MXM_BUF_WR_NXT_LD_Q_0, NULL_PTR, 0);
583 
584  if (retval == STD_NOT_OK) {
585  /* TODO error handling
586  * transfer again? */
587  *pInstance->processed = MXM_41B_STATE_ERROR;
588  } else {
590  }
591  }
592  } else if (pInstance->substate == MXM_41B_UART_WAIT_FOR_RX_STATUS_CHANGE_WRITE) {
593  /* poll RX status change */
594  retval = MXM_41BRegisterRead(pInstance, MXM_REG_RX_STATUS_R, pInstance->spiRXBuffer, 1);
595 
596  if (retval == STD_NOT_OK) {
597  /* TODO error handling
598  * transfer again? */
599  *pInstance->processed = MXM_41B_STATE_ERROR;
600  } else {
602  }
604  /* update RX status register copy with received buffer */
605  pInstance->regRXStatus = (uint8_t)pInstance->spiRXBuffer[1];
606  /* check if RX_STOP_Status is 1 */
607  MXM_41B_REG_BIT_VALUE rx_stop_status_value = MXM_41B_REG_FALSE;
608  MXM_41BReadRegisterFunction(pInstance, MXM_41B_REG_FUNCTION_RX_STOP_STATUS, &rx_stop_status_value);
609  if (rx_stop_status_value == MXM_41B_REG_TRUE) {
610  /* received full UART frame --> continue */
611  /* read back receive buffer */
612  retval = MXM_41BRegisterRead(
613  pInstance,
615  pInstance->spiRXBuffer,
616  pInstance->payloadLength + 1u + pInstance->extendMessageBytes);
617 
618  if (retval == STD_NOT_OK) {
619  /* TODO error handling */
620  *pInstance->processed = MXM_41B_STATE_ERROR;
621  } else {
623  pInstance->waitCounter = 0u;
624  }
625  } else {
626  /* no UART frame received yet --> check again */
628  pInstance->waitCounter++;
629  }
630  } else if (pInstance->substate == MXM_41B_UART_READ_BACK_RECEIVE_BUFFER_SAVE) {
631  for (uint8_t i = 0; i < (pInstance->payloadLength + pInstance->extendMessageBytes); i++) {
632  if (i < pInstance->rxBufferLength) {
633  pInstance->pRxBuffer[i] = pInstance->spiRXBuffer[i + 1u];
634  }
635  }
636 
637  pInstance->state = MXM_STATEMACH_41B_IDLE;
638  *pInstance->processed = MXM_41B_STATE_PROCESSED;
639 
640  } else {
641  /* TODO we should not be here */
642  }
643  break;
645  retval = STD_NOT_OK;
646  if (pInstance->substate == MXM_41B_ENTRY_SUBSTATE) {
648  }
649 
650  if (pInstance->substate == MXM_41B_FMEA_REQUEST_REGISTER) {
651  retval = MXM_41BRegisterRead(pInstance, MXM_REG_FMEA_R, pInstance->spiRXBuffer, 1);
652 
653  if (retval == STD_OK) {
654  pInstance->substate = MXM_41B_FMEA_VERIFY;
655  }
656  } else if (pInstance->substate == MXM_41B_FMEA_VERIFY) {
657  if (MXM_GetSPIStateReady() == STD_OK) {
658  if (pInstance->spiRXBuffer[1] == 0u) {
659  retval = STD_OK;
660  } else {
661  retval = STD_NOT_OK;
662  }
663  }
664 
665  if (retval == STD_NOT_OK) {
666  /* ERR
667  * TODO FMEA check went bad */
668  pInstance->state = MXM_STATEMACH_41B_IDLE;
669  *pInstance->processed = MXM_41B_STATE_ERROR;
670  } else {
671  /* TODO advance to next state or idle state and set notice of good FMEA check somewhere */
672  pInstance->state = MXM_STATEMACH_41B_IDLE;
673  *pInstance->processed = MXM_41B_STATE_PROCESSED;
674  }
675  } else {
676  /* something is very broken */
677  *pInstance->processed = MXM_41B_STATE_ERROR;
678  }
679  break;
681  if (pInstance->substate == MXM_41B_ENTRY_SUBSTATE) {
683  }
684 
685  if (pInstance->substate == MXM_41B_VERSION_REQUEST_REGISTER) {
686  /* read two byte in order to read also the adjacent version register */
687  retval = MXM_41BRegisterRead(pInstance, MXM_REG_MODEL_R, pInstance->spiRXBuffer, 2);
688 
689  if (retval == STD_OK) {
690  pInstance->substate = MXM_41B_VERSION_VERIFY;
691  }
692  } else if (pInstance->substate == MXM_41B_VERSION_VERIFY) {
693  if (MXM_GetSPIStateReady() == STD_OK) {
694  /* model is in model byte and high nibble of version byte */
695  pInstance->hwModel = (pInstance->spiRXBuffer[1] << 4u);
696  pInstance->hwModel |= (pInstance->spiRXBuffer[2] >> 4u);
697 
698  /* mask revision is low nibble of version byte */
699  pInstance->hwMaskRevision = ((uint8_t)pInstance->spiRXBuffer[2] & 0xFu);
700 
701  pInstance->state = MXM_STATEMACH_41B_IDLE;
702  *pInstance->processed = MXM_41B_STATE_PROCESSED;
703  }
704 
705  } else {
706  /* something is very broken */
707  *pInstance->processed = MXM_41B_STATE_ERROR;
708  }
709  break;
711  /* clear receive buffer --> reset UART RX into defined state */
712  retval = MXM_41BRegisterWrite(pInstance, MXM_BUF_CLR_RX_BUF, NULL_PTR, 0);
713 
714  if (STD_OK == retval) {
715  /* writing successful, return to idle */
716  pInstance->state = MXM_STATEMACH_41B_IDLE;
717  *pInstance->processed = MXM_41B_STATE_PROCESSED;
718  } else {
719  /* an error has occurred, retry and set error */
720  *pInstance->processed = MXM_41B_STATE_ERROR;
721  }
722  break;
724  /* clear receive buffer --> reset UART RX into defined state */
725  retval = MXM_41BRegisterWrite(pInstance, MXM_BUF_CLR_TX_BUF, NULL_PTR, 0);
726 
727  if (STD_OK == retval) {
728  /* writing successful, return to idle */
729  pInstance->state = MXM_STATEMACH_41B_IDLE;
730  *pInstance->processed = MXM_41B_STATE_PROCESSED;
731  } else {
732  /* an error has occurred, retry and set error */
733  *pInstance->processed = MXM_41B_STATE_ERROR;
734  }
735  break;
736  default:
737  /* this default case should never be reached */
739  break;
740  }
741 }
742 
743 /*========== Externalized Static Function Implementations (Unit Test) =======*/
#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
void MXM_41BStateMachine(MXM_41B_INSTANCE_s *pInstance)
Execute state-machine for the MAX17841B.
Definition: mxm_17841b.c:429
STD_RETURN_TYPE_e MXM_41BWriteRegisterFunction(MXM_41B_INSTANCE_s *pInstance, MXM_41B_REG_FUNCTION_e registerFunction, MXM_41B_REG_BIT_VALUE value)
Write a register function.
Definition: mxm_17841b.c:347
static STD_RETURN_TYPE_e MXM_41BConfigRegisterWrite(MXM_41B_INSTANCE_s *pInstance)
Write the config register of MAX17841B.
Definition: mxm_17841b.c:244
static STD_RETURN_TYPE_e MXM_41BBufferWrite(MXM_41B_INSTANCE_s *pInstance, const uint16_t *const kpkMessage, uint16_t message_length, uint8_t extend_message)
Write a buffer transaction to MAX17841B.
Definition: mxm_17841b.c:260
const uint8_t mxm_kConfig3KeepAlive160us41BRegister
standard configuration for register config 3
Definition: mxm_17841b.c:84
const uint8_t mxm_kConfig2EnableTransmitPreamblesMode41BRegister
standard configuration for register config 2
Definition: mxm_17841b.c:83
const uint8_t mxm_kRXInterruptEnableRXErrorRXOverflow41BRegister
standard configuration for register rx interrupt
Definition: mxm_17841b.c:85
static const uint8_t mxm_41B_reg_default_values[7]
Default values for the configuration and interrupt registers.
Definition: mxm_17841b.c:80
STD_RETURN_TYPE_e MXM_41BSetStateRequest(MXM_41B_INSTANCE_s *pInstance, MXM_STATEMACH_41B_e state, uint16_t *pPayload, uint16_t payloadLength, uint8_t extendMessageBytes, uint16_t *pRxBuffer, uint16_t rxBufferLength, MXM_41B_STATE_REQUEST_STATUS_e *processed)
Set state transition for MAX17841B-state-machine.
Definition: mxm_17841b.c:291
static STD_RETURN_TYPE_e MXM_41BRegisterWrite(MXM_41B_INSTANCE_s *pInstance, MXM_41B_REG_ADD_t command, const uint8_t *const kpkPayload, uint16_t lengthPayload)
Write one or multiple registers of MAX17841B.
Definition: mxm_17841b.c:183
STD_RETURN_TYPE_e MXM_41BReadRegisterFunction(const MXM_41B_INSTANCE_s *const kpkInstance, MXM_41B_REG_FUNCTION_e registerFunction, MXM_41B_REG_BIT_VALUE *pValue)
Read the value of a register function.
Definition: mxm_17841b.c:391
static STD_RETURN_TYPE_e MXM_41BRegisterRead(MXM_41B_INSTANCE_s *pInstance, MXM_41B_REG_ADD_t command, uint16_t *pRxBuffer, uint16_t length)
Read one or multiple registers of MAX17841B.
Definition: mxm_17841b.c:219
Headers for the driver for the MAX17841B ASCI and MAX1785x monitoring chip.
enum MXM_41B_STATE_REQUEST_STATUS MXM_41B_STATE_REQUEST_STATUS_e
Request status of MAX17841B states.
enum MXM_41B_REG_FUNCTION MXM_41B_REG_FUNCTION_e
Register functions.
#define MXM_SPI_TX_BUFFER_LENGTH
SPI TX buffer length.
Definition: mxm_17841b.h:75
@ MXM_41B_STATE_ERROR
Definition: mxm_17841b.h:127
@ MXM_41B_STATE_UNPROCESSED
Definition: mxm_17841b.h:125
@ MXM_41B_STATE_PROCESSED
Definition: mxm_17841b.h:126
@ MXM_41B_REG_FUNCTION_RX_BUSY_STATUS
Definition: mxm_17841b.h:134
@ MXM_41B_REG_FUNCTION_RX_EMPTY_STATUS
Definition: mxm_17841b.h:136
@ MXM_41B_REG_FUNCTION_RX_STOP_STATUS
Definition: mxm_17841b.h:135
@ MXM_41B_REG_FUNCTION_TX_PREAMBLES
Definition: mxm_17841b.h:137
@ MXM_41B_REG_FUNCTION_RX_ERROR_INT
Definition: mxm_17841b.h:139
@ MXM_41B_REG_FUNCTION_KEEP_ALIVE
Definition: mxm_17841b.h:138
@ MXM_41B_REG_FUNCTION_RX_OVERFLOW_INT
Definition: mxm_17841b.h:140
enum MXM_STATEMACH_41B MXM_STATEMACH_41B_e
States of the MAX17841B state-machine.
@ MXM_STATEMACH_41B_MAXSTATE
Definition: mxm_17841b.h:91
@ MXM_STATEMACH_41B_GET_VERSION
Definition: mxm_17841b.h:85
@ MXM_STATEMACH_41B_CLEAR_RECEIVE_BUFFER
Definition: mxm_17841b.h:89
@ MXM_STATEMACH_41B_CLEAR_TRANSMIT_BUFFER
Definition: mxm_17841b.h:90
@ MXM_STATEMACH_41B_UNINITIALIZED
Definition: mxm_17841b.h:81
@ MXM_STATEMACH_41B_INIT
Definition: mxm_17841b.h:82
@ MXM_STATEMACH_41B_WRITE_CONF_AND_INT_REGISTER
Definition: mxm_17841b.h:86
@ MXM_STATEMACH_41B_CHECK_FMEA
Definition: mxm_17841b.h:84
@ MXM_STATEMACH_41B_READ_STATUS_REGISTER
Definition: mxm_17841b.h:87
@ MXM_STATEMACH_41B_IDLE
Definition: mxm_17841b.h:83
@ MXM_STATEMACH_41B_UART_TRANSACTION
Definition: mxm_17841b.h:88
@ MXM_41B_FMEA_REQUEST_REGISTER
Definition: mxm_17841b.h:102
@ MXM_41B_UART_WAIT_FOR_RX_STATUS_CHANGE_WRITE
Definition: mxm_17841b.h:110
@ MXM_41B_VERSION_VERIFY
Definition: mxm_17841b.h:105
@ MXM_41B_INIT_CHECK_INITIALIZATION
Definition: mxm_17841b.h:101
@ MXM_41B_FMEA_VERIFY
Definition: mxm_17841b.h:103
@ MXM_41B_UART_READ_BACK_RECEIVE_BUFFER_SAVE
Definition: mxm_17841b.h:112
@ MXM_41B_VERSION_REQUEST_REGISTER
Definition: mxm_17841b.h:104
@ MXM_41B_ENTRY_SUBSTATE
Definition: mxm_17841b.h:98
@ MXM_41B_UART_WRITE_LOAD_QUEUE
Definition: mxm_17841b.h:107
@ MXM_41B_UART_READ_LOAD_QUEUE
Definition: mxm_17841b.h:108
@ MXM_41B_INIT_READ_CONFIG_REGISTERS
Definition: mxm_17841b.h:100
@ MXM_41B_UART_VERIFY_LOAD_QUEUE_AND_TRANSMIT
Definition: mxm_17841b.h:109
@ MXM_41B_READ_STATUS_REGISTER_SEND
Definition: mxm_17841b.h:113
@ MXM_41B_READ_STATUS_REGISTER_PROCESS
Definition: mxm_17841b.h:114
@ MXM_41B_INIT_WRITE_DEFAULT_VALUES
Definition: mxm_17841b.h:99
@ MXM_41B_UART_WAIT_FOR_RX_STATUS_CHANGE_READ_AND_READ_BACK_RCV_BUF
Definition: mxm_17841b.h:111
Register map of the MAX17841 bridge IC.
#define MXM_REG_RX_INTERRUPT_ENABLE_W
RX interrupt enable register write address.
#define MXM_BUF_RD_LD_Q_0
Read load queue starting from location 0.
#define MXM_BUF_CLR_RX_BUF
Reset receive buffer and pointers to default state.
#define MXM_REG_FMEA_R
FMEA register read address.
#define MXM_REG_RX_INTERRUPT_ENABLE_R
RX interrupt enable register read address.
#define MXM_BUF_RD_NXT_MSG
Read receive buffer starting at the oldest unread message.
#define MXM_REG_RX_STATUS_R
RX status register read address.
#define MXM_REG_MODEL_R
Model register read address.
#define MXM_BUF_WR_LD_Q_0
Write load queue starting from location 0.
#define MXM_BUF_CLR_TX_BUF
Reset transmit buffer to default state and clear TX_Q and LD_Q.
#define MXM_BUF_WR_NXT_LD_Q_0
Select next load queue and write starting from location 0.
uint8_t MXM_41B_REG_ADD_t
MAX17841B register addresses.
MXM_41B_REG_BIT_VALUE mxm_41bWriteValue(MXM_41B_REG_BIT_VALUE value, uint8_t numberOfBits, MXM_41B_REG_BITS shift, uint8_t reg)
write a value to a register supplied as variable
MXM_41B_REG_BIT_VALUE mxm_41bReadValue(uint8_t reg, uint8_t numberOfBits, MXM_41B_REG_BITS position)
read a value from a register supplied as variable
Bit extraction function for MXM_17841b.
#define MXM_41B_KEEP_ALIVE
#define MXM_41B_RX_BUSY_STATUS
#define MXM_41B_REG_FALSE
#define MXM_41B_RX_EMPTY_STATUS
uint8_t MXM_41B_REG_BIT_VALUE
Bit-values for registers.
#define MXM_41B_RX_STOP_STATUS
#define MXM_41B_RX_OVERFLOW_INT_ENABLE
#define MXM_41B_RX_ERROR
#define MXM_41B_TX_PREAMBLES
#define MXM_41B_REG_TRUE
STD_RETURN_TYPE_e MXM_ReceiveData(uint16_t *txBuffer, uint16_t *rxBuffer, uint16_t length)
Send and Receive data over SPI.
Definition: mxm_cfg.c:92
STD_RETURN_TYPE_e MXM_GetSPIStateReady(void)
Return whether SPI interface is ready.
Definition: mxm_cfg.c:81
STD_RETURN_TYPE_e MXM_SendData(uint16_t *txBuffer, uint16_t length)
Transmit data over SPI.
Definition: mxm_cfg.c:86
Struct for the state-variable of state-machine.
Definition: mxm_17841b.h:149
uint8_t regConfig2
Definition: mxm_17841b.h:165
uint16_t spiRXBuffer[100]
Definition: mxm_17841b.h:169
MXM_41B_STATE_REQUEST_STATUS_e * processed
Definition: mxm_17841b.h:156
uint8_t waitCounter
Definition: mxm_17841b.h:159
uint16_t rxBufferLength
Definition: mxm_17841b.h:155
uint16_t * pRxBuffer
Definition: mxm_17841b.h:154
uint16_t hwModel
Definition: mxm_17841b.h:167
uint8_t regConfig3
Definition: mxm_17841b.h:166
uint8_t regConfig1
Definition: mxm_17841b.h:164
MXM_STATEMACH_41B_e state
Definition: mxm_17841b.h:150
MXM_41B_SUBSTATES_e substate
Definition: mxm_17841b.h:151
uint8_t extendMessageBytes
Definition: mxm_17841b.h:158
uint16_t spiTXBuffer[MXM_SPI_TX_BUFFER_LENGTH]
Definition: mxm_17841b.h:170
uint16_t * pPayload
Definition: mxm_17841b.h:152
uint8_t regTXIntEnable
Definition: mxm_17841b.h:161
uint16_t payloadLength
Definition: mxm_17841b.h:153
uint8_t hwMaskRevision
Definition: mxm_17841b.h:168
uint8_t regTXStatus
Definition: mxm_17841b.h:163
uint8_t regRXStatus
Definition: mxm_17841b.h:162
uint8_t regRXIntEnable
Definition: mxm_17841b.h:160