/* Copyright Statement:
 *
 * This software/firmware and related documentation ("AutoChips Software") are
 * protected under relevant copyright laws. The information contained herein is
 * confidential and proprietary to AutoChips Inc. and/or its licensors. Without
 * the prior written permission of AutoChips inc. and/or its licensors, any
 * reproduction, modification, use or disclosure of AutoChips Software, and
 * information contained herein, in whole or in part, shall be strictly
 * prohibited.
 *
 * AutoChips Inc. (C) 2024. All rights reserved.
 *
 * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
 * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("AUTOCHIPS SOFTWARE")
 * RECEIVED FROM AUTOCHIPS AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
 * ON AN "AS-IS" BASIS ONLY. AUTOCHIPS EXPRESSLY DISCLAIMS ANY AND ALL
 * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
 * NONINFRINGEMENT. NEITHER DOES AUTOCHIPS PROVIDE ANY WARRANTY WHATSOEVER WITH
 * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
 * INCORPORATED IN, OR SUPPLIED WITH THE AUTOCHIPS SOFTWARE, AND RECEIVER AGREES
 * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
 * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
 * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN AUTOCHIPS
 * SOFTWARE. AUTOCHIPS SHALL ALSO NOT BE RESPONSIBLE FOR ANY AUTOCHIPS SOFTWARE
 * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
 * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND AUTOCHIPS'S
 * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE AUTOCHIPS SOFTWARE
 * RELEASED HEREUNDER WILL BE, AT AUTOCHIPS'S OPTION, TO REVISE OR REPLACE THE
 * AUTOCHIPS SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
 * CHARGE PAID BY RECEIVER TO AUTOCHIPS FOR SUCH AUTOCHIPS SOFTWARE AT ISSUE.
 */
/******************************************************************************
 * @version: V3.1.0  AC7840x  Demo
 ******************************************************************************/

/* ===========================================  Includes  =========================================== */
#include "flash_drv.h"
#include "gpio.h"


/* ============================================  Define  ============================================ */
#define TestDflashWriteAddress    0x1000000U     /*!< Dflash 测试地址 */
#define TestPflashWriteAddress    0xFF800U       /*!< Pflash 测试地址 */
#define TestSize                  0x200U         /*!< 测试区域大小 */

/* ===========================================  Typedef  ============================================ */

/* ==========================================  Variables  =========================================== */
uint8_t g_wBuff[TestSize];                       /* 测试buffer */

flash_config_t g_Flash_Config;                   /*!< Flash 配置结构体 */
const flash_user_config_t Flash_InitConfig = 
{
    .pFlashBase = 0x00000000U,                   /*!< Pflash 起始地址 */
    .pFlashSize = 0x100000U,                     /*!< Pflash 大小，1MPflash， 其他大小的Pflash 需要用户手动修改此配置 */
    .dFlashBase = 0x01000000U,                   /*!< Dflash 起始地址 */
    .flexRAMBase = 0x14000000U,                  /*!< FlexRAM 起始地址 */
    .callback = NULL,                            /*!< 回调 */
};

/* ====================================  Functions declaration  ===================================== */

/* ======================================  Functions define  ======================================== */

/*!<
* @brief Job_WriteDataUpdate,数据更新，每次调用测试buf值自加1
*
* @param[in] none
* @return none
*/
void Job_WriteDataUpdate(void)
{
    uint16_t i = 0;
    for(i=0; i<TestSize; i++)
    {
        g_wBuff[i] += 1;
    }
}

/*!<
* @brief Job_DflashDataRead， 读取Dflash指定地址数据
*
* @param[in] none
* @return none
*/
void Job_DflashDataRead(void)
{
    uint16_t i = 0;
    uint8_t DflashReadBuf[TestSize] = {0};
    FLASH_DRV_Read(&g_Flash_Config,TestDflashWriteAddress, DflashReadBuf, TestSize);   /*!< 读取数据*/
    printf("Dflash read: ");
    for(i=0; i<TestSize; i++)
    {
        printf("%d ", DflashReadBuf[i]);
    }
    printf("\r\n");
}

/*!<
* @brief Job_DflashDataWrite， 擦除Dflash指定地址数据，再写入新数据
*
* @param[in] none
* @return none
*/
void Job_DflashDataWrite(void)
{
    status_t ret = STATUS_SUCCESS;
    ret = FLASH_DRV_UnlockCtrl();                                                          /*!< Unlock Flash */
    if(STATUS_SUCCESS != ret)
    {
         printf("Line %d: Unlock error %d\r\n", __LINE__, ret);
         return  ;
    }
    ret = FLASH_DRV_EraseBlock(&g_Flash_Config, TestDflashWriteAddress);                  /*!< 擦除整块Dflash， 如果Dflash中存在CSE分区，无法整块擦除，需要取消分区后，才可以成功执行此操作 */
    if(STATUS_SUCCESS != ret)
    {
         printf("Line %d: Erase Dflash all sectors error %d\r\n", __LINE__, ret);
         return ; 
    }
    else 
    {
        ret = FLASH_DRV_VerifyBlock(&g_Flash_Config,TestDflashWriteAddress);              /*!< 擦除成功后校验 */
        if(STATUS_SUCCESS != ret)
        {
            printf("Line %d: Dflash VerifyBlock error %d\r\n", __LINE__, ret);
            return;
        }
    }
    printf("Erase Dflash...\r\n");
    ret = FLASH_DRV_Program(&g_Flash_Config, TestDflashWriteAddress, TestSize, g_wBuff);  /*!< 将WBuff[0]~WBuff[TestSize-1]的数据写入Dflash中， 写入起始地址为TestDflashWriteAddress */
    if(STATUS_SUCCESS != ret)
    {
        printf("Line %d: Program error %d\r\n", __LINE__, ret);
        return  ;
    }
    printf("Write Dflash...\r\n");
    FLASH_DRV_LockCtrl();                                                                 /*!< Lock Flash */
}

/*!<
* @brief  Job_PflashDataRead， 读取Pflash指定地址数据
*
* @param[in] none
* @return none
*/
void Job_PflashDataRead(void)
{
    uint16_t i = 0;
    uint8_t PflashReadBuf[TestSize] = {0};
    FLASH_DRV_Read(&g_Flash_Config,TestPflashWriteAddress, PflashReadBuf, TestSize);     /*!< 读取数据 */
    printf("Pflash read: ");
    for(i=0; i<TestSize; i++)
    {
        printf("%d ", PflashReadBuf[i]);
    }
    printf("\r\n");

}

/*!<
* @brief Job_PflashDataWrite， 擦除Pflash 指定地址数据， 再写入新数据
*
* @param[in] none
* @return none
*/
void Job_PflashDataWrite(void)
{
    status_t ret = STATUS_SUCCESS;
    ret = FLASH_DRV_UnlockCtrl();                                                          /*!< Unlock Flash */
    if(STATUS_SUCCESS != ret)
    {
         printf("Line %d: Unlock error %d\r\n", __LINE__, ret);
         return  ;
    }

    ret = FLASH_DRV_EraseSector(&g_Flash_Config, TestPflashWriteAddress, 0x800U);          /*!< 擦除大小要是扇区大小2048(0x800)的整数倍 */
    if(STATUS_SUCCESS != ret)
    {
        printf("Line %d: Erase error %d\r\n", __LINE__, ret);
        return  ;
    }

    printf("Erase Pflash...\r\n");
    ret = FLASH_DRV_Program(&g_Flash_Config, TestPflashWriteAddress, TestSize, g_wBuff);  /*!<  将WBuff[0]~WBuff[TestSize-1]的数据写入Dflash中， 写入起始地址为TestPflashWriteAddress*/
    if(STATUS_SUCCESS != ret)
    {
        printf("Line %d: Program error %d\r\n", __LINE__, ret);
        return  ;
    }
    printf("Write Pflash...\r\n");
    FLASH_DRV_LockCtrl();                                                                 /*!< Lock Flash */
}

/*!<
* @brief Flash 基本使用测试，包括Flash擦除、写入和读取操作
*
* @param[in] none
* @return none
*/
void FlashTest(void)
{
    uint16_t i = 0;
    GPIO_LedInit();                                                                        /*!< LED IO初始化 */
    GPIO_KeyInit();                                                                        /*!< KEY IO初始化 */
    FLASH_DRV_Init(&Flash_InitConfig, &g_Flash_Config);                                    /*!< Flash 模块初始化 */

    for(i=0; i<TestSize; i++)                                                              /*!< 测试数据初始化 */
    {
        g_wBuff[i] = i;
    }
    printf("==**************************************************************==\r\n");
    printf("==   Key3: Erase，Write，read Dflash and update write data...   ==\r\n");
    printf("==   Key4: Erase，Write，read Pflash and update write data...   ==\r\n");
    printf("==**************************************************************==\r\n");
    
    
    /*!< 如需在Pflash < 1M 的型号上测试此DEMO, 需要用户手动修改Pflash 测试地址TestPflashWriteAddress的值 */
    
    while(1)
    {
        if(1U == Get_Key3Value())                                                          /*!< KEY3 按下， 执行擦除Flash、写Flash和读Flash以及数据更新操作 */
        {
            Job_DflashDataWrite();                                                         /*!< 写Pflash */
            Job_DflashDataRead();                                                          /*!< 读Pflash */
            Job_WriteDataUpdate();                                                         /*!< 数据更新 */
            LED3_TOGGLE;                                                                   /*!< LED 翻转 */
        }
        if(1U == Get_Key4Value())                                                          /*!< KEY4 按下， 执行擦除Flash、写Flash和读Flash以及数据更新操作 */
        {
            Job_PflashDataWrite();                                                         /*!< 写Dflash */
            Job_PflashDataRead();                                                          /*!< 读Dflash */
            Job_WriteDataUpdate();                                                         /*!< 数据更新 */
            LED3_TOGGLE;                                                                   /*!< LED 翻转 */
        }

    };
}

/* =============================================  EOF  ============================================== */

