INTERLOCK Module Sources


interlock.c

/**
 *
 * @copyright © 2010 - 2019, 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    interlock.c
 * @author  foxBMS Team
 * @date    23.09.2015 (date of creation)
 * @ingroup DRIVERS
 * @prefix  ILCK
 *
 * @brief   Driver for the interlock.
 *
 */

/*================== Includes =============================================*/
#include "interlock.h"

#include "database.h"
#include "diag.h"
#include "FreeRTOS.h"
#include "task.h"

#if BUILD_MODULE_ENABLE_ILCK == 1
/*================== Macros and Definitions ===============================*/

/**
 * Saves the last state and the last substate
 */
#define ILCK_SAVELASTSTATES()   ilck_state.laststate = ilck_state.state; \
                                ilck_state.lastsubstate = ilck_state.substate;

#define ILCK_CLOSEINTERLOCK()   ILCK_SwitchInterlockOn();
#define ILCK_OPENINTERLOCK()    ILCK_SwitchInterlockOff();

/*================== Constant and Variable Definitions ====================*/

/**
 * contains the state of the contactor state machine
 *
 */
static ILCK_STATE_s ilck_state = {
    .timer                  = 0,
    .statereq               = ILCK_STATE_NO_REQUEST,
    .state                  = ILCK_STATEMACH_UNINITIALIZED,
    .substate               = ILCK_ENTRY,
    .laststate              = ILCK_STATEMACH_UNINITIALIZED,
    .lastsubstate           = 0,
    .triggerentry           = 0,
    .ErrRequestCounter      = 0,
    .counter                = 0,
};


/*================== Function Prototypes ==================================*/

static ILCK_RETURN_TYPE_e ILCK_CheckStateRequest(ILCK_STATE_REQUEST_e statereq);
static ILCK_STATE_REQUEST_e ILCK_GetStateRequest(void);
static ILCK_STATE_REQUEST_e ILCK_TransferStateRequest(void);
static uint8_t ILCK_CheckReEntrance(void);
static void ILCK_CheckFeedback(void);


/*================== Function Implementations =============================*/

ILCK_ELECTRICAL_STATE_TYPE_s ILCK_GetInterlockSetValue() {
    ILCK_ELECTRICAL_STATE_TYPE_s interlockSetInformation = FALSE;
    taskENTER_CRITICAL();
    interlockSetInformation = ilck_interlock_state.set;
    taskEXIT_CRITICAL();
    return interlockSetInformation;
}




ILCK_ELECTRICAL_STATE_TYPE_s ILCK_GetInterlockFeedback(void) {
    ILCK_ELECTRICAL_STATE_TYPE_s measuredInterlockState = ILCK_SWITCH_UNDEF;
    IO_PIN_STATE_e pinstate = IO_PIN_RESET;
    taskENTER_CRITICAL();
    pinstate = IO_ReadPin(ilck_interlock_config.feedback_pin);
    taskEXIT_CRITICAL();
    if (IO_PIN_SET == pinstate) {
        measuredInterlockState = ILCK_SWITCH_ON;
    } else if (IO_PIN_RESET == pinstate) {
        measuredInterlockState = ILCK_SWITCH_OFF;
    }
    ilck_interlock_state.feedback = measuredInterlockState;
    return measuredInterlockState;
}



STD_RETURN_TYPE_e ILCK_SetInterlockState(ILCK_ELECTRICAL_STATE_TYPE_s requestedInterlockState) {
    STD_RETURN_TYPE_e retVal = E_OK;

    if (requestedInterlockState == ILCK_SWITCH_ON) {
        ilck_interlock_state.set = ILCK_SWITCH_ON;
        IO_WritePin(ilck_interlock_config.control_pin, IO_PIN_SET);
    } else if (requestedInterlockState  ==  ILCK_SWITCH_OFF) {
        ilck_interlock_state.set = ILCK_SWITCH_OFF;
        IO_WritePin(ilck_interlock_config.control_pin, IO_PIN_RESET);
    } else {
        retVal = E_NOT_OK;
    }

    return retVal;
}



STD_RETURN_TYPE_e ILCK_SwitchInterlockOff(void) {
    STD_RETURN_TYPE_e retVal = E_NOT_OK;
    retVal = ILCK_SetInterlockState(ILCK_SWITCH_OFF);
    return retVal;
}


STD_RETURN_TYPE_e ILCK_SwitchInterlockOn(void) {
    STD_RETURN_TYPE_e retVal = E_NOT_OK;
    retVal = ILCK_SetInterlockState(ILCK_SWITCH_ON);
    return retVal;
}




/**
 * @brief   re-entrance check of ILCK state machine trigger function
 *
 * This function is not re-entrant and should only be called time- or event-triggered.
 * It increments the triggerentry counter from the state variable ilck_state.
 * It should never be called by two different processes, so if it is the case, triggerentry
 * should never be higher than 0 when this function is called.
 *
 * @return  retval  0 if no further instance of the function is active, 0xff else
 *
 */
static uint8_t ILCK_CheckReEntrance(void) {
    uint8_t retval = 0;

    taskENTER_CRITICAL();
    if (!ilck_state.triggerentry) {
        ilck_state.triggerentry++;
    } else {
        retval = 0xFF;    /* multiple calls of function */
    }
    taskEXIT_CRITICAL();

    return retval;
}




/**
 * @brief   gets the current state request.
 *
 * This function is used in the functioning of the ILCK state machine.
 *
 * @return  retval  current state request, taken from ILCK_STATE_REQUEST_e
 */
static ILCK_STATE_REQUEST_e ILCK_GetStateRequest(void) {
    ILCK_STATE_REQUEST_e retval = ILCK_STATE_NO_REQUEST;

    taskENTER_CRITICAL();
    retval    = ilck_state.statereq;
    taskEXIT_CRITICAL();

    return retval;
}


/**
 * @brief   gets the current state.
 *
 * This function is used in the functioning of the ILCK state machine.
 *
 * @return  current state, taken from ILCK_STATEMACH_e
 */
ILCK_STATEMACH_e ILCK_GetState(void) {
    return ilck_state.state;
}


/**
 * @brief   transfers the current state request to the state machine.
 *
 * This function takes the current state request from ilck_state and transfers it to the state machine.
 * It resets the value from ilck_state to ILCK_STATE_NO_REQUEST
 *
 * @return  retVal          current state request, taken from ILCK_STATE_REQUEST_e
 *
 */
static ILCK_STATE_REQUEST_e ILCK_TransferStateRequest(void) {
    ILCK_STATE_REQUEST_e retval = ILCK_STATE_NO_REQUEST;

    taskENTER_CRITICAL();
    retval    = ilck_state.statereq;
    ilck_state.statereq = ILCK_STATE_NO_REQUEST;
    taskEXIT_CRITICAL();

    return retval;
}


/**
 * @brief   sets the current state request of the state variable ilck_state.
 *
 * This function is used to make a state request to the state machine,e.g, start voltage measurement,
 * read result of voltage measurement, re-initialization
 * It calls ILCK_CheckStateRequest() to check if the request is valid.
 * The state request is rejected if is not valid.
 * The result of the check is returned immediately, so that the requester can act in case
 * it made a non-valid state request.
 *
 * @param   statereq                state request to set
 *
 * @return  retVal                  current state request, taken from ILCK_STATE_REQUEST_e
 */
ILCK_RETURN_TYPE_e ILCK_SetStateRequest(ILCK_STATE_REQUEST_e statereq) {
    ILCK_RETURN_TYPE_e retVal = ILCK_STATE_NO_REQUEST;

    taskENTER_CRITICAL();
    retVal = ILCK_CheckStateRequest(statereq);

    if (retVal == ILCK_OK) {
            ilck_state.statereq = statereq;
    }
    taskEXIT_CRITICAL();

    return retVal;
}


/**
 * @brief   checks the state requests that are made.
 *
 * This function checks the validity of the state requests.
 * The results of the checked is returned immediately.
 *
 * @param   statereq    state request to be checked
 *
 * @return              result of the state request that was made, taken from ILCK_RETURN_TYPE_e
 */
static ILCK_RETURN_TYPE_e ILCK_CheckStateRequest(ILCK_STATE_REQUEST_e statereq) {
    if (statereq == ILCK_STATE_ERROR_REQUEST) {
        return ILCK_OK;
    }

    if (ilck_state.statereq == ILCK_STATE_NO_REQUEST) {
        /* init only allowed from the uninitialized state */
        if (statereq == ILCK_STATE_INIT_REQUEST) {
            if (ilck_state.state == ILCK_STATEMACH_UNINITIALIZED) {
                return ILCK_OK;
            } else {
                return ILCK_ALREADY_INITIALIZED;
            }
        }

        if ((statereq == ILCK_STATE_OPEN_REQUEST) || (statereq == ILCK_STATE_CLOSE_REQUEST)) {
            return ILCK_OK;
        } else {
            return ILCK_ILLEGAL_REQUEST;
        }
    } else {
        return ILCK_REQUEST_PENDING;
    }
}

/**
 * @brief   trigger function for the ILCK driver state machine.
 *
 * This function contains the sequence of events in the ILCK state machine.
 * It must be called time-triggered, every 1ms.
 */
void ILCK_Trigger(void) {
    ILCK_STATE_REQUEST_e statereq = ILCK_STATE_NO_REQUEST;

    /* Check re-entrance of function */
    if (ILCK_CheckReEntrance()) {
        return;
    }

    DIAG_SysMonNotify(DIAG_SYSMON_ILCK_ID, 0);        /* task is running, state = ok */

    /****Happens every time the state machine is triggered**************/
    if (ilck_state.state != ILCK_STATEMACH_UNINITIALIZED) {
            ILCK_CheckFeedback();
    }

    if (ilck_state.timer) {
        if (--ilck_state.timer) {
            ilck_state.triggerentry--;
            return;    /* handle state machine only if timer has elapsed */
        }
    }


    switch (ilck_state.state) {
        /****************************UNINITIALIZED***********************************/
        case ILCK_STATEMACH_UNINITIALIZED:
            /* waiting for Initialization Request */
            statereq = ILCK_TransferStateRequest();
            if (statereq == ILCK_STATE_INIT_REQUEST) {
                ILCK_SAVELASTSTATES();
                ilck_state.timer = ILCK_STATEMACH_SHORTTIME_MS;
                ilck_state.state = ILCK_STATEMACH_INITIALIZATION;
                ilck_state.substate = ILCK_ENTRY;
            } else if (statereq == ILCK_STATE_NO_REQUEST) {
                /* no actual request pending   */
            } else {
                ilck_state.ErrRequestCounter++;   /* illegal request pending */
            }
            break;

        /****************************INITIALIZATION**********************************/
        case ILCK_STATEMACH_INITIALIZATION:
            ILCK_SAVELASTSTATES();
            ILCK_OPENINTERLOCK();

            ilck_state.timer = ILCK_STATEMACH_SHORTTIME_MS;
            ilck_state.state = ILCK_STATEMACH_INITIALIZED;
            ilck_state.substate = ILCK_ENTRY;
            break;

        /****************************INITIALIZED*************************************/
        case ILCK_STATEMACH_INITIALIZED:
            ILCK_SAVELASTSTATES();
            ilck_state.timer = ILCK_STATEMACH_SHORTTIME_MS;
            ilck_state.state = ILCK_STATEMACH_WAIT_FIRST_REQUEST;
            ilck_state.substate = ILCK_ENTRY;
            break;

        /****************************INITIALIZED*************************************/
        case ILCK_STATEMACH_WAIT_FIRST_REQUEST:
            ILCK_SAVELASTSTATES();
            statereq = ILCK_TransferStateRequest();
            if (statereq == ILCK_STATE_OPEN_REQUEST) {
                ilck_state.timer = ILCK_STATEMACH_SHORTTIME_MS;
                ilck_state.state = ILCK_STATEMACH_OPEN;
                ilck_state.substate = ILCK_ENTRY;
                break;
            } else if (statereq == ILCK_STATE_CLOSE_REQUEST) {
                ilck_state.timer = ILCK_STATEMACH_SHORTTIME_MS;
                ilck_state.state = ILCK_STATEMACH_CLOSED;
                ilck_state.substate = ILCK_ENTRY;
                break;
            } else {
                ilck_state.timer = ILCK_STATEMACH_SHORTTIME_MS;
                break;
            }
            break;

        /****************************OPEN*************************************/
        case ILCK_STATEMACH_OPEN:
            ILCK_SAVELASTSTATES();
            ILCK_OPENINTERLOCK();
            ilck_state.timer = ILCK_STATEMACH_SHORTTIME_MS;
            statereq = ILCK_TransferStateRequest();
            if (statereq == ILCK_STATE_CLOSE_REQUEST) {
                ilck_state.timer = ILCK_STATEMACH_SHORTTIME_MS;
                ilck_state.state = ILCK_STATEMACH_CLOSED;
                ilck_state.substate = ILCK_ENTRY;
                break;
            }
            break;

        /****************************CLOSED*************************************/
        case ILCK_STATEMACH_CLOSED:
            ILCK_SAVELASTSTATES();
            ILCK_CLOSEINTERLOCK();
            ilck_state.timer = ILCK_STATEMACH_SHORTTIME_MS;
            statereq = ILCK_TransferStateRequest();
            if (statereq == ILCK_STATE_OPEN_REQUEST) {
                ilck_state.timer = ILCK_STATEMACH_SHORTTIME_MS;
                ilck_state.state = ILCK_STATEMACH_OPEN;
                ilck_state.substate = ILCK_ENTRY;
                break;
            }
            break;

        default:
            break;
    }  /* end switch (ilck_state.state) */

    ilck_state.triggerentry--;
}


void ILCK_CheckFeedback(void) {
    DATA_BLOCK_ILCKFEEDBACK_s ilckfeedback_tab;
    uint8_t interlock_feedback = 0;

    interlock_feedback = ILCK_GetInterlockFeedback();

    ilckfeedback_tab.interlock_feedback = interlock_feedback;

    DB_WriteBlock(&ilckfeedback_tab, DATA_BLOCK_ID_ILCKFEEDBACK);

    STD_RETURN_TYPE_e result = E_NOT_OK;
    if (interlock_feedback == ILCK_GetInterlockSetValue()) {
        result = E_OK;
    }
    DIAG_checkEvent(result, DIAG_CH_INTERLOCK_FEEDBACK, 0);
}
#endif

interlock.h

/**
 *
 * @copyright © 2010 - 2019, 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    interlock.h
 * @author  foxBMS Team
 * @date    23.09.2015 (date of creation)
 * @ingroup DRIVERS
 * @prefix  ILCK
 *
 * @brief   Headers for the driver for the interlock.
 *
 */

#ifndef INTERLOCK_H_
#define INTERLOCK_H_

/*================== Includes =============================================*/
#include "interlock_cfg.h"

/*================== Macros and Definitions ===============================*/

/*================== Constant and Variable Definitions ====================*/

/*================== Function Prototypes ==================================*/
/**
 * @brief   Checks the configuration of the interlock-module
 * @return  retVal (type: STD_RETURN_TYPE_e)
 */
extern STD_RETURN_TYPE_e ILCK_Init(void);

/**
 * @brief   Gets the latest value (TRUE, FALSE) the interlock was set to.
 *
 * Meaning of the return value:
 *   - FALSE means interlock was set to be opened
 *   - TRUE means interlock was set to be closed
 *
 * @return  setInformation (type: ILCK_ELECTRICAL_STATE_TYPE_s)
 */
extern ILCK_ELECTRICAL_STATE_TYPE_s ILCK_GetInterlockSetValue(void);

/**
 * @brief   Reads the feedback pin of the interlock and returns its current value
 *          (ILCK_SWITCH_OFF/ILCK_SWITCH_ON)
 * @return  measuredInterlockState (type: ILCK_ELECTRICAL_STATE_TYPE_s)
 */
extern ILCK_ELECTRICAL_STATE_TYPE_s ILCK_GetInterlockFeedback(void);

/**
 * @brief   Sets the interlock state to its requested state, if the interlock is at that time not in the requested state.
 *
 * It returns E_OK if the requested state was successfully set or if the interlock was at the requested state before.
 * @param   requstedInterlockState (type: ILCK_ELECTRICAL_STATE_TYPE_s)
 * @return  retVal (type: STD_RETURN_TYPE_e)
 */
extern STD_RETURN_TYPE_e ILCK_SetInterlockState(ILCK_ELECTRICAL_STATE_TYPE_s requstedInterlockState);

/**
 * @brief   Switches the interlock off and returns E_NOT_OK on success.
 * @return  retVal (type: STD_RETURN_TYPE_e)
 */
extern STD_RETURN_TYPE_e ILCK_SwitchInterlockOff(void);

/**
 * @brief   Switches the interlock on and returns E_OK on success.
 * @return  retVal (type: STD_RETURN_TYPE_e)
 */
extern STD_RETURN_TYPE_e ILCK_SwitchInterlockOn(void);

/*================== Function Implementations =============================*/


/*================== Constant and Variable Definitions ====================*/


/**
 * States of the ILCK state machine
 */
typedef enum {
    /* Init-Sequence */
    ILCK_STATEMACH_UNINITIALIZED             = 0,    /*!<    */
    ILCK_STATEMACH_INITIALIZATION            = 1,    /*!<    */
    ILCK_STATEMACH_INITIALIZED               = 2,    /*!<    */
    ILCK_STATEMACH_WAIT_FIRST_REQUEST             = 3,    /*!<    */
    ILCK_STATEMACH_OPEN                      = 4,    /*!<    */
    ILCK_STATEMACH_CLOSED                    = 5,    /*!<    */
    ILCK_STATEMACH_UNDEFINED                 = 20,   /*!< undefined state                                */
    ILCK_STATEMACH_RESERVED1                 = 0x80, /*!< reserved state                                 */
    ILCK_STATEMACH_ERROR                     = 0xF0, /*!< Error-State:  */
} ILCK_STATEMACH_e;


/**
 * Substates of the ILCK state machine
 */
typedef enum {
    ILCK_ENTRY                                    = 0,    /*!< Substate entry state       */
    ILCK_OPEN_FIRST_CONTACTOR                     = 1,    /*!< Open-sequence: first contactor */
    ILCK_OPEN_SECOND_CONTACTOR_MINUS              = 2,    /*!< Open-sequence: second contactor */
    ILCK_OPEN_SECOND_CONTACTOR_PLUS               = 3,    /*!< Open-sequence: second contactor */
    ILCK_STANDBY                                  = 4,    /*!< Substate stanby */
    ILCK_PRECHARGE_CLOSE_MINUS                    = 5,    /*!< Begin of precharge sequence: close main minus */
    ILCK_PRECHARGE_CLOSE_PRECHARGE                = 6,    /*!< Next step of precharge sequence: close precharge */
    ILCK_PRECHARGE_CLOSE_PLUS                     = 7,    /*!< Next step of precharge sequence: close main plus */
    ILCK_PRECHARGE_CHECK_VOLTAGES                 = 8,    /*!< Next step of precharge sequence: check if voltages OK */
    ILCK_PRECHARGE_OPEN_PRECHARGE                 = 9,    /*!< Next step of precharge sequence: open precharge */
} ILCK_STATEMACH_SUB_e;


/**
 * State requests for the ILCK statemachine
 */
typedef enum {
    ILCK_STATE_INIT_REQUEST                = ILCK_STATEMACH_INITIALIZATION,           /*!<    */
    ILCK_STATE_OPEN_REQUEST             = ILCK_STATEMACH_OPEN,                     /*!<    */
    ILCK_STATE_CLOSE_REQUEST              = ILCK_STATEMACH_CLOSED,                /*!<    */
    ILCK_STATE_ERROR_REQUEST               = ILCK_STATEMACH_ERROR,   /*!<    */
    ILCK_STATE_NO_REQUEST                  = ILCK_STATEMACH_RESERVED1,                /*!<    */
} ILCK_STATE_REQUEST_e;


/**
 * Possible return values when state requests are made to the ILCK statemachine
 */
typedef enum {
    ILCK_OK                                 = 0,    /*!< ILCK --> ok                             */
    ILCK_BUSY_OK                            = 1,    /*!< ILCK under load --> ok                  */
    ILCK_REQUEST_PENDING                    = 2,    /*!< requested to be executed               */
    ILCK_ILLEGAL_REQUEST                    = 3,    /*!< Request can not be executed            */
    ILCK_INIT_ERROR                         = 7,    /*!< Error state: Source: Initialization    */
    ILCK_OK_FROM_ERROR                      = 8,    /*!< Return from error --> ok               */
    ILCK_ERROR                              = 20,   /*!< General error state                    */
    ILCK_ALREADY_INITIALIZED                = 30,   /*!< Initialization of LTC already finished */
    ILCK_ILLEGAL_TASK_TYPE                  = 99,   /*!< Illegal                                */
} ILCK_RETURN_TYPE_e;


/**
 * This structure contains all the variables relevant for the ILCK state machine.
 * The user can get the current state of the ILCK state machine with this variable
 */
typedef struct {
    uint16_t timer;                         /*!< time in ms before the state machine processes the next state, e.g. in counts of 1ms    */
    ILCK_STATE_REQUEST_e statereq;          /*!< current state request made to the state machine                                        */
    ILCK_STATEMACH_e state;                 /*!< state of Driver State Machine                                                          */
    ILCK_STATEMACH_SUB_e substate;          /*!< current substate of the state machine                                                  */
    ILCK_STATEMACH_e laststate;             /*!< previous state of the state machine                                                    */
    ILCK_STATEMACH_SUB_e lastsubstate;      /*!< previous substate of the state machine                                                 */
    uint32_t ErrRequestCounter;             /*!< counts the number of illegal requests to the LTC state machine */
    uint8_t triggerentry;                   /*!< counter for re-entrance protection (function running flag) */
    uint8_t counter;                        /*!< general purpose counter */
} ILCK_STATE_s;


/*================== Function Prototypes ==================================*/

extern ILCK_RETURN_TYPE_e ILCK_SetStateRequest(ILCK_STATE_REQUEST_e statereq);
extern  ILCK_STATEMACH_e ILCK_GetState(void);
extern void ILCK_Trigger(void);

#endif /* INTERLOCK_H_ */

interlock_cfg.c

/**
 *
 * @copyright &copy; 2010 - 2019, 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:
 *
 * &Prime;This product uses parts of foxBMS&reg;&Prime;
 *
 * &Prime;This product includes parts of foxBMS&reg;&Prime;
 *
 * &Prime;This product is derived from foxBMS&reg;&Prime;
 *
 */

/**
 * @file    interlock_cfg.c
 * @author  foxBMS Team
 * @date    23.09.2015 (date of creation)
 * @ingroup DRIVERS_CONF
 * @prefix  CONT
 *
 * @brief   Configuration for the driver for the interlock.
 *
 */

/*================== Includes =============================================*/
#include "interlock_cfg.h"

#if BUILD_MODULE_ENABLE_ILCK == 1
/*================== Macros and Definitions ===============================*/

/*================== Constant and Variable Definitions ====================*/


ILCK_CONFIG_s ilck_interlock_config = {
        ILCK_INTERLOCK_CONTROL,         ILCK_INTERLOCK_FEEDBACK,        ILCK_FEEDBACK_TYPE_DONT_CARE
};

ILCK_ELECTRICAL_STATE_s ilck_interlock_state = {
        FALSE,     ILCK_SWITCH_OFF
};

/*================== Function Prototypes ==================================*/

/*================== Function Implementations =============================*/
#endif

interlock_cfg.h

/**
 *
 * @copyright &copy; 2010 - 2019, 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:
 *
 * &Prime;This product uses parts of foxBMS&reg;&Prime;
 *
 * &Prime;This product includes parts of foxBMS&reg;&Prime;
 *
 * &Prime;This product is derived from foxBMS&reg;&Prime;
 *
 */

/**
 * @file    interlock_cfg.h
 * @author  foxBMS Team
 * @date    23.09.2015 (date of creation)
 * @ingroup DRIVERS_CONF
 * @prefix  ILCK
 *
 * @brief   Header for the configuration for the driver for the interlock
 *
 */

#ifndef INTERLOCK_CFG_H_
#define INTERLOCK_CFG_H_

/*================== Includes =============================================*/
#include "general.h"

#include "io.h"

/*================== Macros and Definitions ===============================*/

/*
 * The number of defines per contactor must be the same as the length
 *  of the array ilck_contactors_cfg in contactor_cfg.c
 * Every contactor consists of 1 control pin and 1 feedback pin
 * counting together as 1 contactor.
 * E.g. if you have 1 contactor your define has to be:
 *      #define ILCK_INTERLOCK_CONTROL       PIN_MCU_0_INTERLOCK_CONTROL
 *      #define ILCK_INTERLOCK_FEEDBACK      PIN_MCU_0_INTERLOCK_FEEDBACK
 */
#define ILCK_INTERLOCK_CONTROL                  IO_PIN_INTERLOCK_CONTROL
/**
 * Defines the pin where interlock feedback pin is connected to the mcu
 */
#define ILCK_INTERLOCK_FEEDBACK                 IO_PIN_INTERLOCK_FEEDBACK

/**
 * This define MUST represent the cycle time of the task in which context the
 * functions run, e.g., if the ILCK_Trigger() is running in the 10 ms task
 * then the define must be set to 10.
 *
 * This define also sets the minimum time.
 */

#define ILCK_TASK_CYCLE_CONTEXT_MS (10)


/**
 * ILCK statemachine short time definition in ms
 */

#define ILCK_STATEMACH_SHORTTIME_MS     (ILCK_TASK_CYCLE_CONTEXT_MS)


/*================== Constant and Variable Definitions ====================*/

/**
 * Symbolic names for current flow direction in the battery
 */
typedef enum {
    ILCK_CURRENT_CHARGE     = 0,    /*!<       */
    ILCK_CURRENT_DISCHARGE  = 1,    /*!<       */
} ILCK_CURRENT_DIRECTION_e;

/**
 * Symbolic names for contactors' possible states
 */
typedef enum {
    ILCK_SWITCH_OFF     = 0,    /*!< Contactor off         --> Contactor is open           */
    ILCK_SWITCH_ON      = 1,    /*!< Contactor on          --> Contactor is closed         */
    ILCK_SWITCH_UNDEF   = 2,    /*!< Contactor undefined   --> Contactor state not known   */
} ILCK_ELECTRICAL_STATE_TYPE_s;

/**
 * Symbolic names defining the electric behavior of the contactor
 */
typedef enum {
    ILCK_FEEDBACK_NORMALLY_OPEN     = 0,    /*!< Feedback line of a contactor is normally open      */
    ILCK_FEEDBACK_NORMALLY_CLOSED   = 1,    /*!< Feedback line of a contactor is normally closed    */
    ILCK_FEEDBACK_TYPE_DONT_CARE    = 0xFF  /*!< Feedback line of the contactor is not used         */
} ILCK_FEEDBACK_TYPE_e;

typedef struct {
    ILCK_ELECTRICAL_STATE_TYPE_s set;
    ILCK_ELECTRICAL_STATE_TYPE_s feedback;
} ILCK_ELECTRICAL_STATE_s;

typedef struct {
    IO_PORTS_e control_pin;
    IO_PORTS_e feedback_pin;
    ILCK_FEEDBACK_TYPE_e feedback_pin_type;
} ILCK_CONFIG_s;

extern ILCK_CONFIG_s ilck_interlock_config;
extern ILCK_ELECTRICAL_STATE_s ilck_interlock_state;

/*================== Function Prototypes ==================================*/

/*================== Function Implementations =============================*/

#endif /* INTERLOCK_CFG_H_ */

interlock_cfg.c

/**
 *
 * @copyright &copy; 2010 - 2019, 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:
 *
 * &Prime;This product uses parts of foxBMS&reg;&Prime;
 *
 * &Prime;This product includes parts of foxBMS&reg;&Prime;
 *
 * &Prime;This product is derived from foxBMS&reg;&Prime;
 *
 */

/**
 * @file    interlock_cfg.c
 * @author  foxBMS Team
 * @date    23.09.2015 (date of creation)
 * @ingroup DRIVERS_CONF
 * @prefix  CONT
 *
 * @brief   Configuration for the driver for the interlock.
 *
 */

/*================== Includes =============================================*/
#include "interlock_cfg.h"

/*================== Macros and Definitions ===============================*/

/*================== Constant and Variable Definitions ====================*/


ILCK_CONFIG_s ilck_interlock_config = {
        ILCK_INTERLOCK_CONTROL,         ILCK_INTERLOCK_FEEDBACK,        ILCK_FEEDBACK_TYPE_DONT_CARE
};

ILCK_ELECTRICAL_STATE_s ilck_interlock_state = {
        FALSE,     ILCK_SWITCH_OFF
};

/*================== Function Prototypes ==================================*/

/*================== Function Implementations =============================*/

interlock_cfg.h

/**
 *
 * @copyright &copy; 2010 - 2019, 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:
 *
 * &Prime;This product uses parts of foxBMS&reg;&Prime;
 *
 * &Prime;This product includes parts of foxBMS&reg;&Prime;
 *
 * &Prime;This product is derived from foxBMS&reg;&Prime;
 *
 */

/**
 * @file    interlock_cfg.h
 * @author  foxBMS Team
 * @date    23.09.2015 (date of creation)
 * @ingroup DRIVERS_CONF
 * @prefix  ILCK
 *
 * @brief   Header for the configuration for the driver for the interlock
 *
 */

#ifndef INTERLOCK_CFG_H_
#define INTERLOCK_CFG_H_

/*================== Includes =============================================*/
#include "general.h"

#include "io.h"

/*================== Macros and Definitions ===============================*/

/*
 * The number of defines per contactor must be the same as the length
 *  of the array ilck_contactors_cfg in contactor_cfg.c
 * Every contactor consists of 1 control pin and 1 feedback pin
 * counting together as 1 contactor.
 * E.g. if you have 1 contactor your define has to be:
 *      #define ILCK_INTERLOCK_CONTROL       PIN_MCU_0_INTERLOCK_CONTROL
 *      #define ILCK_INTERLOCK_FEEDBACK      PIN_MCU_0_INTERLOCK_FEEDBACK
 */
#define ILCK_INTERLOCK_CONTROL                  IO_PIN_INTERLOCK_CONTROL
/**
 * Defines the pin where interlock feedback pin is connected to the mcu
 */
#define ILCK_INTERLOCK_FEEDBACK                 IO_PIN_INTERLOCK_FEEDBACK


/**
 * Symbolic names for current flow direction in the battery
 */
typedef enum {
    ILCK_CURRENT_CHARGE     = 0,    /*!<            */
    ILCK_CURRENT_DISCHARGE      = 1,    /*!<       */
} ILCK_CURRENT_DIRECTION_e;



/**
 * ILCK statemachine short time definition in ms
 */

#define ILCK_STATEMACH_SHORTTIME_MS     1


/*================== Constant and Variable Definitions ====================*/

/**
 * Symbolic names for contactors' possible states
 */
typedef enum {
    ILCK_SWITCH_OFF     = 0,    /*!< Contactor off         --> Contactor is open           */
    ILCK_SWITCH_ON      = 1,    /*!< Contactor on          --> Contactor is closed         */
    ILCK_SWITCH_UNDEF   = 2,    /*!< Contactor undefined   --> Contactor state not known   */
} ILCK_ELECTRICAL_STATE_TYPE_s;

/**
 * Symbolic names for the contactors, which are used in
 * the contactor_config[] array
 */
typedef enum {
    ILCK_MAIN_PLUS      = 0,    /*!< Main contactor in the positive path of the powerline      */
    ILCK_PRECHARGE_PLUS = 1,    /*!< Precharge contactor in the positive path of the powerline */
    ILCK_MAIN_MINUS     = 2,    /*!< Main contactor in the negative path of the powerline      */
} ILCK_NAMES_e;

/**
 * Symbolic names defining the electric behavior of the contactor
 */
typedef enum {
    ILCK_FEEDBACK_NORMALLY_OPEN     = 0,    /*!< Feedback line of a contactor is normally open      */
    ILCK_FEEDBACK_NORMALLY_CLOSED   = 1,    /*!< Feedback line of a contactor is normally closed    */
    ILCK_FEEDBACK_TYPE_DONT_CARE    = 0xFF  /*!< Feedback line of the contactor is not used         */
} ILCK_FEEDBACK_TYPE_e;

typedef struct {
    ILCK_ELECTRICAL_STATE_TYPE_s set;
    ILCK_ELECTRICAL_STATE_TYPE_s feedback;
} ILCK_ELECTRICAL_STATE_s;

typedef struct {
    IO_PORTS_e control_pin;
    IO_PORTS_e feedback_pin;
    ILCK_FEEDBACK_TYPE_e feedback_pin_type;
} ILCK_CONFIG_s;

extern ILCK_CONFIG_s ilck_interlock_config;
extern ILCK_ELECTRICAL_STATE_s ilck_interlock_state;

/*================== Function Prototypes ==================================*/

/*================== Function Implementations =============================*/

#endif /* INTERLOCK_CFG_H_ */