foxBMS  1.6.0
The foxBMS Battery Management System API Documentation
can.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 can.c
44  * @author foxBMS Team
45  * @date 2019-12-04 (date of creation)
46  * @updated 2023-10-12 (date of last update)
47  * @version v1.6.0
48  * @ingroup DRIVERS
49  * @prefix CAN
50  *
51  * @brief Driver for the CAN module
52  *
53  * @details Implementation of the CAN Interrupts, initialization, buffers,
54  * receive and transmit interfaces.
55  */
56 
57 /*========== Includes =======================================================*/
58 #include "general.h"
59 
60 #include "can.h"
61 
62 #include "HL_het.h"
63 #include "HL_reg_system.h"
64 
65 #include "can_helper.h"
66 #include "database.h"
67 #include "diag.h"
68 #include "ftask.h"
69 #include "pex.h"
70 
71 #include <stdbool.h>
72 #include <stdint.h>
73 
74 /*========== Macros and Definitions =========================================*/
75 /** lower limit of timestamp counts for a valid CAN timing */
76 #define CAN_TIMING_LOWER_LIMIT_COUNTS (95u)
77 
78 /** upper limit of timestamp counts for a valid CAN timing */
79 #define CAN_TIMING_UPPER_LIMIT_COUNTS (105u)
80 
81 /** return value of function canGetData if no data was lost during reception */
82 #define CAN_HAL_RETVAL_NO_DATA_LOST (1u)
83 
84 /**
85  * IF2ARB register configuration
86  *
87  * Bits 28-0 ID: Message identifier
88  * ID[28:0] 29-bit Identifier ("Extended Frame").
89  * ID[28:18] 11-bit Identifier ("Standard Frame").
90  */
91 /** ID shift for standard identifier */
92 #define CAN_IF2ARB_STANDARD_IDENTIFIER_SHIFT (18u)
93 /** ID shift for extended identifier */
94 #define CAN_IF2ARB_EXTENDED_IDENTIFIER_SHIFT (0u)
95 
96 /* Bit 29 Dir: Message direction
97  * 0 Direction = Receive: On Tx Request, a Remote Frame with the identifier of this message object is
98  * transmitted. On receiving a Data Frame with a matching identifier, this message is stored in this
99  * message object.
100  * 1 Direction = Transmit: On TxRequest, the respective message object is transmitted as a Data
101  * Frame. On receiving a Remote Frame with a matching identifier, the TxRequest bit of this message
102  * object is set (if RmtEn = 1).
103  */
104 /** IF2ARB set TX direction */
105 #define CAN_IF2ARB_SET_TX_DIRECTION ((uint32)1u << 29u)
106 /* Bit 30 - Xtd: Extended identifier
107  * 0 The 11-bit ("standard") identifier is used for this message object
108  * 1 The 29-bit ("extended") identifier is used for this message object
109  */
110 /** IF2ARB use standard identifier */
111 #define CAN_IF2ARB_USE_STANDARD_IDENTIFIER ((uint32)0u << 30u)
112 /** IF2ARB use extended identifier */
113 #define CAN_IF2ARB_USE_EXTENDED_IDENTIFIER ((uint32)1u << 30u)
114 
115 /** Range of mailboxes that are explicitly configured for the reception of
116  * messages with extended identifiers. */ /**@{*/
117 #define CAN_LOWEST_MAILBOX_FOR_EXTENDED_IDENTIFIERS (61u)
118 #define CAN_HIGHEST_MAILBOX_FOR_EXTENDED_IDENTIFIERS (64u)
119 /**@}*/
120 
123  "Lower mailbox number must not be greater than higher mailbox number");
126  "Highest mailbox number must not be larger than total number of mailboxes");
127 
128 /*========== Static Constant and Variable Definitions =======================*/
129 
130 /** tracks the local state of the can module */
132  .periodicEnable = false,
133  .currentSensorPresent = {GEN_REPEAT_U(false, GEN_STRIP(BS_NR_OF_STRINGS))},
134  .currentSensorCCPresent = {GEN_REPEAT_U(false, GEN_STRIP(BS_NR_OF_STRINGS))},
135  .currentSensorECPresent = {GEN_REPEAT_U(false, GEN_STRIP(BS_NR_OF_STRINGS))},
136 };
137 
138 /** stores the number of CAN_periodicTransmit calls at which the internal
139  * counter will reset to prevent overflow in CAN_IsPeriodElapsed */
140 static uint32_t can_counterResetValue = 0u;
141 
142 /*========== Extern Constant and Variable Definitions =======================*/
143 
144 /*========== Static Function Prototypes =====================================*/
145 
146 /**
147  * @brief Called in case of CAN TX interrupt.
148  * @param pNode CAN interface on which message was sent
149  * @param messageBox message box on which message was sent
150  */
151 static void CAN_TxInterrupt(canBASE_t *pNode, uint32 messageBox);
152 
153 /**
154  * @brief Called in case of CAN RX interrupt.
155  * @param pNode CAN interface on which message was received
156  * @param messageBox message box on which message was received
157  */
158 static void CAN_RxInterrupt(canBASE_t *pNode, uint32 messageBox);
159 
160 /**
161  * @brief Handles the processing of messages that are meant to be
162  * transmitted.
163  * @details This function looks for the repetition times and the repetition
164  * phase of messages that are intended to be sent periodically.
165  * If a comparison with an internal counter (i.e., the counter how
166  * often this function has been called) states that a transmit is
167  * pending, the message is composed by call of CANS_ComposeMessage
168  * and transferred to the buffer of the CAN module.
169  * If a callback function is declared in configuration, this callback
170  * is called after successful transmission.
171  * @return #STD_OK if a CAN transfer was made, #STD_NOT_OK otherwise
172  */
174 
175 /**
176  * @brief Checks if a configured period CAN message should be transmitted depending
177  * on the configured message period and message phase.
178  * @param ticksSinceStart internal counter of a periodically called function
179  * @param messageIndex index of the message to check in the tx message array
180  * @return true if phase matches and message should be transmitted, false otherwise
181 */
182 
183 static bool CAN_IsMessagePeriodElapsed(uint32_t ticksSinceStart, uint16_t messageIndex);
184 
185 /**
186  * @brief Checks if the CAN messages come in the specified time window
187  * @details The time delta where a message is expected to be received needs to
188  * be between the configured limits #CAN_TIMING_LOWER_LIMIT_COUNTS and
189  * #CAN_TIMING_UPPER_LIMIT_COUNTS,
190  * If the message is received within the time frame the check is true,
191  * false otherwise.
192  * The result is then reported via flags in the DIAG module.
193  */
194 static void CAN_CheckCanTiming(void);
195 
196 #if BS_CURRENT_SENSOR_PRESENT == true
197 /**
198  * @brief Sets flag to indicate current sensor is present.
199  * @param command true if current sensor present, otherwise false
200  * @param stringNumber string addressed
201  */
202 static void CAN_SetCurrentSensorPresent(bool command, uint8_t stringNumber);
203 
204 /**
205  * @brief Sets flag to indicate current sensor sends C-C values.
206  * @param command true if coulomb counting message detected,
207  * otherwise false
208  * @param stringNumber string addressed
209  */
210 static void CAN_SetCurrentSensorCcPresent(bool command, uint8_t stringNumber);
211 
212 /**
213  * @brief Sets flag to indicate current sensor sends C-C values.
214  * @param command true if energy counting message detected, otherwise
215  * false
216  * @param stringNumber string addressed
217  */
218 static void CAN_SetCurrentSensorEcPresent(bool command, uint8_t stringNumber);
219 
220 static void CAN_CheckCanTimingOfCurrentSensor(void);
221 #endif /* BS_CURRENT_SENSOR_PRESENT == true */
222 
223 /**
224  * @brief Initialize RX mailboxes for usage with extended identifiers
225  * @details The first 32 mailboxes are configured via HALCoGen as RX mailboxes
226  * to be used with standard 11-bit identifiers. As the configuration
227  * if standard or extended identifiers should be used can only be
228  * configured for all mailboxes and not individually for each mailbox
229  * this configuration is done here.
230  *
231  * The HALCoGen configuration for the mailboxes 61-64 is overwritten
232  * here and they are configured to received all CAN messages with an
233  * extended identifier.
234  *
235  * This configuration is only done for CAN nodes canReg1 and canReg2!
236  */
238 
239 /** initialize the SPI interface to the CAN transceiver */
240 static void CAN_InitializeTransceiver(void);
241 
242 /**
243  * @brief Calculate Reset Value for internal counter in CAN_PeriodicTransmit
244  * @details Calculate the least common multiply of message periods in
245  * can_TxMessages array. All periods will elapse at this time, so the
246  * counter can safely be reset.
247  * @return Reset Value for internal counter in CAN_PeriodicTransmit
248  */
249 static uint32_t CAN_CalculateCounterResetValue(void);
250 
251 /** checks that the configured message period for Tx messages is valid */
252 static void CAN_ValidateConfiguredTxMessagePeriod(void);
253 
254 /** checks that the configured message phase for Tx messages is valid */
255 static void CAN_ValidateConfiguredTxMessagePhase(void);
256 
257 /** checks the struct block for storing and passing on the local
258  * database table handle for containing no null pointers*/
259 static void CAN_CheckDatabaseNullPointer(CAN_SHIM_s canShim);
260 
261 /**
262  * @brief get pointer CAN node configuration struct from register address
263  * @param pNodeRegister pointer to CAN node hardware register address
264  * @return pointer to node configuration struct
265  */
266 static CAN_NODE_s *CAN_GetNodeConfigurationStructFromRegisterAddress(canBASE_t *pNodeRegister);
267 
268 /*========== Static Function Implementations ================================*/
269 
271  /* Content copied from HALCoGen generated configuration file HL_can.c
272  * Date: 11-Dec-2018
273  * Version: 04.07.01
274  */
275 
276  /* AXIVION Disable Style Generic-NoMagicNumbers: Content copied from HALCoGen generated configuration file */
277  /* AXIVION Disable Style MisraC2012-2.2: Content copied from HALCoGen generated configuration file */
278  /* AXIVION Disable Style IISB-LiteralSuffixesCheck: Content copied from HALCoGen generated configuration file */
279  /* AXIVION Disable Style Generic-NoEmptyLoops: Content copied from HALCoGen generated configuration file */
280 
281  /* Reconfigure CAN1 mailboxes 42, 61, 62, 63 and 64 */
282 
283  /** - Setup control register
284  * - Disable automatic wakeup on bus activity
285  * - Local power down mode disabled
286  * - Disable DMA request lines
287  * - Enable global Interrupt Line 0 and 1
288  * - Disable debug mode
289  * - Release from software reset
290  * - Enable/Disable parity or ECC
291  * - Enable/Disable auto bus on timer
292  * - Setup message completion before entering debug state
293  * - Setup normal operation mode
294  * - Request write access to the configuration registers
295  * - Setup automatic retransmission of messages
296  * - Disable error interrupts
297  * - Disable status interrupts
298  * - Enter initialization mode
299  */
300  canREG1->CTL = (uint32)0x00000000U | (uint32)0x00000000U | (uint32)((uint32)0x0000000AU << 10U) |
301  (uint32)0x00020043U;
302 
303  /** - Clear all pending error flags and reset current status */
304  canREG1->ES |= 0xFFFFFFFFU;
305 
306  /** - Setup auto bus on timer period */
307  canREG1->ABOTR = (uint32)0U;
308 
309  /** - Initialize message 42
310  * - Wait until IF1 is ready for use
311  * - Set message mask
312  * - Set message control word
313  * - Set message arbitration
314  * - Set IF1 control byte
315  * - Set IF1 message number
316  */
317  /* SAFETYMCUSW 28 D MR:NA <APPROVED> "Potentially infinite loop found -
318  * Hardware Status check for execution sequence" */
319  while ((canREG1->IF1STAT & 0x80U) == 0x80U) {
320  } /* Wait */
321 
322  canREG1->IF1MSK = 0xC0000000U | (uint32)((uint32)((uint32)0x00000000U & (uint32)0x000007FFU) << (uint32)18U);
323  canREG1->IF1ARB = (uint32)0x80000000U | (uint32)0x00000000U | (uint32)0x00000000U |
324  (uint32)((uint32)((uint32)0U & (uint32)0x000007FFU) << (uint32)18U);
325  canREG1->IF1MCTL = 0x00001000U | (uint32)0x00000400U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)8U;
326  canREG1->IF1CMD = (uint8)0xF8U;
327  canREG1->IF1NO = 42U;
328 
329  /** - Initialize message 61
330  * - Wait until IF1 is ready for use
331  * - Set message mask
332  * - Set message control word
333  * - Set message arbitration
334  * - Set IF1 control byte
335  * - Set IF1 message number
336  */
337  /* SAFETYMCUSW 28 D MR:NA <APPROVED> "Potentially infinite loop found -
338  * Hardware Status check for execution sequence" */
339  while ((canREG1->IF1STAT & 0x80U) == 0x80U) {
340  } /* Wait */
341 
342  canREG1->IF1MSK = 0xC0000000U | (uint32)((uint32)((uint32)0x00000000U & (uint32)0x1FFFFFFFU) << (uint32)0U);
343  canREG1->IF1ARB = (uint32)0x80000000U | (uint32)0x40000000U | (uint32)0x00000000U |
344  (uint32)((uint32)((uint32)0U & (uint32)0x1FFFFFFFU) << (uint32)0U);
345  canREG1->IF1MCTL = 0x00001000U | (uint32)0x00000400U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)8U;
346  canREG1->IF1CMD = (uint8)0xF8U;
347  canREG1->IF1NO = 61U;
348 
349  /** - Initialize message 62
350  * - Wait until IF2 is ready for use
351  * - Set message mask
352  * - Set message control word
353  * - Set message arbitration
354  * - Set IF2 control byte
355  * - Set IF2 message number
356  */
357  /* SAFETYMCUSW 28 D MR:NA <APPROVED> "Potentially infinite loop found -
358  * Hardware Status check for execution sequence" */
359  while ((canREG1->IF2STAT & 0x80U) == 0x80U) {
360  } /* Wait */
361 
362  canREG1->IF2MSK = 0xC0000000U | (uint32)((uint32)((uint32)0x00000000U & (uint32)0x1FFFFFFFU) << (uint32)0U);
363  canREG1->IF2ARB = (uint32)0x80000000U | (uint32)0x40000000U | (uint32)0x00000000U |
364  (uint32)((uint32)((uint32)0U & (uint32)0x1FFFFFFFU) << (uint32)0U);
365  canREG1->IF2MCTL = 0x00001000U | (uint32)0x00000400U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)8U;
366  canREG1->IF2CMD = (uint8)0xF8U;
367  canREG1->IF2NO = 62U;
368 
369  /** - Initialize message 63
370  * - Wait until IF1 is ready for use
371  * - Set message mask
372  * - Set message control word
373  * - Set message arbitration
374  * - Set IF1 control byte
375  * - Set IF1 message number
376  */
377  /* SAFETYMCUSW 28 D MR:NA <APPROVED> "Potentially infinite loop found -
378  * Hardware Status check for execution sequence" */
379  while ((canREG1->IF1STAT & 0x80U) == 0x80U) {
380  } /* Wait */
381 
382  canREG1->IF1MSK = 0xC0000000U | (uint32)((uint32)((uint32)0x00000000U & (uint32)0x1FFFFFFFU) << (uint32)0U);
383  canREG1->IF1ARB = (uint32)0x80000000U | (uint32)0x40000000U | (uint32)0x00000000U |
384  (uint32)((uint32)((uint32)0U & (uint32)0x1FFFFFFFU) << (uint32)0U);
385  canREG1->IF1MCTL = 0x00001000U | (uint32)0x00000400U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)8U;
386  canREG1->IF1CMD = (uint8)0xF8U;
387  canREG1->IF1NO = 63U;
388 
389  /** - Initialize message 64
390  * - Wait until IF2 is ready for use
391  * - Set message mask
392  * - Set message control word
393  * - Set message arbitration
394  * - Set IF2 control byte
395  * - Set IF2 message number
396  */
397  /* SAFETYMCUSW 28 D MR:NA <APPROVED> "Potentially infinite loop found -
398  * Hardware Status check for execution sequence" */
399  while ((canREG1->IF2STAT & 0x80U) == 0x80U) {
400  } /* Wait */
401 
402  canREG1->IF2MSK = 0xC0000000U | (uint32)((uint32)((uint32)0x00000000U & (uint32)0x1FFFFFFFU) << (uint32)0U);
403  canREG1->IF2ARB = (uint32)0x80000000U | (uint32)0x40000000U | (uint32)0x00000000U |
404  (uint32)((uint32)((uint32)0U & (uint32)0x1FFFFFFFU) << (uint32)0U);
405  canREG1->IF2MCTL = 0x00001000U | (uint32)0x00000400U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)8U;
406  canREG1->IF2CMD = (uint8)0xF8U;
407  canREG1->IF2NO = 64U;
408 
409  /** - Setup IF1 for data transmission
410  * - Wait until IF1 is ready for use
411  * - Set IF1 control byte
412  */
413  /* SAFETYMCUSW 28 D MR:NA <APPROVED> "Potentially infinite loop found -
414  * Hardware Status check for execution sequence" */
415  while ((canREG1->IF1STAT & 0x80U) == 0x80U) {
416  } /* Wait */
417  canREG1->IF1CMD = 0x87U;
418 
419  /** - Setup IF2 for reading data
420  * - Wait until IF1 is ready for use
421  * - Set IF1 control byte
422  */
423  /* SAFETYMCUSW 28 D MR:NA <APPROVED> "Potentially infinite loop found -
424  * Hardware Status check for execution sequence" */
425  while ((canREG1->IF2STAT & 0x80U) == 0x80U) {
426  } /* Wait */
427  canREG1->IF2CMD = 0x17U;
428 
429  /** - Leave configuration and initialization mode */
430  canREG1->CTL &= ~(uint32)(0x00000041U);
431 
432  /** Reconfigure CAN2 mailboxes 61 - 64 */
433 
434  /** - Setup control register
435  * - Disable automatic wakeup on bus activity
436  * - Local power down mode disabled
437  * - Disable DMA request lines
438  * - Enable global Interrupt Line 0 and 1
439  * - Disable debug mode
440  * - Release from software reset
441  * - Enable/Disable parity or ECC
442  * - Enable/Disable auto bus on timer
443  * - Setup message completion before entering debug state
444  * - Setup normal operation mode
445  * - Request write access to the configuration registers
446  * - Setup automatic retransmission of messages
447  * - Disable error interrupts
448  * - Disable status interrupts
449  * - Enter initialization mode
450  */
451  canREG2->CTL = (uint32)0x00000000U | (uint32)0x00000000U | (uint32)((uint32)0x0000000AU << 10U) | 0x00020043U;
452 
453  /** - Clear all pending error flags and reset current status */
454  canREG2->ES |= 0xFFFFFFFFU;
455 
456  /** - Initialize message 61
457  * - Wait until IF1 is ready for use
458  * - Set message mask
459  * - Set message control word
460  * - Set message arbitration
461  * - Set IF1 control byte
462  * - Set IF1 message number
463  */
464  /* SAFETYMCUSW 28 D MR:NA <APPROVED> "Potentially infinite loop found -
465  * Hardware Status check for execution sequence" */
466  while ((canREG2->IF1STAT & 0x80U) == 0x80U) {
467  } /* Wait */
468 
469  canREG2->IF1MSK = 0xC0000000U | (uint32)((uint32)((uint32)0x00000000U & (uint32)0x1FFFFFFFU) << (uint32)0U);
470  canREG2->IF1ARB = (uint32)0x80000000U | (uint32)0x40000000U | (uint32)0x00000000U |
471  (uint32)((uint32)((uint32)0U & (uint32)0x1FFFFFFFU) << (uint32)0U);
472  canREG2->IF1MCTL = 0x00001000U | (uint32)0x00000400U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)8U;
473  canREG2->IF1CMD = (uint8)0xF8U;
474  canREG2->IF1NO = 61U;
475 
476  /** - Initialize message 62
477  * - Wait until IF2 is ready for use
478  * - Set message mask
479  * - Set message control word
480  * - Set message arbitration
481  * - Set IF2 control byte
482  * - Set IF2 message number
483  */
484  /* SAFETYMCUSW 28 D MR:NA <APPROVED> "Potentially infinite loop found -
485  * Hardware Status check for execution sequence" */
486  while ((canREG2->IF2STAT & 0x80U) == 0x80U) {
487  } /* Wait */
488 
489  canREG2->IF2MSK = 0xC0000000U | (uint32)((uint32)((uint32)0x00000000U & (uint32)0x1FFFFFFFU) << (uint32)0U);
490  canREG2->IF2ARB = (uint32)0x80000000U | (uint32)0x40000000U | (uint32)0x00000000U |
491  (uint32)((uint32)((uint32)0U & (uint32)0x1FFFFFFFU) << (uint32)0U);
492  canREG2->IF2MCTL = 0x00001000U | (uint32)0x00000400U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)8U;
493  canREG2->IF2CMD = (uint8)0xF8U;
494  canREG2->IF2NO = 62U;
495 
496  /** - Initialize message 63
497  * - Wait until IF1 is ready for use
498  * - Set message mask
499  * - Set message control word
500  * - Set message arbitration
501  * - Set IF1 control byte
502  * - Set IF1 message number
503  */
504  /* SAFETYMCUSW 28 D MR:NA <APPROVED> "Potentially infinite loop found -
505  * Hardware Status check for execution sequence" */
506  while ((canREG2->IF1STAT & 0x80U) == 0x80U) {
507  } /* Wait */
508 
509  canREG2->IF1MSK = 0xC0000000U | (uint32)((uint32)((uint32)0x00000000U & (uint32)0x1FFFFFFFU) << (uint32)0U);
510  canREG2->IF1ARB = (uint32)0x80000000U | (uint32)0x40000000U | (uint32)0x00000000U |
511  (uint32)((uint32)((uint32)0U & (uint32)0x1FFFFFFFU) << (uint32)0U);
512  canREG2->IF1MCTL = 0x00001000U | (uint32)0x00000400U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)8U;
513  canREG2->IF1CMD = (uint8)0xF8U;
514  canREG2->IF1NO = 63U;
515 
516  /** - Initialize message 64
517  * - Wait until IF2 is ready for use
518  * - Set message mask
519  * - Set message control word
520  * - Set message arbitration
521  * - Set IF2 control byte
522  * - Set IF2 message number
523  */
524  /* SAFETYMCUSW 28 D MR:NA <APPROVED> "Potentially infinite loop found -
525  * Hardware Status check for execution sequence" */
526  while ((canREG2->IF2STAT & 0x80U) == 0x80U) {
527  } /* Wait */
528 
529  canREG2->IF2MSK = 0xC0000000U | (uint32)((uint32)((uint32)0x00000000U & (uint32)0x1FFFFFFFU) << (uint32)0U);
530  canREG2->IF2ARB = (uint32)0x80000000U | (uint32)0x40000000U | (uint32)0x00000000U |
531  (uint32)((uint32)((uint32)0U & (uint32)0x1FFFFFFFU) << (uint32)0U);
532  canREG2->IF2MCTL = 0x00001000U | (uint32)0x00000400U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)8U;
533  canREG2->IF2CMD = (uint8)0xF8U;
534  canREG2->IF2NO = 64U;
535 
536  /** - Setup IF1 for data transmission
537  * - Wait until IF1 is ready for use
538  * - Set IF1 control byte
539  */
540  /* SAFETYMCUSW 28 D MR:NA <APPROVED> "Potentially infinite loop found -
541  * Hardware Status check for execution sequence" */
542  while ((canREG2->IF1STAT & 0x80U) == 0x80U) {
543  } /* Wait */
544  canREG2->IF1CMD = 0x87U;
545 
546  /** - Setup IF2 for reading data
547  * - Wait until IF1 is ready for use
548  * - Set IF1 control byte
549  */
550  /* SAFETYMCUSW 28 D MR:NA <APPROVED> "Potentially infinite loop found -
551  * Hardware Status check for execution sequence" */
552  while ((canREG2->IF2STAT & 0x80U) == 0x80U) {
553  } /* Wait */
554  canREG2->IF2CMD = 0x17U;
555 
556  /** - Leave configuration and initialization mode */
557  canREG2->CTL &= ~(uint32)(0x00000041U);
558 
559  /* AXIVION Enable Style Generic-NoMagicNumbers: */
560  /* AXIVION Enable Style MisraC2012-2.2: */
561  /* AXIVION Enable Style IISB-LiteralSuffixesCheck: */
562  /* AXIVION Enable Style Generic-NoEmptyLoops: */
563 }
564 
565 static void CAN_InitializeTransceiver(void) {
566  /** Initialize transceiver for CAN1 */
571 
572  /** Initialize transceiver for CAN2 */
577 }
578 
580  for (uint16_t i = 0u; i < can_txMessagesLength; i++) {
581  if ((can_txMessages[i].timing.period == 0u) || ((can_txMessages[i].timing.period % CAN_TICK_ms) != 0u)) {
583  }
584  }
585 }
586 
588  for (uint16_t i = 0u; i < can_txMessagesLength; i++) {
589  if ((can_txMessages[i].timing.phase >= can_txMessages[i].timing.period) ||
590  ((can_txMessages[i].timing.phase % CAN_TICK_ms) != 0u)) {
592  }
593  }
594 }
595 
597  FAS_ASSERT(canShim.pQueueImd != NULL_PTR);
598  FAS_ASSERT(canShim.pTableCellVoltage != NULL_PTR); /*!< pointer database table with cell voltages */
599  FAS_ASSERT(canShim.pTableCellTemperature != NULL_PTR); /*!< pointer database table with cell temperatures */
600  FAS_ASSERT(canShim.pTableCurrentSensor != NULL_PTR); /*!< pointer database table with current sensor measurements */
601  FAS_ASSERT(canShim.pTableErrorState != NULL_PTR); /*!< pointer database table with error state variables */
602  FAS_ASSERT(canShim.pTableInsulation != NULL_PTR); /*!< pointer database table with insulation monitoring info */
603  FAS_ASSERT(canShim.pTableMinMax != NULL_PTR); /*!< pointer database table with min/max values */
604  FAS_ASSERT(canShim.pTableMol != NULL_PTR); /*!< pointer database table with MOL flags */
605  FAS_ASSERT(canShim.pTableMsl != NULL_PTR); /*!< pointer database table with MSL flags */
606  FAS_ASSERT(canShim.pTableOpenWire != NULL_PTR); /*!< pointer database table with open wire status */
607  FAS_ASSERT(canShim.pTablePackValues != NULL_PTR); /*!< pointer database table with pack values */
608  FAS_ASSERT(canShim.pTableRsl != NULL_PTR); /*!< pointer database table with RSL flags */
609  FAS_ASSERT(canShim.pTableSoc != NULL_PTR); /*!< pointer database table with SOC values */
610  FAS_ASSERT(canShim.pTableSoe != NULL_PTR); /*!< pointer database table with SOE values */
611  FAS_ASSERT(canShim.pTableSof != NULL_PTR); /*!< pointer database table with SOF values */
612  FAS_ASSERT(canShim.pTableSoh != NULL_PTR); /*!< pointer database table with SOH values */
613  FAS_ASSERT(canShim.pTableStateRequest != NULL_PTR); /*!< pointer database table with state requests */
614 }
615 
617  FAS_ASSERT(pNodeRegister != NULL_PTR);
618  CAN_NODE_s *node = NULL_PTR;
619  /* Find correct CAN node configuration struct */
620  if (pNodeRegister == can_node1.canNodeRegister) {
621  node = (CAN_NODE_s *)&can_node1;
622  } else if (pNodeRegister == can_node2Isolated.canNodeRegister) {
623  node = (CAN_NODE_s *)&can_node2Isolated;
624  } else {
625  /* Invalid address. This should not have happened */
627  }
628  return node;
629 }
630 
631 static void CAN_RxInterrupt(canBASE_t *pNode, uint32 messageBox) {
632  FAS_ASSERT(pNode != NULL_PTR);
633  FAS_ASSERT(messageBox <= CAN_TOTAL_NUMBER_OF_MESSAGE_BOXES); /* hardware starts counting at 1 -> use <= */
634 
635  uint8_t messageData[CAN_DEFAULT_DLC] = {0u};
636  /**
637  * Read even if queues are not created, otherwise message boxes get full.
638  * Possible return values:
639  * - 0: no new data
640  * - 1: no data lost
641  * - 3: data lost */
642  uint32_t retval = canGetData(pNode, messageBox, (uint8 *)&messageData[0]); /* copy to RAM */
643 
644  /* Check that CAN RX queue is started before using it and data is valid */
645  if ((ftsk_allQueuesCreated == true) && (retval == CAN_HAL_RETVAL_NO_DATA_LOST)) {
646  CAN_BUFFER_ELEMENT_s can_rxBuffer = {NULL_PTR, 0u, CAN_INVALID_TYPE, {0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u}};
647  /* Find configured CAN node from register address */
649 
650  /* Check message box number if it is a mailbox reserved for extended identifiers or not */
651  if (!((messageBox >= CAN_LOWEST_MAILBOX_FOR_EXTENDED_IDENTIFIERS) &&
653  /* Extract standard identifier from IF2ARB register*/
654  can_rxBuffer.id = canGetID(pNode, messageBox) >> CAN_IF2ARB_STANDARD_IDENTIFIER_SHIFT;
655  can_rxBuffer.idType = CAN_STANDARD_IDENTIFIER_11_BIT;
656  } else {
657  /* Extract extended identifier from IF2ARB register*/
658  can_rxBuffer.id = canGetID(pNode, messageBox) >> CAN_IF2ARB_EXTENDED_IDENTIFIER_SHIFT;
659  can_rxBuffer.idType = CAN_EXTENDED_IDENTIFIER_29_BIT;
660  }
661 
662  /* Write data into buffer */
663  can_rxBuffer.data[CAN_BYTE_0_POSITION] = messageData[CAN_BYTE_0_POSITION];
664  can_rxBuffer.data[CAN_BYTE_1_POSITION] = messageData[CAN_BYTE_1_POSITION];
665  can_rxBuffer.data[CAN_BYTE_2_POSITION] = messageData[CAN_BYTE_2_POSITION];
666  can_rxBuffer.data[CAN_BYTE_3_POSITION] = messageData[CAN_BYTE_3_POSITION];
667  can_rxBuffer.data[CAN_BYTE_4_POSITION] = messageData[CAN_BYTE_4_POSITION];
668  can_rxBuffer.data[CAN_BYTE_5_POSITION] = messageData[CAN_BYTE_5_POSITION];
669  can_rxBuffer.data[CAN_BYTE_6_POSITION] = messageData[CAN_BYTE_6_POSITION];
670  can_rxBuffer.data[CAN_BYTE_7_POSITION] = messageData[CAN_BYTE_7_POSITION];
671 
672  if (OS_SendToBackOfQueueFromIsr(ftsk_canRxQueue, (void *)&can_rxBuffer, NULL_PTR) == OS_SUCCESS) {
673  /* queue is not full */
675  } else {
676  /* queue is full */
678  }
679  }
680 }
681 
683  STD_RETURN_TYPE_e retVal = STD_NOT_OK;
684  static uint32_t counterTicks = 0;
685  uint8_t data[CAN_MAX_DLC] = {0};
686 
688 
689  for (uint16_t i = 0u; i < can_txMessagesLength; i++) {
690  if (CAN_IsMessagePeriodElapsed(counterTicks, i) == true) {
691  if (can_txMessages[i].callbackFunction != NULL_PTR) {
693  can_txMessages[i].message, data, can_txMessages[i].pMuxId, &can_kShim);
694  if (CAN_DataSend(
695  can_txMessages[i].canNode,
696  can_txMessages[i].message.id,
698  data) != STD_OK) {
699  /* message was not sent */
700  /* store the message */
701  CAN_BUFFER_ELEMENT_s unsentMessage = {
703  .id = can_txMessages[i].message.id,
704  .idType = can_txMessages[i].message.idType,
705  .data = {0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u}};
706 
707  for (uint8_t j = 0; j < can_txMessages[i].message.dlc; j++) {
708  unsentMessage.data[j] = data[j];
709  }
710 
711  /* add message to queue */
712  if (OS_SendToBackOfQueue(ftsk_canTxUnsentMessagesQueue, (void *)&unsentMessage, 0u) == OS_SUCCESS) {
713  /* Queue is not full */
715  } else {
716  /* Queue is full */
718  }
719  }
720  retVal = STD_OK;
721  }
722  }
723  }
724 
725  /* check if counter needs to be reset */
726  counterTicks++;
727  if (counterTicks == can_counterResetValue) {
728  counterTicks = 0;
729  }
730 
731  return retVal;
732 }
733 
734 static uint32_t CAN_CalculateCounterResetValue(void) {
735  /* initialize with first array entry for first iteration */
736  uint32_t resetValue = can_txMessages[0].timing.period;
737 
738  /* calculate least common multiple (LCM) of the first and second can_TxMessage period.
739  After that, calculate LCM of the next can_TxMessage period and last iterations LCM
740  until no more can_TxMessages remain. */
741  for (uint8_t i = 1u; i < can_txMessagesLength; i++) {
742  const uint32_t value1 = resetValue;
743  const uint32_t value2 = can_txMessages[i].timing.period;
744 
745  /* calculate greatest common divisor using Euclid's algorithm */
746  /* the algorithm is designed for starting with bigger value, but also
747  works when starting with smaller value, so just start with value1 */
748 
749  uint32_t result = value1;
750  uint32_t divisor = value2;
751  uint32_t tempValue = 0u;
752 
753  while (divisor != 0u) {
754  tempValue = result % divisor;
755  result = divisor;
756  divisor = tempValue;
757  }
758 
759  /* calculate least common multiple using the greatest common divisor */
760  resetValue = (value1 / result) * value2;
761  /* AXIVION Routine FaultDetection-DivisionByZero: /: message periods cannot be 0, so result is never 0 */
762  /* AXIVION Routine MisraC2012Directive-4.1: /: message periods cannot be 0, so result is never 0 */
763  /* AXIVION Routine MisraC2012Directive-4.1: *: only wraps around if periods are too big */
764  }
765 
766  /* scale down to match internal counter of CAN_PeriodicTransmit */
767  resetValue /= CAN_TICK_ms;
768  return resetValue;
769 }
770 
771 static bool CAN_IsMessagePeriodElapsed(uint32_t ticksSinceStart, uint16_t messageIndex) {
772  /* AXIVION Routine Generic-MissingParameterAssert: ticksSinceStart: parameter accepts whole range */
773  FAS_ASSERT(messageIndex < can_txMessagesLength);
774 
775  bool retVal = false;
776  if (((ticksSinceStart * CAN_TICK_ms) % (can_txMessages[messageIndex].timing.period)) ==
777  can_txMessages[messageIndex].timing.phase) {
778  /* AXIVION Routine MisraC2012Directive-4.1: *: counter gets reset in periodicTransmit, no wrap around */
779  /* AXIVION Routine FaultDetection-DivisionByZero: %: message period is never zero, checked by config */
780  /* AXIVION Routine MisraC2012Directive-4.1: %: message period is never zero, checked by config */
781  retVal = true;
782  }
783  return retVal;
784 }
785 
786 static void CAN_CheckCanTiming(void) {
787  uint32_t currentTime;
790 
791  currentTime = OS_GetTickCount();
792  DATA_READ_DATA(&stateRequestTab, &errorFlagsTab);
793 
794  /* Is the BMS still getting CAN messages? */
795  if ((currentTime - stateRequestTab.header.timestamp) <= CAN_TIMING_UPPER_LIMIT_COUNTS) {
796  if (((stateRequestTab.header.timestamp - stateRequestTab.header.previousTimestamp) >=
798  ((stateRequestTab.header.timestamp - stateRequestTab.header.previousTimestamp) <=
801  } else {
803  }
804  } else {
806  }
807 
808 #if BS_CURRENT_SENSOR_PRESENT == true
810 #endif /* BS_CURRENT_SENSOR_PRESENT == true */
811 }
812 
813 #if BS_CURRENT_SENSOR_PRESENT == true
815  uint32_t currentTime = OS_GetTickCount();
817  /* check time stamps of current measurements */
818  DATA_READ_DATA(&currentTab);
819 
820  for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) {
821  /* Current has been measured at least once */
822  if (currentTab.timestampCurrent[s] != 0u) {
823  /* Check time since last received string current data */
824  if ((currentTime - currentTab.timestampCurrent[s]) > BS_CURRENT_MEASUREMENT_RESPONSE_TIMEOUT_ms) {
826  } else {
828  if (can_state.currentSensorPresent[s] == false) {
830  }
831  }
832  }
833 
834  /* check time stamps of CC measurements */
835  /* if timestamp_cc != 0, this means current sensor cc message has been received at least once */
836  if (currentTab.timestampCurrentCounting[s] != 0) {
837  if ((currentTime - currentTab.timestampCurrentCounting[s]) >
840  } else {
842  if (can_state.currentSensorCCPresent[s] == false) {
844  }
845  }
846  }
847 
848  /* check time stamps of EC measurements */
849  /* if timestamp_ec != 0, this means current sensor ec message has been received at least once */
850  if (currentTab.timestampEnergyCounting[s] != 0) {
851  if ((currentTime - currentTab.timestampEnergyCounting[s]) >
854  } else {
856  if (can_state.currentSensorECPresent[s] == false) {
858  }
859  }
860  }
861  }
862 }
863 
864 static void CAN_SetCurrentSensorPresent(bool command, uint8_t stringNumber) {
865  if (command == true) {
867  can_state.currentSensorPresent[stringNumber] = true;
869  } else {
871  can_state.currentSensorPresent[stringNumber] = false;
873  }
874 }
875 
876 static void CAN_SetCurrentSensorCcPresent(bool command, uint8_t stringNumber) {
877  if (command == true) {
879  can_state.currentSensorCCPresent[stringNumber] = true;
881  } else {
883  can_state.currentSensorCCPresent[stringNumber] = false;
885  }
886 }
887 
888 static void CAN_SetCurrentSensorEcPresent(bool command, uint8_t stringNumber) {
889  if (command == true) {
891  can_state.currentSensorECPresent[stringNumber] = true;
893  } else {
895  can_state.currentSensorECPresent[stringNumber] = false;
897  }
898 }
899 #endif /* BS_CURRENT_SENSOR_PRESENT == true */
900 
901 static void CAN_TxInterrupt(canBASE_t *pNode, uint32 messageBox) {
902  /* AXIVION Routine Generic-MissingParameterAssert: pNode: unused parameter */
903  /* AXIVION Routine Generic-MissingParameterAssert: messageBox: unused parameter */
904  (void)pNode;
905  (void)messageBox;
906 }
907 
908 /*========== Extern Function Implementations ================================*/
909 
910 extern void CAN_Initialize(void) {
911  canInit();
912  /* This function overwrites HALCoGen configuration mailbox configuration 61 - 64 for CAN1 and CAN2. */
914  /* PEX pins are used for transceiver configuration -> I2C and port expander
915  * needs to be initialized previously for a successful initialization. */
921 }
922 
923 extern STD_RETURN_TYPE_e CAN_DataSend(CAN_NODE_s *pNode, uint32_t id, CAN_IDENTIFIER_TYPE_e idType, uint8 *pData) {
924  FAS_ASSERT(pNode != NULL_PTR);
925  /* AXIVION Routine Generic-MissingParameterAssert: id: parameter accepts whole range */
927  FAS_ASSERT(pData != NULL_PTR);
928  FAS_ASSERT((pNode == CAN_NODE_1) || (pNode == CAN_NODE_2));
929 
930  STD_RETURN_TYPE_e result = STD_NOT_OK;
931 
932  /**
933  * Parse all TX message boxes until we find a free one,
934  * then use it to send the CAN message.
935  * In the HAL, message box numbers start from 1, not 0.
936  */
937  for (uint8_t messageBox = 1u; messageBox <= CAN_NR_OF_TX_MESSAGE_BOX; messageBox++) {
938  if (canIsTxMessagePending(pNode->canNodeRegister, messageBox) == 0u) {
939  /* id shifted by 18 to use standard frame */
940  /* standard frame: bits [28:18] */
941  /* extended frame: bits [28:0] */
942  /* bit 29 set to 1: to set direction Tx in IF2ARB register */
943  /* bit 30 set to 1: 29-bit ("extended") identifier is used for this message object */
944  if (idType == CAN_STANDARD_IDENTIFIER_11_BIT) {
945  canUpdateID(
946  pNode->canNodeRegister,
947  messageBox,
950  } else {
951  /* Extended 29-bit identifier is used for this node */
952  canUpdateID(
953  pNode->canNodeRegister,
954  messageBox,
957  }
958  canTransmit(pNode->canNodeRegister, messageBox, pData);
959  result = STD_OK;
960  break;
961  }
962  }
963  return result;
964 }
965 
966 extern void CAN_SendMessagesFromQueue(void) {
967  CAN_BUFFER_ELEMENT_s message = {NULL_PTR, 0u, CAN_INVALID_TYPE, {0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u}};
968 
969  while (OS_ReceiveFromQueue(ftsk_canTxUnsentMessagesQueue, (void *)&message, 0u) == OS_SUCCESS) {
970  /* Queue was not empty */
971  if (CAN_DataSend(message.canNode, message.id, message.idType, message.data) == STD_NOT_OK) {
972  /* Message was not sent */
973  if (OS_SendToBackOfQueue(ftsk_canTxUnsentMessagesQueue, (void *)&message, 0u) == OS_FAIL) {
974  /* Queue is full. */
975  }
976  break;
977  }
978  }
979 }
980 
981 extern void CAN_MainFunction(void) {
983  if (can_state.periodicEnable == true) {
985  }
986 }
987 
988 extern void CAN_ReadRxBuffer(void) {
989  if (ftsk_allQueuesCreated == true) {
990  CAN_BUFFER_ELEMENT_s can_rxBuffer = {NULL_PTR, 0u, CAN_INVALID_TYPE, {0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u}};
991  while (OS_ReceiveFromQueue(ftsk_canRxQueue, (void *)&can_rxBuffer, 0u) == OS_SUCCESS) {
992  /* data queue was not empty */
993  for (uint16_t i = 0u; i < can_rxMessagesLength; i++) {
994  if ((can_rxBuffer.canNode == can_rxMessages[i].canNode) &&
995  (can_rxBuffer.id == can_rxMessages[i].message.id) &&
996  (can_rxBuffer.idType == can_rxMessages[i].message.idType)) {
997  if (can_rxMessages[i].callbackFunction != NULL_PTR) {
998  can_rxMessages[i].callbackFunction(can_rxMessages[i].message, can_rxBuffer.data, &can_kShim);
999  }
1000  }
1001  }
1002  }
1003  }
1004 }
1005 
1006 extern void CAN_EnablePeriodic(bool command) {
1007  if (command == true) {
1008  can_state.periodicEnable = true;
1009  } else {
1010  can_state.periodicEnable = false;
1011  }
1012 }
1013 
1014 extern bool CAN_IsCurrentSensorPresent(uint8_t stringNumber) {
1015  FAS_ASSERT(stringNumber < BS_NR_OF_STRINGS);
1016  return can_state.currentSensorPresent[stringNumber];
1017 }
1018 
1019 extern bool CAN_IsCurrentSensorCcPresent(uint8_t stringNumber) {
1020  FAS_ASSERT(stringNumber < BS_NR_OF_STRINGS);
1021  return can_state.currentSensorCCPresent[stringNumber];
1022 }
1023 
1024 extern bool CAN_IsCurrentSensorEcPresent(uint8_t stringNumber) {
1025  FAS_ASSERT(stringNumber < BS_NR_OF_STRINGS);
1026  return can_state.currentSensorECPresent[stringNumber];
1027 }
1028 
1029 /** called in case of CAN interrupt, defined as weak in HAL */
1030 /* 'extern' is omitted here (as opposed to how the foxBMS project declares
1031  and defines functions) as the TI HAL convention does omit the keyword here
1032  and we want to stay consistent with TI's declaration.) */
1033 /* AXIVION Next Codeline Style Linker-Multiple_Definition: TI HAL only provides a weak implementation */
1034 void UNIT_TEST_WEAK_IMPL canMessageNotification(canBASE_t *node, uint32 messageBox) {
1035  /* AXIVION Routine Generic-MissingParameterAssert: node: unchecked in interrupt */
1036  /* AXIVION Routine Generic-MissingParameterAssert: messageBox: unchecked in interrupt */
1037 
1038  if (messageBox <= CAN_NR_OF_TX_MESSAGE_BOX) {
1039  CAN_TxInterrupt(node, messageBox);
1040  } else {
1041  CAN_RxInterrupt(node, messageBox);
1042  }
1043 }
1044 
1045 /*========== Externalized Static Function Implementations (Unit Test) =======*/
1046 #ifdef UNITY_UNIT_TEST
1047 extern CAN_STATE_s *TEST_CAN_GetCANState(void) {
1048  return &can_state;
1049 }
1050 extern void TEST_CAN_ValidateConfiguredTxMessagePeriod(void) {
1052 }
1053 extern void TEST_CAN_ValidateConfiguredTxMessagePhase(void) {
1055 }
1056 extern void TEST_CAN_CheckDatabaseNullPointer(CAN_SHIM_s canShim) {
1058 }
1059 extern void TEST_CAN_TxInterrupt(canBASE_t *pNode, uint32 messageBox) {
1060  CAN_TxInterrupt(pNode, messageBox);
1061 }
1062 extern void TEST_CAN_RxInterrupt(canBASE_t *pNode, uint32 messageBox) {
1063  CAN_RxInterrupt(pNode, messageBox);
1064 }
1065 extern STD_RETURN_TYPE_e TEST_CAN_PeriodicTransmit(void) {
1066  return CAN_PeriodicTransmit();
1067 }
1068 extern uint32_t TEST_CAN_CalculateCounterResetValue(void) {
1070 }
1071 extern void TEST_CAN_CheckCanTiming(void) {
1073 }
1074 extern bool TEST_CAN_IsMessagePeriodElapsed(uint32_t ticksSinceStart, uint16_t messageIndex) {
1075  return CAN_IsMessagePeriodElapsed(ticksSinceStart, messageIndex);
1076 }
1077 #if BS_CURRENT_SENSOR_PRESENT == true
1078 extern void TEST_CAN_SetCurrentSensorPresent(bool command, uint8_t stringNumber) {
1079  CAN_SetCurrentSensorPresent(command, stringNumber);
1080 }
1081 extern void TEST_CAN_SetCurrentSensorCcPresent(bool command, uint8_t stringNumber) {
1082  CAN_SetCurrentSensorCcPresent(command, stringNumber);
1083 }
1084 extern void TEST_CAN_SetCurrentSensorEcPresent(bool command, uint8_t stringNumber) {
1085  CAN_SetCurrentSensorEcPresent(command, stringNumber);
1086 }
1087 extern void TEST_CAN_CheckCanTimingOfCurrentSensor(void) {
1089 }
1090 #endif /* BS_CURRENT_SENSOR_PRESENT == true */
1091 extern void TEST_CAN_ConfigureRxMailboxesForExtendedIdentifiers(void) {
1093 }
1094 extern void TEST_CAN_InitializeTransceiver(void) {
1096 }
1097 extern CAN_NODE_s *TEST_CAN_GetNodeConfigurationStructFromRegisterAddress(canBASE_t *pNodeRegister) {
1099 }
1100 #endif
#define BS_ENERGY_COUNTING_MEASUREMENT_RESPONSE_TIMEOUT_ms
#define BS_NR_OF_STRINGS
Number of parallel strings in the battery pack.
#define BS_COULOMB_COUNTING_MEASUREMENT_RESPONSE_TIMEOUT_ms
#define BS_CURRENT_MEASUREMENT_RESPONSE_TIMEOUT_ms
#define CAN_IF2ARB_EXTENDED_IDENTIFIER_SHIFT
Definition: can.c:94
static CAN_NODE_s * CAN_GetNodeConfigurationStructFromRegisterAddress(canBASE_t *pNodeRegister)
get pointer CAN node configuration struct from register address
Definition: can.c:616
static void CAN_RxInterrupt(canBASE_t *pNode, uint32 messageBox)
Called in case of CAN RX interrupt.
Definition: can.c:631
bool CAN_IsCurrentSensorCcPresent(uint8_t stringNumber)
get flag if CC message from current sensor is received.
Definition: can.c:1019
void CAN_MainFunction(void)
Calls the functions to drive the CAN interface. Makes the CAN timing checks and sends the periodic me...
Definition: can.c:981
static void CAN_ValidateConfiguredTxMessagePeriod(void)
Definition: can.c:579
static void CAN_SetCurrentSensorCcPresent(bool command, uint8_t stringNumber)
Sets flag to indicate current sensor sends C-C values.
Definition: can.c:876
static STD_RETURN_TYPE_e CAN_PeriodicTransmit(void)
Handles the processing of messages that are meant to be transmitted.
Definition: can.c:682
#define CAN_IF2ARB_USE_EXTENDED_IDENTIFIER
Definition: can.c:113
static uint32_t can_counterResetValue
Definition: can.c:140
#define CAN_IF2ARB_SET_TX_DIRECTION
Definition: can.c:105
static void CAN_ValidateConfiguredTxMessagePhase(void)
Definition: can.c:587
#define CAN_HAL_RETVAL_NO_DATA_LOST
Definition: can.c:82
static void CAN_CheckCanTiming(void)
Checks if the CAN messages come in the specified time window.
Definition: can.c:786
#define CAN_IF2ARB_STANDARD_IDENTIFIER_SHIFT
Definition: can.c:92
#define CAN_TIMING_LOWER_LIMIT_COUNTS
Definition: can.c:76
static void CAN_InitializeTransceiver(void)
Definition: can.c:565
void UNIT_TEST_WEAK_IMPL canMessageNotification(canBASE_t *node, uint32 messageBox)
Definition: can.c:1034
bool CAN_IsCurrentSensorEcPresent(uint8_t stringNumber)
get flag if EC message from current sensor is received
Definition: can.c:1024
#define CAN_HIGHEST_MAILBOX_FOR_EXTENDED_IDENTIFIERS
Definition: can.c:118
static void CAN_TxInterrupt(canBASE_t *pNode, uint32 messageBox)
Called in case of CAN TX interrupt.
Definition: can.c:901
void CAN_SendMessagesFromQueue(void)
Reads messages from TX Queue and sends them via CAN.
Definition: can.c:966
void CAN_ReadRxBuffer(void)
Checks the data received per CAN. A receive buffer is used because CAN frames are received in an inte...
Definition: can.c:988
bool CAN_IsCurrentSensorPresent(uint8_t stringNumber)
set flag for presence of current sensor.
Definition: can.c:1014
static void CAN_SetCurrentSensorEcPresent(bool command, uint8_t stringNumber)
Sets flag to indicate current sensor sends C-C values.
Definition: can.c:888
#define CAN_TIMING_UPPER_LIMIT_COUNTS
Definition: can.c:79
STD_RETURN_TYPE_e CAN_DataSend(CAN_NODE_s *pNode, uint32_t id, CAN_IDENTIFIER_TYPE_e idType, uint8 *pData)
Sends over CAN the data passed in parameters. This function goes over the message boxes and marks the...
Definition: can.c:923
static void CAN_CheckCanTimingOfCurrentSensor(void)
Definition: can.c:814
#define CAN_IF2ARB_USE_STANDARD_IDENTIFIER
Definition: can.c:111
static bool CAN_IsMessagePeriodElapsed(uint32_t ticksSinceStart, uint16_t messageIndex)
Checks if a configured period CAN message should be transmitted depending on the configured message p...
Definition: can.c:771
static void CAN_ConfigureRxMailboxesForExtendedIdentifiers(void)
Initialize RX mailboxes for usage with extended identifiers.
Definition: can.c:270
static void CAN_CheckDatabaseNullPointer(CAN_SHIM_s canShim)
Definition: can.c:596
#define CAN_LOWEST_MAILBOX_FOR_EXTENDED_IDENTIFIERS
Definition: can.c:117
static void CAN_SetCurrentSensorPresent(bool command, uint8_t stringNumber)
Sets flag to indicate current sensor is present.
Definition: can.c:864
void CAN_Initialize(void)
Enables the CAN transceiver.. This function sets th pins to enable the CAN transceiver....
Definition: can.c:910
static CAN_STATE_s can_state
Definition: can.c:131
FAS_STATIC_ASSERT((CAN_LOWEST_MAILBOX_FOR_EXTENDED_IDENTIFIERS<=CAN_HIGHEST_MAILBOX_FOR_EXTENDED_IDENTIFIERS), "Lower mailbox number must not be greater than higher mailbox number")
void CAN_EnablePeriodic(bool command)
Enables periodic sending per CAN. This is used to prevent sending uninitialized data per CAN (e....
Definition: can.c:1006
static uint32_t CAN_CalculateCounterResetValue(void)
Calculate Reset Value for internal counter in CAN_PeriodicTransmit.
Definition: can.c:734
Header for the driver for the CAN module.
#define CAN_NR_OF_TX_MESSAGE_BOX
Definition: can.h:74
#define CAN_TOTAL_NUMBER_OF_MESSAGE_BOXES
Definition: can.h:69
#define CAN_TICK_ms
Definition: can.h:79
const CAN_SHIM_s can_kShim
Definition: can_cfg.c:105
const CAN_NODE_s can_node1
Definition: can_cfg.c:74
const CAN_NODE_s can_node2Isolated
Definition: can_cfg.c:78
const CAN_RX_MESSAGE_TYPE_s can_rxMessages[]
Definition: can_cfg_rx.c:76
#define CAN2_ENABLE_PIN
Definition: can_cfg.h:94
#define CAN1_STANDBY_PIN
Definition: can_cfg.h:93
#define CAN_NODE_2
Definition: can_cfg.h:81
#define CAN1_ENABLE_PIN
Definition: can_cfg.h:92
const uint8_t can_rxMessagesLength
Definition: can_cfg_rx.c:93
#define CAN2_STANDBY_PIN
Definition: can_cfg.h:95
const uint8_t can_txMessagesLength
Definition: can_cfg_tx.c:103
#define CAN_NODE_1
Definition: can_cfg.h:80
const CAN_TX_MESSAGE_TYPE_s can_txMessages[]
Definition: can_cfg_tx.c:86
#define CAN_DEFAULT_DLC
Definition: can_cfg.h:103
#define CAN_MAX_DLC
Definition: can_cfg.h:101
CAN_IDENTIFIER_TYPE_e
Definition: can_cfg.h:162
@ CAN_EXTENDED_IDENTIFIER_29_BIT
Definition: can_cfg.h:164
@ CAN_INVALID_TYPE
Definition: can_cfg.h:165
@ CAN_STANDARD_IDENTIFIER_11_BIT
Definition: can_cfg.h:163
Headers for the helper functions for the CAN module.
#define CAN_BYTE_2_POSITION
Definition: can_helper.h:73
#define CAN_BYTE_4_POSITION
Definition: can_helper.h:75
#define CAN_BYTE_0_POSITION
Definition: can_helper.h:71
#define CAN_BYTE_6_POSITION
Definition: can_helper.h:77
#define CAN_BYTE_7_POSITION
Definition: can_helper.h:78
#define CAN_BYTE_3_POSITION
Definition: can_helper.h:74
#define CAN_BYTE_5_POSITION
Definition: can_helper.h:76
#define CAN_BYTE_1_POSITION
Definition: can_helper.h:72
Database module header.
#define DATA_READ_DATA(...)
Definition: database.h:86
@ DATA_BLOCK_ID_ERROR_STATE
Definition: database_cfg.h:95
@ DATA_BLOCK_ID_STATE_REQUEST
Definition: database_cfg.h:112
@ DATA_BLOCK_ID_CURRENT_SENSOR
Definition: database_cfg.h:93
DIAG_RETURNTYPE_e DIAG_Handler(DIAG_ID_e diagId, DIAG_EVENT_e event, DIAG_IMPACT_LEVEL_e impact, uint32_t data)
DIAG_Handler provides generic error handling, based on diagnosis group.
Definition: diag.c:246
Diagnosis driver header.
@ DIAG_EVENT_NOT_OK
Definition: diag_cfg.h:268
@ DIAG_EVENT_OK
Definition: diag_cfg.h:267
@ DIAG_SYSTEM
Definition: diag_cfg.h:280
@ DIAG_STRING
Definition: diag_cfg.h:281
@ DIAG_ID_CAN_CC_RESPONDING
Definition: diag_cfg.h:187
@ DIAG_ID_CAN_TIMING
Definition: diag_cfg.h:184
@ DIAG_ID_CURRENT_SENSOR_RESPONDING
Definition: diag_cfg.h:189
@ DIAG_ID_CAN_RX_QUEUE_FULL
Definition: diag_cfg.h:185
@ DIAG_ID_CAN_EC_RESPONDING
Definition: diag_cfg.h:188
@ DIAG_ID_CAN_TX_QUEUE_FULL
Definition: diag_cfg.h:186
#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
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_canTxUnsentMessagesQueue
volatile bool ftsk_allQueuesCreated
OS_QUEUE ftsk_canRxQueue
General macros and definitions for the whole platform.
#define GEN_REPEAT_U(x, n)
Macro that helps to generate a series of literals (for array initializers).
Definition: general.h:250
#define GEN_STRIP(x)
Definition: general.h:261
#define UNIT_TEST_WEAK_IMPL
Definition: general.h:97
@ OS_SUCCESS
Definition: os.h:86
@ OS_FAIL
Definition: os.h:87
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
OS_STD_RETURN_e OS_SendToBackOfQueueFromIsr(OS_QUEUE xQueue, const void *const pvItemToQueue, long *const pxHigherPriorityTaskWoken)
Post an item to the back the provided queue during an ISR.
Definition: os_freertos.c:289
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
void PEX_SetPin(uint8_t portExpander, uint8_t pin)
sets pin to high.
Definition: pex.c:336
void PEX_SetPinDirectionOutput(uint8_t portExpander, uint8_t pin)
sets pin to input.
Definition: pex.c:409
Header for the driver for the NXP PCA9539 port expander module.
#define PEX_PORT_EXPANDER2
Definition: pex_cfg.h:76
CAN_NODE_s * canNode
Definition: can_cfg.h:170
uint8_t data[CAN_MAX_DLC]
Definition: can_cfg.h:173
CAN_IDENTIFIER_TYPE_e idType
Definition: can_cfg.h:172
CAN_IDENTIFIER_TYPE_e idType
Definition: can_cfg.h:201
canBASE_t * canNodeRegister
Definition: can_cfg.h:76
CAN_RxCallbackFunction_f callbackFunction
Definition: can_cfg.h:246
CAN_MESSAGE_PROPERTIES_s message
Definition: can_cfg.h:244
CAN_NODE_s * canNode
Definition: can_cfg.h:243
DATA_BLOCK_ERROR_STATE_s * pTableErrorState
Definition: can_cfg.h:182
DATA_BLOCK_CELL_VOLTAGE_s * pTableCellVoltage
Definition: can_cfg.h:179
DATA_BLOCK_STATE_REQUEST_s * pTableStateRequest
Definition: can_cfg.h:194
DATA_BLOCK_PACK_VALUES_s * pTablePackValues
Definition: can_cfg.h:188
DATA_BLOCK_RSL_FLAG_s * pTableRsl
Definition: can_cfg.h:189
DATA_BLOCK_SOE_s * pTableSoe
Definition: can_cfg.h:191
DATA_BLOCK_CURRENT_SENSOR_s * pTableCurrentSensor
Definition: can_cfg.h:181
DATA_BLOCK_CELL_TEMPERATURE_s * pTableCellTemperature
Definition: can_cfg.h:180
DATA_BLOCK_MSL_FLAG_s * pTableMsl
Definition: can_cfg.h:186
DATA_BLOCK_MOL_FLAG_s * pTableMol
Definition: can_cfg.h:185
DATA_BLOCK_MIN_MAX_s * pTableMinMax
Definition: can_cfg.h:184
DATA_BLOCK_SOH_s * pTableSoh
Definition: can_cfg.h:193
DATA_BLOCK_OPEN_WIRE_s * pTableOpenWire
Definition: can_cfg.h:187
DATA_BLOCK_INSULATION_MONITORING_s * pTableInsulation
Definition: can_cfg.h:183
OS_QUEUE * pQueueImd
Definition: can_cfg.h:178
DATA_BLOCK_SOC_s * pTableSoc
Definition: can_cfg.h:190
DATA_BLOCK_SOF_s * pTableSof
Definition: can_cfg.h:192
bool currentSensorCCPresent[BS_NR_OF_STRINGS]
Definition: can.h:85
bool currentSensorECPresent[BS_NR_OF_STRINGS]
Definition: can.h:86
bool currentSensorPresent[BS_NR_OF_STRINGS]
Definition: can.h:84
bool periodicEnable
Definition: can.h:83
CAN_TxCallbackFunction_f callbackFunction
Definition: can_cfg.h:235
CAN_MESSAGE_PROPERTIES_s message
Definition: can_cfg.h:233
CAN_TX_MESSAGE_TIMING_s timing
Definition: can_cfg.h:234
CAN_NODE_s * canNode
Definition: can_cfg.h:232
uint32_t timestampCurrent[BS_NR_OF_STRINGS]
Definition: database_cfg.h:224
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:219
uint32_t timestampEnergyCounting[BS_NR_OF_STRINGS]
Definition: database_cfg.h:239
uint32_t timestampCurrentCounting[BS_NR_OF_STRINGS]
Definition: database_cfg.h:235
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:337
uint32_t previousTimestamp
Definition: database_cfg.h:127
DATA_BLOCK_ID_e uniqueId
Definition: database_cfg.h:125
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:553