#include "Fls.h"

#if(STD_ON == FLS_DETECT_DEV_ERROR_EN)
#include "Det.h"
#endif

#include "CDD_Usart.h"
#include "Mcu.h"
#include "Port.h"

/* printf function configs to USART1*/
#define DEBUG_USART  USART1

uint8 g_aaAppBufferForWriteB[1024];
uint8 g_aaAppBufferForRead[1024];

typedef enum
{
    FLS_ERASE = 0,
    FLS_BLANKCHECK,
    FLS_READ,
    FLS_COMPARE,
    FLS_WRITE,
} FLS_OperateMode_T;


void SysDelay(int cnt)
{
    while(cnt--);
}

void Fls_JobEndNotification( void )
{
}

void Fls_JobErrorNotification( void )
{
}

FUNC( void, FLS_CODE ) Fls_RealOperation( FLS_OperateMode_T type )
{
#if(STD_ON == FLS_DETECT_DEV_ERROR_EN)
    FLS_OperateMode_T operatetype = type;
    const char *result_str;
#endif
    while (MEMIF_IDLE != Fls_GetStatus())
    {
        Fls_MainFunction();
        SysDelay(100000);
    }

#if(STD_ON == FLS_DETECT_DEV_ERROR_EN)
    result_str = ((0 == g_detEventErrNum) && (0 == g_detRuntimeEventErrNum)) ? "success" : "fail";

    switch (operatetype)
    {
        case FLS_ERASE:
            printf("\r\nSet the erase operation %s\r\n", result_str);
            break;

        case FLS_READ:
            printf("\r\nSet the read operation %s\r\n", result_str);
            break;

        case FLS_COMPARE:
            printf("\r\nSet the compare operation %s\r\n", result_str);
            break;

        case FLS_WRITE:
            printf("\r\nSet the write operation %s\r\n", result_str);
            break;

        case FLS_BLANKCHECK:
            printf("\r\nSet the blank check operation %s\r\n", result_str);
            break;

        default:
            break;
    }
#endif
}

int main(void)
{
    VAR( Std_ReturnType, AUTOMATIC ) u8RetVal = (Std_ReturnType)E_NOT_OK;
    VAR( MemIf_StatusType, AUTOMATIC ) eRetVal = MEMIF_IDLE;
    VAR( MemIf_JobResultType, AUTOMATIC ) eJobRetVal = MEMIF_JOB_FAILED;
    uint32_t dataNum = 0;
#if(STD_ON == FLS_DETECT_DEV_ERROR_EN)
    g_detEventErrNum = 0;
    g_detRuntimeEventErrNum = 0;
#endif
    /* Initialize MCU module */
    Mcu_Init(&g_mcuConfig);
    /* Initialize clock */
    Mcu_InitClock(McuClockSettingConfig_0);
    /* Initialize PORT module */
    Port_Init(&g_portConfig);
    /* Initialize LPUART1 */
    Usart_Init(g_usartConfg);//TX PIN:PA9

    printf("\r\n---------------- FLS_ITA Start ----------------\r\n");

    /* Initialize FLS module */
    Fls_Init(&g_flsConfig);
    /* Set the mode to MEMIF_MODE_FAST */
    Fls_SetMode(MEMIF_MODE_FAST);

    /* Set the erase operation , erase 1KB Data Flash starting from address 0x08008000 */
    u8RetVal = Fls_Erase(0x8000, 1024);

    eJobRetVal = Fls_GetJobResult();

    eRetVal = Fls_GetStatus();

    if((E_OK == u8RetVal) && (MEMIF_JOB_PENDING == eJobRetVal) && (MEMIF_BUSY == eRetVal))
    {
       /* Erase 1KB Data Flash starting from address 0x08008000 */
       Fls_RealOperation(FLS_ERASE);
    }
    else
    {
        printf(" \r\nSet the erase operation fail\r\n");
    }

    /* Check 1KB Data Flash starting from address 0x08008000 */
    u8RetVal = Fls_BlankCheck(0x8000, 1024);
    if(E_OK == u8RetVal)
    {
        Fls_RealOperation(FLS_BLANKCHECK);
    }
    else
    {
        printf(" \r\nSet the blank check operation fail\r\n");
    }

    for(dataNum = 0;dataNum < 1024;dataNum++)
    {
        g_aaAppBufferForWriteB[dataNum] = dataNum;
    }

    /* Set the write operation , write 1KB Data Flash starting from address 0x08008000 */
    u8RetVal = Fls_Write(0x8000, (const uint8 *)&g_aaAppBufferForWriteB[0], 1024);
    if(E_OK == u8RetVal)
    {
        Fls_RealOperation(FLS_WRITE);
    }
    else
    {
        printf(" \r\nSet the write operation fail\r\n");
    }

    /* Set the read operation , read 1KB Data Flash starting from address 0x08008000 */
    u8RetVal = Fls_Read(0x8000,(uint8 *)&g_aaAppBufferForRead[0], 1024);
    if(E_OK == u8RetVal)
    {
        Fls_RealOperation(FLS_READ);
    }
    else
    {
        printf(" \r\nSet the read operation fail\r\n");
    }

    /* Set the compare operation , compare 1KB Data Flash starting from address 0x08008000 with g_aaAppBufferForRead buffer*/
    u8RetVal = Fls_Compare(0x8000,(uint8 *)&g_aaAppBufferForRead[0], 1024);
    if(E_OK == u8RetVal)
    {
        Fls_RealOperation(FLS_COMPARE);
    }
    else
    {
        printf(" \r\nSet the compare operation fail\r\n");
    }

#if(STD_ON == FLS_DETECT_DEV_ERROR_EN)
    if ((0 == g_detEventErrNum) && (0 == g_detRuntimeEventErrNum))
    {
        printf(" \r\nSet the all Fls operation success!\r\n");
    }
    else
    {
        printf(" \r\nSet the Fls operation with error, please check!\r\n");
    }
#endif
    printf("\r\n---------------- FLS_ITA End ----------------\r\n");

    while(1);
}

#if defined (__CC_ARM) || defined (__ICCARM__) || (defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050))

/*!
* @brief       Redirect C Library function printf to serial port.
*              After Redirection, you can use printf function.
*
* @param       ch:  The characters that need to be send.
*
* @param       *f:  pointer to a FILE that can recording all information
*              needed to control a stream
*
* @retval      The characters that need to be send.
*
* @note
*/
int fputc(int ch, FILE* f)
{
    int reVal = 0;
    reVal = Usart_PutRedefinition(USART1_ID,&ch);
    
    return reVal;
}

/* If configuring the full library using versions after IAR 9.30,
   it is necessary to implement the _write function for printf redirection.*/
size_t __write(int handle,const unsigned char *buf,size_t bufSize)
{
    int32 tempCh = 0;
    for(int i=0; i<bufSize; i++)
    {
        Usart_PutRedefinition(USART1_ID,&tempCh);
    }
    return bufSize;
}

#elif defined (__GNUC__)

/* For Arm Cross GCC: Eclipse */
int _write(int fd,const unsigned char *buf,int len)
{
    int32 tempCh = 0;
    for(int i=0; i<len; i++)
    {
        int32 tempCh = (int32)buf[i];
        Usart_PutRedefinition(USART1_ID,&tempCh);
    }
    return len;
}

#endif
