/*
 * hal_adapter.c
 *
 *  Created on: 2022年1月18日
 *      Author: QiXiang_CHENJIE
 */
#include "hal_adapter.h"
#include "AppGlobalVar.h"
#include "stdio.h"
#include "stdarg.h"
uint8_t __attribute__((section(".non_cacheable_data"))) RX_Buffer[3][BUFFER_SIZE];
uint32_t bufferIdx[3] = {0};
    
volatile Uart_StatusType Uart_TransmitStatus[3] = {UART_STATUS_TIMEOUT, UART_STATUS_TIMEOUT, UART_STATUS_TIMEOUT};
QueueHandle_t UartRecvQueue[3];
QueueHandle_t UartSendQueue[3];
QueueHandle_t UartHalQueueHandle;
Std_ReturnType UartStartRecvFunc(uint8 channel);

void create_ringBuffer(ringbuffer_t *ringBuf, uint8_t *buf, uint32_t buf_len);
void clear_ringBuffer(ringbuffer_t *ringBuf);
uint32_t write_ringBuffer(uint8_t *buffer, uint32_t size, ringbuffer_t *ringBuf);
uint32_t read_ringBuffer(uint8_t *buffer, uint32_t size, ringbuffer_t *ringBuf);
uint8 ringBufferforUart[3][BUFFER_SIZE];
ringbuffer_t uartRingBuffer[3];

sint8 AtcmdDelayRecvFunc(uint8 recvChannel,char *ResultStrPtr,uint16 delayTime)
{
	sint8 outValue = -1;
	uint8 delayCnt = 0;
	uint8 UartData[256];
	uint16 ReadLen = 0;
	char *retptr = NULL;
	char *busy = "busy p...";
	char *error = "ERROR";
	//while (delayCnt<(delayTime/500) && outValue!=0)
	while (delayCnt < (delayTime/500))
	{
		UART_Receive_Data(recvChannel,UartData, &ReadLen,500);
		retptr = (char *)strstr((char *)UartData, ResultStrPtr);
		if (retptr)
		{
			outValue = 0;
			break;
		}
		else if(strstr((char *)UartData, error))
		{
			outValue = -1;
			break;
		}
		else
		{
			delayCnt++;
		}
	}
	return outValue;
}

void create_ringBuffer(ringbuffer_t *ringBuf, uint8_t *buf, uint32_t buf_len)
{
    ringBuf->br = 0;
    ringBuf->bw = 0;
    ringBuf->btoRead = 0;
    ringBuf->source = buf;
    ringBuf->length = buf_len;
}
void clear_ringBuffer(ringbuffer_t *ringBuf)
{
    ringBuf->br = 0;
    ringBuf->bw = 0;
    ringBuf->btoRead = 0;
}
uint32_t write_ringBuffer(uint8_t *buffer, uint32_t size, ringbuffer_t *ringBuf)
{
    uint32_t len = 0;
    volatile uint32_t ringBuf_bw = ringBuf->bw;
    uint32_t ringBuf_len = ringBuf->length;
    uint8_t *ringBuf_source = ringBuf->source;

    if ((ringBuf_bw + size) > ringBuf_len)
    {
        ringBuf_bw = 0;
    }
    memcpy(ringBuf_source + ringBuf_bw, buffer, size);
    ringBuf->bw = (ringBuf_bw + size) % ringBuf_len;
    ringBuf->btoRead += size;

    /*
        if(ringBuf->br!=0)
        {
            memcpy(ringBuf_source, buffer, size);
            ringBuf->br = 0;
        }
    */
    /*
        if( (ringBuf_bw + size) <= ringBuf_len  )
        {
            memcpy(ringBuf_source + ringBuf_bw, buffer, size);
        }
        else
        {
            len = ringBuf_len - ringBuf_bw;
            memcpy(ringBuf_source + ringBuf_bw, buffer, len);
            memcpy(ringBuf_source, buffer + ringBuf_bw, size - len);
        }
        ringBuf->bw = (ringBuf->bw + size) % ringBuf_len;
        ringBuf->btoRead += size;
    */

    return size;
}
uint32_t read_ringBuffer(uint8_t *buffer, uint32_t size, ringbuffer_t *ringBuf)
{
    uint32_t len = 0;
    volatile uint32_t ringBuf_br = ringBuf->br;
    uint32_t ringBuf_len = ringBuf->length;
    uint8_t *ringBuf_source = ringBuf->source;

    memcpy(buffer, ringBuf_source, size);
    ringBuf->br = size;
    //    if( (ringBuf_br + size ) <= ringBuf_len )
    //    {
    //        memcpy(buffer, ringBuf_source + ringBuf_br, size);
    //    }
    //    else
    //    {
    //        len = ringBuf_len - ringBuf_br;
    //        memcpy(buffer, ringBuf_source + ringBuf_br, len);
    //        memcpy(buffer + len, ringBuf_source, size - len);
    //    }
    //    ringBuf->br = (ringBuf->br + size) % ringBuf_len;
    //    ringBuf->btoRead -= size;

    return size;
}

Std_ReturnType UART_Query_Data(uint8 transChannel, uint8 recvChannel, uint8 *txBuffer, uint16 sendLength, uint8 *rxBuffer, uint16 *rxlen, uint32 T_timeout)
{
    UartMsg_t UartRecvMsg;
    UartMsg_t UartSendMsg;
    BaseType_t Sendret = pdFALSE;
    BaseType_t Recvret = pdFALSE;
    uint32 retVal = E_NOT_OK;
    UartSendMsg.DataLen = sendLength;
    UartSendMsg.dataPtr = txBuffer;
    *rxlen = 0;
    Sendret = xQueueSend(UartSendQueue[transChannel], &UartSendMsg, 50);

    if (Sendret == pdTRUE)
    {
        Recvret = xQueueReceive(UartRecvQueue[recvChannel], &UartRecvMsg, T_timeout);
        if (Recvret == pdTRUE)
        {
            *rxlen = UartRecvMsg.DataLen;
            //		read_ringBuffer(rxBuffer, queueRecvSize, &uartRingBuffer[recvChannel]);
            memcpy(rxBuffer, (uint8 *)(UartRecvMsg.dataAddr), UartRecvMsg.DataLen);
            retVal = E_OK;
        }
        else
        {
            retVal = 3;
        }
    }
    else
    {
        retVal = 2;
    }
    return retVal;
}
Std_ReturnType UART_Receive_Data(uint8 recvChannel, uint8 *rxBuffer, uint16 *rxlen, uint32 T_timeout)
{
    UartMsg_t UartRecvMsg;
    BaseType_t ret = pdFALSE;
    uint32 retVal = E_NOT_OK;
    *rxlen = 0;
    ret = xQueueReceive(UartRecvQueue[recvChannel], &UartRecvMsg, T_timeout);
    if (ret == pdTRUE)
    {
        *rxlen = UartRecvMsg.DataLen;

        memcpy(rxBuffer, (uint8 *)UartRecvMsg.dataAddr, UartRecvMsg.DataLen);

        retVal = E_OK;
    }
    return retVal;
}
Std_ReturnType UART_Reset(uint8 recvChannel)
{
    uint32 retVal = E_NOT_OK;
    retVal = xQueueReset(UartRecvQueue[recvChannel]);
    return retVal;
}
Std_ReturnType UART_Send_Data(uint8 transChannel, const uint8 *txBuffer, uint32 sendLength, uint32 T_timeout)
{
    UartMsg_t UartSendMsg;
    BaseType_t ret = pdFALSE;
    uint32 retVal = E_NOT_OK;
    UartSendMsg.DataLen = sendLength;
    UartSendMsg.dataPtr = (uint8 *)txBuffer;
    ret = xQueueSend(UartSendQueue[transChannel], &UartSendMsg, T_timeout);
    if (ret == pdTRUE)
    {
        retVal = E_OK;
    }
    return retVal;
}
void UartInit(void)
{
    create_ringBuffer(&uartRingBuffer[0], ringBufferforUart[0], sizeof(ringBufferforUart[0]));
    create_ringBuffer(&uartRingBuffer[1], ringBufferforUart[1], sizeof(ringBufferforUart[1]));
    create_ringBuffer(&uartRingBuffer[2], ringBufferforUart[2], sizeof(ringBufferforUart[2]));
    UartRecvQueue[0] = xQueueCreate(6, sizeof(UartMsg_t));
    UartRecvQueue[1] = xQueueCreate(6, sizeof(UartMsg_t));
    UartRecvQueue[2] = xQueueCreate(6, sizeof(UartMsg_t));
    UartSendQueue[0] = xQueueCreate(3, sizeof(UartMsg_t));
    UartSendQueue[1] = xQueueCreate(1, sizeof(UartMsg_t));
    UartSendQueue[2] = xQueueCreate(1, sizeof(UartMsg_t));
    UartHalQueueHandle = xQueueCreate(9, sizeof(UartHalMsg_t));

    xTaskCreate(Uart_Hal_RecvTask, (const char *const)"UartRecv", 512, (void *)0, main_TASK_PRIORITY + 5, NULL);
    xTaskCreate(Uart_Hal_SendTask, (const char *const)"UartSend", 256, (void *)0, main_TASK_PRIORITY + 4, NULL);
}
Std_ReturnType UartStartRecvFunc(uint8 channel)
{
    sint8 out = 0;
    volatile Std_ReturnType R_Uart_Status = E_NOT_OK;
    bufferIdx[channel] = 0;
    memset(RX_Buffer[channel], 0x00, BUFFER_SIZE);
    switch (channel)
    {
    case 0:
        IP_LPUART0->CTRL |= LPUART_CTRL_ILIE(1);
        break;
    case 1:
        IP_LPUART1->CTRL |= LPUART_CTRL_ILIE(1);
        break;
    case 2:
        IP_LPUART2->CTRL |= LPUART_CTRL_ILIE(1);
        break;
    default:
        break;
    }
    Uart_SetBuffer(channel, RX_Buffer[channel], DMA_SIZE, UART_RECEIVE);
    R_Uart_Status = Uart_AsyncReceive(channel, RX_Buffer[channel], DMA_SIZE);
    if (E_OK != R_Uart_Status)
    {
        Uart_Abort(channel, UART_RECEIVE);
        out = E_NOT_OK;
    }
    return out;
}
void Uart_Hal_RecvTask(void *pvParameters)
{
    UartHalMsg_t UartHalMsgRecv;
    UartMsg_t UartRecvMsg;
    uint16 recvSize = 0;
    BaseType_t ret = pdFALSE;
    BaseType_t ret_send = pdFALSE;
    uint32 T_bytesRemaining[3] = {0};
    uint16 T_timeout[3] = {0};
    volatile Uart_StatusType Uart_ReceiveStatus[3] = {UART_STATUS_TIMEOUT, UART_STATUS_TIMEOUT, UART_STATUS_TIMEOUT};
    uint8 UartIdx = UART_LPUART0;
    uint8 UartState[3] = {UartAbortRecv, UartAbortRecv, UartAbortRecv};
    while (1)
    {
        if ((T_timeout[UartIdx] > 1000) && (Uart_ReceiveStatus[UartIdx] != UART_STATUS_NO_ERROR)) //判定UART停止，超时停止，不是接收状态则停止
        {
            Uart_Abort(UartIdx, UART_RECEIVE);
            UartState[UartIdx] = UartAbortRecv;
            T_timeout[UartIdx] = 0;
        }
        else if (Uart_ReceiveStatus[UartIdx] == UART_STATUS_NO_ERROR)
        {
            UartState[UartIdx] = UartRecvComplete;
        }
        else{}

        if ((UartState[UartIdx] == UartAbortRecv) || (UartState[UartIdx] == UartRecvComplete)) //判定UART开始接收：UART停止后开始接收
        {
            if (E_OK == UartStartRecvFunc(UartIdx))
            {
                UartState[UartIdx] = UartStartRecv;
            }
        }
        Uart_ReceiveStatus[UartIdx] = Uart_GetStatus(UartIdx, &T_bytesRemaining[UartIdx], UART_RECEIVE);
        T_timeout[UartIdx]++;
        UartIdx = (UartIdx + 1) > 2 ? 0 : (UartIdx + 1);
        ret = xQueueReceive(UartHalQueueHandle, &UartHalMsgRecv, 1);
        if (ret == pdTRUE)
        {
            if (UartHalMsgRecv.event == LPUART_UART_IP_EVENT_RECV_IDLE)
            {
                if (UartHalMsgRecv.value > 0)
                {
                    recvSize = write_ringBuffer(RX_Buffer[UartHalMsgRecv.Channel], UartHalMsgRecv.value, &uartRingBuffer[UartHalMsgRecv.Channel]);
                    UartRecvMsg.DataLen = UartHalMsgRecv.value;
                    UartRecvMsg.dataAddr = (uint32)(uartRingBuffer[UartHalMsgRecv.Channel].bw + uartRingBuffer[UartHalMsgRecv.Channel].source - UartHalMsgRecv.value);
                    ret_send = xQueueSend(UartRecvQueue[UartHalMsgRecv.Channel], &UartRecvMsg, 10);
                }
                T_timeout[UartHalMsgRecv.Channel] = 0;
                UartState[UartHalMsgRecv.Channel] = UartRecvComplete;
            }
        }
    }
}
void Uart_Hal_SendTask(void *pvParameters)
{
    UartMsg_t UartSendMsg;
    BaseType_t ret = pdFALSE;
    uint32 T_bytesRemaining[3] = {0};
    uint16 T_timeout[3] = {0};
    volatile Std_ReturnType T_Uart_Status[3];
    uint8 UartIdx = UART_LPUART0;
    uint8 UartSendState[3] = {UartNoDataSend, UartNoDataSend, UartNoDataSend};
    while (1)
    {
        ret = xQueueReceive(UartSendQueue[UartIdx], &UartSendMsg, 1);

        if (ret == pdTRUE)
        {

            T_Uart_Status[UartIdx] = Uart_AsyncSend(UartIdx, UartSendMsg.dataPtr, UartSendMsg.DataLen);
            if (E_OK != T_Uart_Status[UartIdx])
            {
                Uart_Abort(UartIdx, UART_SEND);
                UartSendState[UartIdx] = UartAbortSend;
            }
            else
            {
                UartSendState[UartIdx] = UartStartSend;

            }
        }
        /*开始发送后的判定*/
        if (UartSendState[UartIdx] == UartStartSend)
        {
            Uart_TransmitStatus[UartIdx] = Uart_GetStatus(UartIdx, &T_bytesRemaining[UartIdx], UART_SEND);
            T_timeout[UartIdx]++;
        }
        if (T_timeout[UartIdx] >= 1000 || ((Uart_TransmitStatus[UartIdx] != UART_STATUS_OPERATION_ONGOING) && (UartSendState[UartIdx] == UartStartSend)))
        {
            if (T_timeout[UartIdx] >= 1000)
            {
                Uart_Abort(UartIdx, UART_SEND);
                UartSendState[UartIdx] = UartAbortSend;
            }
            else if (Uart_TransmitStatus[UartIdx] == UART_STATUS_NO_ERROR)
            {
                UartSendState[UartIdx] = UartSendComplete;
            }
            T_timeout[UartIdx] = 0;
        }

        UartIdx = (UartIdx + 1) > 2 ? 0 : (UartIdx + 1);
    }
}
extern Lpuart_Uart_Ip_StateStructureType *Lpuart_Uart_Ip_apStateStructuresArray[LPUART_UART_IP_NUMBER_OF_INSTANCES];
void UART_Callback(uint32 hwInstance, Lpuart_Uart_Ip_EventType event)
{
    //    (void)userData;
    Lpuart_Uart_Ip_StateStructureType *UartState;
    UartState = (Lpuart_Uart_Ip_StateStructureType *)Lpuart_Uart_Ip_apStateStructuresArray[hwInstance];

    /* Check the event type */
    if (event == LPUART_UART_IP_EVENT_RX_FULL)
    {
        /* The reception stops when receiving idle is detected or the buffer is full */
        if (bufferIdx[hwInstance] <= (BUFFER_SIZE - DMA_SIZE))
        {
            /* Update the buffer index and the rx buffer */
            bufferIdx[hwInstance] += DMA_SIZE;
            Uart_SetBuffer(hwInstance, &RX_Buffer[hwInstance][bufferIdx[hwInstance]], DMA_SIZE, UART_RECEIVE);
            // Lpuart_Uart_Ip_SetRxBuffer(hwInstance, &RX_Buffer[bufferIdx], DMA_SIZE);
        }
    }
    if (event == LPUART_UART_IP_EVENT_ERROR)
    {
        //     	/*Get the transfered data size. DMA Channel 1 is used for LPUART DMA receiving, please modify accordingly.*/
        //     	temp = DMA_SIZE - (uint32_t)IP_DMA->TCD->CITER.ELINKNO;
        //     	/*Add the remaining data size to the sum of the received size*/
        //     	bufferIdx[hwInstance] += temp;
        /*Abort the receiving after detecting IDLE receiving*/
        Lpuart_Uart_Ip_AbortReceivingData(hwInstance);
        Lpuart_Uart_Ip_AbortSendingData(hwInstance);
        //    	bufferIdx = 0;
    }
    if (event == LPUART_UART_IP_EVENT_RECV_IDLE)
    {
        uint32_t temp;
        UartHalMsg_t UartHalMsg;
        UartHalMsg.Channel = hwInstance;
        UartHalMsg.event = event;
        /*Get the transfered data size. DMA Channel 1 is used for LPUART DMA receiving, please modify accordingly.*/
        temp = DMA_SIZE - (uint32_t)IP_DMA->TCD[hwInstance].CITER.ELINKNO;
        /*Add the remaining data size to the sum of the received size*/
        bufferIdx[hwInstance] += temp;
        /*Abort the receiving after detecting IDLE receiving*/
        UartHalMsg.value = bufferIdx[hwInstance];
        xQueueSendFromISR(UartHalQueueHandle, &UartHalMsg, pdFALSE);
    }
}

/*CAN*/
Can_PduType Can_CreatePduInfo(Can_IdType id, CAN_IdFrameType idFrame, PduIdType swPduHandle, uint8 length, uint8 *sdu)
{
    Can_PduType PduInfo;
    switch (idFrame)
    {
    case CAN_STANDARD_ID_TYPE:
        id = id & 0x7FF;
        break;
    case CANFD_STANDARD_ID_TYPE:
        id = (id & 0x7FF) | 0x40000000;
        break;
    case CAN_EXTENDED_ID_TYPE:
        id = id | 0x80000000;
        break;
    case CANFD_EXTENDED_ID_TYPE:
        id = id | 0xC0000000;
        break;
    default:
        id = id & 0x7FF;
        break;
    }
    PduInfo.id = id;
    PduInfo.swPduHandle = swPduHandle;
    PduInfo.length = length;
    PduInfo.sdu = sdu;
    return PduInfo;
}
Std_ReturnType CanIf_SendMessage(uint8 ControllerId, Can_Msg_Type CanMsg)
{
    volatile Can_PduType Can_PduInfo;
    volatile Std_ReturnType CAN_Write_Status;
    Std_ReturnType retVal = E_NOT_OK;
    uint32 u8TimeOut = 100 * 100;
    Can_HwHandleType Hth = Can0HardwareObject_TX + (Can_HwHandleType)ControllerId; // controller 0 --> Can0HardwareObject_TX

    Can_PduInfo = Can_CreatePduInfo(CanMsg.id, CanMsg.idFrame, 0, CanMsg.length, CanMsg.sdu);

    CAN_Write_Status = Can_Write(Hth, &Can_PduInfo);

    CanIf_bTxFlag = FALSE;
    if (CAN_Write_Status == E_OK)
    {
        while ((!CanIf_bTxFlag) && (u8TimeOut != 0U))
        {
            Can_MainFunction_Write();
            u8TimeOut--;
        }
    }

    if (CanIf_bTxFlag == TRUE)
    {
        retVal = E_OK;
    }
    else
    {
        retVal = E_NOT_OK;
    }
    return retVal;
}
Can_Msg_Type Can_GetMsgInfo(Can_IdType id, uint8 length, uint8 *sdu)
{
    Can_Msg_Type CanMsgInfo;

    CanMsgInfo.idFrame = (CAN_IdFrameType)((id >> 30) & 0x03);
    if (CanMsgInfo.idFrame & 0x01)
    {
        CanMsgInfo.id = id & 0x7FF;
    }
    else
    {
        CanMsgInfo.id = id & 0x1FFFFFFF;
    }
    CanMsgInfo.length = length;
    CanMsgInfo.sdu = sdu;

    return CanMsgInfo;
}

void CanIf_ControllerBusOff(uint8 ControllerId)
{
    (void)ControllerId;
}

void CanIf_ControllerModeIndication(uint8 ControllerId, Can_ControllerStateType ControllerMode)
{
    (void)ControllerId;
    (void)ControllerMode;
}
void CanIf_TxConfirmation(PduIdType CanTxPduId)
{
    CanIf_u8TxConfirmCnt++;
    CanIf_bTxFlag = TRUE;
    (void)CanTxPduId;
}
void CanIf_RxIndication(const Can_HwType *Mailbox, const PduInfoType *PduInfoPtr)
{
    Can_Msg_Type canRxMsg_Buff;
    Can_Msg_Type_Data canRxMsgQueueData;
    CanIf_bRxFlag = TRUE; // should not be delete
    // should put the msg into message queue
    canRxMsg_Buff = Can_GetMsgInfo(Mailbox->CanId, PduInfoPtr->SduLength, PduInfoPtr->SduDataPtr);
    canRxMsgQueueData.id = canRxMsg_Buff.id;
    canRxMsgQueueData.length = canRxMsg_Buff.length;
    memcpy(canRxMsgQueueData.data, canRxMsg_Buff.sdu, canRxMsgQueueData.length);
    xQueueSend(CanRecvQueueHandle, &canRxMsgQueueData, 0);
}

void CanIf_CurrentIcomConfiguration(uint8 ControllerId, IcomConfigIdType ConfigurationId, IcomSwitch_ErrorType Error)
{
    (void)ControllerId;
    (void)ConfigurationId;
    (void)Error;
}

/*EEP*/
static Std_ReturnType TestEep_FlexNvmProgramPartCmd(
    VAR(TestEep_CsecKeySize, AUTOMATIC) eepKeysize,
    VAR(TestEep_SfeType, AUTOMATIC) eepSecurityFlagExtension,
    VAR(TestEep_LoadFlexRamType, AUTOMATIC) eepLoadFlexRamAtReset,
    VAR(TestEep_Eeprom_FlexRamPartitionType, AUTOMATIC) eepFlexRamPartition,
    VAR(TestEep_Eeprom_FlexNvmPartitionType, AUTOMATIC) eepFlexNvmPartition)
{
    Std_ReturnType u8RetVal = (Std_ReturnType)E_OK;
    uint32 u32FlexNvmPartSize = 0;

    uint32 u32RegSimFcfg1 = 0UL;

    u32RegSimFcfg1 = IP_SIM->FCFG1;

    /*get DEPART value */
    u32FlexNvmPartSize = (uint32)((u32RegSimFcfg1 & SIM_FCFG1_DEPART_MASK) >> SIM_FCFG1_DEPART_SHIFT);

    /* check that it was not partitioned before */
    if (u32FlexNvmPartSize == 0xF)
    {
        //         /* if error flags are set the cmd is not executed */
        //         REG_WRITE8(TEST_EEP_EEPROM_FSTAT_ADDR32, TEST_EEP_EEPROM_FSTAT_ACCERR_U8 | TEST_EEP_EEPROM_FSTAT_FPVIOL_U8);
        //
        //         /*erase DF 0 sector*/
        //         u32Addr=(TEST_EEP_DEEPROM_SECTOR_0_ADDR32 - D_EEPROM_BASE_ADDR) + 0x800000UL;
        //
        //         REG_WRITE8(TEST_EEP_EEPROM_FCCOB0_ADDR32, TEST_EEP_EEPROM_CMD_ERASE_SECTOR);
        //         REG_WRITE8(TEST_EEP_EEPROM_FCCOB1_ADDR32, (uint8)(u32Addr >> 16UL));
        //         REG_WRITE8(TEST_EEP_EEPROM_FCCOB2_ADDR32, (uint8)(u32Addr >> 8UL));
        //         REG_WRITE8(TEST_EEP_EEPROM_FCCOB3_ADDR32, (uint8)(u32Addr >> 0UL));
        //         REG_WRITE8(TEST_EEP_EEPROM_FSTAT_ADDR32 , TEST_EEP_EEPROM_FSTAT_CCIF_U8);
        //         while((0U == REG_BIT_GET8(TEST_EEP_EEPROM_FSTAT_ADDR32, TEST_EEP_EEPROM_FSTAT_CCIF_U8)))
        //         {
        //         }
        //
        if (0U == REG_BIT_GET8(TEST_EEP_EEPROM_FSTAT_ADDR32, TEST_EEP_EEPROM_FSTAT_ACCERR_U8 | TEST_EEP_EEPROM_FSTAT_FPVIOL_U8))
        {
            /* run program partition command */
            REG_WRITE8(TEST_EEP_EEPROM_FCCOB0_ADDR32, EEPROM_CMD_PROGRAM_PARTITION);
            REG_WRITE8(TEST_EEP_EEPROM_FCCOB1_ADDR32, (uint8)eepKeysize);
            REG_WRITE8(TEST_EEP_EEPROM_FCCOB2_ADDR32, (uint8)eepSecurityFlagExtension);
            REG_WRITE8(TEST_EEP_EEPROM_FCCOB3_ADDR32, (uint8)eepLoadFlexRamAtReset);
            REG_WRITE8(TEST_EEP_EEPROM_FCCOB4_ADDR32, (uint8)eepFlexRamPartition);
            REG_WRITE8(TEST_EEP_EEPROM_FCCOB5_ADDR32, (uint8)eepFlexNvmPartition);
            REG_WRITE8(TEST_EEP_EEPROM_FSTAT_ADDR32, TEST_EEP_EEPROM_FSTAT_CCIF_U8);
            while ((0U == REG_BIT_GET8(TEST_EEP_EEPROM_FSTAT_ADDR32, TEST_EEP_EEPROM_FSTAT_CCIF_U8)))
            {
                /* wait for operation to finish */
            }
            /* check if errors occured  */
            if (REG_BIT_GET8(TEST_EEP_EEPROM_FSTAT_ADDR32, TEST_EEP_EEPROM_FSTAT_ACCERR_U8 | TEST_EEP_EEPROM_FSTAT_FPVIOL_U8))
            {
                /* NOK, error flags are set */
                u8RetVal = (Std_ReturnType)E_NOT_OK;
            }
        }
        else
        {
            /* NOK, error flags are set */
            u8RetVal = (Std_ReturnType)E_NOT_OK;
        }
    }
    else
    {
        /* NOK, partitioned already */
        u8RetVal = (Std_ReturnType)E_NOT_OK;
    }
    return u8RetVal;
}

void Eep_DepartParitition(TestEep_Eeprom_FlexNvmPartitionType T_EEP_SIZE)
{
    uint32 u32FlexNvmPartSize = 0;

    uint32 u32RegSimFcfg1 = 0UL;

    u32RegSimFcfg1 = IP_SIM->FCFG1;

    /*get DEPART value */
    u32FlexNvmPartSize = (uint32)((u32RegSimFcfg1 & SIM_FCFG1_DEPART_MASK) >> SIM_FCFG1_DEPART_SHIFT);
    if (u32FlexNvmPartSize == 0xF) /* We just partition again if curent size different with expected */
    {
        /* partition for EERAM 64K with NOT loading EERAM at reset in hardware */
        TestEep_FlexNvmProgramPartCmd(EEP_FTFC_KEY_SIZE_0_BYTES, EEP_FTFC_VERIFY_ONLY_DISABLED,
                                      EEP_FTFC_LOAD_AT_RESET_ENABLED, EEP_FTFC_EERAM_SIZE_4K, T_EEP_SIZE);
    }
}
/* Erase memory by writing erase value */
Std_ReturnType HAL_EEP_Erase(uint32 eepEraseStartAddr, uint32 eepEraseSize)
{
    Std_ReturnType retReturnType = E_OK;
    MemIf_JobResultType retJobResultType;
    retReturnType = Eep_Erase(eepEraseStartAddr, eepEraseSize);
    if (E_OK != retReturnType)
    {
        return E_NOT_OK;
    }
    while (MEMIF_IDLE != Eep_GetStatus())
    {
        Eep_MainFunction();
    }
    retJobResultType = Eep_GetJobResult();
    if (MEMIF_JOB_OK != retJobResultType)
    {
        return E_NOT_OK;
    }
    return E_OK;
}

/* Write one or more complete eeprom pages to the eeprom device */
Std_ReturnType HAL_EEP_Write(uint32 eepWriteStartAddr, uint8 *pDataNeedtoWrite, uint32 dataSize)
{
    Std_ReturnType retReturnType = E_OK;
    MemIf_JobResultType retJobResultType;

    /*Erase the EEP before write*/
    retReturnType = HAL_EEP_Erase(eepWriteStartAddr, dataSize);
    if (E_OK != retReturnType)
    {
        return E_NOT_OK;
    }

    retReturnType = Eep_Write(eepWriteStartAddr, pDataNeedtoWrite, dataSize);
    if (E_OK != retReturnType)
    {
        return E_NOT_OK;
    }
    while (MEMIF_IDLE != Eep_GetStatus())
    {
        Eep_MainFunction();
    }
    retJobResultType = Eep_GetJobResult();
    if (MEMIF_JOB_OK != retJobResultType)
    {
        return E_NOT_OK;
    }
    return E_OK;
}

/* Reads from eeprom memory */
Std_ReturnType HAL_EEP_Read(uint32 eepReadStartAddr, uint8 *pDataBuffer, uint32 dataSize)
{
    Std_ReturnType retReturnType = E_OK;
    MemIf_JobResultType retJobResultType;
    retReturnType = Eep_Read(eepReadStartAddr, pDataBuffer, dataSize);
    if (E_OK != retReturnType)
    {
        return E_NOT_OK;
    }
    while (MEMIF_IDLE != Eep_GetStatus())
    {
        Eep_MainFunction();
    }
    retJobResultType = Eep_GetJobResult();
    if (MEMIF_JOB_OK != retJobResultType)
    {
        return E_NOT_OK;
    }
    return E_OK;
}

/* Compares a eeprom memory area with an application data buffer */
Std_ReturnType HAL_EEP_Compare(uint32 eepCompareStartAddr, uint8 *pDataNeedtoCompare, uint32 dataSize)
{
    Std_ReturnType retReturnType = E_OK;
    MemIf_JobResultType retJobResultType;
    retReturnType = Eep_Compare(eepCompareStartAddr, pDataNeedtoCompare, dataSize);
    if (E_OK != retReturnType)
    {
        return E_NOT_OK;
    }
    while (MEMIF_IDLE != Eep_GetStatus())
    {
        Eep_MainFunction();
    }
    retJobResultType = Eep_GetJobResult();
    if (MEMIF_JOB_OK != retJobResultType)
    {
        return E_NOT_OK;
    }
    return E_OK;
}
/* @brief VECTKEY value so that AIRCR register write is not ignored. */
#define FEATURE_SCB_VECTKEY (0x05FAU)
void SystemSoftwareReset(void)
{
    uint32_t regValue;

    /* Read Application Interrupt and Reset Control Register */
    regValue = S32_SCB->AIRCR;

    /* Clear register key */
    regValue &= ~(S32_SCB_AIRCR_VECTKEY_MASK);

    /* Configure System reset request bit and Register Key */
    regValue |= S32_SCB_AIRCR_VECTKEY(FEATURE_SCB_VECTKEY);
    regValue |= S32_SCB_AIRCR_SYSRESETREQ(0x1u);

    /* Write computed register value */
    S32_SCB->AIRCR = regValue;
}
