/**
 * @file lin_core.c
 * @brief
 * @version 0.1
 * @date 2023-10-25
 *
 * (c) Copyright 2020-2022 Yuntu Microelectronics co.,ltd.
 *
 * All Rights Reserved
 *
 */

#include "lin_lib_config.h"
#include "lin_core.h"
#include "lin_tp.h"
#include "lin_types.h"
#include "interrupt_manager.h"
#include <stdint.h>



#define LIN_L8_TO_L16(p) ((l_u16)(((l_u16)(p)[0])<<8)|((l_u16)(p)[1]))


#define LIN_L16_TO_L8(p,v) do{\
    (p)[0]=(l_u8)((v)>>8);\
    (p)[1]=(l_u8)(v);\
}while(0)





#ifdef LIN_HAS_MASTER
/**
 * @brief check whether coll has happen, if happen, will switch to resolve sch
 * @param[in] inst ifc handle
 * @return l_bool true: coll happen, false: coll not happen
 */
static l_bool lin_coll_check(l_ifc_handle inst) {
    l_u16 lastSlot;
    l_bool ret=l_false;
    lin_master_state_t* masterState=g_linGlobalState[inst].masterState;
    if(masterState->collPending) {
        masterState->collPending=false;
        if(g_linGlobalSchTable[masterState->activeSch]->schType!=LIN_SCH_TYPE_NORMAL){
            /* if right now active diag or others, we must switch to normal, then we can get correct resolveSch */
            lin_sch_back(inst);
        }

        ret=l_true;
        lastSlot=masterState->activeSlot;
        if(lastSlot==0) {
            lastSlot=g_linGlobalSchTable[masterState->activeSch]->numSlot-1U;
        } else {
            lastSlot--;
        }
        /* switch */
        l_sch_set(inst,g_linGlobalSchTable[masterState->activeSch]->slotList[lastSlot].event.resolveSch,0);
    }

    return ret;
}

/**
 * @brief sch table end callback, called when sch table end
 * @param[in] inst ifc handle
 */
static void lin_sch_end_callback(l_ifc_handle inst) {
    lin_master_state_t* masterState=g_linGlobalState[inst].masterState;
    if(masterState->activeSch!=LIN_INVALID_SCH_INDEX){
        switch(g_linGlobalSchTable[masterState->activeSch]->schType) {
        case LIN_SCH_TYPE_NORMAL:
            lin_tp_sch_handle(inst);
            break;
        case LIN_SCH_TYPE_COLLISION_RESOLVED:
            /* switch normal table first*/
            lin_sch_back(inst);
            lin_tp_sch_handle(inst);
            break;
        case LIN_SCH_TYPE_MASTER_REQUEST:
            if(masterState->masterTpState->diagOnly){
                lin_tp_sch_handle(inst);
            }else{
                lin_sch_back(inst);
                /* if active is invalid, check tp sch here */
                if(masterState->activeSch==LIN_INVALID_SCH_INDEX){
                    lin_tp_sch_handle(inst);
                }
            }
            break;
        case LIN_SCH_TYPE_SLAVE_RESPONSE:
            /* diag */
            if(masterState->masterTpState->diagOnly){
                lin_tp_sch_handle(inst);
            }else{
                lin_sch_back(inst);
                /* if active is invalid, check tp sch here */
                if(masterState->activeSch==LIN_INVALID_SCH_INDEX){
                    lin_tp_sch_handle(inst);
                }
            }
            break;
        case LIN_SCH_TYPE_SLEEP:
            masterState->activeSch=LIN_INVALID_SCH_INDEX;
            break;

        }   
    }
}
#endif

static inline l_u16 lin_calc_max_header_timeout_cnt(l_u16 baudRate)
{
    return (l_u16)((14U * 34U * 100000U / (500 * baudRate)) + 1U);
}
/*!
 * @brief Computes the maximum response timeout
 *
 * TResponse_Maximum = 1.4 * TResponse_Nominal, TResponse_Nominal = 10 * (NData+ 1) * TBit
 *
 * @param[in] baudRate LIN network baud rate
 * @param[in] size     frame size in bytes
 * @return maximum response timeout for the given baud rate and frame size
 *
 * Implements : lin_calc_max_res_timeout_cnt_Activity
 */
static inline l_u16 lin_calc_max_res_timeout_cnt(l_u16 baudRate,
                                                 l_u8 size)
{
    l_u16 a = (l_u16)(14U * (1U + (l_u16)size));

    return (l_u16)((a * 1000000U / (500 * baudRate)) + 1U);
}
/**
 * @brief set signal flag
 * @param[in] inst ifc handle
 * @param[in] signal signal pointer
 */
static void lin_set_signal_flag(l_ifc_handle inst,const lin_signal_t* signal) {
    lin_core_state_t* state=&g_linGlobalState[inst];
    l_u16 byteOffset=signal->flagBitOffset/8;
    state->signalFlagPool[byteOffset]|=(1<<(signal->flagBitOffset%8));
}


/**
 * @brief get signal flag
 * @param[in] inst ifc handle
 * @param[in] signal signal pointer
 * @return l_bool true: flag is set, false: flag is not set
 */
static l_bool lin_get_signal_flag(l_ifc_handle inst,const lin_signal_t* signal) {
    lin_core_state_t const* state=&g_linGlobalState[inst];
    l_u16 byteOffset=signal->flagBitOffset/8;
    l_u8 bitOffset=signal->flagBitOffset%8;
    return (state->signalFlagPool[byteOffset]&(1<<bitOffset))!=0?l_true:l_false;
}

/**
 * @brief clear signal flag
 * @param[in] inst ifc handle
 * @param[in] signal signal pointer
 */
static void lin_clr_signal_flag(l_ifc_handle inst,const lin_signal_t* signal) {
    lin_core_state_t* state=&g_linGlobalState[inst];
    l_u16 byteOffset=signal->flagBitOffset/8;
    l_u8 bitOffset=signal->flagBitOffset%8;
    state->signalFlagPool[byteOffset]&=~(1<<bitOffset);
}

/**
 * @brief set frame flag
 * @param[in] inst ifc handle
 * @param[in] frame frame pointer
 */
static void lin_set_frame_flag(l_ifc_handle inst,const lin_frame_t* frame) {
    lin_core_state_t* state=&g_linGlobalState[inst];
    l_u16 byteOffset=frame->flagBitOffset/8;
    state->frameFlagPool[byteOffset]|=(1<<(frame->flagBitOffset%8));
}

/**
 * @brief get frame flag
 * @param[in] inst ifc handle
 * @param[in] frame frame pointer
 * @return l_bool true: flag is set, false: flag is not set
 */
static l_bool lin_get_frame_flag(l_ifc_handle inst,const lin_frame_t* frame) {
    lin_core_state_t const* state=&g_linGlobalState[inst];
    l_u16 byteOffset=frame->flagBitOffset/8;
    l_u8 bitOffset=frame->flagBitOffset%8;
    return (state->frameFlagPool[byteOffset]&(1<<bitOffset))!=0?l_true:l_false;
}

/**
 * @brief clear frame flag
 * @param[in] inst ifc handle
 * @param[in] frame frame pointer
 */
static void lin_clr_frame_flag(l_ifc_handle inst,const lin_frame_t* frame) {
    lin_core_state_t* state=&g_linGlobalState[inst];
    l_u16 byteOffset=frame->flagBitOffset/8;
    l_u8 bitOffset=frame->flagBitOffset%8;
    state->frameFlagPool[byteOffset]&=~(1<<bitOffset);
}

/**
 * @brief set update flag
 * @param[in] inst ifc handle
 * @param[in] signal signal pointer
 */
static void lin_set_update_flag(l_ifc_handle inst,const lin_signal_t* signal) {
    lin_core_state_t* state=&g_linGlobalState[inst];
    l_u16 byteOffset=signal->flagBitOffset/8;
    state->updateFlagPool[byteOffset]|=(1<<(signal->flagBitOffset%8));
}


/**
 * @brief get update flag
 * @param[in] inst ifc handle
 * @param[in] signal signal pointer
 * @return l_bool true: flag is set, false: flag is not set
 */
static l_bool lin_get_update_flag(l_ifc_handle inst,const lin_signal_t* signal) {
    lin_core_state_t const* state=&g_linGlobalState[inst];
    l_u16 byteOffset=signal->flagBitOffset/8;
    l_u8 bitOffset=signal->flagBitOffset%8;
    return (state->updateFlagPool[byteOffset]&(1<<bitOffset))!=0?l_true:l_false;
}


/**
 * @brief clear update flag
 * @param[in] inst ifc handle
 * @param[in] signal signal pointer
 */
static void lin_clr_update_flag(l_ifc_handle inst,const lin_signal_t* signal) {
    lin_core_state_t* state=&g_linGlobalState[inst];
    l_u16 byteOffset=signal->flagBitOffset/8;
    l_u8 bitOffset=signal->flagBitOffset%8;
    state->updateFlagPool[byteOffset]&=~(1<<bitOffset);
}

/**
 * @brief set flag for frame and signal
 * @param[in] inst ifc handle
 * @param[in] frame frame pointer
 */
static void lin_set_flag(l_ifc_handle inst,const lin_frame_t* frame) {
    lin_set_frame_flag(inst,frame);
    for(int i=0; i<frame->signalNum; i++) {
        lin_set_signal_flag(inst,&g_linGlobalConfig[inst]->signalList[frame->signalList[i]]);
    }
}

/**
 * @brief convert id to pid
 * @param[in] id id
 * @return l_u8 pid
 */
static l_u8 lin_id_to_pid(l_u8 id) {
#ifdef LIN_USE_UART
    l_u8 ret =LIN_DRV_ProcessParity(id,MAKE_PARITY);
#else
    l_u8 ret=LINFlexD_DRV_ProcessParity(id,MAKE_PARITY);
#endif
    return ret;
}

/**
 * @brief from hwid to ifc handle
 * @param[in] hwId hwid
 * @return l_ifc_handle ifc handle
 */
static l_ifc_handle lin_hw_to_ifc(uint32_t hwId) {
    l_ifc_handle ret=0;
    for(; ret<LIN_IFC_INST; ret++) {
        if(g_linGlobalConfig[ret]->hwInst==hwId) {
            break;
        }
    }
    return ret;
}

/**
 * @brief get frame by id, if id is changeable, will get frame by idRamIndex
 * @param[in] inst ifc handle
 * @param[in] id id
 * @return const lin_frame_t* NULL: not found, other: frame pointer
 */
static const lin_frame_t* lin_get_frame_by_id(l_ifc_handle inst,l_u8 id)
{
    const lin_frame_t* ret=NULL;
    
    l_u8 cid;
    for(l_u16 wIndex=0; wIndex<g_linGlobalConfig[inst]->frameNum; wIndex++)
    {
        cid=g_linGlobalConfig[inst]->frameList[wIndex].id;
        if(g_linGlobalConfig[inst]->tpCfg&&g_linGlobalConfig[inst]->frameList[wIndex].idChangeable==l_true){
            cid=g_linGlobalConfig[inst]->tpCfg->idList[g_linGlobalConfig[inst]->frameList[wIndex].idRamIndex]&0x3f;
        }
        if(cid==id)
        {
            ret=&g_linGlobalConfig[inst]->frameList[wIndex];
            break;
        }
    }
    return ret;
}

/**
 * @brief update ifc status, call before tx or rx
 * @param[in] inst ifc handle
 */
static void lin_update_ifc_status(l_ifc_handle inst){
    lin_core_state_t* state=&g_linGlobalState[inst];
    /* update pid, higher 8 bit*/
    state->ifcStatus&=~LIN_IFC_STATUS_PID_MASK;
    state->ifcStatus|=(lin_id_to_pid(state->frameStatus.frameId)<<LIN_IFC_STATUS_PID_SHIFT);
   

    if(state->frameStatus.busActive==l_true){
        state->ifcStatus|=LIN_IFC_STATUS_BUS_ACTIVITY;
        state->frameStatus.busActive=l_false;
    }
    if(state->frameStatus.frameCnt>1)
    {
        /* we reset frame cnt in l_ifc_read_status*/
        state->ifcStatus|=LIN_IFC_STATUS_OVERRUN;
    }
    if(state->frameStatus.errorInResp==l_true){
        state->ifcStatus|=LIN_IFC_STATUS_ERROR_IN_RESP;
        state->frameStatus.errorInResp=l_false;
    }
    if(state->frameStatus.eventColl==l_true){
        state->ifcStatus|=LIN_IFC_STATUS_EVENT_COLLISION;
        state->frameStatus.eventColl=l_false;
    }
    if(state->frameStatus.succTransfer==l_true){
        state->ifcStatus|=LIN_IFC_STATUS_SUCCESS;
        state->frameStatus.succTransfer=l_false;
    }
    if(state->frameStatus.saveConfig==l_true){
        state->ifcStatus|=LIN_IFC_STATUS_SLAVE_CONFIGURED;
        state->frameStatus.saveConfig=l_false;
    }
    if(state->frameStatus.goToSleep==l_true){
        state->ifcStatus|=LIN_IFC_STATUS_GO_TO_SLEEP;
        state->frameStatus.goToSleep=l_false;
    }

}

/**
 * @brief update data from poll to frame buffer
 * @param[in] inst ifc handle
 * @param[in] frame frame pointer
 */
static void lin_copy_tx_frame(l_ifc_handle inst,const lin_frame_t* frame) {
    const lin_core_state_t* state = &g_linGlobalState[inst];
#ifdef LIN_USE_UART
    l_u8* data=(l_u8*)(state->dataBuffer);
#else
    l_u8* data=(l_u8*)(state->frameBuf.data);
#endif
    if(frame->frameType==LIN_FRAME_TYPE_DIAG) {
#ifdef LIN_HAS_MASTER
        if(g_linGlobalConfig[inst]->nodeType==LIN_NODE_MASTER){
            /* master node need handle cmd,sleep or normal*/
            const lin_sch_slot_t* schSlot=&g_linGlobalSchTable[state->masterState->activeSch]->slotList[state->masterState->activeSlot];
            if(schSlot->diag.diagType==0){
                /* normal diag */
                lin_tp_handle(inst,LIN_TP_TX_DATA_PRE);
            }else if(schSlot->diag.diagType==1){
                data[0]=0;
                data[1]=0xff;
                data[2]=0xff;
                data[3]=0xff;
                data[4]=0xff;
                data[5]=0xff;
                data[6]=0xff;
                data[7]=0xff;
            }else{
                /* cmd, invalid*/
            }
        }
        else
#endif
        {
            lin_tp_handle(inst,LIN_TP_TX_DATA_PRE);
        }
       
    }
    else {
        /* option, clear frame */
        for(int i=0;i<frame->bufLen;i++)
        {
            data[i]=0;
        }
        if(frame->frameType==LIN_FRAME_TYPE_EVENT){
            /* put the frame PID into the first bytes */
            l_u8 tid=g_linGlobalConfig[inst]->frameList[frame->subIdIndex].id;
            if(state->tpInit==l_true&&g_linGlobalConfig[inst]->frameList[frame->subIdIndex].idChangeable){
                tid=g_linGlobalConfig[inst]->tpCfg->idList[g_linGlobalConfig[inst]->frameList[frame->subIdIndex].idRamIndex]&0x3f;
            }
            data[0]=lin_id_to_pid(tid);
        }
        for(int i = 0; i < frame->signalNum; i++) {
            const lin_signal_t* signal = &g_linGlobalConfig[inst]->signalList[frame->signalList[i]];
            l_u8* pool = &g_linGlobalState[inst].dataPool[signal->bufOffset];
            l_u8 offset = frame->signalOffset[i];
            l_u8 bitLen = signal->bitLen;

            if(signal->signalType == LIN_SIGNAL_TYPE_SCALAR) {
                /* just copy in the case*/
                if(offset%8==0 && bitLen ==8) {
                    data[offset/8]=pool[0];
                } else {
                    l_u16 tmp;
                    if(bitLen <= 8) {
                        tmp = pool[0];
                    } else {
                        tmp=LIN_L8_TO_L16(pool);
                    }

                    /* Update data into buffer from tmp */
                    for(int bit = 0; bit < bitLen; bit++) {
                        l_u8 byteIndex = (offset + bit) / 8U;
                        l_u8 bitIndex = ((offset + bit) % 8);

                        if(tmp & (1 << bit)) {
                            data[byteIndex] |= (1 << bitIndex);
                        } else {
                            data[byteIndex] &= ~(1 << bitIndex);
                        }
                    }
                }
            }
            else if(signal->signalType == LIN_SIGNAL_TYPE_ARRAY) {
                l_u8 arrayLen = (bitLen + 7) / 8;
                if(offset % 8 == 0) {
                    /* Directly copy bytes if offset is byte-aligned */
                    lin_memcpy(&data[offset / 8], pool, arrayLen);
                } else {                   
                    for(int byte = 0; byte < arrayLen; byte++) {
                        for(int bit = 0; bit < 8 && (byte * 8 + bit) < bitLen; bit++) {
                            l_u8 dstByteIndex = (offset + byte * 8 + bit) / 8;
                            l_u8 dstBitIndex = 7 - ((offset + byte * 8 + bit) % 8);

                            if(pool[byte] & (1 << (7-bit))) {
                                data[dstByteIndex] |= (1 << dstBitIndex);
                            } else {
                                data[dstByteIndex] &= ~(1 << dstBitIndex);
                            }
                        }
                    }
                }
            }
        }
    }
}

#ifdef LIN_USE_UART
static void lin_error_handle(l_ifc_handle inst,l_u8 id,lin_state_t const* linState){
    lin_error_t err=LIN_CORE_NO_ERROR;
    
         if(g_linGlobalConfig[inst]->coreErrorCb){
        switch (linState->currentEventId) {
        case LIN_FRAME_ERROR:
            err=LIN_CORE_FRAME_BIT_ERROR;
            break;
        case LIN_CHECKSUM_ERROR:
            err=LIN_CORE_CHECKSUM_ERROR;
            break;
        default:
            err=LIN_CORE_OTHERS_ERROR;
            break;
        
        }
        g_linGlobalConfig[inst]->coreErrorCb(inst,id,err);
    
        
    }
    /* reset the uart internal state machine */
    LIN_DRV_GotoIdleState(g_linGlobalConfig[inst]->hwInst);
   
}
#else
static void lin_error_handle(l_ifc_handle inst,l_u8 id,linflexd_state_t const* linState){
    lin_error_t err=LIN_CORE_NO_ERROR;
    if(g_linGlobalConfig[inst]->coreErrorCb){
        switch (linState->currentEventId) {
        case LINFlexD_BIT_ERROR_EVENT:
        case LINFlexD_FRAME_ERROR_EVENT:
            err=LIN_CORE_FRAME_BIT_ERROR;
            break;
        case LINFlexD_CHECKSUM_ERROR_EVENT:
            err=LIN_CORE_CHECKSUM_ERROR;
            break;
        case LINFlexD_OUTPUT_COMPARE_EVENT:
            err=LIN_CORE_TIMEOUT_ERROR;
            break;
        default:
            err=LIN_CORE_OTHERS_ERROR;
            break;
        
        }
        g_linGlobalConfig[inst]->coreErrorCb(inst,id,err);
    }
}
#endif
/**
 * @brief copy data from frame buffer to pool
 * @param[in] inst inst handle
 * @param[in] frame frame pointer
 */
static void lin_copy_rx_frame(l_ifc_handle inst, const lin_frame_t* frame) {
    const lin_core_state_t* state=&g_linGlobalState[inst];
#ifdef LIN_USE_UART
    const l_u8* data=(const l_u8*)(state->dataBuffer);
#else
    const l_u8* data=state->frameBuf.data;
#endif

    if(frame->frameType==LIN_FRAME_TYPE_DIAG) {
        /* sleep cmd handle */
        if(g_linGlobalConfig[inst]->nodeType==LIN_NODE_SLAVE&&data[0]==0){
            /* sleep cmd */
            g_linGlobalState[inst].frameStatus.goToSleep=l_true;
        }else{
                lin_tp_handle(inst,LIN_TP_RX_DATA_DONE);
        }
    } else {
        /* update frame signal buffer */
        for(int i=0; i<frame->signalNum; i++) {
            const lin_signal_t* signal=&g_linGlobalConfig[inst]->signalList[frame->signalList[i]];
            l_u8* pool=&g_linGlobalState[inst].dataPool[signal->bufOffset];
            l_u8 offset=frame->signalOffset[i];
            l_u8 bitLen=signal->bitLen;
            if(signal->signalType==LIN_SIGNAL_TYPE_SCALAR) {
                /* just copy in the case*/
                if(offset%8==0 && bitLen ==8) {
                    pool[0]=data[offset/8];
                } else {
                    /* scalar max length is 16bit*/
                    l_u16 tmp = 0;
                    /* copy data from buffer into tmp */
                    for(int bit = 0; bit < bitLen; bit++) {
                        l_u8 byteIndex = (offset + bit) / 8;
                        l_u8 bitIndex = (offset + bit) % 8;

                        if(data[byteIndex] & (1 << bitIndex)) {
                            tmp |= (1 << bit);
                        }
                    }
                    if(bitLen<=8) {
                        pool[0]=(l_u8)tmp;
                    } else {
                        LIN_L16_TO_L8(pool,tmp);
                    }
                }
            } else {
                l_u8 arrayLen = (bitLen+7)/8; // assumed in bytes
                if(offset%8==0) {
                    lin_memcpy(pool, &data[offset / 8], arrayLen);
                } else {
                    for(int byte = 0; byte < arrayLen; byte++) {
                        for(int bit = 0; bit < 8; bit++) {
                            l_u8 srcByteIndex = (offset + byte * 8 + bit) / 8;
                            l_u8 srcBitIndex = (offset + byte * 8 + bit) % 8;

                            if(data[srcByteIndex] & (1 << srcBitIndex)) {
                                pool[byte] |= (1 << bit);
                            } else {
                                pool[byte] &= ~(1 << bit);
                            }
                        }
                    }
                }
            }
        }
    }
}

void l_lfx_tx(l_ifc_handle inst)
{
    status_t status;
    lin_core_state_t* state=&g_linGlobalState[inst];
    int ret=0;
    
    l_bool updateFlag=l_true;
    /* master node send frame directly */
    if(state->frameSm==LIN_FRAME_SM_PID
            ||(g_linGlobalConfig[inst]->nodeType==LIN_NODE_MASTER&&state->frameSm==LIN_FRAME_SM_IDLE)) {

        lin_update_ifc_status(inst);
#ifdef LIN_HAS_MASTER
        if(g_linGlobalConfig[inst]->nodeType==LIN_NODE_MASTER) {
            const lin_sch_slot_t* schSlot;
            /* master node need handle sporadic frame*/
            schSlot=&g_linGlobalSchTable[state->masterState->activeSch]->slotList[state->masterState->activeSlot];
            if(schSlot->frameType==LIN_FRAME_TYPE_SPRDC) {
                updateFlag=l_false;
                /* check relative unconditional frame update flag, the frameList must sort by priority*/
                for(int i=0; i<schSlot->sprdc.frameNum; i++) {
                    const lin_frame_t* frame=  &g_linGlobalConfig[inst]->frameList[schSlot->sprdc.frameList[i]];
                    for(int j=0; j<frame->signalNum; j++) {
                        const lin_signal_t* signal=&g_linGlobalConfig[inst]->signalList[frame->signalList[j]];
                        if(lin_get_update_flag(inst,signal)) {
                            updateFlag=l_true;
                            state->activeFrame=frame;
                            break;
                        }
                    }
                    if(updateFlag) {
                        break;
                    }

                }
            }else if(schSlot->frameType==LIN_FRAME_TYPE_DIAG){
                /* Send when there is data in the queue */
                if(state->tpState->txStatus==LD_QUEUE_EMPTY||state->tpState->diagState!=LIN_DIAG_TX_PHY){
                    updateFlag = l_false;
                }
            }else{
                /* do nothing */
            }
        }
        else 
#endif
        {
#ifdef LIN_HAS_SLAVE
            /* slave node event handler */
            if(state->activeFrame->frameType==LIN_FRAME_TYPE_EVENT) {
                updateFlag=l_false;
                /* check whether the event frame has data update*/
                for(int i=0; i<state->activeFrame->signalNum; i++) {
                    const lin_signal_t* signal=&g_linGlobalConfig[inst]->signalList[state->activeFrame->signalList[i]];
                    if(lin_get_update_flag(inst,signal)) {
                        updateFlag=l_true;
                        break;
                    }
                }
            }else if(state->activeFrame->frameType==LIN_FRAME_TYPE_DIAG){
                /* TX_PH */
                if(state->tpState->txStatus==LD_QUEUE_EMPTY||state->tpState->diagState!=LIN_DIAG_TX_PHY){
                    updateFlag=l_false;
                }
            }else{
                /* do nothing */
            }
#endif
        }

        if(updateFlag&&state->activeFrame->dir==LIN_DIR_PUBLISH) {
#ifdef LIN_USE_UART
            state->id=state->activeFrame->id;
            state->dataLength=state->activeFrame->bufLen;
            if(state->frameSm==LIN_FRAME_SM_IDLE){
                state->frameSm=LIN_FRAME_SM_PID;
            }else{
                state->frameSm=LIN_FRAME_SM_TX;
            }
#else
            state->frameBuf.dataLength=state->activeFrame->bufLen;
            state->frameBuf.checksumType=(linflexd_cs_t)state->activeFrame->checksumType;
            state->frameBuf.id=state->activeFrame->id;
            state->frameSm=LIN_FRAME_SM_TX;
#endif
            
            /* update frame status */
            state->frameStatus.frameCnt++;
         
           
            /* copy data from pool to frame buffer */
            lin_copy_tx_frame(inst,state->activeFrame);
#ifdef LIN_DEBUG
            state->preSendCnt++;
#endif      
            
            if(g_linGlobalConfig[inst]->nodeType==LIN_NODE_MASTER) {
#ifdef LIN_USE_UART
                /* uart header and data send separate */
                if(state->frameSm==LIN_FRAME_SM_PID){
                    state->frameTimeout=lin_calc_max_header_timeout_cnt(g_linGlobalConfig[inst]->baudRate);
                    status=LIN_DRV_MasterSendHeader(g_linGlobalConfig[inst]->hwInst, state->id);
                }else{
                    state->frameTimeout=lin_calc_max_res_timeout_cnt(g_linGlobalConfig[inst]->baudRate,state->activeFrame->bufLen);
                    LIN_DRV_SetTimeoutCounter(g_linGlobalConfig[inst]->hwInst, state->frameTimeout);
                    status=LIN_DRV_SendFrameData(g_linGlobalConfig[inst]->hwInst, state->dataBuffer, state->dataLength);
                }

#else
                state->frameTimeout=lin_calc_max_res_timeout_cnt(g_linGlobalConfig[inst]->baudRate,state->activeFrame->bufLen)+lin_calc_max_header_timeout_cnt(g_linGlobalConfig[inst]->baudRate);
                state->frameBuf.responseType=LIN_MASTER_RESPONSE;
                status=LINFlexD_DRV_MasterTransfer(g_linGlobalConfig[inst]->hwInst, &state->frameBuf);
#endif
            } else {
                state->frameTimeout=lin_calc_max_res_timeout_cnt(g_linGlobalConfig[inst]->baudRate,state->activeFrame->bufLen);
#ifdef LIN_USE_UART
                LIN_DRV_SetTimeoutCounter(g_linGlobalConfig[inst]->hwInst, state->frameTimeout);
                status=LIN_DRV_SendFrameData(g_linGlobalConfig[inst]->hwInst, state->dataBuffer, state->dataLength);
#else
                state->frameBuf.responseType=LIN_SLAVE_RESPONSE;
                status= LINFlexD_DRV_SlaveResponse(g_linGlobalConfig[inst]->hwInst, &state->frameBuf);
#endif
            }
            ret = status==STATUS_SUCCESS?0:-1;
            if(ret != 0) {
                state->frameSm=LIN_FRAME_SM_IDLE;
                state->frameStatus.errorInResp=l_true;
                state->frameStatus.frameId=lin_id_to_pid(state->activeFrame->id);
                if(g_linGlobalConfig[inst]->coreErrorCb){
                    g_linGlobalConfig[inst]->coreErrorCb(inst,state->activeFrame->id,LIN_CORE_PRE_TX_ERROR);
                }
            }else{
                state->frameStatus.busActive=l_true;
            }
        }else{
            state->frameSm=LIN_FRAME_SM_IDLE;
        }
    }

}





void l_lfx_rx(l_ifc_handle inst)
{
    status_t status;
    lin_core_state_t* state=&g_linGlobalState[inst];

    if(state->frameSm==LIN_FRAME_SM_PID||(g_linGlobalConfig[inst]->nodeType==LIN_NODE_MASTER&&state->frameSm==LIN_FRAME_SM_IDLE)) {
        if(state->activeFrame->dir!=LIN_DIR_PUBLISH) {
            lin_update_ifc_status(inst);
#ifdef LIN_USE_UART
            state->id=state->activeFrame->id;
            state->dataLength=state->activeFrame->bufLen;
            if(state->frameSm==LIN_FRAME_SM_IDLE){
                state->frameSm=LIN_FRAME_SM_PID;
            }else{
                state->frameSm=LIN_FRAME_SM_RX;
            }
#else
            state->frameBuf.checksumType=(linflexd_cs_t)state->activeFrame->checksumType;
            state->frameBuf.id=state->activeFrame->id;
            state->frameBuf.dataLength=state->activeFrame->bufLen;
            state->frameSm=LIN_FRAME_SM_RX;
#endif            
            

            if((state->tpInit==l_true)&&(state->activeFrame->frameType==LIN_FRAME_TYPE_DIAG)\
                &&(state->tpState->rxMsgStatus==LD_IN_PROGRESS)&&(state->tpState->ffReceived==l_false)) {
                state->tpState->hasRecvMsg=l_true;
            } 

            state->frameStatus.frameCnt++;
            
            if(g_linGlobalConfig[inst]->nodeType==LIN_NODE_MASTER) {
#ifdef LIN_USE_UART
                if(state->frameSm==LIN_FRAME_SM_PID){
                    state->frameTimeout=lin_calc_max_header_timeout_cnt(g_linGlobalConfig[inst]->baudRate);
                    status=LIN_DRV_MasterSendHeader(g_linGlobalConfig[inst]->hwInst, state->id);
                }else{
                    state->frameTimeout=lin_calc_max_res_timeout_cnt(g_linGlobalConfig[inst]->baudRate,state->activeFrame->bufLen);
                    LIN_DRV_SetTimeoutCounter(g_linGlobalConfig[inst]->hwInst, state->frameTimeout);
                    status=LIN_DRV_ReceiveFrameData(g_linGlobalConfig[inst]->hwInst, state->dataBuffer, state->dataLength);
                }
#else
                state->frameTimeout=lin_calc_max_res_timeout_cnt(g_linGlobalConfig[inst]->baudRate,state->activeFrame->bufLen)+lin_calc_max_header_timeout_cnt(g_linGlobalConfig[inst]->baudRate);
                state->frameBuf.responseType=LIN_SLAVE_RESPONSE;
                status=LINFlexD_DRV_MasterTransfer(g_linGlobalConfig[inst]->hwInst, &state->frameBuf);
#endif
            } else {
                state->frameTimeout=lin_calc_max_res_timeout_cnt(g_linGlobalConfig[inst]->baudRate,state->activeFrame->bufLen);
#ifdef LIN_USE_UART
                LIN_DRV_SetTimeoutCounter(g_linGlobalConfig[inst]->hwInst, state->frameTimeout);
                status=LIN_DRV_ReceiveFrameData(g_linGlobalConfig[inst]->hwInst, state->dataBuffer, state->dataLength);
#else
                state->frameBuf.responseType=LIN_MASTER_RESPONSE;
                status= LINFlexD_DRV_SlaveResponse(g_linGlobalConfig[inst]->hwInst, &state->frameBuf);
#endif
            }
            if(status != STATUS_SUCCESS) {
                state->frameSm=LIN_FRAME_SM_IDLE;
                state->frameStatus.errorInResp=l_true;
                state->frameStatus.frameId=lin_id_to_pid(state->activeFrame->id);
                if(g_linGlobalConfig[inst]->coreErrorCb){
                    g_linGlobalConfig[inst]->coreErrorCb(inst,state->activeFrame->id,LIN_CORE_PRE_RX_ERROR);
                }
            }else{
                state->frameStatus.busActive=l_true;
            }
        }
    }
}

l_irqmask l_sys_irq_disable (void) {
    INT_SYS_DisableIRQGlobal();
    return 0;
}

void l_sys_irq_restore (l_irqmask previous)
{
    (void)previous;
    INT_SYS_EnableIRQGlobal();

}


void l_sch_set(l_ifc_handle inst,l_schedule_handle schedule,l_u8 entry) {
#ifdef LIN_HAS_MASTER
    lin_master_state_t* masterState=g_linGlobalState[inst].masterState;
    /* Check whether the parameter schedule is valid */
    if((schedule < g_linGlobalSchTableNum)||(schedule == LIN_INVALID_SCH_INDEX))
    {
        /* Last active sch is normal table, store it*/
        if(masterState->activeSch!=LIN_INVALID_SCH_INDEX&&(LIN_SCH_TYPE_NORMAL==g_linGlobalSchTable[masterState->activeSch]->schType)){
            masterState->previousSch=masterState->activeSch;
            masterState->previousSlot=masterState->activeSlot;
        }  
        masterState->activeSch=schedule;
        if(schedule!=LIN_INVALID_SCH_INDEX&&entry<g_linGlobalSchTable[schedule]->numSlot){
            masterState->activeSlot=entry;
        }
    }
    
#endif
}


l_bool l_sys_init(){

    lin_config_init();
    for(int i=0;i<LIN_IFC_INST;i++){
        g_linGlobalState[i].frameSm = LIN_FRAME_SM_IDLE;
        g_linGlobalState[i].event = 0;
        g_linGlobalState[i].ifcStatus = 0;
        g_linGlobalState[i].activeFrame = NULL;
        g_linGlobalState[i].tpInit = l_false;
        g_linGlobalState[i].frameStatus.busActive = l_false;
        g_linGlobalState[i].frameStatus.frameCnt = 0;
        g_linGlobalState[i].frameStatus.frameId = 0;
        g_linGlobalState[i].frameStatus.saveConfig = l_false;
        g_linGlobalState[i].frameStatus.eventColl = l_false;
        g_linGlobalState[i].frameStatus.goToSleep = l_false;
        g_linGlobalState[i].frameStatus.succTransfer = l_false;
        g_linGlobalState[i].frameStatus.errorInResp = l_false;

        /* clear flag */
        for(int j=0;j<sizeof(g_linGlobalState[i].signalFlagPool);j++){
            g_linGlobalState[i].signalFlagPool[j]=0;
        }
        for(int j=0;j<sizeof(g_linGlobalState[i].frameFlagPool);j++){
            g_linGlobalState[i].frameFlagPool[j]=0;
        }
        for(int j=0;j<sizeof(g_linGlobalState[i].updateFlagPool);j++){
            g_linGlobalState[i].updateFlagPool[j]=0;
        }

        if(g_linGlobalConfig[i]->nodeType==LIN_NODE_MASTER){
            g_linGlobalState[i].masterState->activeSch=LIN_INVALID_SCH_INDEX;
            g_linGlobalState[i].masterState->activeSlot=0;
            g_linGlobalState[i].masterState->tick=0;
            g_linGlobalState[i].masterState->collPending=l_false;
            g_linGlobalState[i].masterState->sleepPending=l_false;
        }else{
            if(g_linGlobalConfig[i]->slaveCfg->initNad==g_linGlobalConfig[i]->slaveCfg->configNad){
                g_linGlobalState[i].slaveState->nadConfigured=l_true;
            }else{
                g_linGlobalState[i].slaveState->nadConfigured=l_false;
            }
        }
    }

    return l_true;
}


l_u8 l_sch_tick(l_ifc_handle inst) {
    l_u8 ret=0;
#ifdef LIN_HAS_MASTER
    lin_core_state_t* state=&g_linGlobalState[inst];
    lin_master_state_t* masterState=g_linGlobalState[inst].masterState;
    const lin_frame_t* frame;

 
    if(masterState->activeSch!=LIN_INVALID_SCH_INDEX) {
        
        /*The call to l_sch_tick will not only start the transition of the next frame due,
        it will also update the signal values for those signals received since the previous call to l_sch_tick*/
        /* at next time base tick after the maximum frame length.
        The master node updates its received signals periodically at the time base start (i.e. at task level).*/
        if(masterState->rxFrame) {
            lin_copy_rx_frame(inst,masterState->rxFrame);
            masterState->rxFrame=NULL;
        }

        if(masterState->tick<=0) {
            /* coll will happen in middle of sch */
            if(lin_coll_check(inst)==l_false){
                /* no coll happen, here we need switch slave response*/
                if(state->masterState->sleepPending==l_true){
                    state->masterState->sleepPending=l_false;
                    /* sleep pending, we need switch to sleep sch*/
                    l_sch_set(inst,g_linGlobalConfig[inst]->masterCfg->sleepSchIndex,0);
                }
                else if(state->tpInit==l_true&&masterState->masterTpState->diagOnly==l_true){
                    if(g_linGlobalSchTable[masterState->activeSch]->schType==LIN_SCH_TYPE_MASTER_REQUEST&&state->tpState->diagState==LIN_DIAG_RX_PHY){
                        l_sch_set(inst,g_linGlobalConfig[inst]->masterCfg->slaveRespSchIndex,0);
                    }else if(g_linGlobalSchTable[masterState->activeSch]->schType==LIN_SCH_TYPE_SLAVE_RESPONSE&&state->tpState->diagState==LIN_DIAG_IDLE){
                        lin_sch_back(inst);
                    }else{
                        /* do nothing */
                    }
                }else{
                    /* do nothing */
                }
            }

            const lin_sch_slot_t* slot=&g_linGlobalSchTable[masterState->activeSch]->slotList[masterState->activeSlot];
            masterState->tick=slot->delay;

            if(slot->frameType==LIN_FRAME_TYPE_SPRDC) {
                l_lfx_tx(inst);
            } else if(slot->frameType==LIN_FRAME_TYPE_EVENT) {
                frame=&g_linGlobalConfig[inst]->frameList[slot->event.frameIndex];
                g_linGlobalState[inst].activeFrame=frame;
                l_lfx_rx(inst);
            } else {
                frame=&g_linGlobalConfig[inst]->frameList[slot->uncd.frameIndex];
                g_linGlobalState[inst].activeFrame=frame;
                if(frame->dir==LIN_DIR_PUBLISH) {
                    l_lfx_tx(inst);
                } else {
                    l_lfx_rx(inst);
                }
            }
            /* update slot */
            masterState->activeSlot++;
            if(masterState->activeSlot>=g_linGlobalSchTable[masterState->activeSch]->numSlot) {
                masterState->activeSlot=0;
                lin_sch_end_callback(inst);
            }
        }

       

        masterState->tick-=g_linGlobalConfig[inst]->masterCfg->timeBase;
        if(masterState->tick<=0) {
            /*if the next call of l_sch_tick will start the transmission of the frame in the next schedule table entry.
            The return value will in this case be the next schedule table entry's number
             (counted from the beginning of the sched- ule table) in the schedule table.
             The return value will be in range 1 to N if the schedule table has N entries.
            */
            ret=masterState->activeSlot+1;
        }
    }else{
        lin_tp_sch_handle(inst);
    }
#endif
    return ret;
}



void l_bool_wr(l_signal_handle handle,l_bool v) {

    l_u16 inst=handle>>16;
    l_u16 index=handle&0xffff;
    /* update v to data pool*/
    const lin_signal_t* signal=&g_linGlobalConfig[inst]->signalList[index];
    l_u8* pool=&g_linGlobalState[inst].dataPool[signal->bufOffset];
    if(v!=pool[0]){
        pool[0]=v;
        /* set update flag */
        lin_set_update_flag(inst,signal);
    }
}

l_bool l_bool_rd(const l_signal_handle handle) {
    l_u16 inst=handle>>16;
    l_u16 index=handle&0xffff;
    /* update v to data pool*/
    const lin_signal_t* signal=&g_linGlobalConfig[inst]->signalList[index];
    return g_linGlobalState[inst].dataPool[signal->bufOffset];
}

void l_u8_wr (l_signal_handle handle, l_u8 v)
{
    l_u16 inst=handle>>16;
    l_u16 index=handle&0xffff;
    /* update v to data pool*/
    const lin_signal_t* signal=&g_linGlobalConfig[inst]->signalList[index];
    l_u8* pool=&g_linGlobalState[inst].dataPool[signal->bufOffset];
    if(v!=pool[0]){
        pool[0]=v;
        /* set update flag */
        lin_set_update_flag(inst,signal);
    }
}

l_u8 l_u8_rd(const l_signal_handle handle) {
    l_u16 inst=handle>>16;
    l_u16 index=handle&0xffff;
    /* update v to data pool*/
    const lin_signal_t* signal=&g_linGlobalConfig[inst]->signalList[index];
    return g_linGlobalState[inst].dataPool[signal->bufOffset];
}


void l_u16_wr (l_signal_handle handle, l_u16 v)
{
    /* update v, vmax is 16bit,need update multi bytes to data pool*/
    l_u16 inst=handle>>16;
    l_u16 index=handle&0xffff;


    const lin_signal_t* signal=&g_linGlobalConfig[inst]->signalList[index];
    l_u8* pool=&g_linGlobalState[inst].dataPool[signal->bufOffset];
    l_u16 tmp=LIN_L8_TO_L16(pool);
    if(v!=tmp){
        LIN_L16_TO_L8(pool, v);
        /* set update flag */
        lin_set_update_flag(inst,signal);
    }
}


l_u16 l_u16_rd(l_signal_handle handle)
{
    l_u16 inst=handle>>16;
    l_u16 index=handle&0xffff;
    const lin_signal_t* signal=&g_linGlobalConfig[inst]->signalList[index];
    l_u8* pool=&g_linGlobalState[inst].dataPool[signal->bufOffset];
    
    l_u16 tmp;
    tmp=LIN_L8_TO_L16(pool);


    return tmp;
}

void l_bytes_rd (l_signal_handle handle, l_u8 start,l_u8 count,l_u8* const data)
{
    l_u16 inst=handle>>16;
    l_u16 index=handle&0xffff;
    const lin_signal_t* signal=&g_linGlobalConfig[inst]->signalList[index];
    l_u8 const* pool=&g_linGlobalState[inst].dataPool[signal->bufOffset];
    lin_memcpy(data,&pool[start],count);
}
void l_flg_clr (l_flag_handle handle){
    l_u16 inst=handle>>24;
    l_bool isFrame=(handle>>16)&0xff;
    l_u16 index=handle&0xffff;
    if(isFrame){
        lin_clr_frame_flag(inst,&g_linGlobalConfig[inst]->frameList[index]);
    }else{
        lin_clr_signal_flag(inst,&g_linGlobalConfig[inst]->signalList[index]);
    }
}

l_bool l_flg_tst (l_flag_handle handle){
    l_u16 inst=handle>>24;
    l_bool isFrame=(handle>>16)&0xff;
    l_u16 index=handle&0xffff;
    if(isFrame){
        return lin_get_frame_flag(inst,&g_linGlobalConfig[inst]->frameList[index]);
    }else{
        return lin_get_signal_flag(inst,&g_linGlobalConfig[inst]->signalList[index]);
    }

}



void l_bytes_wr (l_signal_handle handle,l_u8 start,l_u8 count,const l_u8* const data)
{
    l_u16 inst=handle>>16;
    l_u16 index=handle&0xffff;
    const lin_signal_t* signal=&g_linGlobalConfig[inst]->signalList[index];
    l_u8* pool=&g_linGlobalState[inst].dataPool[signal->bufOffset];
    l_bool updated=l_false;
    for(int i=0;i<count;i++){
        if(pool[start+i]!=data[i]){
            pool[start+i]=data[i];
            updated=l_true;
        }
    }
    if(updated){
        /* set update flag */
        lin_set_update_flag(inst,signal);
    }
   
}


l_u16 l_ifc_read_status (l_ifc_handle inst){
    
    l_u16 tmp;
    l_irqmask irq=l_sys_irq_disable();
    /* update frame Cnt here */
    g_linGlobalState[inst].frameStatus.frameCnt=0;
    tmp= g_linGlobalState[inst].ifcStatus;
    g_linGlobalState[inst].ifcStatus=0;
    l_sys_irq_restore(irq);
    return tmp;
}

l_bool l_ifc_init (l_ifc_handle inst){
#ifdef LIN_USE_UART
    LIN_DRV_InstallCallback(g_linGlobalConfig[inst]->hwInst,lin_frame_rx_handler);
#else
    LINFlexD_DRV_InstallCallback(g_linGlobalConfig[inst]->hwInst,lin_frame_rx_handler);
#endif
    return l_true;
}


void l_ifc_goto_sleep (l_ifc_handle inst){
    lin_core_state_t const* state=&g_linGlobalState[inst];
    if(g_linGlobalConfig[inst]->nodeType==LIN_NODE_MASTER){
        if(state->masterState->activeSch!=LIN_INVALID_SCH_INDEX){
            g_linGlobalState[inst].masterState->sleepPending=l_true;
        }else{
            l_sch_set(inst,g_linGlobalConfig[inst]->masterCfg->sleepSchIndex,0);
        }
        
    }
}

void l_ifc_wake_up (l_ifc_handle inst){

#ifdef LIN_USE_UART
    LIN_DRV_SendWakeupSignal(g_linGlobalConfig[inst]->hwInst);
#else
    LINFlexD_DRV_SendWakeupSignal(g_linGlobalConfig[inst]->hwInst);
#endif
}
void l_ifc_aux (l_ifc_handle inst){
    /* do nothing */
    (void)inst;
}

void lin_frame_rx_handler(uint32_t hwInst, void *param)
{
    l_ifc_handle inst=lin_hw_to_ifc(hwInst);
    lin_core_state_t* state=&g_linGlobalState[inst];
#ifdef LIN_USE_UART
    const lin_state_t*  linState=(lin_state_t*)param;
#else
    const linflexd_state_t*  linState=(linflexd_state_t*)param;
#endif
    state->event=linState->currentEventId;
    switch (state->frameSm) {
    case LIN_FRAME_SM_IDLE:
#ifdef LIN_USE_UART    
        if(linState->currentEventId==LIN_PID_OK) {
#else
        if(linState->currentEventId==LINFlexD_HEADER_RECEIVED_EVENT) {
#endif
            const lin_frame_t* frame=lin_get_frame_by_id(inst,linState->currentId);
            if(frame) {
                state->activeFrame=frame;
                state->frameSm=LIN_FRAME_SM_PID;
                if(frame->dir==LIN_DIR_PUBLISH) {
                    l_lfx_tx(inst);
                } else {
                    l_lfx_rx(inst);
                }
            }
        }
        break;
#ifdef LIN_USE_UART
    case LIN_FRAME_SM_PID:
        if(state->activeFrame->dir==LIN_DIR_PUBLISH){
            l_lfx_tx(inst);
        }else{
            l_lfx_rx(inst);
        }
        break;
#endif
    case LIN_FRAME_SM_TX:
#ifdef LIN_USE_UART
        if(linState->currentEventId==LIN_TX_COMPLETED) {
#else
        if(linState->currentEventId==LINFlexD_DATA_SENT_EVENT) {
#endif
#ifdef LIN_DEBUG
            state->sendCnt++;
#endif      
#ifdef LIN_USE_UART
            state->frameStatus.frameId=lin_id_to_pid(state->id);
#else
            state->frameStatus.frameId=lin_id_to_pid(state->frameBuf.id);
#endif
            if(state->activeFrame->frameType==LIN_FRAME_TYPE_DIAG){

                /*check whether is sleep frame */
#ifdef LIN_USE_UART
                if(g_linGlobalConfig[inst]->nodeType==LIN_NODE_MASTER&&state->dataBuffer[0]==0){
#else
                if(g_linGlobalConfig[inst]->nodeType==LIN_NODE_MASTER&&state->frameBuf.data[0]==0){
#endif
                    /* sleep frame */
                    state->frameStatus.goToSleep=l_true;
                }else{
#ifdef LIN_USE_UART
                    if(g_linGlobalConfig[inst]->nodeType==LIN_NODE_SLAVE&&state->dataBuffer[2]==0x7F&&state->dataBuffer[4]==0x78){
#else
                    if(g_linGlobalConfig[inst]->nodeType==LIN_NODE_SLAVE&&state->frameBuf.data[2]==0x7F&&state->frameBuf.data[4]==0x78){
#endif
                        /* The slave responds with nrc 78, which means there is still data to be sent. */
                        lin_tp_handle(inst,LIN_TP_TX_DATA_NRC78_DONE);
                    }else{
                        /* diag frame need copy to rx queue */
                        lin_tp_handle(inst,LIN_TP_TX_DATA_DONE);
                    }
                }
            }
            /* Successful transfer is set if a frame has been transmitted/received without an error.*/
            state->frameStatus.succTransfer=l_true;

            /* update flag */
            lin_set_flag(inst,state->activeFrame);

            /* clear update flag */
            for(int i=0; i<state->activeFrame->signalNum; i++) {
                lin_clr_update_flag(inst,&g_linGlobalConfig[inst]->signalList[state->activeFrame->signalList[i]]);
            }
          
        }
#if defined(CPU_YTM32B1MD1) || defined(CPU_YTM32B1HA0)
        else if(linState->currentEventId==LINFlexD_RECEIVE_EDGE_DETECTION_EVENT) {
            break;
        }
#endif
        else {
            if(state->activeFrame->frameType==LIN_FRAME_TYPE_EVENT) {
                /* none, accept error in slave node*/
#ifdef LIN_USE_UART
                LIN_DRV_AbortTransferData(hwInst);
#else
                LINFlexD_DRV_AbortTransferData(hwInst);
#endif
            } else if(state->activeFrame->frameType==LIN_FRAME_TYPE_DIAG) {
                state->frameStatus.errorInResp=l_true;
                lin_tp_handle(inst,LIN_TP_TX_ERROR);
            } else {
                state->frameStatus.errorInResp=l_true;
                lin_error_handle(inst,state->activeFrame->id,linState);
            }
        }
        state->frameSm=LIN_FRAME_SM_IDLE;
        break;
    case LIN_FRAME_SM_RX:
#ifdef LIN_USE_UART
        if(linState->currentEventId==LIN_RX_COMPLETED) {
#else
        if(linState->currentEventId==LINFlexD_DATA_RECEIVED_EVENT) {
#endif
            if(state->activeFrame->dir==LIN_DIR_SUBSCRIBE) {
#ifdef LIN_USE_UART
                state->frameStatus.frameId=lin_id_to_pid(state->id);
#else
                state->frameStatus.frameId=lin_id_to_pid(state->frameBuf.id);
#endif
                if(state->activeFrame->frameType==LIN_FRAME_TYPE_EVENT) {
                    /* the first byte is PID, PID&0x3f get id */
#ifdef LIN_USE_UART
                    const lin_frame_t* eventFrame=lin_get_frame_by_id(inst,state->dataBuffer[0]&0x3f);
#else
                    const lin_frame_t* eventFrame=lin_get_frame_by_id(inst,state->frameBuf.data[0]&0x3f);
#endif
                    if(eventFrame) {
                        if(g_linGlobalConfig[inst]->nodeType==LIN_NODE_MASTER)
                        {
                            /* update in l_sch_tick */
                            state->masterState->rxFrame=eventFrame;
                        } else {
                            lin_copy_rx_frame(inst,eventFrame);
                        }
                        /* update flag */
                        lin_set_flag(inst,eventFrame);
                        /* Successful transfer is set if a frame has been transmitted/received without an error.*/
                        state->frameStatus.succTransfer=l_true;
                    } else {
                        /* the reserved first byte is error, drop the frame*/
                    }

                } else {
                    if(g_linGlobalConfig[inst]->nodeType==LIN_NODE_MASTER)
                    {
                        /* update in l_sch_tick */
                        state->masterState->rxFrame=state->activeFrame;
                    } else {
                        lin_copy_rx_frame(inst,state->activeFrame);
                    }
                    /* update flag */
                    lin_set_flag(inst,state->activeFrame);
                    /* Successful transfer is set if a frame has been transmitted/received without an error.*/
                    state->frameStatus.succTransfer=l_true;
                }
            }
        } 
#if defined(CPU_YTM32B1MD1) || defined(CPU_YTM32B1HA0)
        else if(linState->currentEventId==LINFlexD_RECEIVE_EDGE_DETECTION_EVENT) {
            break;
        }
#endif
        else {
            /* error handler, timeout or bus error */
            if(state->activeFrame->frameType==LIN_FRAME_TYPE_EVENT) {
#ifdef LIN_USE_UART
                if(linState->cntByte==1){
#else
                if((linState->rxSize+1)==state->activeFrame->bufLen) {
#endif
                    /* need swich coll resolve table */
                    lin_master_state_t* masterState=g_linGlobalState[inst].masterState;
                    masterState->collPending=true;
                    state->frameStatus.eventColl=l_true;   
                }
                state->frameStatus.succTransfer=l_true;  
#ifdef LIN_USE_UART 
                state->frameStatus.frameId=lin_id_to_pid(state->id);
#else
                state->frameStatus.frameId=lin_id_to_pid(state->frameBuf.id);
#endif
                
            } else if(state->activeFrame->frameType==LIN_FRAME_TYPE_DIAG) {
                /* diag frame need copy to rx queue */
                if((linState->rxSize)!=state->activeFrame->bufLen) {
                    state->frameStatus.errorInResp=l_true;
                    lin_tp_handle(inst,LIN_TP_RX_ERROR);
                }else{
                    state->frameStatus.succTransfer=l_true;  
#ifdef LIN_USE_UART 
                    state->frameStatus.frameId=lin_id_to_pid(state->id);
#else
                    state->frameStatus.frameId=lin_id_to_pid(state->frameBuf.id);
#endif
                }
            }
            else {
                state->frameStatus.errorInResp=l_true;
                lin_error_handle(inst,state->activeFrame->id,linState);
            }
        }
        state->frameSm=LIN_FRAME_SM_IDLE;
        break;
    default:
        break;

    }
    state->idleTimeout=g_linGlobalConfig[inst]->maxIdleTimeoutMs * 1000;
    lin_update_ifc_status(inst);
}


void lin_sch_back(l_ifc_handle inst) {
    lin_master_state_t* masterState=g_linGlobalState[inst].masterState;
    masterState->activeSch=masterState->previousSch;
    masterState->activeSlot=masterState->previousSlot;
}

void lin_timeout_handle(l_ifc_handle inst){
    lin_core_state_t* state=&g_linGlobalState[inst];
    if(state->tpInit==l_true){
        lin_tp_timeout_handle(inst,500);
    }
    switch (state->frameSm) {
        case LIN_FRAME_SM_IDLE:
            state->idleTimeout-=500;
            if(state->idleTimeout<0){
#ifdef LIN_USE_UART
                LIN_DRV_GotoIdleState(g_linGlobalConfig[inst]->hwInst);
#else                
                LINFlexD_DRV_GotoIdleState(g_linGlobalConfig[inst]->hwInst);
#endif
                state->idleTimeout=g_linGlobalConfig[inst]->maxIdleTimeoutMs * 1000;
            }
            break;
        case LIN_FRAME_SM_PID:
            state->frameTimeout--;
            if(state->frameTimeout<0){
                state->frameStatus.errorInResp=l_true;
#ifdef LIN_USE_UART
                LIN_DRV_GotoIdleState(g_linGlobalConfig[inst]->hwInst);
#else
                LINFlexD_DRV_GotoIdleState(g_linGlobalConfig[inst]->hwInst);
#endif
                state->idleTimeout=g_linGlobalConfig[inst]->maxIdleTimeoutMs * 1000;
                state->frameSm=LIN_FRAME_SM_IDLE;
            }
            break;
        case LIN_FRAME_SM_TX:
        case LIN_FRAME_SM_RX:
#ifdef LIN_USE_UART
            /* use driver build in timeout*/
            LIN_DRV_TimeoutService(g_linGlobalConfig[inst]->hwInst);
#else
            /* slave received pid, but no event happen, no timeout/error/sent/received/ interrupt happen */
            state->frameTimeout--;
            if(state->frameTimeout<0){
                state->frameStatus.errorInResp=l_true;
                LINFlexD_DRV_AbortTransferData(g_linGlobalConfig[inst]->hwInst);

                state->idleTimeout=g_linGlobalConfig[inst]->maxIdleTimeoutMs * 1000;
                state->frameSm=LIN_FRAME_SM_IDLE;
            }
#endif
            break;

        default:
            /* do nothing */
            break;  
    }
}