Diagnosis Module Sources¶
diag.c¶
/**
*
* @copyright © 2010 - 2021, Fraunhofer-Gesellschaft zur Foerderung der
* angewandten Forschung e.V. All rights reserved.
*
* BSD 3-Clause License
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* We kindly request you to use one or more of the following phrases to refer
* to foxBMS in your hardware, software, documentation or advertising
* materials:
*
* ″This product uses parts of foxBMS®″
*
* ″This product includes parts of foxBMS®″
*
* ″This product is derived from foxBMS®″
*
*/
/**
* @file diag.c
* @author foxBMS Team
* @date 09.11.2015 (date of creation)
* @ingroup ENGINE
* @prefix DIAG
*
* @brief Diagnosis driver implementation
*
* This diagnose module is responsible for error handling and reporting.
* Reported errors are logged into the global database and can be reviewed
* on user request.
*/
/*================== Includes =============================================*/
#include "diag.h"
#if BUILD_MODULE_ENABLE_CONTACTOR == 1
#include "contactor.h"
#endif
#include "com.h"
#include "os.h"
#if BUILD_MODULE_ENABLE_NVRAM == 1
#include "nvramhandler.h"
#endif
#include "rtc.h"
#include "stdio.h"
extern int _write(int fd, char *ptr, int len);
/*================== Macros and Definitions ===============================*/
/*================== Constant and Variable Definitions ====================*/
static DIAG_s diag;
static DIAG_DEV_s *diag_devptr;
static uint32_t diagsysmonTimestamp = 0;
static uint8_t diag_locked = 0;
DIAG_SYSMON_NOTIFICATION_s diag_sysmon[DIAG_SYSMON_MODULE_ID_MAX];
DIAG_SYSMON_NOTIFICATION_s diag_sysmon_last[DIAG_SYSMON_MODULE_ID_MAX];
uint32_t diag_sysmon_cnt[DIAG_SYSMON_MODULE_ID_MAX];
DIAG_ERROR_ENTRY_s MEM_BKP_SRAM diag_memory[DIAG_FAIL_ENTRY_LENGTH];
DIAG_ERROR_ENTRY_s MEM_BKP_SRAM *diag_entry_wrptr;
DIAG_ERROR_ENTRY_s MEM_BKP_SRAM *diag_entry_rdptr;
DIAG_CONTACTOR_ERROR_ENTRY_s MEM_BKP_SRAM diagContactorErrorMemory[DIAG_FAIL_ENTRY_CONTACTOR_LENGTH];
DIAG_CONTACTOR_ERROR_ENTRY_s MEM_BKP_SRAM *diagContactorError_entry_wrptr;
DIAG_CONTACTOR_ERROR_ENTRY_s MEM_BKP_SRAM *diagContactorError_entry_rdptr;
DIAG_FAILURECODE_s diag_fc;
/*================== Function Prototypes ==================================*/
static void DIAG_Reset(void);
static uint8_t DIAG_EntryWrite(uint8_t eventID, DIAG_EVENT_e event, uint32_t item_nr);
/*================== Function Implementations =============================*/
/**
* @brief DIAG_Reset resets/initializes all needed structures/buffers.
*
* This function gets called during initialization of the diagnose module.
* It clears memory and counters used by diag later on.
*/
static void DIAG_Reset(void) {
uint32_t i;
uint32_t *u32ptr = (uint32_t*)(&diag_memory[0]);
diag_locked = 1;
/* Delete memory */
for (i = 0; i < (sizeof(diag_memory))/4; i++) {
*u32ptr++ = 0;
}
/* Reset counter */
for (i = 0; i < sizeof(diag.entry_cnt); i++) {
diag.entry_cnt[i] = 0;
}
/* Set pointer to beginning of buffer */
diag_entry_wrptr = diag_entry_rdptr = &diag_memory[0];
diag.errcnttotal = 0;
/* Set pointer to beginning of buffer */
u32ptr = (uint32_t*)(&diagContactorErrorMemory[0]);
/* Delete memory */
for (i = 0; i < (sizeof(diagContactorErrorMemory))/4; i++) {
*u32ptr++ = 0;
}
/* Set pointer to beginning of buffer */
diagContactorError_entry_wrptr = diagContactorError_entry_rdptr = &diagContactorErrorMemory[0];
diag_locked = 0;
}
STD_RETURN_TYPE_e DIAG_Init(DIAG_DEV_s *diag_dev_pointer, STD_RETURN_TYPE_e bkpramValid) {
STD_RETURN_TYPE_e retval = E_OK;
uint8_t c = 0;
uint8_t id_nr = DIAG_ID_MAX;
uint32_t tmperr_Check[(DIAG_ID_MAX+31)/32];
diag_devptr = diag_dev_pointer;
diag.state = DIAG_STATE_UNINITIALIZED;
uint16_t checkfail = 0;
if ((diag_entry_rdptr < &diag_memory[0]) || (diag_entry_rdptr >= &diag_memory[DIAG_FAIL_ENTRY_LENGTH])) {
checkfail |= 0x01;
}
if ((diag_entry_wrptr < &diag_memory[0]) || (diag_entry_wrptr >= &diag_memory[DIAG_FAIL_ENTRY_LENGTH])) {
checkfail |= 0x02;
}
if (bkpramValid == E_NOT_OK) {
checkfail |= 0x04;
}
if ((diagContactorError_entry_rdptr < &diagContactorErrorMemory[0]) ||
(diagContactorError_entry_rdptr >= &diagContactorErrorMemory[DIAG_FAIL_ENTRY_CONTACTOR_LENGTH])) {
checkfail |= 0x08;
}
if ((diagContactorError_entry_wrptr < &diagContactorErrorMemory[0]) ||
(diagContactorError_entry_wrptr >= &diagContactorErrorMemory[DIAG_FAIL_ENTRY_CONTACTOR_LENGTH])) {
checkfail |= 0x10;
}
if (checkfail) {
DIAG_Reset();
}
/* Fill lookup table id2ch */
for (c = 0; c < diag_dev_pointer->nr_of_ch; c++) {
id_nr = diag_dev_pointer->ch_cfg[c].id;
if (id_nr < DIAG_ID_MAX) {
diag.id2ch[id_nr] = c; /* e.g. diag.id2ch[DIAG_ID_90] = configured channel index */
} else {
/* Configuration error -> set retval to E_NOT_OK */
checkfail |= 0x20;
retval = E_NOT_OK;
}
}
for (int i = 0; i < (DIAG_ID_MAX+31)/32; i++) {
tmperr_Check[i] = 0;
}
/* Fill enable array err_enableflag */
for (int i = 0; i < diag_dev_pointer->nr_of_ch; i++) {
if (diag_dev_pointer->ch_cfg[i].state == DIAG_DISABLED) {
/* Disable diagnosis entry */
tmperr_Check[diag_dev_pointer->ch_cfg[i].id/32] |= 1 << (diag_dev_pointer->ch_cfg[i].id % 32);
}
}
/* take over configured error enable masks*/
for (c = 0; c < (DIAG_ID_MAX+31)/32; c++) {
diag.err_enableflag[c] = ~tmperr_Check[c];
}
diag.state = DIAG_STATE_INITIALIZED;
if (checkfail) {
/* make first entry after DIAG_Reset() */
(void)(DIAG_Handler(DIAG_CH_BKPDIAG_FAILURE, DIAG_EVENT_NOK, checkfail));
}
return retval;
}
void DIAG_PrintErrors(void) {
/* FIXME if read once, rdptr is on writeptr, therefore in the next call the errors aren't
* printed again. Maybe tmp save rdptr and set again at end of function. But when is the
* diag memory cleared then? */
if (diag_entry_rdptr == diag_entry_wrptr) {
printf("no new entries in DIAG\r\n");
} else {
printf("DIAG error entries:\r\n");
printf("Date and Time: Error Code/Item Status Description\r\n");
}
uint8_t c = 0;
while (diag_entry_rdptr != diag_entry_wrptr && c < 7) {
if (diag_entry_rdptr >= &diag_memory[DIAG_FAIL_ENTRY_LENGTH]) {
diag_entry_rdptr = &diag_memory[0];
}
printf("%02d.%02d.20%02d - %02d:%02d:%02d ", diag_entry_rdptr->DD, diag_entry_rdptr->MM, diag_entry_rdptr->YY,
diag_entry_rdptr->hh, diag_entry_rdptr->mm, diag_entry_rdptr->ss);
printf("%02d / 0x%08x ", diag_entry_rdptr->event_id, diag_entry_rdptr->event_id);
if (diag_entry_rdptr->event == DIAG_EVENT_OK)
printf("cleared ");
else if (diag_entry_rdptr->event == DIAG_EVENT_NOK)
printf("occurred ");
else
printf("reset ");
printf("%s\r\n", diag_devptr->ch_cfg[diag.id2ch[diag_entry_rdptr->event_id]].description);
diag_entry_rdptr++;
c++;
}
/* More entries in diag buffer */
if (diag_entry_rdptr != diag_entry_wrptr)
printf("Please repeat command. Additional error entries in DIAG buffer available!\r\n");
}
#if BUILD_MODULE_ENABLE_CONTACTOR == 1
void DIAG_PrintContactorInfo(void) {
/* FIXME if read once, rdptr is on writeptr, therefore in the next call the errors aren't
* printed again. Maybe tmp save rdptr and set again at end of function. But when is the
* diag memory cleared then? */
DIAG_CONTACTOR_s diagContactor;
NVM_Get_contactorcnt(&diagContactor);
printf("Contactor switching entries:");
printf("\r\n");
for (uint8_t i = 0; i < BS_NR_OF_CONTACTORS; i++) {
printf("Contactor %02d\r\n", i);
printf("Opening switches: %04x\r\n", diagContactor.cont_switch_opened[i]);
printf("Closing switches: %04x\r\n", diagContactor.cont_switch_closed[i]);
printf("Opening switches hard at current: %04x\r\n", diagContactor.cont_switch_opened_hard_at_current[i]);
printf("\r\n\n");
printf("\r\n");
}
printf("\r\n");
if (diagContactorError_entry_rdptr == diagContactorError_entry_wrptr) {
printf("no entries in Contactor");
printf("\r\n");
} else {
printf("Contactor error entries:");
printf("\r\n");
printf("Date and Time Contactor Opening current");
printf("\r\n");
}
while (diagContactorError_entry_rdptr != diagContactorError_entry_wrptr) {
if (diagContactorError_entry_rdptr >= &diagContactorErrorMemory[DIAG_FAIL_ENTRY_CONTACTOR_LENGTH]) {
diagContactorError_entry_rdptr = &diagContactorErrorMemory[0];
}
printf("%02d.%02d.%02d - %02d:%02d:%02d ", diagContactorError_entry_rdptr->DD, diagContactorError_entry_rdptr->MM,
diagContactorError_entry_rdptr->YY, diagContactorError_entry_rdptr->hh, diagContactorError_entry_rdptr->mm,
diagContactorError_entry_rdptr->ss);
printf("%02d ", diagContactorError_entry_rdptr->contactor);
printf("%fmA\r\n", (double)diagContactorError_entry_rdptr->openingCurrent);
diagContactorError_entry_rdptr++;
}
/* Reset counter for open errors */
diagContactor.errcntreported = 0;
}
#endif
/**
* @brief DIAG_EntryWrite adds an error entry.
*
* This function adds an entry to the error buffer.
* It provides some functionality to prevent duplicates from being logged.
* Multiple occurring error doesn't get logged anymore after they reached a
* pre-defined error count.
*
* @param eventID: ID of entry
* @param event: OK, NOK or RESET
* @param item_nr: item number of event
*
* @return 0xFF if event is logged, otherwise 0
*/
static uint8_t DIAG_EntryWrite(uint8_t eventID, DIAG_EVENT_e event, uint32_t item_nr) {
uint8_t ret_val = 0;
uint8_t c;
RTC_Time_s currTime;
RTC_Date_s currDate;
if (diag_locked) {
return ret_val; /* only locked when clearing the diagnosis memory */
}
if (diag.entry_event[eventID] == event) {
/* same event of same error type already recorded before -> ignore until event toggles */
return ret_val;
}
if ((diag.entry_event[eventID] == DIAG_EVENT_OK) && (event == DIAG_EVENT_RESET)) {
/* do record DIAG_EVENT_RESET-event only if last event was an error (re-initialization) */
/* meaning: DIAG_EVENT_RESET-event at first time call or after DIAG_EVENT_OK-event will not be recorded */
return ret_val;
}
if (++diag.entry_cnt[eventID] > DIAG_MAX_ENTRIES_OF_ERROR) {
/* this type of error has been recorded too many times -> ignore to avoid filling buffer with same failurecodes */
diag.entry_cnt[eventID] = DIAG_MAX_ENTRIES_OF_ERROR;
return ret_val;
}
if (diag_entry_wrptr >= &diag_memory[DIAG_FAIL_ENTRY_LENGTH]) {
diag_entry_wrptr = &diag_memory[0];
}
/* now record failurecode */
ret_val = 0xFF;
RTC_getTime(&currTime);
RTC_getDate(&currDate);
diag_entry_wrptr->YY = currDate.Year;
diag_entry_wrptr->MM = currDate.Month;
diag_entry_wrptr->DD = currDate.Date;
diag_entry_wrptr->hh = currTime.Hours;
diag_entry_wrptr->mm = currTime.Minutes;
diag_entry_wrptr->ss = currTime.Seconds;
diag_entry_wrptr->event_id = eventID; /* Error Code 0... 4x32-1 */
diag_entry_wrptr->item = item_nr; /* */
diag_entry_wrptr->event = (uint8_t)event; /* DIAG_EVENT_OK, DIAG_EVENT_NOK, DIAG_EVENT_RESET */
diag_entry_wrptr->Val0 = diag_fc.Val0;
diag_entry_wrptr->Val1 = diag_fc.Val1;
diag_entry_wrptr->Val2 = diag_fc.Val2;
diag_entry_wrptr->Val3 = diag_fc.Val3;
++diag_entry_wrptr;
++diag.errcntreported; /* counts of (new) diagnosis entry records which is still not been read by external Tool */
/* which will reset this value to 0 after having read all new entries which means <acknowledged by user> */
++diag.errcnttotal; /* total counts of diagnosis entry records */
diag.entry_event[eventID] = event;
c = (uint8_t) diag.errcntreported;
fprintf(stderr, "New Error entry! (%03d): Error Code/Item %03d/0x%08x ", c, eventID, (unsigned int)item_nr);
fprintf(stderr, "%s", diag_devptr->ch_cfg[diag.id2ch[eventID]].description);
if (event == DIAG_EVENT_OK) {
fprintf(stderr, " cleared\r\n");
} else if (event == DIAG_EVENT_NOK) {
fprintf(stderr, " occured\r\n");
} else {
/* DIAG_EVENT_RESET */
fprintf(stderr, " reset\r\n");
}
return ret_val;
}
DIAG_RETURNTYPE_e DIAG_Handler(DIAG_CH_ID_e diag_ch_id, DIAG_EVENT_e event, uint32_t item_nr) {
uint32_t ret_val = DIAG_HANDLER_RETURN_UNKNOWN;
uint32_t *u32ptr_errCodemsk, *u32ptr_warnCodemsk;
uint16_t *u16ptr_threshcounter;
uint16_t cfg_threshold;
uint16_t err_enable_idx;
uint32_t err_enable_bitmask;
DIAG_TYPE_RECORDING_e recordingenabled;
if (diag.state == DIAG_STATE_UNINITIALIZED) {
return (DIAG_HANDLER_RETURN_NOT_READY);
}
if (diag_ch_id >= DIAG_ID_MAX) {
return (DIAG_HANDLER_RETURN_WRONG_ID);
}
if ((diag_ch_id == DIAG_CH_CONTACTOR_DAMAGED) || (diag_ch_id == DIAG_CH_CONTACTOR_OPENING) ||
(diag_ch_id == DIAG_CH_CONTACTOR_CLOSING)) {
return (DIAG_HANDLER_INVALID_TYPE);
}
err_enable_idx = diag_ch_id/32; /* array index of diag.err_enableflag[..] */
err_enable_bitmask = 1 << (diag_ch_id%32); /* bit number (mask) of diag.err_enableflag[idx] */
u32ptr_errCodemsk = &diag.errflag[err_enable_idx];
u32ptr_warnCodemsk = &diag.warnflag[err_enable_idx];
u16ptr_threshcounter = &diag.occurrence_cnt[diag_ch_id];
cfg_threshold = diag_devptr->ch_cfg[diag.id2ch[diag_ch_id]].thresholds;
recordingenabled = diag_devptr->ch_cfg[diag.id2ch[diag_ch_id]].enablerecording;
if (event == DIAG_EVENT_OK) {
if (diag.err_enableflag[err_enable_idx] & err_enable_bitmask) {
/* if (((*u16ptr_threshcounter) == 0) && (*u32ptr_errCodemsk == 0)) */
if (((*u16ptr_threshcounter) == 0)) {
/* everything ok, nothing to be handled */
} else if ((*u16ptr_threshcounter) > 1) {
(*u16ptr_threshcounter)--; /* Error did not occur, decrement Error-Counter */
} else if ((*u16ptr_threshcounter) == 1) {
/* else if ((*u16ptr_threshcounter) <= 1) */
/* Error did not occur, now decrement to zero and clear Error- or Warning-Flag and make recording if enabled */
*u32ptr_errCodemsk &= ~err_enable_bitmask; /* ERROR: clear corresponding bit in errflag[idx] */
*u32ptr_warnCodemsk &= ~err_enable_bitmask; /* WARNING: clear corresponding bit in warnflag[idx] */
(*u16ptr_threshcounter) = 0;
/* Make entry in error-memory (error disappeared) */
if (recordingenabled == DIAG_RECORDING_ENABLED)
DIAG_EntryWrite(diag_ch_id, event, item_nr);
/* Call callback function and reset error */
diag_ch_cfg[diag.id2ch[diag_ch_id]].callbackfunc(diag_ch_id, DIAG_EVENT_RESET);
}
}
ret_val = DIAG_HANDLER_RETURN_OK; /* Function does not return an error-message! */
} else if (event == DIAG_EVENT_NOK) {
if (diag.err_enableflag[err_enable_idx] & err_enable_bitmask) {
if ((*u16ptr_threshcounter) < cfg_threshold) {
(*u16ptr_threshcounter)++; /* error-threshold not exceeded yet, increment Error-Counter */
ret_val = DIAG_HANDLER_RETURN_OK; /* Function does not return an error-message! */
} else if ((*u16ptr_threshcounter) == cfg_threshold) {
/* Error occured AND error-threshold exceeded */
(*u16ptr_threshcounter)++;
*u32ptr_errCodemsk |= err_enable_bitmask; /* ERROR: set corresponding bit in errflag[idx] */
*u32ptr_warnCodemsk &= ~err_enable_bitmask; /* WARNING: clear corresponding bit in warnflag[idx] */
/* Make entry in error-memory (error occurred) */
if (recordingenabled == DIAG_RECORDING_ENABLED) {
DIAG_EntryWrite(diag_ch_id, event, item_nr);
}
/* Call callback function and set error */
diag_ch_cfg[diag.id2ch[diag_ch_id]].callbackfunc(diag_ch_id, DIAG_EVENT_NOK);
/* Function returns an error-message! */
ret_val = DIAG_HANDLER_RETURN_ERR_OCCURRED;
} else if (((*u16ptr_threshcounter) > cfg_threshold)) {
/* error-threshold already exceeded, nothing to be handled */
ret_val = DIAG_HANDLER_RETURN_ERR_OCCURRED;
}
} else {
/* Error occured BUT NOT enabled by mask */
*u32ptr_errCodemsk &= ~err_enable_bitmask; /* ERROR: clear corresponding bit in errflag[idx] */
*u32ptr_warnCodemsk |= err_enable_bitmask; /* WARNING: set corresponding bit in warnflag[idx] */
ret_val = DIAG_HANDLER_RETURN_WARNING_OCCURRED; /* Function returns an error-message! */
}
} else if (event == DIAG_EVENT_RESET) {
if (diag.err_enableflag[err_enable_idx] & err_enable_bitmask) {
/* clear counter, Error-, Warning-Flag and make recording if enabled */
*u32ptr_errCodemsk &= ~err_enable_bitmask; /* ERROR: clear corresponding bit in errflag[idx] */
*u32ptr_warnCodemsk &= ~err_enable_bitmask; /* WARNING: clear corresponding bit in warnflag[idx] */
(*u16ptr_threshcounter) = 0;
if (recordingenabled == DIAG_RECORDING_ENABLED)
DIAG_EntryWrite(diag_ch_id, event, item_nr); /* Make entry in error-memory (error disappeared) if error was recorded before */
}
ret_val = DIAG_HANDLER_RETURN_OK; /* Function does not return an error-message! */
}
return (ret_val);
}
STD_RETURN_TYPE_e DIAG_checkEvent(STD_RETURN_TYPE_e cond,
DIAG_CH_ID_e diag_ch_id,
uint32_t item_nr) {
STD_RETURN_TYPE_e retVal = E_NOT_OK;
if (cond == E_OK) {
DIAG_Handler(diag_ch_id, DIAG_EVENT_OK, item_nr);
} else {
DIAG_Handler(diag_ch_id, DIAG_EVENT_NOK, item_nr);
}
return retVal;
}
#if BUILD_MODULE_ENABLE_CONTACTOR == 1
/**
* @brief DIAG_ContHandler provides generic contactor switching handling, based on configuration.
*
* This function does all the handling based on the user defined configuration.
* It needs to get called in every occurrence where a contactor is either opened or closed.
* According to its return value further treatment is left to the calling module itself.
*
* @param eventID switching event that occurred
* @param cont_nr contactor that switches
* @param openingCur current flow during contactor opening
*
* @return DIAG_HANDLER_RETURN_ERR_OCCURRED if hard opening threshold is reached,\n
* DIAG_HANDLER_RETURN_OK if normal opening/closing of contactor occurred or threshold not reached,\n
* DIAG_HANDLER_INVALID_TYPE if called with wrong eventID,\n
* DIAG_HANDLER_INVALID_DATA if no opening current is passed in case of hard opening
*/
DIAG_RETURNTYPE_e DIAG_ContHandler(DIAG_CH_ID_e eventID, uint32_t cont_nr, float* openingCur) {
DIAG_RETURNTYPE_e retVal = DIAG_HANDLER_RETURN_UNKNOWN;
uint8_t updateNVRAM = 0;
if (diag_locked)
return retVal; /* only locked when clearing the diagnosis memory */
DIAG_CONTACTOR_s diagContactor;
NVM_Get_contactorcnt(&diagContactor);
if (eventID == DIAG_CH_CONTACTOR_OPENING) {
diagContactor.cont_switch_opened[cont_nr]++;
retVal = DIAG_HANDLER_RETURN_OK;
} else if (eventID == DIAG_CH_CONTACTOR_CLOSING) {
diagContactor.cont_switch_closed[cont_nr]++;
retVal = DIAG_HANDLER_RETURN_OK;
} else if (eventID == DIAG_CH_CONTACTOR_DAMAGED) {
if (NULL_PTR == openingCur) {
retVal = DIAG_HANDLER_INVALID_DATA;
} else {
RTC_Time_s currTime;
RTC_Date_s currDate;
updateNVRAM = 1;
diagContactor.cont_switch_opened_hard_at_current[cont_nr]++;
if (diagContactor.cont_switch_opened_hard_at_current[cont_nr] >= CONT_NUMBER_OF_BAD_COUNTINGS)
retVal = DIAG_HANDLER_RETURN_ERR_OCCURRED;
else
retVal = DIAG_HANDLER_RETURN_OK;
if (diagContactorError_entry_wrptr >= &diagContactorErrorMemory[DIAG_FAIL_ENTRY_CONTACTOR_LENGTH]) {
diagContactorError_entry_wrptr = &diagContactorErrorMemory[0];
}
/* Write error entry */
/* Get time and date */
RTC_getTime(&currTime);
RTC_getDate(&currDate);
/* Set time and date */
diagContactorError_entry_wrptr->YY = currDate.Year;
diagContactorError_entry_wrptr->MM = currDate.Month;
diagContactorError_entry_wrptr->DD = currDate.Date;
diagContactorError_entry_wrptr->hh = currTime.Hours;
diagContactorError_entry_wrptr->mm = currTime.Minutes;
diagContactorError_entry_wrptr->ss = currTime.Seconds;
diagContactorError_entry_wrptr->contactor = (uint8_t)cont_nr;
diagContactorError_entry_wrptr->openingCurrent = *openingCur;
diagContactorError_entry_wrptr++;
printf("new Contactor error entry! currently %02d error entrys\r\n", diagContactor.errcntreported);
}
} else {
retVal = DIAG_HANDLER_INVALID_TYPE;
}
if ((DIAG_HANDLER_RETURN_ERR_OCCURRED == retVal) || (DIAG_HANDLER_RETURN_OK == retVal)) {
/* Write new value in nvram buffer */
NVM_Set_contactorcnt(&diagContactor);
if (updateNVRAM == 1) {
/* Update NVRAM only if contactor opened hard at current */
NVRAM_setWriteRequest(NVRAM_BLOCK_ID_CONT_COUNTER);
}
}
return retVal;
}
#endif
/**
* @brief overall system monitoring
*
* checks notifications (state and timestamps) of all system-relevant tasks or functions
* all checks should be customized corresponding to its timing and state requirements
*/
void DIAG_SysMon(void) {
DIAG_SYSMON_MODULE_ID_e module_id;
uint32_t localTimer = OS_getOSSysTick();
if (diagsysmonTimestamp == localTimer) {
return;
}
diagsysmonTimestamp = localTimer;
/* check modules */
for (module_id = 0; module_id < DIAG_SYSMON_MODULE_ID_MAX; module_id++) {
if ((diag_sysmon_ch_cfg[module_id].type == DIAG_SYSMON_CYCLICTASK) &&
(diag_sysmon_ch_cfg[module_id].state == DIAG_ENABLED)) {
if (diag_sysmon[module_id].timestamp - diag_sysmon_last[module_id].timestamp < 1) {
/* module not running */
if (++diag_sysmon_cnt[module_id] >= diag_sysmon_ch_cfg[module_id].threshold) {
/* @todo configurable timeouts ! */
if (diag_sysmon_ch_cfg[module_id].enablerecording == DIAG_RECORDING_ENABLED) {
DIAG_Handler(DIAG_CH_SYSTEMMONITORING_TIMEOUT, DIAG_EVENT_NOK, module_id);
}
#if BUILD_MODULE_ENABLE_CONTACTOR == 1
if (diag_sysmon_ch_cfg[module_id].handlingtype == DIAG_SYSMON_HANDLING_SWITCHOFFCONTACTOR) {
/* system not working trustfully, switch off contactors! */
CONT_SwitchAllContactorsOff();
}
#endif
diag_sysmon_cnt[module_id] = 0;
/* @todo: call callback function if error occurred */
diag_sysmon_ch_cfg[module_id].callbackfunc(module_id);
}
} else {
/* module running */
diag_sysmon_cnt[module_id] = 0;
if (diag_sysmon[module_id].state != 0) {
/* check state of module */
/* @todo: do something now! */
}
}
} else {
/* if Sysmon type != cyclic task (not used at the moment) */
}
diag_sysmon_last[module_id] = diag_sysmon[module_id]; /*save last values for next check*/
}
}
void DIAG_SysMonNotify(DIAG_SYSMON_MODULE_ID_e module_id, uint32_t state) {
if (module_id < DIAG_SYSMON_MODULE_ID_MAX) {
taskENTER_CRITICAL();
diag_sysmon[module_id].timestamp = OS_getOSSysTick();
diag_sysmon[module_id].state = state;
taskEXIT_CRITICAL();
}
}
void DIAG_configASSERT(void) {
#ifdef STM32F4
uint32_t lr_register;
uint32_t sp_register;
__ASM volatile("mov %0, r14" : "=r" (lr_register));
__ASM volatile("mov %0, r13" : "=r" (sp_register));
lr_register = lr_register & 0xFFFFFFFE; /* mask out LSB as this only is indicates thumb instruction */
diag_fc.Val0 = sp_register; /* actual stack pointer */
diag_fc.Val1 = lr_register; /* report instruction address where this function has been called */
diag_fc.Val2 = *(uint32_t*)(sp_register + 0x1C); /* return address of callers context (one above caller) */
DIAG_Handler(DIAG_CH_CONFIGASSERT, DIAG_EVENT_NOK, 0);
#endif
while (1) {
/* TODO: explain why infinite loop */
}
}
diag.h¶
/**
*
* @copyright © 2010 - 2021, Fraunhofer-Gesellschaft zur Foerderung der
* angewandten Forschung e.V. All rights reserved.
*
* BSD 3-Clause License
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* We kindly request you to use one or more of the following phrases to refer
* to foxBMS in your hardware, software, documentation or advertising
* materials:
*
* ″This product uses parts of foxBMS®″
*
* ″This product includes parts of foxBMS®″
*
* ″This product is derived from foxBMS®″
*
*/
/**
* @file diag.h
* @author foxBMS Team
* @date 09.11.2015 (date of creation)
* @ingroup ENGINE
* @prefix DIAG
*
* @brief Diagnosis driver header
*
*/
#ifndef DIAG_H_
#define DIAG_H_
/*================== Includes =============================================*/
#include "diag_cfg.h"
/*================== Macros and Definitions ===============================*/
/** diagnosis handler return types */
typedef enum {
DIAG_HANDLER_RETURN_OK, /*!< error not occurred or occurred but threshold not reached */
DIAG_HANDLER_RETURN_ERR_OCCURRED, /*!< error occurred and enabled */
DIAG_HANDLER_RETURN_WARNING_OCCURRED, /*!< warning occurred (error occurred but not enabled) */
DIAG_HANDLER_RETURN_WRONG_ID, /*!< wrong diagnosis id */
DIAG_HANDLER_RETURN_UNKNOWN, /*!< unknown return type */
DIAG_HANDLER_INVALID_TYPE, /*!< invalid diagnosis type, error in configuration */
DIAG_HANDLER_INVALID_DATA, /*!< invalid data, dependent of the diagHandler */
DIAG_HANDLER_RETURN_NOT_READY, /*!< diagnosis handler not ready */
} DIAG_RETURNTYPE_e;
/**
* state of diagnosis module
*/
typedef enum {
DIAG_STATE_UNINITIALIZED, /*!< diagnosis module not initialized */
DIAG_STATE_INITIALIZED, /*!< diagnosis module initialized (ready for use) */
} DIAG_STATE_e;
/**
* structure of failure entry record
*/
typedef struct {
uint8_t YY;
uint8_t MM;
uint8_t DD;
uint8_t hh;
uint8_t mm;
uint8_t ss;
DIAG_EVENT_e event;
DIAG_CH_ID_e event_id;
uint32_t item;
uint32_t dummy1;
uint32_t Val0;
uint32_t Val1;
uint32_t Val2;
uint32_t Val3;
} DIAG_ERROR_ENTRY_s;
/* FIXME maybe short explanation why there is separate Error entry for contactor in a few words */
/**
* structure of failure code entry record for contactor
*/
typedef struct {
uint8_t YY;
uint8_t MM;
uint8_t DD;
uint8_t hh;
uint8_t mm;
uint8_t ss;
/* DIAG_EVENT_e event; */
/* DIAG_CH_ID_e event_id; */
uint8_t contactor;
float openingCurrent;
} DIAG_CONTACTOR_ERROR_ENTRY_s;
/**
* structure contains number of switching actions for each contactor
*/
typedef struct {
uint16_t cont_switch_closed[BS_NR_OF_CONTACTORS];
uint16_t cont_switch_opened[BS_NR_OF_CONTACTORS];
uint16_t cont_switch_opened_hard_at_current[BS_NR_OF_CONTACTORS];
uint16_t errcntreported; /*!< number of hard switches occurred since last call of DIAG_PrintContactorInfo */
/* sizeof(struct) - (memory of contactors) - errcntreported - chksum */
uint8_t reserved[0x40 - (3*BS_NR_OF_CONTACTORS*2) - 2 - 4]; /*!< reserved for future use */
} DIAG_CONTACTOR_s;
/* FIXME doxygen comment missing */
typedef struct {
uint32_t Val0;
uint32_t Val1;
uint32_t Val2;
uint32_t Val3;
} DIAG_FAILURECODE_s;
typedef struct {
DIAG_STATE_e state; /*!< actual state of diagnosis module */
uint16_t errcnttotal; /*!< total counts of diagnosis entry records*/
uint16_t errcntreported; /*!< reported error counts to external tool*/
uint32_t entry_event[DIAG_ID_MAX]; /*!< last detected entry event*/
uint8_t entry_cnt[DIAG_ID_MAX]; /*!< reported event counter used for limitation */
uint16_t occurrence_cnt[DIAG_ID_MAX]; /*!< */
uint8_t id2ch[DIAG_ID_MAX]; /*!< diagnosis-id to configuration channel selector*/
uint8_t nr_of_ch; /*!< number of configured channels*/
uint32_t errflag[(DIAG_ID_MAX+31)/32]; /*!< detected error flags (bit_nr = diag_id) */
uint32_t warnflag[(DIAG_ID_MAX+31)/32]; /*!< detected warning flags (bit_nr = diag_id) */
uint32_t err_enableflag[(DIAG_ID_MAX+31)/32]; /*!< enabled error flags (bit_nr = diag_id) */
} DIAG_s;
/*================== Constant and Variable Definitions ====================*/
/* FIXME doxygen comment missing */
extern DIAG_FAILURECODE_s diag_fc;
/*================== Function Prototypes ==================================*/
/**
* @brief DIAG_Handler provides generic error handling, based on diagnosis group.
@ingroup API_DIAG
* This function calls the handler functions depending on the diagnosis group of call.
* It needs to get called in every function which wants to apply some kind of diagnosis handling.
* According to its return value further treatment is either left to the calling module itself, or
* can be done in the callback function defined in diag_cfg.c
*
*
* @param diag_ch_id: event ID of the event that has occurred
* @param event: event that occurred (OK, NOK, RESET)
* @param item_nr: item nr of event, to distinguish between different calling locations of the event
*
* @return DIAG_HANDLER_RETURN_UNKNOWN if invalid DIAG_TYPE_e, otherwise return value of
* DIAG_GeneralHandler or DIAG_ContHandler
*/
extern DIAG_RETURNTYPE_e DIAG_Handler(DIAG_CH_ID_e diag_ch_id,
DIAG_EVENT_e event,
uint32_t item_nr);
/**
* @brief DIAG_checkEvent provides a simple interface to check an event for E_OK
*
* @details DIAG_checkEvent is a wrapper function for DIAG_Handler. In simple cases where a return value
* that is not E_OK (or a 0 casted to E_OK) should increase the error counter in a diagnosis
* channel, this function should be used instead of directly calling the DIAG_Handler().
*
* @param cond: condition
* @param diag_ch_id: event ID of the event that has occurred
* @param item_nr: item nr of event, to distinguish between different calling locations of the event
*
* @return E_OK if ok, E_NOK if not ok
*/
extern STD_RETURN_TYPE_e DIAG_checkEvent(STD_RETURN_TYPE_e cond, DIAG_CH_ID_e diag_ch_id, uint32_t item_nr);
/**
* @brief DIAG_Init initializes all needed structures/buffers.
*
* This function provides initialization of the diagnose module.
* In case of miss behaviour it calls Reset and adds an entry into database
* to ensure data validity/report back malfunction
*
* @param diag_dev_pointer
*/
extern STD_RETURN_TYPE_e DIAG_Init(DIAG_DEV_s *diag_dev_pointer, STD_RETURN_TYPE_e bkpramValid);
#if BUILD_MODULE_ENABLE_CONTACTOR == 1
DIAG_RETURNTYPE_e DIAG_ContHandler(DIAG_CH_ID_e eventID, uint32_t cont_nr, float* openingCur);
#endif
/**
* @brief trap of configuration errors derived by FreeRTOS configASSERT
*/
extern void DIAG_configASSERT(void);
/**
* @brief overall system monitoring
*
* checks notifications (state and timestamps) of all system-relevant tasks or functions
* all checks should be customized corresponding to its timing and state requirements
*/
extern void DIAG_SysMon(void);
/**
* @brief DIAG_PrintErrors prints contents of the error buffer on user request.
*
* This function prints out complete error buffer using the UART interface.
*/
extern void DIAG_PrintErrors(void);
#if BUILD_MODULE_ENABLE_CONTACTOR == 1
/**
* @brief DIAG_PrintContactorInfo prints contents of the contactor switching buffer on user request.
*
* This function prints out complete contactor information using the UART interface.
*/
extern void DIAG_PrintContactorInfo(void);
#endif
/**
* @brief DIAG_SysMonNotify has to be called in every function using the system monitoring.
*
* @param module_id: module id to notify system monitoring
* @param state: state of module
*/
extern void DIAG_SysMonNotify(DIAG_SYSMON_MODULE_ID_e module_id, uint32_t state);
/*================== Function Implementations =============================*/
#endif /* DIAG_H_ */
diag_cfg.c (primary)¶
/**
*
* @copyright © 2010 - 2021, Fraunhofer-Gesellschaft zur Foerderung der
* angewandten Forschung e.V. All rights reserved.
*
* BSD 3-Clause License
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* We kindly request you to use one or more of the following phrases to refer
* to foxBMS in your hardware, software, documentation or advertising
* materials:
*
* ″This product uses parts of foxBMS®″
*
* ″This product includes parts of foxBMS®″
*
* ″This product is derived from foxBMS®″
*
*/
/**
* @file diag_cfg.c
* @author foxBMS Team
* @date 09.11.2015 (date of creation)
* @ingroup ENGINE_CONF
* @prefix DIAG
*
* @brief Diagnostic module configuration
*
* The configuration of the different diagnosis events defined in diag_cfg.h is set in the array
* diag_ch_cfg[], e.g. initialization errors or runtime errors.
*
* Every entry of the diag_ch_cfg[] array consists of
* - name of the diagnosis event (defined in diag_cfg.h)
* - type of diagnosis event
* - diagnosis sensitivity (after how many occurrences event is counted as error)
* - enabling of the recording for diagnosis event
* - enabling of the diagnosis event
* - callback function for diagnosis event if wished, otherwise dummyfu
*
* The system monitoring configuration defined in diag_cfg.h is set in the array
* diag_sysmon_ch_cfg[]. The system monitoring is at the moment only used for
* supervising the cyclic/periodic tasks.
*
* Every entry of the diag_sysmon_ch_cfg[] consists of
* - enum of monitored object
* - type of monitored object (at the moment only DIAG_SYSMON_CYCLICTASK is supported)
* - maximum delay in [ms] in which the object needs to call the DIAG_SysMonNotify function defined in diag.c
* - enabling of the recording for system monitoring
* - enabling of the system monitoring for the monitored object
* - callback function if system monitoring notices an error if wished, otherwise dummyfu2
*/
/*================== Includes ===============================================*/
#include "diag_cfg.h"
#include "database.h"
#include "rtc.h"
/*================== Macros and Definitions =================================*/
/*================== Static Constant and Variable Definitions ===============*/
static DATA_BLOCK_ERRORSTATE_s error_flags = { 0 };
static DATA_BLOCK_MOL_FLAG_s mol_flags = { 0 };
static DATA_BLOCK_RSL_FLAG_s rsl_flags = { 0 };
static DATA_BLOCK_MSL_FLAG_s msl_flags = { 0 };
/*================== Static Function Prototypes =============================*/
/* dummy functions */
static void dummyfu(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event);
static void dummyfu2(DIAG_SYSMON_MODULE_ID_e ch_id);
/* functions for SOA related events */
static void DIAG_overvoltage(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event);
static void DIAG_undervoltage(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event);
static void DIAG_overtemperature_charge(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event);
static void DIAG_overtemperature_discharge(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event);
static void DIAG_undertemperature_charge(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event);
static void DIAG_undertemperature_discharge(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event);
static void DIAG_overcurrent_charge(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event);
static void DIAG_overcurrent_discharge(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event);
/* functions for system related events */
static void DIAG_error_cantiming(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event);
static void DIAG_error_ltc(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event);
static void DIAG_error_cancurrentsensor(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event);
static void DIAG_cont_feedback(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event);
static void DIAG_error_fuseState(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event);
static void DIAG_error_interlock(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event);
static void DIAG_error_insulation(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event);
static void DIAG_error_openWire(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event);
static void DIAG_error_deep_discharge_detected(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event);
static void DIAG_error_MCUdieTemperature(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event);
static void DIAG_error_coinCellVoltage(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event);
/* functions for plausibility related events */
static void DIAG_error_plausibility_check(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event);
/*================== Extern Constant and Variable Definitions ===============*/
/**
* Enable and Disable of Error Checks for Testing Purposes
*
* Each Bit enables or disables the diagnosis (checking of) the corresponding failure code
* FIXME struct isn't used anywhere in the code at the moment.
* FIXME delete if not needed
*/
DIAG_CODE_s diag_mask = {
.GENERALmsk = 0xFFFFFFFF,
.CELLMONmsk = 0xFFFFFFFF,
.COMmsk = 0xFFFFFFFF,
.ADCmsk = 0xFFFFFFFF,
};
DIAG_CH_CFG_s diag_ch_cfg[] = {
/* OS-Framework and startup events */
{DIAG_CH_FLASHCHECKSUM, "FLASHCHECKSUM", DIAG_ERROR_SENSITIVITY_HIGH, DIAG_RECORDING_ENABLED, DIAG_ENABLED, dummyfu},
{DIAG_CH_BKPDIAG_FAILURE, "BKPDIAG", DIAG_ERROR_SENSITIVITY_HIGH, DIAG_RECORDING_ENABLED, DIAG_ENABLED, dummyfu},
{DIAG_CH_WATCHDOGRESET_FAILURE, "WATCHDOGRESET", DIAG_ERROR_SENSITIVITY_HIGH, DIAG_RECORDING_ENABLED, DIAG_ENABLED, dummyfu},
{DIAG_CH_POSTOSINIT_FAILURE, "POSTOSINIT", DIAG_ERROR_SENSITIVITY_HIGH, DIAG_RECORDING_ENABLED, DIAG_ENABLED, dummyfu},
{DIAG_CH_CALIB_EEPR_FAILURE, "CALIB_EEPR", DIAG_ERROR_SENSITIVITY_HIGH, DIAG_RECORDING_ENABLED, DIAG_ENABLED, dummyfu},
{DIAG_CH_CAN_INIT_FAILURE, "CAN_INIT", DIAG_ERROR_SENSITIVITY_HIGH, DIAG_RECORDING_ENABLED, DIAG_ENABLED, dummyfu},
{DIAG_CH_VIC_INIT_FAILURE, "VIC_INIT", DIAG_ERROR_SENSITIVITY_HIGH, DIAG_RECORDING_ENABLED, DIAG_ENABLED, dummyfu},
/* HW-/SW-Runtime events */
{DIAG_CH_DIV_BY_ZERO_FAILURE, "DIV_BY_ZERO", DIAG_ERROR_SENSITIVITY_HIGH, DIAG_RECORDING_ENABLED, DIAG_ENABLED, dummyfu},
{DIAG_CH_UNDEF_INSTRUCTION_FAILURE, "UNDEF_INSTRUCTION", DIAG_ERROR_SENSITIVITY_HIGH, DIAG_RECORDING_ENABLED, DIAG_ENABLED, dummyfu},
{DIAG_CH_DATA_BUS_FAILURE, "DATA_BUS_FAILURE", DIAG_ERROR_SENSITIVITY_HIGH, DIAG_RECORDING_ENABLED, DIAG_ENABLED, dummyfu},
{DIAG_CH_INSTRUCTION_BUS_FAILURE, "INSTRUCTION_BUS", DIAG_ERROR_SENSITIVITY_HIGH, DIAG_RECORDING_ENABLED, DIAG_ENABLED, dummyfu},
{DIAG_CH_HARDFAULT_NOTHANDLED, "HARDFAULT_NOTHANDLED", DIAG_ERROR_SENSITIVITY_HIGH, DIAG_RECORDING_ENABLED, DIAG_ENABLED, dummyfu},
{DIAG_CH_CONFIGASSERT, "CONFIGASSERT", DIAG_ERROR_SENSITIVITY_HIGH, DIAG_RECORDING_ENABLED, DIAG_ENABLED, dummyfu},
{DIAG_CH_SYSTEMMONITORING_TIMEOUT, "SYSTEMMONITORING_TIMEOUT", DIAG_ERROR_SENSITIVITY_HIGH, DIAG_RECORDING_ENABLED, DIAG_ENABLED, dummyfu},
/* Measurement events */
{DIAG_CH_CANS_MAX_VALUE_VIOLATE, "CANS_MAX_VALUE_VIOLATE", DIAG_ERROR_SENSITIVITY_HIGH, DIAG_RECORDING_ENABLED, DIAG_ENABLED, dummyfu},
{DIAG_CH_CANS_MIN_VALUE_VIOLATE, "CANS_MIN_VALUE_VIOLATE", DIAG_ERROR_SENSITIVITY_HIGH, DIAG_RECORDING_ENABLED, DIAG_ENABLED, dummyfu},
{DIAG_CH_CANS_CAN_MOD_FAILURE, "CANS_CAN_MOD_FAILURE", DIAG_ERROR_SENSITIVITY_HIGH, DIAG_RECORDING_ENABLED, DIAG_ENABLED, dummyfu},
#if BUILD_MODULE_ENABLE_ISOGUARD == 1
{DIAG_CH_ISOMETER_TIM_ERROR, "ISOMETER_TIM_ERROR", DIAG_ERROR_SENSITIVITY_MID, DIAG_RECORDING_ENABLED, DIAG_ENABLED, dummyfu},
{DIAG_CH_ISOMETER_GROUNDERROR, "ISOMETER_GROUNDERROR", DIAG_ERROR_SENSITIVITY_HIGH, DIAG_RECORDING_ENABLED, DIAG_ENABLED, dummyfu},
{DIAG_CH_ISOMETER_ERROR, "ISOMETER_ERROR", DIAG_ERROR_SENSITIVITY_MID, DIAG_RECORDING_ENABLED, DIAG_ENABLED, dummyfu},
{DIAG_CH_ISOMETER_MEAS_INVALID, "ISOMETER_MEAS_INVALID", DIAG_ERROR_SENSITIVITY_HIGH, DIAG_RECORDING_ENABLED, DIAG_ENABLED, dummyfu},
{DIAG_CH_INSULATION_ERROR, "INSULATION_ERROR", DIAG_ERROR_INSULATION_SENSITIVITY, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_error_insulation},
#else
{DIAG_CH_ISOMETER_TIM_ERROR, "ISOMETER_TIM_ERROR", DIAG_ERROR_SENSITIVITY_MID, DIAG_RECORDING_DISABLED, DIAG_DISABLED, dummyfu},
{DIAG_CH_ISOMETER_GROUNDERROR, "ISOMETER_GROUNDERROR", DIAG_ERROR_SENSITIVITY_HIGH, DIAG_RECORDING_DISABLED, DIAG_DISABLED, dummyfu},
{DIAG_CH_ISOMETER_ERROR, "ISOMETER_ERROR", DIAG_ERROR_SENSITIVITY_MID, DIAG_RECORDING_DISABLED, DIAG_DISABLED, dummyfu},
{DIAG_CH_ISOMETER_MEAS_INVALID, "ISOMETER_MEAS_INVALID", DIAG_ERROR_SENSITIVITY_HIGH, DIAG_RECORDING_DISABLED, DIAG_DISABLED, dummyfu},
{DIAG_CH_INSULATION_ERROR, "INSULATION_ERROR", DIAG_ERROR_INSULATION_SENSITIVITY, DIAG_RECORDING_DISABLED, DIAG_DISABLED, dummyfu},
#endif
/* Under and over temperature, voltage and current at cell level */
{DIAG_CH_CELLVOLTAGE_OVERVOLTAGE_MSL, "CELLVOLT_OVERVOLT_MSL", DIAG_ERROR_VOLTAGE_SENSITIVITY_MSL, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_overvoltage},
{DIAG_CH_CELLVOLTAGE_OVERVOLTAGE_RSL, "CELLVOLT_OVERVOLT_RSL", DIAG_ERROR_VOLTAGE_SENSITIVITY_RSL, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_overvoltage},
{DIAG_CH_CELLVOLTAGE_OVERVOLTAGE_MOL, "CELLVOLT_OVERVOLT_MOL", DIAG_ERROR_VOLTAGE_SENSITIVITY_MOL, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_overvoltage},
{DIAG_CH_CELLVOLTAGE_UNDERVOLTAGE_MSL, "CELLVOLT_UNDERVOLT_MSL", DIAG_ERROR_VOLTAGE_SENSITIVITY_MSL, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_undervoltage},
{DIAG_CH_CELLVOLTAGE_UNDERVOLTAGE_RSL, "CELLVOLT_UNDERVOLT_RSL", DIAG_ERROR_VOLTAGE_SENSITIVITY_RSL, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_undervoltage},
{DIAG_CH_CELLVOLTAGE_UNDERVOLTAGE_MOL, "CELLVOLT_UNDERVOLT_MOL", DIAG_ERROR_VOLTAGE_SENSITIVITY_MOL, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_undervoltage},
{DIAG_CH_TEMP_OVERTEMPERATURE_CHARGE_MSL, "OVERTEMP_CHARGE_MSL", DIAG_ERROR_TEMPERATURE_SENSITIVITY_MSL, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_overtemperature_charge},
{DIAG_CH_TEMP_OVERTEMPERATURE_CHARGE_RSL, "OVERTEMP_CHARGE_RSL", DIAG_ERROR_TEMPERATURE_SENSITIVITY_RSL, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_overtemperature_charge},
{DIAG_CH_TEMP_OVERTEMPERATURE_CHARGE_MOL, "OVERTEMP_CHARGE_MOL", DIAG_ERROR_TEMPERATURE_SENSITIVITY_MOL, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_overtemperature_charge},
{DIAG_CH_TEMP_OVERTEMPERATURE_DISCHARGE_MSL, "OVERTEMP_DISCHARGE_MSL", DIAG_ERROR_TEMPERATURE_SENSITIVITY_MSL, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_overtemperature_discharge},
{DIAG_CH_TEMP_OVERTEMPERATURE_DISCHARGE_RSL, "OVERTEMP_DISCHARGE_RSL", DIAG_ERROR_TEMPERATURE_SENSITIVITY_MSL, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_overtemperature_discharge},
{DIAG_CH_TEMP_OVERTEMPERATURE_DISCHARGE_MOL, "OVERTEMP_DISCHARGE_MOL", DIAG_ERROR_TEMPERATURE_SENSITIVITY_MSL, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_overtemperature_discharge},
{DIAG_CH_TEMP_UNDERTEMPERATURE_CHARGE_MSL, "UNDERTEMP_CHARGE_MSL", DIAG_ERROR_TEMPERATURE_SENSITIVITY_MSL, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_undertemperature_charge},
{DIAG_CH_TEMP_UNDERTEMPERATURE_CHARGE_RSL, "UNDERTEMP_CHARGE_RSL", DIAG_ERROR_TEMPERATURE_SENSITIVITY_MSL, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_undertemperature_charge},
{DIAG_CH_TEMP_UNDERTEMPERATURE_CHARGE_MOL, "UNDERTEMP_CHARGE_MOL", DIAG_ERROR_TEMPERATURE_SENSITIVITY_MSL, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_undertemperature_charge},
{DIAG_CH_TEMP_UNDERTEMPERATURE_DISCHARGE_MSL, "UNDERTEMP_DISCHARGE_MSL", DIAG_ERROR_TEMPERATURE_SENSITIVITY_MSL, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_undertemperature_discharge},
{DIAG_CH_TEMP_UNDERTEMPERATURE_DISCHARGE_RSL, "UNDERTEMP_DISCHARGE_RSL", DIAG_ERROR_TEMPERATURE_SENSITIVITY_MSL, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_undertemperature_discharge},
{DIAG_CH_TEMP_UNDERTEMPERATURE_DISCHARGE_MOL, "UNDERTEMP_DISCHARGE_MOL", DIAG_ERROR_TEMPERATURE_SENSITIVITY_MSL, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_undertemperature_discharge},
{DIAG_CH_OVERCURRENT_PL_NONE, "OVERCUR_NO_POWERLINE", DIAG_ERROR_CURRENT_SENSITIVITY_MSL, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_overcurrent_charge},
{DIAG_CH_OVERCURRENT_CHARGE_CELL_MSL, "OVERCUR_CHRG_CELL_MSL", DIAG_ERROR_CURRENT_SENSITIVITY_MSL, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_overcurrent_charge},
{DIAG_CH_OVERCURRENT_CHARGE_CELL_RSL, "OVERCUR_CHRG_CELL_RSL", DIAG_ERROR_CURRENT_SENSITIVITY_RSL, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_overcurrent_charge},
{DIAG_CH_OVERCURRENT_CHARGE_CELL_MOL, "OVERCUR_CHRG_CELL_MOL", DIAG_ERROR_CURRENT_SENSITIVITY_MOL, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_overcurrent_charge},
{DIAG_CH_OVERCURRENT_DISCHARGE_CELL_MSL, "OVERCUR_DCHRG_CELL_MSL", DIAG_ERROR_CURRENT_SENSITIVITY_MSL, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_overcurrent_discharge},
{DIAG_CH_OVERCURRENT_DISCHARGE_CELL_RSL, "OVERCUR_DCHRG_CELL_RSL", DIAG_ERROR_CURRENT_SENSITIVITY_RSL, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_overcurrent_discharge},
{DIAG_CH_OVERCURRENT_DISCHARGE_CELL_MOL, "OVERCUR_DCHRG_CELL_MOL", DIAG_ERROR_CURRENT_SENSITIVITY_MOL, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_overcurrent_discharge},
{DIAG_CH_OVERCURRENT_CHARGE_PL0_MSL, "OVERCUR_CHRG_PL0_MSL", DIAG_ERROR_CURRENT_SENSITIVITY_MSL, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_overcurrent_charge},
{DIAG_CH_OVERCURRENT_CHARGE_PL0_RSL, "OVERCUR_CHRG_PL0_RSL", DIAG_ERROR_CURRENT_SENSITIVITY_RSL, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_overcurrent_charge},
{DIAG_CH_OVERCURRENT_CHARGE_PL0_MOL, "OVERCUR_CHRG_PL0_MOL", DIAG_ERROR_CURRENT_SENSITIVITY_MOL, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_overcurrent_charge},
{DIAG_CH_OVERCURRENT_DISCHARGE_PL0_MSL, "OVERCUR_DCHRG_PL0_MSL", DIAG_ERROR_CURRENT_SENSITIVITY_MSL, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_overcurrent_discharge},
{DIAG_CH_OVERCURRENT_DISCHARGE_PL0_RSL, "OVERCUR_DCHRG_PL0_RSL", DIAG_ERROR_CURRENT_SENSITIVITY_RSL, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_overcurrent_discharge},
{DIAG_CH_OVERCURRENT_DISCHARGE_PL0_MOL, "OVERCUR_DCHRG_PL0_MOL", DIAG_ERROR_CURRENT_SENSITIVITY_MOL, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_overcurrent_discharge},
{DIAG_CH_OVERCURRENT_CHARGE_PL1_MSL, "OVERCUR_CHRG_PL1_MSL", DIAG_ERROR_CURRENT_SENSITIVITY_MSL, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_overcurrent_charge},
{DIAG_CH_OVERCURRENT_CHARGE_PL1_RSL, "OVERCUR_CHRG_PL1_RSL", DIAG_ERROR_CURRENT_SENSITIVITY_RSL, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_overcurrent_charge},
{DIAG_CH_OVERCURRENT_CHARGE_PL1_MOL, "OVERCUR_CHRG_PL1_MOL", DIAG_ERROR_CURRENT_SENSITIVITY_MOL, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_overcurrent_charge},
{DIAG_CH_OVERCURRENT_DISCHARGE_PL1_MSL, "OVERCUR_DCHRG_PL1_MSL", DIAG_ERROR_CURRENT_SENSITIVITY_MSL, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_overcurrent_discharge},
{DIAG_CH_OVERCURRENT_DISCHARGE_PL1_RSL, "OVERCUR_DCHRG_PL1_RSL", DIAG_ERROR_CURRENT_SENSITIVITY_RSL, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_overcurrent_discharge},
{DIAG_CH_OVERCURRENT_DISCHARGE_PL1_MOL, "OVERCUR_DCHRG_PL1_MOL", DIAG_ERROR_CURRENT_SENSITIVITY_MOL, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_overcurrent_discharge},
{DIAG_CH_LTC_SPI, "LTC_SPI", DIAG_ERROR_LTC_SPI_SENSITIVITY, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_error_ltc},
{DIAG_CH_LTC_PEC, "LTC_PEC", DIAG_ERROR_LTC_PEC_SENSITIVITY, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_error_ltc},
{DIAG_CH_LTC_MUX, "LTC_MUX", DIAG_ERROR_LTC_MUX_SENSITIVITY, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_error_ltc},
{DIAG_CH_LTC_CONFIG, "LTC_CONFIG", DIAG_ERROR_SENSITIVITY_HIGH, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_error_ltc},
/* Communication events */
{DIAG_CH_CAN_TIMING, "CAN_TIMING", DIAG_ERROR_CAN_TIMING_SENSITIVITY, DIAG_RECORDING_ENABLED, DIAG_CAN_TIMING, DIAG_error_cantiming},
{DIAG_CH_CAN_CC_RESPONDING, "CAN_CC_RESPONDING", DIAG_ERROR_CAN_TIMING_CC_SENSITIVITY, DIAG_RECORDING_ENABLED, DIAG_CAN_SENSOR_PRESENT, DIAG_error_cantiming},
{DIAG_CH_CURRENT_SENSOR_RESPONDING, "CURRENT_SENSOR_RESPONDING", DIAG_ERROR_CAN_SENSOR_SENSITIVITY, DIAG_RECORDING_ENABLED, DIAG_CAN_SENSOR_PRESENT, DIAG_error_cancurrentsensor},
#if BUILD_MODULE_ENABLE_CONTACTOR == 1
/* Contactor Damage Error */
{DIAG_CH_CONTACTOR_DAMAGED, "CONTACTOR_DAMAGED", DIAG_ERROR_SENSITIVITY_HIGH, DIAG_RECORDING_ENABLED, DIAG_ENABLED, dummyfu},
{DIAG_CH_CONTACTOR_OPENING, "CONTACTOR_OPENING", DIAG_ERROR_SENSITIVITY_HIGH, DIAG_RECORDING_ENABLED, DIAG_ENABLED, dummyfu},
{DIAG_CH_CONTACTOR_CLOSING, "CONTACTOR_CLOSING", DIAG_ERROR_SENSITIVITY_HIGH, DIAG_RECORDING_ENABLED, DIAG_ENABLED, dummyfu},
/* Contactor Feedback Error */
{DIAG_CH_CONTACTOR_MAIN_PLUS_FEEDBACK, "CONT_MAIN_PLUS_FEED", DIAG_ERROR_MAIN_PLUS_SENSITIVITY, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_cont_feedback },
{DIAG_CH_CONTACTOR_MAIN_MINUS_FEEDBACK, "CONT_MAIN_MINUS_FEED", DIAG_ERROR_MAIN_MINUS_SENSITIVITY, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_cont_feedback },
{DIAG_CH_CONTACTOR_PRECHARGE_FEEDBACK, "CONT_PRECHARGE_FEED", DIAG_ERROR_PRECHARGE_SENSITIVITY, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_cont_feedback },
{DIAG_CH_CONTACTOR_CHARGE_MAIN_PLUS_FEEDBACK, "CONT_CHRGE_MAIN_PLUS_FEED", DIAG_ERROR_MAIN_PLUS_SENSITIVITY, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_cont_feedback },
{DIAG_CH_CONTACTOR_CHARGE_MAIN_MINUS_FEEDBACK, "CONT_CHRGE_MAIN_MINUS_FEED", DIAG_ERROR_MAIN_MINUS_SENSITIVITY, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_cont_feedback },
{DIAG_CH_CONTACTOR_CHARGE_PRECHARGE_FEEDBACK, "CONT_CHRGE_PRECHARGE_FEED", DIAG_ERROR_PRECHARGE_SENSITIVITY, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_cont_feedback },
/* Fuse state */
{DIAG_CH_FUSE_STATE_NORMAL, "FUSE_STATE_NORMAL", DIAG_ERROR_SENSITIVITY_LOW, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_error_fuseState },
{DIAG_CH_FUSE_STATE_CHARGE, "FUSE_STATE_CHARGE", DIAG_ERROR_SENSITIVITY_LOW, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_error_fuseState },
#else
/* Contactor Damage Error */
{DIAG_CH_CONTACTOR_DAMAGED, "CONTACTOR_DAMAGED", DIAG_ERROR_SENSITIVITY_HIGH, DIAG_RECORDING_DISABLED, DIAG_DISABLED, dummyfu},
{DIAG_CH_CONTACTOR_OPENING, "CONTACTOR_OPENING", DIAG_ERROR_SENSITIVITY_HIGH, DIAG_RECORDING_DISABLED, DIAG_DISABLED, dummyfu},
{DIAG_CH_CONTACTOR_CLOSING, "CONTACTOR_CLOSING", DIAG_ERROR_SENSITIVITY_HIGH, DIAG_RECORDING_DISABLED, DIAG_DISABLED, dummyfu},
/* Contactor Feedback Error */
{DIAG_CH_CONTACTOR_MAIN_PLUS_FEEDBACK, "CONT_MAIN_PLUS_FEED", DIAG_ERROR_MAIN_PLUS_SENSITIVITY, DIAG_RECORDING_DISABLED, DIAG_DISABLED, DIAG_cont_feedback},
{DIAG_CH_CONTACTOR_MAIN_MINUS_FEEDBACK, "CONT_MAIN_MINUS_FEED", DIAG_ERROR_MAIN_MINUS_SENSITIVITY, DIAG_RECORDING_DISABLED, DIAG_DISABLED, DIAG_cont_feedback},
{DIAG_CH_CONTACTOR_PRECHARGE_FEEDBACK, "CONT_PRECHARGE_FEED", DIAG_ERROR_PRECHARGE_SENSITIVITY, DIAG_RECORDING_DISABLED, DIAG_DISABLED, DIAG_cont_feedback},
{DIAG_CH_CONTACTOR_CHARGE_MAIN_PLUS_FEEDBACK, "CONT_CHRGE_MAIN_PLUS_FEED", DIAG_ERROR_MAIN_PLUS_SENSITIVITY, DIAG_RECORDING_DISABLED, DIAG_DISABLED, DIAG_cont_feedback},
{DIAG_CH_CONTACTOR_CHARGE_MAIN_MINUS_FEEDBACK, "CONT_CHRGE_MAIN_MINUS_FEED", DIAG_ERROR_MAIN_MINUS_SENSITIVITY, DIAG_RECORDING_DISABLED, DIAG_DISABLED, DIAG_cont_feedback},
{DIAG_CH_CONTACTOR_CHARGE_PRECHARGE_FEEDBACK, "CONT_CHRGE_PRECHARGE_FEED", DIAG_ERROR_PRECHARGE_SENSITIVITY, DIAG_RECORDING_DISABLED, DIAG_DISABLED, DIAG_cont_feedback},
/* Fuse state */
{DIAG_CH_FUSE_STATE_NORMAL, "FUSE_STATE_NORMAL", DIAG_ERROR_SENSITIVITY_LOW, DIAG_RECORDING_DISABLED, DIAG_DISABLED, DIAG_error_fuseState},
{DIAG_CH_FUSE_STATE_CHARGE, "FUSE_STATE_CHARGE", DIAG_ERROR_SENSITIVITY_LOW, DIAG_RECORDING_DISABLED, DIAG_DISABLED, DIAG_error_fuseState},
#endif
#if BUILD_MODULE_ENABLE_ILCK == 1
/* Interlock Feedback Error */
{DIAG_CH_INTERLOCK_FEEDBACK, "INTERLOCK_FEEDBACK", DIAG_ERROR_INTERLOCK_SENSITIVITY, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_error_interlock},
#else
{DIAG_CH_INTERLOCK_FEEDBACK, "INTERLOCK_FEEDBACK", DIAG_ERROR_INTERLOCK_SENSITIVITY, DIAG_RECORDING_DISABLED, DIAG_DISABLED, DIAG_error_interlock},
#endif
/* Slave PCB temperature errors for under and over temperature */
{DIAG_CH_SLAVE_PCB_UNDERTEMPERATURE_MSL, "SLAVE_PCB_UNDERTEMP_MSL", DIAG_ERROR_SLAVE_TEMP_SENSITIVITY_MSL, DIAG_RECORDING_ENABLED, DIAG_ENABLED, dummyfu},
{DIAG_CH_SLAVE_PCB_UNDERTEMPERATURE_RSL, "SLAVE_PCB_UNDERTEMP_RSL", DIAG_ERROR_SLAVE_TEMP_SENSITIVITY_RSL, DIAG_RECORDING_ENABLED, DIAG_ENABLED, dummyfu},
{DIAG_CH_SLAVE_PCB_UNDERTEMPERATURE_MOL, "SLAVE_PCB_UNDERTEMP_MOL", DIAG_ERROR_SLAVE_TEMP_SENSITIVITY_MOL, DIAG_RECORDING_ENABLED, DIAG_ENABLED, dummyfu},
{DIAG_CH_SLAVE_PCB_OVERTEMPERATURE_MSL, "SLAVE_PCB_OVERTEMP_MSL", DIAG_ERROR_SLAVE_TEMP_SENSITIVITY_MSL, DIAG_RECORDING_ENABLED, DIAG_ENABLED, dummyfu},
{DIAG_CH_SLAVE_PCB_OVERTEMPERATURE_RSL, "SLAVE_PCB_OVERTEMP_RSL", DIAG_ERROR_SLAVE_TEMP_SENSITIVITY_RSL, DIAG_RECORDING_ENABLED, DIAG_ENABLED, dummyfu},
{DIAG_CH_SLAVE_PCB_OVERTEMPERATURE_MOL, "SLAVE_PCB_OVERTEMP_MOL", DIAG_ERROR_SLAVE_TEMP_SENSITIVITY_MOL, DIAG_RECORDING_ENABLED, DIAG_ENABLED, dummyfu},
{DIAG_CH_ERROR_MCU_DIE_TEMPERATURE, "MCU_DIE_TEMPERATURE", DIAG_ERROR_SENSITIVITY_LOW, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_error_MCUdieTemperature},
{DIAG_CH_LOW_COIN_CELL_VOLTAGE, "COIN_CELL_VOLT_LOW", DIAG_ERROR_SENSITIVITY_LOW, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_error_coinCellVoltage},
{DIAG_CH_CRIT_LOW_COIN_CELL_VOLTAGE, "COIN_CELL_VOLT_CRITICAL", DIAG_ERROR_SENSITIVITY_LOW, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_error_coinCellVoltage},
{DIAG_CH_OPEN_WIRE, "OPEN_WIRE", DIAG_ERROR_SENSITIVITY_HIGH, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_error_openWire},
{DIAG_CH_DEEP_DISCHARGE_DETECTED, "DEEP-DISCHARGE detected", DIAG_ERROR_SENSITIVITY_HIGH, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_error_deep_discharge_detected},
/* Plausibility checks */
{DIAG_CH_PLAUSIBILITY_CELL_VOLTAGE, "PL_CELL_VOLT", DIAG_ERROR_SENSITIVITY_HIGH, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_error_plausibility_check},
{DIAG_CH_PLAUSIBILITY_CELL_TEMP, "PL_CELL_TEMP", DIAG_ERROR_SENSITIVITY_HIGH, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_error_plausibility_check},
{DIAG_CH_PLAUSIBILITY_PACK_VOLTAGE, "PL_PACK_VOLT", DIAG_ERROR_PLAUSIBILITY_PACK_SENSITIVITY, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_error_plausibility_check},
};
DIAG_SYSMON_CH_CFG_s diag_sysmon_ch_cfg[] = {
{DIAG_SYSMON_DATABASE_ID, DIAG_SYSMON_CYCLICTASK, 10, DIAG_RECORDING_ENABLED, DIAG_SYSMON_HANDLING_SWITCHOFFCONTACTOR, DIAG_ENABLED, dummyfu2},
{DIAG_SYSMON_SYS_ID, DIAG_SYSMON_CYCLICTASK, 20, DIAG_RECORDING_ENABLED, DIAG_SYSMON_HANDLING_SWITCHOFFCONTACTOR, DIAG_ENABLED, dummyfu2},
{DIAG_SYSMON_BMS_ID, DIAG_SYSMON_CYCLICTASK, 20, DIAG_RECORDING_ENABLED, DIAG_SYSMON_HANDLING_SWITCHOFFCONTACTOR, DIAG_ENABLED, dummyfu2},
#if BUILD_MODULE_ENABLE_CONTACTOR == 1
{DIAG_SYSMON_CONT_ID, DIAG_SYSMON_CYCLICTASK, 20, DIAG_RECORDING_ENABLED, DIAG_SYSMON_HANDLING_SWITCHOFFCONTACTOR, DIAG_ENABLED, dummyfu2},
#else
{DIAG_SYSMON_CONT_ID, DIAG_SYSMON_CYCLICTASK, 20, DIAG_RECORDING_DISABLED, DIAG_SYSMON_HANDLING_SWITCHOFFCONTACTOR, DIAG_DISABLED, dummyfu2},
#endif
#if BUILD_MODULE_ENABLE_ILCK == 1
{DIAG_SYSMON_ILCK_ID, DIAG_SYSMON_CYCLICTASK, 20, DIAG_RECORDING_ENABLED, DIAG_SYSMON_HANDLING_SWITCHOFFCONTACTOR, DIAG_ENABLED, dummyfu2},
#else
{DIAG_SYSMON_ILCK_ID, DIAG_SYSMON_CYCLICTASK, 20, DIAG_RECORDING_DISABLED, DIAG_SYSMON_HANDLING_SWITCHOFFCONTACTOR, DIAG_DISABLED, dummyfu2},
#endif
{DIAG_SYSMON_LTC_ID, DIAG_SYSMON_CYCLICTASK, 5, DIAG_RECORDING_ENABLED, DIAG_SYSMON_HANDLING_SWITCHOFFCONTACTOR, DIAG_ENABLED, dummyfu2},
#if BUILD_MODULE_ENABLE_ISOGUARD == 1
{DIAG_SYSMON_ISOGUARD_ID, DIAG_SYSMON_CYCLICTASK, 400, DIAG_RECORDING_ENABLED, DIAG_SYSMON_HANDLING_SWITCHOFFCONTACTOR, DIAG_ENABLED, dummyfu2},
#else
{DIAG_SYSMON_ISOGUARD_ID, DIAG_SYSMON_CYCLICTASK, 400, DIAG_RECORDING_DISABLED, DIAG_SYSMON_HANDLING_SWITCHOFFCONTACTOR, DIAG_DISABLED, dummyfu2},
#endif
{DIAG_SYSMON_CANS_ID, DIAG_SYSMON_CYCLICTASK, 20, DIAG_RECORDING_ENABLED, DIAG_SYSMON_HANDLING_SWITCHOFFCONTACTOR, DIAG_ENABLED, dummyfu2},
{DIAG_SYSMON_APPL_CYCLIC_1ms, DIAG_SYSMON_CYCLICTASK, 20, DIAG_RECORDING_ENABLED, DIAG_SYSMON_HANDLING_SWITCHOFFCONTACTOR, DIAG_ENABLED, dummyfu2},
{DIAG_SYSMON_APPL_CYCLIC_10ms, DIAG_SYSMON_CYCLICTASK, 20, DIAG_RECORDING_ENABLED, DIAG_SYSMON_HANDLING_SWITCHOFFCONTACTOR, DIAG_ENABLED, dummyfu2},
{DIAG_SYSMON_APPL_CYCLIC_100ms, DIAG_SYSMON_CYCLICTASK, 200, DIAG_RECORDING_ENABLED, DIAG_SYSMON_HANDLING_SWITCHOFFCONTACTOR, DIAG_ENABLED, dummyfu2},
};
DIAG_DEV_s diag_dev = {
.nr_of_ch = sizeof(diag_ch_cfg)/sizeof(DIAG_CH_CFG_s),
.ch_cfg = &diag_ch_cfg[0],
};
/*================== Static Function Implementations ========================*/
/**
* @brief dummy callback function of diagnosis events
*/
void dummyfu(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event) {
/* Dummy function -> empty */
}
/**
* @brief dummy callback function of system monitoring error events
*/
void dummyfu2(DIAG_SYSMON_MODULE_ID_e ch_id) {
/* Dummy function -> empty */
}
/**
* @brief diagnosis callback function for overvoltage events
*/
static void DIAG_overvoltage(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event) {
if (ch_id == DIAG_CH_CELLVOLTAGE_OVERVOLTAGE_MSL) {
if (event == DIAG_EVENT_RESET) {
msl_flags.over_voltage = 0;
}
if (event == DIAG_EVENT_NOK) {
msl_flags.over_voltage = 1;
}
} else if (ch_id == DIAG_CH_CELLVOLTAGE_OVERVOLTAGE_RSL) {
if (event == DIAG_EVENT_RESET) {
rsl_flags.over_voltage = 0;
}
if (event == DIAG_EVENT_NOK) {
rsl_flags.over_voltage = 1;
}
} else if (ch_id == DIAG_CH_CELLVOLTAGE_OVERVOLTAGE_MOL) {
if (event == DIAG_EVENT_RESET) {
mol_flags.over_voltage = 0;
}
if (event == DIAG_EVENT_NOK) {
mol_flags.over_voltage = 1;
}
}
}
/**
* @brief diagnosis callback function for undervoltage events
*/
static void DIAG_undervoltage(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event) {
if (ch_id == DIAG_CH_CELLVOLTAGE_UNDERVOLTAGE_MSL) {
if (event == DIAG_EVENT_RESET) {
msl_flags.under_voltage = 0;
}
if (event == DIAG_EVENT_NOK) {
msl_flags.under_voltage = 1;
}
} else if (ch_id == DIAG_CH_CELLVOLTAGE_UNDERVOLTAGE_RSL) {
if (event == DIAG_EVENT_RESET) {
rsl_flags.under_voltage = 0;
}
if (event == DIAG_EVENT_NOK) {
rsl_flags.under_voltage = 1;
}
} else if (ch_id == DIAG_CH_CELLVOLTAGE_UNDERVOLTAGE_MOL) {
if (event == DIAG_EVENT_RESET) {
mol_flags.under_voltage = 0;
}
if (event == DIAG_EVENT_NOK) {
mol_flags.under_voltage = 1;
}
}
}
/**
* @brief diagnosis callback function for overtemperature charge events
*/
static void DIAG_overtemperature_charge(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event) {
if (ch_id == DIAG_CH_TEMP_OVERTEMPERATURE_CHARGE_MSL) {
if (event == DIAG_EVENT_RESET) {
msl_flags.over_temperature_charge = 0;
}
if (event == DIAG_EVENT_NOK) {
msl_flags.over_temperature_charge = 1;
}
} else if (ch_id == DIAG_CH_TEMP_OVERTEMPERATURE_CHARGE_RSL) {
if (event == DIAG_EVENT_RESET) {
rsl_flags.over_temperature_charge = 0;
}
if (event == DIAG_EVENT_NOK) {
rsl_flags.over_temperature_charge = 1;
}
} else if (ch_id == DIAG_CH_TEMP_OVERTEMPERATURE_CHARGE_MOL) {
if (event == DIAG_EVENT_RESET) {
mol_flags.over_temperature_charge = 0;
}
if (event == DIAG_EVENT_NOK) {
mol_flags.over_temperature_charge = 1;
}
}
}
/**
* @brief diagnosis callback function for overtemperature discharge events
*/
static void DIAG_overtemperature_discharge(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event) {
if (ch_id == DIAG_CH_TEMP_OVERTEMPERATURE_DISCHARGE_MSL) {
if (event == DIAG_EVENT_RESET) {
msl_flags.over_temperature_discharge = 0;
}
if (event == DIAG_EVENT_NOK) {
msl_flags.over_temperature_discharge = 1;
}
} else if (ch_id == DIAG_CH_TEMP_OVERTEMPERATURE_DISCHARGE_RSL) {
if (event == DIAG_EVENT_RESET) {
rsl_flags.over_temperature_discharge = 0;
}
if (event == DIAG_EVENT_NOK) {
rsl_flags.over_temperature_discharge = 1;
}
} else if (ch_id == DIAG_CH_TEMP_OVERTEMPERATURE_DISCHARGE_MOL) {
if (event == DIAG_EVENT_RESET) {
mol_flags.over_temperature_discharge = 0;
}
if (event == DIAG_EVENT_NOK) {
mol_flags.over_temperature_discharge = 1;
}
}
}
/**
* @brief diagnosis callback function for undertemperature charge events
*/
static void DIAG_undertemperature_charge(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event) {
if (ch_id == DIAG_CH_TEMP_UNDERTEMPERATURE_CHARGE_MSL) {
if (event == DIAG_EVENT_RESET) {
msl_flags.under_temperature_charge = 0;
}
if (event == DIAG_EVENT_NOK) {
msl_flags.under_temperature_charge = 1;
}
} else if (ch_id == DIAG_CH_TEMP_UNDERTEMPERATURE_CHARGE_RSL) {
if (event == DIAG_EVENT_RESET) {
rsl_flags.under_temperature_charge = 0;
}
if (event == DIAG_EVENT_NOK) {
rsl_flags.under_temperature_charge = 1;
}
} else if (ch_id == DIAG_CH_TEMP_UNDERTEMPERATURE_CHARGE_MOL) {
if (event == DIAG_EVENT_RESET) {
mol_flags.under_temperature_charge = 0;
}
if (event == DIAG_EVENT_NOK) {
mol_flags.under_temperature_charge = 1;
}
}
}
/**
* @brief diagnosis callback function for undertemperature discharge events
*/
static void DIAG_undertemperature_discharge(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event) {
if (ch_id == DIAG_CH_TEMP_UNDERTEMPERATURE_DISCHARGE_MSL) {
if (event == DIAG_EVENT_RESET) {
msl_flags.under_temperature_discharge = 0;
}
if (event == DIAG_EVENT_NOK) {
msl_flags.under_temperature_discharge = 1;
}
} else if (ch_id == DIAG_CH_TEMP_UNDERTEMPERATURE_DISCHARGE_RSL) {
if (event == DIAG_EVENT_RESET) {
rsl_flags.under_temperature_discharge = 0;
}
if (event == DIAG_EVENT_NOK) {
rsl_flags.under_temperature_discharge = 1;
}
} else if (ch_id == DIAG_CH_TEMP_UNDERTEMPERATURE_DISCHARGE_MOL) {
if (event == DIAG_EVENT_RESET) {
mol_flags.under_temperature_discharge = 0;
}
if (event == DIAG_EVENT_NOK) {
mol_flags.under_temperature_discharge = 1;
}
}
}
/**
* @brief diagnosis callback function for overcurrent charge events
*/
static void DIAG_overcurrent_charge(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event) {
switch (ch_id) {
case DIAG_CH_OVERCURRENT_CHARGE_CELL_MSL:
if (event == DIAG_EVENT_RESET) {
msl_flags.over_current_charge_cell = 0;
} else if (event == DIAG_EVENT_NOK) {
msl_flags.over_current_charge_cell = 1;
} else {
/* no relevant event, do nothing */
}
break;
case DIAG_CH_OVERCURRENT_CHARGE_CELL_RSL:
if (event == DIAG_EVENT_RESET) {
rsl_flags.over_current_charge_cell = 0;
} else if (event == DIAG_EVENT_NOK) {
rsl_flags.over_current_charge_cell = 1;
} else {
/* no relevant event, do nothing */
}
break;
case DIAG_CH_OVERCURRENT_CHARGE_CELL_MOL:
if (event == DIAG_EVENT_RESET) {
mol_flags.over_current_charge_cell = 0;
} else if (event == DIAG_EVENT_NOK) {
mol_flags.over_current_charge_cell = 1;
} else {
/* no relevant event, do nothing */
}
break;
case DIAG_CH_OVERCURRENT_CHARGE_PL0_MSL:
if (event == DIAG_EVENT_RESET) {
msl_flags.over_current_charge_pl0 = 0;
} else if (event == DIAG_EVENT_NOK) {
msl_flags.over_current_charge_pl0 = 1;
} else {
/* no relevant event, do nothing */
}
break;
case DIAG_CH_OVERCURRENT_CHARGE_PL0_RSL:
if (event == DIAG_EVENT_RESET) {
rsl_flags.over_current_charge_pl0 = 0;
} else if (event == DIAG_EVENT_NOK) {
rsl_flags.over_current_charge_pl0 = 1;
} else {
/* no relevant event, do nothing */
}
break;
case DIAG_CH_OVERCURRENT_CHARGE_PL0_MOL:
if (event == DIAG_EVENT_RESET) {
mol_flags.over_current_charge_pl0 = 0;
} else if (event == DIAG_EVENT_NOK) {
mol_flags.over_current_charge_pl0 = 1;
} else {
/* no relevant event, do nothing */
}
break;
case DIAG_CH_OVERCURRENT_CHARGE_PL1_MSL:
if (event == DIAG_EVENT_RESET) {
msl_flags.over_current_charge_pl1 = 0;
} else if (event == DIAG_EVENT_NOK) {
msl_flags.over_current_charge_pl1 = 1;
} else {
/* no relevant event, do nothing */
}
break;
case DIAG_CH_OVERCURRENT_CHARGE_PL1_RSL:
if (event == DIAG_EVENT_RESET) {
rsl_flags.over_current_charge_pl1 = 0;
} else if (event == DIAG_EVENT_NOK) {
rsl_flags.over_current_charge_pl1 = 1;
} else {
/* no relevant event, do nothing */
}
break;
case DIAG_CH_OVERCURRENT_CHARGE_PL1_MOL:
if (event == DIAG_EVENT_RESET) {
mol_flags.over_current_charge_pl1 = 0;
} else if (event == DIAG_EVENT_NOK) {
mol_flags.over_current_charge_pl1 = 1;
} else {
/* no relevant event, do nothing */
}
break;
case DIAG_CH_OVERCURRENT_PL_NONE:
if (event == DIAG_EVENT_RESET) {
error_flags.currentOnOpenPowerline = 0;
} else if (event == DIAG_EVENT_NOK) {
error_flags.currentOnOpenPowerline = 1;
} else {
/* no relevant event, do nothing */
}
break;
default:
/* no relevant channel, do nothing */
break;
}
}
/**
* @brief diagnosis callback function for overcurrent discharge events
*/
static void DIAG_overcurrent_discharge(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event) {
switch (ch_id) {
case DIAG_CH_OVERCURRENT_DISCHARGE_CELL_MSL:
if (event == DIAG_EVENT_RESET) {
msl_flags.over_current_discharge_cell = 0;
} else if (event == DIAG_EVENT_NOK) {
msl_flags.over_current_discharge_cell = 1;
} else {
/* no relevant event, do nothing */
}
break;
case DIAG_CH_OVERCURRENT_DISCHARGE_CELL_RSL:
if (event == DIAG_EVENT_RESET) {
rsl_flags.over_current_discharge_cell = 0;
} else if (event == DIAG_EVENT_NOK) {
rsl_flags.over_current_discharge_cell = 1;
} else {
/* no relevant event, do nothing */
}
break;
case DIAG_CH_OVERCURRENT_DISCHARGE_CELL_MOL:
if (event == DIAG_EVENT_RESET) {
mol_flags.over_current_discharge_cell = 0;
} else if (event == DIAG_EVENT_NOK) {
mol_flags.over_current_discharge_cell = 1;
} else {
/* no relevant event, do nothing */
}
break;
case DIAG_CH_OVERCURRENT_DISCHARGE_PL0_MSL:
if (event == DIAG_EVENT_RESET) {
msl_flags.over_current_discharge_pl0 = 0;
} else if (event == DIAG_EVENT_NOK) {
msl_flags.over_current_discharge_pl0 = 1;
} else {
/* no relevant event, do nothing */
}
break;
case DIAG_CH_OVERCURRENT_DISCHARGE_PL0_RSL:
if (event == DIAG_EVENT_RESET) {
rsl_flags.over_current_discharge_pl0 = 0;
} else if (event == DIAG_EVENT_NOK) {
rsl_flags.over_current_discharge_pl0 = 1;
} else {
/* no relevant event, do nothing */
}
break;
case DIAG_CH_OVERCURRENT_DISCHARGE_PL0_MOL:
if (event == DIAG_EVENT_RESET) {
mol_flags.over_current_discharge_pl0 = 0;
} else if (event == DIAG_EVENT_NOK) {
mol_flags.over_current_discharge_pl0 = 1;
} else {
/* no relevant event, do nothing */
}
break;
case DIAG_CH_OVERCURRENT_DISCHARGE_PL1_MSL:
if (event == DIAG_EVENT_RESET) {
msl_flags.over_current_discharge_pl1 = 0;
} else if (event == DIAG_EVENT_NOK) {
msl_flags.over_current_discharge_pl1 = 1;
} else {
/* no relevant event, do nothing */
}
break;
case DIAG_CH_OVERCURRENT_DISCHARGE_PL1_RSL:
if (event == DIAG_EVENT_RESET) {
rsl_flags.over_current_discharge_pl1 = 0;
} else if (event == DIAG_EVENT_NOK) {
rsl_flags.over_current_discharge_pl1 = 1;
} else {
/* no relevant event, do nothing */
}
break;
case DIAG_CH_OVERCURRENT_DISCHARGE_PL1_MOL:
if (event == DIAG_EVENT_RESET) {
mol_flags.over_current_discharge_pl1 = 0;
} else if (event == DIAG_EVENT_NOK) {
mol_flags.over_current_discharge_pl1 = 1;
} else {
/* no relevant event, do nothing */
}
break;
default:
/* no relevant channel, do nothing */
break;
}
}
/**
* @brief diagnosis callback function for can related events
*/
void DIAG_error_cantiming(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event) {
if (ch_id == DIAG_CH_CAN_TIMING) {
if (event == DIAG_EVENT_RESET) {
error_flags.can_timing = 0;
}
if (event == DIAG_EVENT_NOK) {
error_flags.can_timing = 1;
}
} else if (ch_id == DIAG_CH_CAN_CC_RESPONDING) {
if (event == DIAG_EVENT_RESET) {
error_flags.can_timing_cc = 0;
}
if (event == DIAG_EVENT_NOK) {
error_flags.can_timing_cc = 1;
}
}
}
/**
* @brief diagnosis callback function for current sensor related events
*/
void DIAG_error_cancurrentsensor(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event) {
if (ch_id == DIAG_CH_CURRENT_SENSOR_RESPONDING) {
if (event == DIAG_EVENT_RESET) {
error_flags.currentsensorresponding = 0;
}
if (event == DIAG_EVENT_NOK) {
error_flags.currentsensorresponding = 1;
}
}
}
/**
* @brief diagnosis callback function for LTC module related events
*/
static void DIAG_error_ltc(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event) {
if (ch_id == DIAG_CH_LTC_SPI) {
if (event == DIAG_EVENT_RESET) {
error_flags.spi_error = 0;
}
if (event == DIAG_EVENT_NOK) {
error_flags.spi_error = 1;
}
} else if (ch_id == DIAG_CH_LTC_PEC) {
if (event == DIAG_EVENT_RESET) {
error_flags.crc_error = 0;
}
if (event == DIAG_EVENT_NOK) {
error_flags.crc_error = 1;
}
} else if (ch_id == DIAG_CH_LTC_MUX) {
if (event == DIAG_EVENT_RESET) {
error_flags.mux_error = 0;
}
if (event == DIAG_EVENT_NOK) {
error_flags.mux_error = 1;
}
} else if (ch_id == DIAG_CH_LTC_CONFIG) {
if (event == DIAG_EVENT_RESET) {
error_flags.ltc_config_error = 0;
}
if (event == DIAG_EVENT_NOK) {
error_flags.ltc_config_error = 1;
}
}
}
/**
* @brief diagnosis callback function for contactor feedback events
*/
void DIAG_cont_feedback(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event) {
if (ch_id == DIAG_CH_CONTACTOR_MAIN_PLUS_FEEDBACK) {
if (event == DIAG_EVENT_RESET) {
error_flags.main_plus = 0;
}
if (event == DIAG_EVENT_NOK) {
error_flags.main_plus = 1;
}
} else if (ch_id == DIAG_CH_CONTACTOR_MAIN_MINUS_FEEDBACK) {
if (event == DIAG_EVENT_RESET) {
error_flags.main_minus = 0;
}
if (event == DIAG_EVENT_NOK) {
error_flags.main_minus = 1;
}
} else if (ch_id == DIAG_CH_CONTACTOR_PRECHARGE_FEEDBACK) {
if (event == DIAG_EVENT_RESET) {
error_flags.precharge = 0;
}
if (event == DIAG_EVENT_NOK) {
error_flags.precharge = 1;
}
} else if (ch_id == DIAG_CH_CONTACTOR_CHARGE_MAIN_PLUS_FEEDBACK) {
if (event == DIAG_EVENT_RESET) {
error_flags.charge_main_plus = 0;
}
if (event == DIAG_EVENT_NOK) {
error_flags.charge_main_plus = 1;
}
} else if (ch_id == DIAG_CH_CONTACTOR_CHARGE_MAIN_MINUS_FEEDBACK) {
if (event == DIAG_EVENT_RESET) {
error_flags.charge_main_minus = 0;
}
if (event == DIAG_EVENT_NOK) {
error_flags.charge_main_minus = 1;
}
} else if (ch_id == DIAG_CH_CONTACTOR_CHARGE_PRECHARGE_FEEDBACK) {
if (event == DIAG_EVENT_RESET) {
error_flags.charge_precharge = 0;
}
if (event == DIAG_EVENT_NOK) {
error_flags.charge_precharge = 1;
}
}
}
/**
* @brief diagnosis callback function for fuse related events
*/
void DIAG_error_fuseState(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event) {
if (ch_id == DIAG_CH_FUSE_STATE_NORMAL) {
if (event == DIAG_EVENT_RESET) {
error_flags.fuse_state_normal = 0;
}
if (event == DIAG_EVENT_NOK) {
error_flags.fuse_state_normal = 1;
}
} else if (ch_id == DIAG_CH_FUSE_STATE_CHARGE) {
if (event == DIAG_EVENT_RESET) {
error_flags.fuse_state_charge = 0;
}
if (event == DIAG_EVENT_NOK) {
error_flags.fuse_state_charge = 1;
}
}
}
/**
* @brief diagnosis callback function for interlock events
*/
void DIAG_error_interlock(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event) {
if (ch_id == DIAG_CH_INTERLOCK_FEEDBACK) {
if (event == DIAG_EVENT_RESET) {
error_flags.interlock = 0;
}
if (event == DIAG_EVENT_NOK) {
error_flags.interlock = 1;
}
}
}
/**
* @brief diagnosis callback function for insulation events
*/
void DIAG_error_insulation(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event) {
if (ch_id == DIAG_CH_INSULATION_ERROR) {
if (event == DIAG_EVENT_RESET) {
error_flags.insulation_error = 0;
}
if (event == DIAG_EVENT_NOK) {
error_flags.insulation_error = 1;
}
}
}
/**
* @brief diagnosis callback function for MCU die temperature events
*/
void DIAG_error_MCUdieTemperature(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event) {
if (ch_id == DIAG_CH_ERROR_MCU_DIE_TEMPERATURE) {
if (event == DIAG_EVENT_RESET) {
error_flags.mcuDieTemperature = 0;
}
if (event == DIAG_EVENT_NOK) {
error_flags.mcuDieTemperature = 1;
}
}
}
/**
* @brief diagnosis callback function for coin cell voltage events
*/
void DIAG_error_coinCellVoltage(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event) {
if (ch_id == DIAG_CH_LOW_COIN_CELL_VOLTAGE) {
if (event == DIAG_EVENT_RESET) {
error_flags.coinCellVoltage &= 0xFE;
}
if (event == DIAG_EVENT_NOK) {
error_flags.coinCellVoltage |= 0x01;
}
} else if (ch_id == DIAG_CH_CRIT_LOW_COIN_CELL_VOLTAGE) {
if (event == DIAG_EVENT_RESET) {
error_flags.coinCellVoltage &= 0xFD;
}
if (event == DIAG_EVENT_NOK) {
error_flags.coinCellVoltage |= 0x02;
}
}
}
/**
* @brief diagnosis callback function for plausibility events
*/
void DIAG_error_plausibility_check(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event) {
if (ch_id == DIAG_CH_PLAUSIBILITY_CELL_VOLTAGE) {
if (event == DIAG_EVENT_RESET) {
error_flags.plausibilityCheck &= 0xFE;
}
if (event == DIAG_EVENT_NOK) {
error_flags.plausibilityCheck |= 0x01;
}
} else if (ch_id == DIAG_CH_PLAUSIBILITY_CELL_TEMP) {
if (event == DIAG_EVENT_RESET) {
error_flags.plausibilityCheck &= 0xFD;
}
if (event == DIAG_EVENT_NOK) {
error_flags.plausibilityCheck |= 0x02;
}
} else if (ch_id == DIAG_CH_PLAUSIBILITY_PACK_VOLTAGE) {
if (event == DIAG_EVENT_RESET) {
error_flags.plausibilityCheck &= 0xFB;
}
if (event == DIAG_EVENT_NOK) {
error_flags.plausibilityCheck |= 0x04;
}
}
}
/**
* @brief diagnosis callback function for open-wire events
*/
void DIAG_error_openWire(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event) {
if (ch_id == DIAG_CH_OPEN_WIRE) {
if (event == DIAG_EVENT_RESET) {
error_flags.open_wire = 0;
}
if (event == DIAG_EVENT_NOK) {
error_flags.open_wire = 1;
}
}
}
/**
* @brief diagnosis callback function for deep-discharge related events
*/
void DIAG_error_deep_discharge_detected(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event) {
if (ch_id == DIAG_CH_DEEP_DISCHARGE_DETECTED) {
if (event == DIAG_EVENT_RESET) {
error_flags.deepDischargeDetected = 0;
RTC_DEEP_DISCHARGE_DETECTED = 0;
}
if (event == DIAG_EVENT_NOK) {
error_flags.deepDischargeDetected = 1;
RTC_DEEP_DISCHARGE_DETECTED = 1;
}
}
}
/*================== Extern Function Implementations ========================*/
void DIAG_updateFlags(void) {
DB_WriteBlock(&error_flags, DATA_BLOCK_ID_ERRORSTATE);
DB_WriteBlock(&msl_flags, DATA_BLOCK_ID_MSL);
DB_WriteBlock(&rsl_flags, DATA_BLOCK_ID_RSL);
DB_WriteBlock(&mol_flags, DATA_BLOCK_ID_MOL);
}
diag_cfg.h (primary)¶
/**
*
* @copyright © 2010 - 2021, Fraunhofer-Gesellschaft zur Foerderung der
* angewandten Forschung e.V. All rights reserved.
*
* BSD 3-Clause License
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* We kindly request you to use one or more of the following phrases to refer
* to foxBMS in your hardware, software, documentation or advertising
* materials:
*
* ″This product uses parts of foxBMS®″
*
* ″This product includes parts of foxBMS®″
*
* ″This product is derived from foxBMS®″
*
*/
/**
* @file diag_cfg.h
* @author foxBMS Team
* @date 09.11.2015 (date of creation)
* @ingroup ENGINE_CONF
* @prefix DIAG
*
* @brief Diagnostic module configuration header
*
* In this header filer are the different diagnosis channel
* defines assigned to different diagnosis IDs.
*
* Furthermore are the diagnosis error log settings be configured here..
*/
#ifndef DIAG_CFG_H_
#define DIAG_CFG_H_
/*================== Includes ===============================================*/
#include "general.h"
#include "batterysystem_cfg.h"
/*================== Macros and Definitions =================================*/
#define DIAG_ERROR_SENSITIVITY_HIGH (0) /* logging at first event */
#define DIAG_ERROR_SENSITIVITY_MID (5) /* logging at fifth event */
#define DIAG_ERROR_SENSITIVITY_LOW (10) /* logging at tenth event */
#define DIAG_ERROR_VOLTAGE_SENSITIVITY_MSL (500) /*!< MSL level for event occurrence if over/under voltage event */
#define DIAG_ERROR_VOLTAGE_SENSITIVITY_RSL (500) /*!< RSL level for event occurrence if over/under voltage event */
#define DIAG_ERROR_VOLTAGE_SENSITIVITY_MOL (500) /*!< MOL level for event occurrence if over/under voltage event */
#define DIAG_ERROR_TEMPERATURE_SENSITIVITY_MSL (500) /*!< MSL level for event occurrence if over/under temperature event */
#define DIAG_ERROR_TEMPERATURE_SENSITIVITY_RSL (500) /*!< RSL level for event occurrence if over/under temperature event */
#define DIAG_ERROR_TEMPERATURE_SENSITIVITY_MOL (500) /*!< MOL level for event occurrence if over/under temperature event */
#define DIAG_ERROR_CURRENT_SENSITIVITY_MSL (500) /*!< MSL level for event occurrence if over/under current event */
#define DIAG_ERROR_CURRENT_SENSITIVITY_RSL (500) /*!< RSL level for event occurrence if over/under current event */
#define DIAG_ERROR_CURRENT_SENSITIVITY_MOL (500) /*!< MOL level for event occurrence if over/under current event */
#define DIAG_ERROR_SLAVE_TEMP_SENSITIVITY_MSL (500) /*!< MSL level for event occurrence if slave PCB temperature event */
#define DIAG_ERROR_SLAVE_TEMP_SENSITIVITY_RSL (500) /*!< RSL level for event occurrence if slave PCB temperature event */
#define DIAG_ERROR_SLAVE_TEMP_SENSITIVITY_MOL (500) /*!< MOL level for event occurrence if slave PCB temperature event */
#define DIAG_ERROR_LTC_PEC_SENSITIVITY (5)
#define DIAG_ERROR_LTC_MUX_SENSITIVITY (5)
#define DIAG_ERROR_LTC_SPI_SENSITIVITY (5)
#define DIAG_ERROR_CAN_TIMING_SENSITIVITY (100)
#define DIAG_ERROR_CAN_TIMING_CC_SENSITIVITY (100)
#define DIAG_ERROR_CAN_SENSOR_SENSITIVITY (100)
#define DIAG_ERROR_MAIN_PLUS_SENSITIVITY (50)
#define DIAG_ERROR_MAIN_MINUS_SENSITIVITY (50)
#define DIAG_ERROR_PRECHARGE_SENSITIVITY (50)
#define DIAG_ERROR_INTERLOCK_SENSITIVITY (10)
#define DIAG_ERROR_INSULATION_SENSITIVITY (30)
#define DIAG_ERROR_PLAUSIBILITY_PACK_SENSITIVITY (100)
/** Number of errors that can be logged */
#define DIAG_FAIL_ENTRY_LENGTH (50)
/** Maximum number of the same errors that are logged */
#define DIAG_MAX_ENTRIES_OF_ERROR (5)
/** Number of contactor errors that are logged */
#define DIAG_FAIL_ENTRY_CONTACTOR_LENGTH (50)
typedef enum {
DIAG_CH_FLASHCHECKSUM, /* */
DIAG_CH_BKPDIAG_FAILURE, /* */
DIAG_CH_WATCHDOGRESET_FAILURE, /* */
DIAG_CH_POSTOSINIT_FAILURE, /* */
DIAG_CH_CALIB_EEPR_FAILURE, /* */
DIAG_CH_CAN_INIT_FAILURE, /* */
DIAG_CH_VIC_INIT_FAILURE,
/* HW-/SW-Runtime events: 16-31 */
DIAG_CH_DIV_BY_ZERO_FAILURE, /* */
DIAG_CH_UNDEF_INSTRUCTION_FAILURE, /* */
DIAG_CH_DATA_BUS_FAILURE, /* */
DIAG_CH_INSTRUCTION_BUS_FAILURE, /* */
DIAG_CH_HARDFAULT_NOTHANDLED, /* */
DIAG_CH_RUNTIME_ERROR_RESERVED_1, /* reserved for future needs */
DIAG_CH_RUNTIME_ERROR_RESERVED_2, /* reserved for future needs */
DIAG_CH_RUNTIME_ERROR_RESERVED_3, /* reserved for future needs */
DIAG_CH_CONFIGASSERT, /* */
DIAG_CH_SYSTEMMONITORING_TIMEOUT, /* */
/* Measurement events: 32-47 */
DIAG_CH_CANS_MAX_VALUE_VIOLATE,
DIAG_CH_CANS_MIN_VALUE_VIOLATE,
DIAG_CH_CANS_CAN_MOD_FAILURE,
DIAG_CH_ISOMETER_TIM_ERROR, /* Measured frequency too low or no new value captured during last cycle */
DIAG_CH_ISOMETER_GROUNDERROR, /* Ground error detected */
DIAG_CH_ISOMETER_ERROR, /* Device error, invalid measurement result */
DIAG_CH_ISOMETER_MEAS_INVALID, /* Measurement trustworthy or not, hysteresis to ground error flag */
DIAG_CH_CELLVOLTAGE_OVERVOLTAGE_MSL, /* Cell voltage limits violated */
DIAG_CH_CELLVOLTAGE_OVERVOLTAGE_RSL, /* Cell voltage limits violated */
DIAG_CH_CELLVOLTAGE_OVERVOLTAGE_MOL, /* Cell voltage limits violated */
DIAG_CH_CELLVOLTAGE_UNDERVOLTAGE_MSL, /* Cell voltage limits violated */
DIAG_CH_CELLVOLTAGE_UNDERVOLTAGE_RSL, /* Cell voltage limits violated */
DIAG_CH_CELLVOLTAGE_UNDERVOLTAGE_MOL, /* Cell voltage limits violated */
DIAG_CH_TEMP_OVERTEMPERATURE_CHARGE_MSL, /* Temperature limits violated */
DIAG_CH_TEMP_OVERTEMPERATURE_CHARGE_RSL, /* Temperature limits violated */
DIAG_CH_TEMP_OVERTEMPERATURE_CHARGE_MOL, /* Temperature limits violated */
DIAG_CH_TEMP_OVERTEMPERATURE_DISCHARGE_MSL, /* Temperature limits violated */
DIAG_CH_TEMP_OVERTEMPERATURE_DISCHARGE_RSL, /* Temperature limits violated */
DIAG_CH_TEMP_OVERTEMPERATURE_DISCHARGE_MOL, /* Temperature limits violated */
DIAG_CH_TEMP_UNDERTEMPERATURE_CHARGE_MSL, /* Temperature limits violated */
DIAG_CH_TEMP_UNDERTEMPERATURE_CHARGE_RSL, /* Temperature limits violated */
DIAG_CH_TEMP_UNDERTEMPERATURE_CHARGE_MOL, /* Temperature limits violated */
DIAG_CH_TEMP_UNDERTEMPERATURE_DISCHARGE_MSL, /* Temperature limits violated */
DIAG_CH_TEMP_UNDERTEMPERATURE_DISCHARGE_RSL, /* Temperature limits violated */
DIAG_CH_TEMP_UNDERTEMPERATURE_DISCHARGE_MOL, /* Temperature limits violated */
DIAG_CH_OVERCURRENT_CHARGE_CELL_MSL, /* Overcurrent */
DIAG_CH_OVERCURRENT_CHARGE_CELL_RSL, /* Overcurrent */
DIAG_CH_OVERCURRENT_CHARGE_CELL_MOL, /* Overcurrent */
DIAG_CH_OVERCURRENT_DISCHARGE_CELL_MSL, /* Overcurrent */
DIAG_CH_OVERCURRENT_DISCHARGE_CELL_RSL, /* Overcurrent */
DIAG_CH_OVERCURRENT_DISCHARGE_CELL_MOL, /* Overcurrent */
DIAG_CH_OVERCURRENT_CHARGE_PL0_MSL, /* Overcurrent */
DIAG_CH_OVERCURRENT_CHARGE_PL0_RSL, /* Overcurrent */
DIAG_CH_OVERCURRENT_CHARGE_PL0_MOL, /* Overcurrent */
DIAG_CH_OVERCURRENT_CHARGE_PL1_MSL, /* Overcurrent */
DIAG_CH_OVERCURRENT_CHARGE_PL1_RSL, /* Overcurrent */
DIAG_CH_OVERCURRENT_CHARGE_PL1_MOL, /* Overcurrent */
DIAG_CH_OVERCURRENT_DISCHARGE_PL0_MSL, /* Overcurrent */
DIAG_CH_OVERCURRENT_DISCHARGE_PL0_RSL, /* Overcurrent */
DIAG_CH_OVERCURRENT_DISCHARGE_PL0_MOL, /* Overcurrent */
DIAG_CH_OVERCURRENT_DISCHARGE_PL1_MSL, /* Overcurrent */
DIAG_CH_OVERCURRENT_DISCHARGE_PL1_RSL, /* Overcurrent */
DIAG_CH_OVERCURRENT_DISCHARGE_PL1_MOL, /* Overcurrent */
DIAG_CH_OVERCURRENT_PL_NONE,
DIAG_CH_LTC_SPI, /* LTC */
DIAG_CH_LTC_PEC, /* LTC */
DIAG_CH_LTC_MUX, /* LTC */
DIAG_CH_LTC_CONFIG, /* LTC */
/* Communication events: 50-63*/
DIAG_CH_CAN_TIMING, /* error in CAN timing */
DIAG_CH_CAN_CC_RESPONDING, /* CAN C-C */
DIAG_CH_CURRENT_SENSOR_RESPONDING, /* Current sensor not responding anymore */
/* Contactor events: 69-77*/
DIAG_CH_CONTACTOR_DAMAGED, /* Opening contactor at over current */
DIAG_CH_CONTACTOR_OPENING, /* counter for contactor opening */
DIAG_CH_CONTACTOR_CLOSING, /* counter for contactor closing */
DIAG_CH_CONTACTOR_MAIN_PLUS_FEEDBACK, /* Contactor feedback error */
DIAG_CH_CONTACTOR_MAIN_MINUS_FEEDBACK, /* Contactor feedback error */
DIAG_CH_CONTACTOR_PRECHARGE_FEEDBACK, /* Contactor feedback error */
DIAG_CH_CONTACTOR_CHARGE_MAIN_PLUS_FEEDBACK, /* Contactor feedback error */
DIAG_CH_CONTACTOR_CHARGE_MAIN_MINUS_FEEDBACK, /* Contactor feedback error */
DIAG_CH_CONTACTOR_CHARGE_PRECHARGE_FEEDBACK, /* Contactor feedback error */
DIAG_CH_INTERLOCK_FEEDBACK, /* Interlock feedback error */
DIAG_CH_SLAVE_PCB_UNDERTEMPERATURE_MSL,
DIAG_CH_SLAVE_PCB_UNDERTEMPERATURE_RSL,
DIAG_CH_SLAVE_PCB_UNDERTEMPERATURE_MOL,
DIAG_CH_SLAVE_PCB_OVERTEMPERATURE_MSL,
DIAG_CH_SLAVE_PCB_OVERTEMPERATURE_RSL,
DIAG_CH_SLAVE_PCB_OVERTEMPERATURE_MOL,
DIAG_CH_INSULATION_ERROR, /* Insulation error: measured insulation < threshold */
DIAG_CH_FUSE_STATE_NORMAL, /* Fuse tripped */
DIAG_CH_FUSE_STATE_CHARGE, /* Fuse tripped */
DIAG_CH_ERROR_MCU_DIE_TEMPERATURE, /* MCU die temperature */
DIAG_CH_LOW_COIN_CELL_VOLTAGE, /* coin cell voltage */
DIAG_CH_CRIT_LOW_COIN_CELL_VOLTAGE, /* coin cell voltage */
DIAG_CH_OPEN_WIRE, /* open-wire check */
DIAG_CH_PLAUSIBILITY_CELL_VOLTAGE, /* plausibility checks */
DIAG_CH_PLAUSIBILITY_CELL_TEMP, /* plausibility checks */
DIAG_CH_PLAUSIBILITY_PACK_VOLTAGE, /* plausibility checks */
DIAG_CH_DEEP_DISCHARGE_DETECTED, /* DoD was detected */
DIAG_ID_MAX, /* MAX indicator - do not change */
} DIAG_CH_ID_e;
/** diagnosis check result (event) */
typedef enum {
DIAG_EVENT_OK, /*!< diag channel event OK */
DIAG_EVENT_NOK, /*!< diag channel event NOK */
DIAG_EVENT_RESET, /*!< reset diag channel eventcounter to 0 */
} DIAG_EVENT_e;
/**
* enable state of diagnosis entry
*/
typedef enum {
DIAG_ENABLED,
DIAG_DISABLED,
} DIAG_ENABLE_STATE_e;
#if CHECK_CAN_TIMING == TRUE
#define DIAG_CAN_TIMING DIAG_ENABLED
#else
#define DIAG_CAN_TIMING DIAG_DISABLED
#endif
#if CURRENT_SENSOR_PRESENT == TRUE
#define DIAG_CAN_SENSOR_PRESENT DIAG_ENABLED
#else
#define DIAG_CAN_SENSOR_PRESENT DIAG_DISABLED
#endif
/**
* diagnosis recording activation
*/
typedef enum {
DIAG_RECORDING_ENABLED, /*!< enable diagnosis event recording */
DIAG_RECORDING_DISABLED, /*!< disable diagnosis event recording */
} DIAG_TYPE_RECORDING_e;
/* FIXME some enums are typedefed with DIAG...TYPE_e, some with DIAG_TYPE..._e! Reconsider this */
/**
* diagnosis types for system monitoring
*/
typedef enum {
DIAG_SYSMON_CYCLICTASK, /*!< */
DIAG_SYSMON_RESERVED, /*!< */
} DIAG_SYSMON_TYPE_e;
/**
* diagnosis handling type for system monitoring
*/
typedef enum {
DIAG_SYSMON_HANDLING_DONOTHING, /*!< */
DIAG_SYSMON_HANDLING_SWITCHOFFCONTACTOR, /*!< */
} DIAG_SYSMON_HANDLING_TYPE_e;
/**
* @brief listing of system-relevant tasks or functions which are checked by system monitoring
*
* diag_sysmon_ch_cfg[]=
*/
typedef enum {
DIAG_SYSMON_DATABASE_ID, /*!< diag entry for database */
DIAG_SYSMON_SYS_ID, /*!< diag entry for sys */
DIAG_SYSMON_BMS_ID, /*!< diag entry for bms */
DIAG_SYSMON_CONT_ID, /*!< diag entry for contactors */
DIAG_SYSMON_ILCK_ID, /*!< diag entry for contactors */
DIAG_SYSMON_LTC_ID, /*!< diag entry for ltc */
DIAG_SYSMON_ISOGUARD_ID, /*!< diag entry for isoguard */
DIAG_SYSMON_CANS_ID, /*!< diag entry for can */
DIAG_SYSMON_APPL_CYCLIC_1ms, /*!< diag entry for application 10ms task */
DIAG_SYSMON_APPL_CYCLIC_10ms, /*!< diag entry for application 10ms task */
DIAG_SYSMON_APPL_CYCLIC_100ms, /*!< diag entry for application 100ms task */
DIAG_SYSMON_MODULE_ID_MAX, /*!< end marker do not delete */
} DIAG_SYSMON_MODULE_ID_e;
/* FIXME doxygen comment */
/* FIXME is DIAG_CODE_s an appropriate name for this? */
typedef struct {
uint32_t GENERALmsk;
uint32_t CELLMONmsk;
uint32_t COMmsk;
uint32_t ADCmsk;
} DIAG_CODE_s;
/**
* Channel configuration of one diag channel
*/
typedef struct {
DIAG_CH_ID_e id; /*!< diagnosis event id diag_id */
uint8_t description[40];
uint16_t thresholds; /*!< threshold for number of events which will be tolerated before generating a notification in both direction (OK or NOT OK)
* threshold = 0: reports the value at first occurence, threshold = 1:reports the value at second occurence*/
DIAG_TYPE_RECORDING_e enablerecording; /*!< if enabled recording in diag_memory will be activated */
DIAG_ENABLE_STATE_e state; /*!< if enabled diagnosis event will be evaluated */
void (*callbackfunc)(DIAG_CH_ID_e, DIAG_EVENT_e); /*!< will be called if number of events exceeds threshold (in both direction) with parameter DIAG_EVENT_e */
} DIAG_CH_CFG_s;
/**
* struct for device Configuration of diag module
*/
typedef struct {
uint8_t nr_of_ch; /*!< number of entries in DIAG_CH_CFG_s */
DIAG_CH_CFG_s *ch_cfg; /*!< pointer to diag channel config struct */
} DIAG_DEV_s;
/**
* state (in summary) used for task or function notification
*/
typedef struct {
uint32_t state; /*!< state */
uint32_t timestamp; /*!< timestamp of state */
} DIAG_SYSMON_NOTIFICATION_s;
/**
* Channel configuration of one system monitoring channel
*/
typedef struct {
DIAG_SYSMON_MODULE_ID_e id; /*!< the diag type by its symbolic name */
DIAG_SYSMON_TYPE_e type; /*!< system monitoring types: cyclic or special */
uint16_t threshold; /*!< max. delay time in ms */
DIAG_TYPE_RECORDING_e enablerecording; /*!< enabled if set to DIAG_RECORDING_ENABLED */
DIAG_SYSMON_HANDLING_TYPE_e handlingtype; /*!< type of handling of system monitoring errors */
DIAG_ENABLE_STATE_e state; /*!< enable or disable system monitoring */
void (*callbackfunc)(DIAG_SYSMON_MODULE_ID_e); /*!< */
} DIAG_SYSMON_CH_CFG_s;
/*================== Extern Constant and Variable Declarations ==============*/
/**
* diag device configuration struct
*/
extern DIAG_DEV_s diag_dev;
/**
* diag system monitoring struct
*/
extern DIAG_SYSMON_CH_CFG_s diag_sysmon_ch_cfg[];
extern DIAG_CH_CFG_s diag_ch_cfg[];
/* FIXME why is it in header at all? and why is it in code at all? not used */
extern DIAG_CODE_s diag_mask;
/*================== Extern Function Prototypes =============================*/
/**
* @brief update function for diagnosis flags (errors, MOL/RSL/MSL violations)
*/
extern void DIAG_updateFlags(void);
#endif /* DIAG_CFG_H_ */
diag_cfg.c (secondary)¶
/**
*
* @copyright © 2010 - 2021, Fraunhofer-Gesellschaft zur Foerderung der
* angewandten Forschung e.V. All rights reserved.
*
* BSD 3-Clause License
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* We kindly request you to use one or more of the following phrases to refer
* to foxBMS in your hardware, software, documentation or advertising
* materials:
*
* ″This product uses parts of foxBMS®″
*
* ″This product includes parts of foxBMS®″
*
* ″This product is derived from foxBMS®″
*
*/
/**
* @file diag_cfg.c
* @author foxBMS Team
* @date 09.11.2015 (date of creation)
* @ingroup ENGINE_CONF
* @prefix DIAG
*
* @brief Diagnostic module configuration
*
* The configuration of the different diagnosis events defined in diag_cfg.h is set in the array
* diag_ch_cfg[], e.g. initialization errors or runtime errors.
*
* Every entry of the diag_ch_cfg[] array consists of
* - name of the diagnosis event (defined in diag_cfg.h)
* - type of diagnosis event
* - diagnosis sensitivity (after how many occurrences event is counted as error)
* - enabling of the recording for diagnosis event
* - enabling of the diagnosis event
* - callback function for diagnosis event if wished, otherwise dummyfu
*
* The system monitoring configuration defined in diag_cfg.h is set in the array
* diag_sysmon_ch_cfg[]. The system monitoring is at the moment only used for
* supervising the cyclic/periodic tasks.
*
* Every entry of the diag_sysmon_ch_cfg[] consists of
* - enum of monitored object
* - type of monitored object (at the moment only DIAG_SYSMON_CYCLICTASK is supported)
* - maximum delay in [ms] in which the object needs to call the DIAG_SysMonNotify function defined in diag.c
* - enabling of the recording for system monitoring
* - enabling of the system monitoring for the monitored object
* - callback function if system monitoring notices an error if wished, otherwise dummyfu2
*/
/*================== Includes ===============================================*/
#include "diag_cfg.h"
#include "database.h"
/*================== Macros and Definitions =================================*/
/*================== Static Constant and Variable Definitions ===============*/
static DATA_BLOCK_ERRORSTATE_s error_flags = { 0 };
static DATA_BLOCK_MSL_FLAG_s msl_flags = { 0 };
/*================== Static Function Prototypes =============================*/
/* dummy functions */
static void dummyfu(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event);
static void dummyfu2(DIAG_SYSMON_MODULE_ID_e ch_id);
/* functions for SOA related events */
static void DIAG_overvoltage(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event);
static void DIAG_undervoltage(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event);
static void DIAG_overtemperature_charge(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event);
static void DIAG_overtemperature_discharge(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event);
static void DIAG_undertemperature_charge(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event);
static void DIAG_undertemperature_discharge(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event);
/* functions for system related events */
static void DIAG_error_ltc(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event);
static void DIAG_error_interlock(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event);
static void DIAG_error_MCUdieTemperature(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event);
static void DIAG_error_coinCellVoltage(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event);
/* functions for plausibility related events */
static void DIAG_error_plausibility_check(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event);
/*================== Extern Constant and Variable Definitions ===============*/
/**
* Enable and Disable of Error Checks for Testing Purposes
*
* Each Bit enables or disables the diagnosis (checking of) the corresponding failure code
* FIXME struct isn't used anywhere in the code at the moment.
* FIXME delete if not needed
*/
DIAG_CODE_s diag_mask = {
.GENERALmsk = 0xFFFFFFFF,
.CELLMONmsk = 0xFFFFFFFF,
.COMmsk = 0xFFFFFFFF,
.ADCmsk = 0xFFFFFFFF,
};
DIAG_CH_CFG_s diag_ch_cfg[] = {
/* OS-Framework and startup events */
{DIAG_CH_FLASHCHECKSUM, "FLASHCHECKSUM", DIAG_ERROR_SENSITIVITY_HIGH, DIAG_RECORDING_ENABLED, DIAG_ENABLED, dummyfu},
{DIAG_CH_BKPDIAG_FAILURE, "BKPDIAG", DIAG_ERROR_SENSITIVITY_HIGH, DIAG_RECORDING_ENABLED, DIAG_ENABLED, dummyfu},
{DIAG_CH_WATCHDOGRESET_FAILURE, "WATCHDOGRESET", DIAG_ERROR_SENSITIVITY_HIGH, DIAG_RECORDING_ENABLED, DIAG_ENABLED, dummyfu},
{DIAG_CH_POSTOSINIT_FAILURE, "POSTOSINIT", DIAG_ERROR_SENSITIVITY_HIGH, DIAG_RECORDING_ENABLED, DIAG_ENABLED, dummyfu},
{DIAG_CH_CALIB_EEPR_FAILURE, "CALIB_EEPR", DIAG_ERROR_SENSITIVITY_HIGH, DIAG_RECORDING_ENABLED, DIAG_ENABLED, dummyfu},
{DIAG_CH_CAN_INIT_FAILURE, "CAN_INIT", DIAG_ERROR_SENSITIVITY_HIGH, DIAG_RECORDING_ENABLED, DIAG_ENABLED, dummyfu},
{DIAG_CH_VIC_INIT_FAILURE, "VIC_INIT", DIAG_ERROR_SENSITIVITY_HIGH, DIAG_RECORDING_ENABLED, DIAG_ENABLED, dummyfu},
/* HW-/SW-Runtime events */
{DIAG_CH_DIV_BY_ZERO_FAILURE, "DIV_BY_ZERO", DIAG_ERROR_SENSITIVITY_HIGH, DIAG_RECORDING_ENABLED, DIAG_ENABLED, dummyfu},
{DIAG_CH_UNDEF_INSTRUCTION_FAILURE, "UNDEF_INSTRUCTION", DIAG_ERROR_SENSITIVITY_HIGH, DIAG_RECORDING_ENABLED, DIAG_ENABLED, dummyfu},
{DIAG_CH_DATA_BUS_FAILURE, "DATA_BUS_FAILURE", DIAG_ERROR_SENSITIVITY_HIGH, DIAG_RECORDING_ENABLED, DIAG_ENABLED, dummyfu},
{DIAG_CH_INSTRUCTION_BUS_FAILURE, "INSTRUCTION_BUS", DIAG_ERROR_SENSITIVITY_HIGH, DIAG_RECORDING_ENABLED, DIAG_ENABLED, dummyfu},
{DIAG_CH_HARDFAULT_NOTHANDLED, "HARDFAULT_NOTHANDLED", DIAG_ERROR_SENSITIVITY_HIGH, DIAG_RECORDING_ENABLED, DIAG_ENABLED, dummyfu},
{DIAG_CH_CONFIGASSERT, "CONFIGASSERT", DIAG_ERROR_SENSITIVITY_HIGH, DIAG_RECORDING_ENABLED, DIAG_ENABLED, dummyfu},
{DIAG_CH_SYSTEMMONITORING_TIMEOUT, "SYSTEMMONITORING_TIMEOUT", DIAG_ERROR_SENSITIVITY_HIGH, DIAG_RECORDING_ENABLED, DIAG_ENABLED, dummyfu},
/* Measurement events */
{DIAG_CH_CANS_MAX_VALUE_VIOLATE, "CANS_MAX_VALUE_VIOLATE", DIAG_ERROR_SENSITIVITY_HIGH, DIAG_RECORDING_ENABLED, DIAG_ENABLED, dummyfu},
{DIAG_CH_CANS_MIN_VALUE_VIOLATE, "CANS_MIN_VALUE_VIOLATE", DIAG_ERROR_SENSITIVITY_HIGH, DIAG_RECORDING_ENABLED, DIAG_ENABLED, dummyfu},
{DIAG_CH_CANS_CAN_MOD_FAILURE, "CANS_CAN_MOD_FAILURE", DIAG_ERROR_SENSITIVITY_HIGH, DIAG_RECORDING_ENABLED, DIAG_ENABLED, dummyfu},
#if BUILD_MODULE_ENABLE_ISOGUARD == 1
{DIAG_CH_ISOMETER_TIM_ERROR, "ISOMETER_TIM_ERROR", DIAG_ERROR_SENSITIVITY_MID, DIAG_RECORDING_ENABLED, DIAG_ENABLED, dummyfu},
{DIAG_CH_ISOMETER_GROUNDERROR, "ISOMETER_GROUNDERROR", DIAG_ERROR_SENSITIVITY_HIGH, DIAG_RECORDING_ENABLED, DIAG_ENABLED, dummyfu},
{DIAG_CH_ISOMETER_ERROR, "ISOMETER_ERROR", DIAG_ERROR_SENSITIVITY_MID, DIAG_RECORDING_ENABLED, DIAG_ENABLED, dummyfu},
{DIAG_CH_ISOMETER_MEAS_INVALID, "ISOMETER_MEAS_INVALID", DIAG_ERROR_SENSITIVITY_HIGH, DIAG_RECORDING_ENABLED, DIAG_ENABLED, dummyfu},
#else
{DIAG_CH_ISOMETER_TIM_ERROR, "ISOMETER_TIM_ERROR", DIAG_ERROR_SENSITIVITY_MID, DIAG_RECORDING_DISABLED, DIAG_DISABLED, dummyfu},
{DIAG_CH_ISOMETER_GROUNDERROR, "ISOMETER_GROUNDERROR", DIAG_ERROR_SENSITIVITY_HIGH, DIAG_RECORDING_DISABLED, DIAG_DISABLED, dummyfu},
{DIAG_CH_ISOMETER_ERROR, "ISOMETER_ERROR", DIAG_ERROR_SENSITIVITY_MID, DIAG_RECORDING_DISABLED, DIAG_DISABLED, dummyfu},
{DIAG_CH_ISOMETER_MEAS_INVALID, "ISOMETER_MEAS_INVALID", DIAG_ERROR_SENSITIVITY_HIGH, DIAG_RECORDING_DISABLED, DIAG_DISABLED, dummyfu},
#endif
/* Under and over temperature, voltage and current at cell level */
{DIAG_CH_CELLVOLTAGE_OVERVOLTAGE_MSL, "CELLVOLT_OVERVOLT_MSL", DIAG_ERROR_VOLTAGE_SENSITIVITY_MSL, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_overvoltage},
{DIAG_CH_CELLVOLTAGE_UNDERVOLTAGE_MSL, "CELLVOLT_UNDERVOLT_MSL", DIAG_ERROR_VOLTAGE_SENSITIVITY_MSL, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_undervoltage},
{DIAG_CH_TEMP_OVERTEMPERATURE_CHARGE_MSL, "OVERTEMP_CHARGE_MSL", DIAG_ERROR_TEMPERATURE_SENSITIVITY_MSL, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_overtemperature_charge},
{DIAG_CH_TEMP_OVERTEMPERATURE_DISCHARGE_MSL, "OVERTEMP_DISCHARGE_MSL", DIAG_ERROR_TEMPERATURE_SENSITIVITY_MSL, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_overtemperature_discharge},
{DIAG_CH_TEMP_UNDERTEMPERATURE_CHARGE_MSL, "UNDERTEMP_CHARGE_MSL", DIAG_ERROR_TEMPERATURE_SENSITIVITY_MSL, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_undertemperature_charge},
{DIAG_CH_TEMP_UNDERTEMPERATURE_DISCHARGE_MSL, "UNDERTEMP_DISCHARGE_MSL", DIAG_ERROR_TEMPERATURE_SENSITIVITY_MSL, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_undertemperature_discharge},
{DIAG_CH_LTC_SPI, "LTC_SPI", DIAG_ERROR_LTC_SPI_SENSITIVITY, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_error_ltc},
{DIAG_CH_LTC_PEC, "LTC_PEC", DIAG_ERROR_LTC_PEC_SENSITIVITY, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_error_ltc},
{DIAG_CH_LTC_MUX, "LTC_MUX", DIAG_ERROR_LTC_MUX_SENSITIVITY, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_error_ltc},
{DIAG_CH_LTC_CONFIG, "LTC_CONFIG", DIAG_ERROR_SENSITIVITY_HIGH, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_error_ltc},
#if BUILD_MODULE_ENABLE_ILCK == 1
/* Interlock Feedback Error */
{DIAG_CH_INTERLOCK_FEEDBACK, "INTERLOCK_FEEDBACK", DIAG_ERROR_INTERLOCK_SENSITIVITY, DIAG_RECORDING_DISABLED, DIAG_DISABLED, DIAG_error_interlock},
#else
{DIAG_CH_INTERLOCK_FEEDBACK, "INTERLOCK_FEEDBACK", DIAG_ERROR_INTERLOCK_SENSITIVITY, DIAG_RECORDING_DISABLED, DIAG_DISABLED, DIAG_error_interlock},
#endif
/* Slave PCB temperature errors for under and over temperature */
{DIAG_CH_SLAVE_PCB_UNDERTEMPERATURE_MSL, "SLAVE_PCB_UNDERTEMP_MSL", DIAG_ERROR_SLAVE_TEMP_SENSITIVITY_MSL, DIAG_RECORDING_ENABLED, DIAG_ENABLED, dummyfu},
{DIAG_CH_SLAVE_PCB_OVERTEMPERATURE_MSL, "SLAVE_PCB_OVERTEMP_MSL", DIAG_ERROR_SLAVE_TEMP_SENSITIVITY_MSL, DIAG_RECORDING_ENABLED, DIAG_ENABLED, dummyfu},
{DIAG_CH_ERROR_MCU_DIE_TEMPERATURE, "MCU_DIE_TEMPERATURE", DIAG_ERROR_SENSITIVITY_LOW, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_error_MCUdieTemperature},
{DIAG_CH_LOW_COIN_CELL_VOLTAGE, "COIN_CELL_VOLT_LOW", DIAG_ERROR_SENSITIVITY_LOW, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_error_coinCellVoltage},
{DIAG_CH_CRIT_LOW_COIN_CELL_VOLTAGE, "COIN_CELL_VOLT_CRITICAL", DIAG_ERROR_SENSITIVITY_LOW, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_error_coinCellVoltage},
/* Plausibility checks */
{DIAG_CH_PLAUSIBILITY_CELL_VOLTAGE, "PL_CELL_VOLT", DIAG_ERROR_SENSITIVITY_HIGH, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_error_plausibility_check},
{DIAG_CH_PLAUSIBILITY_CELL_TEMP, "PL_CELL_TEMP", DIAG_ERROR_SENSITIVITY_HIGH, DIAG_RECORDING_ENABLED, DIAG_ENABLED, DIAG_error_plausibility_check},
};
DIAG_SYSMON_CH_CFG_s diag_sysmon_ch_cfg[] = {
{DIAG_SYSMON_DATABASE_ID, DIAG_SYSMON_CYCLICTASK, 10, DIAG_RECORDING_ENABLED, DIAG_SYSMON_HANDLING_SWITCHOFFCONTACTOR, DIAG_ENABLED, dummyfu2},
{DIAG_SYSMON_SYS_ID, DIAG_SYSMON_CYCLICTASK, 20, DIAG_RECORDING_ENABLED, DIAG_SYSMON_HANDLING_SWITCHOFFCONTACTOR, DIAG_ENABLED, dummyfu2},
{DIAG_SYSMON_BMS_ID, DIAG_SYSMON_CYCLICTASK, 20, DIAG_RECORDING_ENABLED, DIAG_SYSMON_HANDLING_SWITCHOFFCONTACTOR, DIAG_ENABLED, dummyfu2},
#if BUILD_MODULE_ENABLE_ILCK == 1
{DIAG_SYSMON_ILCK_ID, DIAG_SYSMON_CYCLICTASK, 20, DIAG_RECORDING_ENABLED, DIAG_SYSMON_HANDLING_SWITCHOFFCONTACTOR, DIAG_ENABLED, dummyfu2},
#else
{DIAG_SYSMON_ILCK_ID, DIAG_SYSMON_CYCLICTASK, 20, DIAG_RECORDING_DISABLED, DIAG_SYSMON_HANDLING_SWITCHOFFCONTACTOR, DIAG_DISABLED, dummyfu2},
#endif
{DIAG_SYSMON_LTC_ID, DIAG_SYSMON_CYCLICTASK, 5, DIAG_RECORDING_ENABLED, DIAG_SYSMON_HANDLING_SWITCHOFFCONTACTOR, DIAG_ENABLED, dummyfu2},
{DIAG_SYSMON_APPL_CYCLIC_1ms, DIAG_SYSMON_CYCLICTASK, 2, DIAG_RECORDING_ENABLED, DIAG_SYSMON_HANDLING_SWITCHOFFCONTACTOR, DIAG_ENABLED, dummyfu2},
{DIAG_SYSMON_APPL_CYCLIC_10ms, DIAG_SYSMON_CYCLICTASK, 20, DIAG_RECORDING_ENABLED, DIAG_SYSMON_HANDLING_SWITCHOFFCONTACTOR, DIAG_ENABLED, dummyfu2},
{DIAG_SYSMON_APPL_CYCLIC_100ms, DIAG_SYSMON_CYCLICTASK, 200, DIAG_RECORDING_ENABLED, DIAG_SYSMON_HANDLING_SWITCHOFFCONTACTOR, DIAG_ENABLED, dummyfu2},
};
DIAG_DEV_s diag_dev = {
.nr_of_ch = sizeof(diag_ch_cfg)/sizeof(DIAG_CH_CFG_s),
.ch_cfg = &diag_ch_cfg[0],
};
/*================== Static Function Implementations ========================*/
/**
* @brief dummy callback function of diagnosis events
*/
void dummyfu(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event) {
/* Dummy function -> empty */
}
/**
* @brief dummy callback function of system monitoring error events
*/
void dummyfu2(DIAG_SYSMON_MODULE_ID_e ch_id) {
/* Dummy function -> empty */
}
/**
* @brief diagnosis callback function for overvoltage events
*/
static void DIAG_overvoltage(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event) {
if (ch_id == DIAG_CH_CELLVOLTAGE_OVERVOLTAGE_MSL) {
if (event == DIAG_EVENT_RESET) {
msl_flags.over_voltage = 0;
}
if (event == DIAG_EVENT_NOK) {
msl_flags.over_voltage = 1;
}
}
}
/**
* @brief diagnosis callback function for undervoltage events
*/
static void DIAG_undervoltage(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event) {
if (ch_id == DIAG_CH_CELLVOLTAGE_UNDERVOLTAGE_MSL) {
if (event == DIAG_EVENT_RESET) {
msl_flags.under_voltage = 0;
}
if (event == DIAG_EVENT_NOK) {
msl_flags.under_voltage = 1;
}
}
}
/**
* @brief diagnosis callback function for overtemperature charge events
*/
static void DIAG_overtemperature_charge(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event) {
if (ch_id == DIAG_CH_TEMP_OVERTEMPERATURE_CHARGE_MSL) {
if (event == DIAG_EVENT_RESET) {
msl_flags.over_temperature_charge = 0;
}
if (event == DIAG_EVENT_NOK) {
msl_flags.over_temperature_charge = 1;
}
}
}
/**
* @brief diagnosis callback function for overtemperature discharge events
*/
static void DIAG_overtemperature_discharge(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event) {
if (ch_id == DIAG_CH_TEMP_OVERTEMPERATURE_DISCHARGE_MSL) {
if (event == DIAG_EVENT_RESET) {
msl_flags.over_temperature_discharge = 0;
}
if (event == DIAG_EVENT_NOK) {
msl_flags.over_temperature_discharge = 1;
}
}
}
/**
* @brief diagnosis callback function for undertemperature charge events
*/
static void DIAG_undertemperature_charge(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event) {
if (ch_id == DIAG_CH_TEMP_UNDERTEMPERATURE_CHARGE_MSL) {
if (event == DIAG_EVENT_RESET) {
msl_flags.under_temperature_charge = 0;
}
if (event == DIAG_EVENT_NOK) {
msl_flags.under_temperature_charge = 1;
}
}
}
/**
* @brief diagnosis callback function for undertemperature discharge events
*/
static void DIAG_undertemperature_discharge(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event) {
if (ch_id == DIAG_CH_TEMP_UNDERTEMPERATURE_DISCHARGE_MSL) {
if (event == DIAG_EVENT_RESET) {
msl_flags.under_temperature_discharge = 0;
}
if (event == DIAG_EVENT_NOK) {
msl_flags.under_temperature_discharge = 1;
}
}
}
/**
* @brief diagnosis callback function for LTC module related events
*/
static void DIAG_error_ltc(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event) {
if (ch_id == DIAG_CH_LTC_SPI) {
if (event == DIAG_EVENT_RESET) {
error_flags.spi_error = 0;
}
if (event == DIAG_EVENT_NOK) {
error_flags.spi_error = 1;
}
} else if (ch_id == DIAG_CH_LTC_PEC) {
if (event == DIAG_EVENT_RESET) {
error_flags.crc_error = 0;
}
if (event == DIAG_EVENT_NOK) {
error_flags.crc_error = 1;
}
} else if (ch_id == DIAG_CH_LTC_MUX) {
if (event == DIAG_EVENT_RESET) {
error_flags.mux_error = 0;
}
if (event == DIAG_EVENT_NOK) {
error_flags.mux_error = 1;
}
} else if (ch_id == DIAG_CH_LTC_CONFIG) {
if (event == DIAG_EVENT_RESET) {
error_flags.ltc_config_error = 0;
}
if (event == DIAG_EVENT_NOK) {
error_flags.ltc_config_error = 1;
}
}
}
/**
* @brief diagnosis callback function for interlock events
*/
void DIAG_error_interlock(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event) {
if (ch_id == DIAG_CH_INTERLOCK_FEEDBACK) {
if (event == DIAG_EVENT_RESET) {
error_flags.interlock = 0;
}
if (event == DIAG_EVENT_NOK) {
error_flags.interlock = 1;
}
}
}
/**
* @brief diagnosis callback function for MCU die temperature events
*/
void DIAG_error_MCUdieTemperature(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event) {
if (ch_id == DIAG_CH_ERROR_MCU_DIE_TEMPERATURE) {
if (event == DIAG_EVENT_RESET) {
error_flags.mcuDieTemperature = 0;
}
if (event == DIAG_EVENT_NOK) {
error_flags.mcuDieTemperature = 1;
}
}
}
/**
* @brief diagnosis callback function for coin cell voltage events
*/
void DIAG_error_coinCellVoltage(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event) {
if (ch_id == DIAG_CH_LOW_COIN_CELL_VOLTAGE) {
if (event == DIAG_EVENT_RESET) {
error_flags.coinCellVoltage &= 0xFE;
}
if (event == DIAG_EVENT_NOK) {
error_flags.coinCellVoltage |= 0x01;
}
} else if (ch_id == DIAG_CH_CRIT_LOW_COIN_CELL_VOLTAGE) {
if (event == DIAG_EVENT_RESET) {
error_flags.coinCellVoltage &= 0xFD;
}
if (event == DIAG_EVENT_NOK) {
error_flags.coinCellVoltage |= 0x02;
}
}
}
/**
* @brief diagnosis callback function for plausibility events
*/
void DIAG_error_plausibility_check(DIAG_CH_ID_e ch_id, DIAG_EVENT_e event) {
if (ch_id == DIAG_CH_PLAUSIBILITY_CELL_VOLTAGE) {
if (event == DIAG_EVENT_RESET) {
error_flags.plausibilityCheck &= 0xFE;
}
if (event == DIAG_EVENT_NOK) {
error_flags.plausibilityCheck |= 0x01;
}
} else if (ch_id == DIAG_CH_PLAUSIBILITY_CELL_TEMP) {
if (event == DIAG_EVENT_RESET) {
error_flags.plausibilityCheck &= 0xFD;
}
if (event == DIAG_EVENT_NOK) {
error_flags.plausibilityCheck |= 0x02;
}
}
}
/*================== Extern Function Implementations ========================*/
void DIAG_updateFlags(void) {
DB_WriteBlock(&error_flags, DATA_BLOCK_ID_ERRORSTATE);
DB_WriteBlock(&msl_flags, DATA_BLOCK_ID_MSL);
}
diag_cfg.h (secondary)¶
/**
*
* @copyright © 2010 - 2021, Fraunhofer-Gesellschaft zur Foerderung der
* angewandten Forschung e.V. All rights reserved.
*
* BSD 3-Clause License
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* We kindly request you to use one or more of the following phrases to refer
* to foxBMS in your hardware, software, documentation or advertising
* materials:
*
* ″This product uses parts of foxBMS®″
*
* ″This product includes parts of foxBMS®″
*
* ″This product is derived from foxBMS®″
*
*/
/**
* @file diag_cfg.h
* @author foxBMS Team
* @date 09.11.2015 (date of creation)
* @ingroup ENGINE_CONF
* @prefix DIAG
*
* @brief Diagnostic module configuration header
*
* In this header filer are the different diagnosis channel
* defines assigned to different diagnosis IDs.
*
* Furthermore are the diagnosis error log settings be configured here..
*/
#ifndef DIAG_CFG_H_
#define DIAG_CFG_H_
/*================== Includes ===============================================*/
#include "general.h"
#include "batterysystem_cfg.h"
/*================== Macros and Definitions =================================*/
#define DIAG_ERROR_SENSITIVITY_HIGH (0) /* logging at first event */
#define DIAG_ERROR_SENSITIVITY_MID (5) /* logging at fifth event */
#define DIAG_ERROR_SENSITIVITY_LOW (10) /* logging at tenth event */
#define DIAG_ERROR_VOLTAGE_SENSITIVITY_MSL (500) /*!< MSL level for event occurrence if over/under voltage event */
#define DIAG_ERROR_TEMPERATURE_SENSITIVITY_MSL (500) /*!< MSL level for event occurrence if over/under temperature event */
#define DIAG_ERROR_CURRENT_SENSITIVITY_MSL (500) /*!< MSL level for event occurrence if over/under current event */
#define DIAG_ERROR_SLAVE_TEMP_SENSITIVITY_MSL (500) /*!< MSL level for event occurrence if slave PCB temperature event */
#define DIAG_ERROR_LTC_PEC_SENSITIVITY (5)
#define DIAG_ERROR_LTC_MUX_SENSITIVITY (5)
#define DIAG_ERROR_LTC_SPI_SENSITIVITY (5)
#define DIAG_ERROR_CAN_TIMING_SENSITIVITY (100)
#define DIAG_ERROR_CAN_TIMING_CC_SENSITIVITY (100)
#define DIAG_ERROR_CAN_SENSOR_SENSITIVITY (100)
#define DIAG_ERROR_MAIN_PLUS_SENSITIVITY (50)
#define DIAG_ERROR_MAIN_MINUS_SENSITIVITY (50)
#define DIAG_ERROR_PRECHARGE_SENSITIVITY (50)
#define DIAG_ERROR_INTERLOCK_SENSITIVITY (10)
/** Number of errors that can be logged */
#define DIAG_FAIL_ENTRY_LENGTH (50)
/** Maximum number of the same errors that are logged */
#define DIAG_MAX_ENTRIES_OF_ERROR (5)
/** Number of contactor errors that are logged */
#define DIAG_FAIL_ENTRY_CONTACTOR_LENGTH (50)
typedef enum {
DIAG_CH_FLASHCHECKSUM, /* */
DIAG_CH_BKPDIAG_FAILURE, /* */
DIAG_CH_WATCHDOGRESET_FAILURE, /* */
DIAG_CH_POSTOSINIT_FAILURE, /* */
DIAG_CH_CALIB_EEPR_FAILURE, /* */
DIAG_CH_CAN_INIT_FAILURE, /* */
DIAG_CH_VIC_INIT_FAILURE,
/* HW-/SW-Runtime events: 16-31 */
DIAG_CH_DIV_BY_ZERO_FAILURE, /* */
DIAG_CH_UNDEF_INSTRUCTION_FAILURE, /* */
DIAG_CH_DATA_BUS_FAILURE, /* */
DIAG_CH_INSTRUCTION_BUS_FAILURE, /* */
DIAG_CH_HARDFAULT_NOTHANDLED, /* */
DIAG_CH_RUNTIME_ERROR_RESERVED_1, /* reserved for future needs */
DIAG_CH_RUNTIME_ERROR_RESERVED_2, /* reserved for future needs */
DIAG_CH_RUNTIME_ERROR_RESERVED_3, /* reserved for future needs */
DIAG_CH_CONFIGASSERT, /* */
DIAG_CH_SYSTEMMONITORING_TIMEOUT, /* */
/* Measurement events: 32-47 */
DIAG_CH_CANS_MAX_VALUE_VIOLATE,
DIAG_CH_CANS_MIN_VALUE_VIOLATE,
DIAG_CH_CANS_CAN_MOD_FAILURE,
DIAG_CH_ISOMETER_TIM_ERROR, /* Measured frequency too low or no new value captured during last cycle */
DIAG_CH_ISOMETER_GROUNDERROR, /* Ground error detected */
DIAG_CH_ISOMETER_ERROR, /* Device error, invalid measurement result */
DIAG_CH_ISOMETER_MEAS_INVALID, /* Measurement trustworthy or not, hysteresis to ground error flag */
DIAG_CH_CELLVOLTAGE_OVERVOLTAGE_MSL, /* Cell voltage limits violated */
DIAG_CH_CELLVOLTAGE_UNDERVOLTAGE_MSL, /* Cell voltage limits violated */
DIAG_CH_TEMP_OVERTEMPERATURE_CHARGE_MSL, /* Temperature limits violated */
DIAG_CH_TEMP_OVERTEMPERATURE_DISCHARGE_MSL, /* Temperature limits violated */
DIAG_CH_TEMP_UNDERTEMPERATURE_CHARGE_MSL, /* Temperature limits violated */
DIAG_CH_TEMP_UNDERTEMPERATURE_DISCHARGE_MSL, /* Temperature limits violated */
DIAG_CH_LTC_SPI, /* LTC */
DIAG_CH_LTC_PEC, /* LTC */
DIAG_CH_LTC_MUX, /* LTC */
DIAG_CH_LTC_CONFIG, /* LTC */
/* Contactor events: 64-79 */
DIAG_CH_CONTACTOR_DAMAGED, /* Opening contactor at over current */
DIAG_CH_CONTACTOR_OPENING, /* counter for contactor opening */
DIAG_CH_CONTACTOR_CLOSING, /* counter for contactor closing */
DIAG_CH_INTERLOCK_FEEDBACK, /* Interlock feedback error */
DIAG_CH_SLAVE_PCB_UNDERTEMPERATURE_MSL,
DIAG_CH_SLAVE_PCB_OVERTEMPERATURE_MSL,
DIAG_CH_ERROR_MCU_DIE_TEMPERATURE, /* MCU die temperature */
DIAG_CH_LOW_COIN_CELL_VOLTAGE, /* coin cell voltage */
DIAG_CH_CRIT_LOW_COIN_CELL_VOLTAGE, /* coin cell voltage */
DIAG_CH_PLAUSIBILITY_CELL_VOLTAGE, /* plausibility checks */
DIAG_CH_PLAUSIBILITY_CELL_TEMP, /* plausibility checks */
DIAG_ID_MAX, /* MAX indicator - do not change */
} DIAG_CH_ID_e;
/** diagnosis check result (event) */
typedef enum {
DIAG_EVENT_OK, /*!< diag channel event OK */
DIAG_EVENT_NOK, /*!< diag channel event NOK */
DIAG_EVENT_RESET, /*!< reset diag channel eventcounter to 0 */
} DIAG_EVENT_e;
/**
* enable state of diagnosis entry
*/
typedef enum {
DIAG_ENABLED,
DIAG_DISABLED,
} DIAG_ENABLE_STATE_e;
/**
* diagnosis recording activation
*/
typedef enum {
DIAG_RECORDING_ENABLED, /*!< enable diagnosis event recording */
DIAG_RECORDING_DISABLED, /*!< disable diagnosis event recording */
} DIAG_TYPE_RECORDING_e;
/* FIXME some enums are typedefed with DIAG...TYPE_e, some with DIAG_TYPE..._e! Reconsider this */
/**
* diagnosis types for system monitoring
*/
typedef enum {
DIAG_SYSMON_CYCLICTASK, /*!< */
DIAG_SYSMON_RESERVED, /*!< */
} DIAG_SYSMON_TYPE_e;
/**
* diagnosis handling type for system monitoring
*/
typedef enum {
DIAG_SYSMON_HANDLING_DONOTHING, /*!< */
DIAG_SYSMON_HANDLING_SWITCHOFFCONTACTOR, /*!< */
} DIAG_SYSMON_HANDLING_TYPE_e;
/**
* @brief listing of system-relevant tasks or functions which are checked by system monitoring
*
* diag_sysmon_ch_cfg[]=
*/
typedef enum {
DIAG_SYSMON_DATABASE_ID, /*!< diag entry for database */
DIAG_SYSMON_SYS_ID, /*!< diag entry for sys */
DIAG_SYSMON_BMS_ID, /*!< diag entry for bms */
DIAG_SYSMON_ILCK_ID, /*!< diag entry for bms */
DIAG_SYSMON_LTC_ID, /*!< diag entry for ltc */
DIAG_SYSMON_APPL_CYCLIC_1ms, /*!< diag entry for application 10ms task */
DIAG_SYSMON_APPL_CYCLIC_10ms, /*!< diag entry for application 10ms task */
DIAG_SYSMON_APPL_CYCLIC_100ms, /*!< diag entry for application 100ms task */
DIAG_SYSMON_MODULE_ID_MAX, /*!< end marker do not delete */
} DIAG_SYSMON_MODULE_ID_e;
/* FIXME doxygen comment */
/* FIXME is DIAG_CODE_s an appropriate name for this? */
typedef struct {
uint32_t GENERALmsk;
uint32_t CELLMONmsk;
uint32_t COMmsk;
uint32_t ADCmsk;
} DIAG_CODE_s;
/**
* Channel configuration of one diag channel
*/
typedef struct {
DIAG_CH_ID_e id; /*!< diagnosis event id diag_id */
uint8_t description[40];
uint16_t thresholds; /*!< threshold for number of events which will be tolerated before generating a notification in both direction (OK or NOT OK)
* threshold = 0: reports the value at first occurence, threshold = 1:reports the value at second occurence*/
DIAG_TYPE_RECORDING_e enablerecording; /*!< if enabled recording in diag_memory will be activated */
DIAG_ENABLE_STATE_e state; /*!< if enabled diagnosis event will be evaluated */
void (*callbackfunc)(DIAG_CH_ID_e, DIAG_EVENT_e); /*!< will be called if number of events exceeds threshold (in both direction) with parameter DIAG_EVENT_e */
} DIAG_CH_CFG_s;
/**
* struct for device Configuration of diag module
*/
typedef struct {
uint8_t nr_of_ch; /*!< number of entries in DIAG_CH_CFG_s */
DIAG_CH_CFG_s *ch_cfg; /*!< pointer to diag channel config struct */
} DIAG_DEV_s;
/**
* state (in summary) used for task or function notification
*/
typedef struct {
uint32_t state; /*!< state */
uint32_t timestamp; /*!< timestamp of state */
} DIAG_SYSMON_NOTIFICATION_s;
/**
* Channel configuration of one system monitoring channel
*/
typedef struct {
DIAG_SYSMON_MODULE_ID_e id; /*!< the diag type by its symbolic name */
DIAG_SYSMON_TYPE_e type; /*!< system monitoring types: cyclic or special */
uint16_t threshold; /*!< max. delay time in ms */
DIAG_TYPE_RECORDING_e enablerecording; /*!< enabled if set to DIAG_RECORDING_ENABLED */
DIAG_SYSMON_HANDLING_TYPE_e handlingtype; /*!< type of handling of system monitoring errors */
DIAG_ENABLE_STATE_e state; /*!< enable or disable system monitoring */
void (*callbackfunc)(DIAG_SYSMON_MODULE_ID_e); /*!< */
} DIAG_SYSMON_CH_CFG_s;
/*================== Extern Constant and Variable Declarations ==============*/
/**
* diag device configuration struct
*/
extern DIAG_DEV_s diag_dev;
/**
* diag system monitoring struct
*/
extern DIAG_SYSMON_CH_CFG_s diag_sysmon_ch_cfg[];
extern DIAG_CH_CFG_s diag_ch_cfg[];
/* FIXME why is it in header at all? and why is it in code at all? not used */
extern DIAG_CODE_s diag_mask;
/*================== Extern Function Prototypes =============================*/
/**
* @brief update function for diagnosis flags (errors, MOL/RSL/MSL violations)
*/
extern void DIAG_updateFlags(void);
#endif /* DIAG_CFG_H_ */