/* 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) 2023. 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: V1.0.0 demo
******************************************************************************/
/*!
 * @file 02_FLASH_WriteProtect_Config.c
 *
 * @brief This file is flash Write Protect oprate guide.
 *
 */

/* ===========================================  Includes  =========================================== */
#include "ac7803x_debugout.h"
#include "ac780x_eflash_reg.h"
#include "Flash_WriteProtect_Config.h"

/* ============================================  Define  ============================================ */
#define     PFLASH              (0UL)
#define     DFLASH              (1UL)
#define     PFLASH_PAGE_254     (0x0803F800U)
#define     DFLASH_PAGE_1       (0x08040400U)
#define     FLASH_PAGE_SIZE     (0x400U)

/* 
    Flash WriteProtect Set by optionbyte or register
    by register :   REG_OR_OPTBYTE = 0,  immediate effect and invalid after reset
    by optionbyte:  REG_OR_OPTBYTE = 1,  take effect after resetting
*/
#define     REG_OR_OPTBYTE      (1UL)
/* ===========================================  Typedef  ============================================ */

/* ==========================================  Variables  =========================================== */

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

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

/*!
 * @brief Job_PflashWriteProtect_Config
 *        This Function is set Pflash page[128~255] writeProtect status
 *        if Write protect is set on Pflash page[128~255], disable write protect; 
 *        if Write protect is unset on Pflash page[128~255], enable write protect; 
 *
 * @param[in] none
 * @return operation status
 *        - EFLASH_STATUS_SUCCESS: Operation was successful
 *        - EFLASH_STATUS_ERROR:   Operation was failure
 *
 */
EFLASH_StatusType Job_PflashWriteProtect_Config(void)
{
    EFLASH_StatusType rev = EFLASH_STATUS_ERROR;
    
  #if REG_OR_OPTBYTE /* Set Write protect optionbyte , take effect after resetting*/
    
    /* Pflash page[0~127] write protect controlled by pWriteProtectConfig[0], page[128~255] write protect controlled by pWriteProtectConfig[1],
       each bit controls the write protection state of 4 pages of pflash,  0: UnWriteProtect  1: WriteProtect */
    uint32_t pWriteProtectConfig[2] = {0};
    
  #else /* Set Write protect by register , immediate effect and invalid after reset */
    
    /* Pflash page[0~127] write protect controlled by setPLWProtectStatus, page[128~255] write protect controlled by setPHWProtectStatus,
       each bit controls the write protection state of 4 pages of pflash, 0: UnWriteProtect  1: WriteProtect */
    uint32_t setPLWProtectStatus = 0U;
    uint32_t setPHWProtectStatus = 0U;
    
  #endif
    
    EFLASH_UnlockCtrl();                                      /* Unlock Flash */
    if(0xFFFFFFFFU == EFLASH_GetPWriteProRegHigh())           /* Get Pflash Page[128~255] WriteProtect Status */
    {
        /* Pflash HighArea(Page 128~255) is WriteProtect */
        printf("\r\nPFlash Page[128 ~ 255] is WriteProtect state, start to disable writeProtect...\r\n");

    #if REG_OR_OPTBYTE
        pWriteProtectConfig[0] = 0U;                                /* Page[0~127] UnWriteProtect */
        pWriteProtectConfig[1] = 0U;                                /* Page[128~255] UnWriteProtect*/
        rev = EFLASH_PFSetWriteProtection(pWriteProtectConfig);     /* Set all page UnWriteProtect */
    #else
        setPLWProtectStatus = 0U;                                   /* Page[0~127] UnWriteProtect */
        setPHWProtectStatus = 0U;                                   /* Page[128~255] UnWriteProtect*/
        rev = EFLASH_SetWriteProtectionByReg(PFLASH, setPLWProtectStatus, setPHWProtectStatus);    /* Set all page UnWriteProtect */
    #endif
        if(EFLASH_STATUS_SUCCESS != rev)
        {
            printf("\r\n[%d]ERROR: Set Pflash Page[128 ~ 255] UnWriteProtect fail...\r\n", __LINE__);
        }
        else
        {
            printf("\r\nDisable Pflash Page[128 ~ 255] WriteProtect done...\r\n");
        }
    }
    else
    {
        /* Pflash HighArea(Page 128~255) is UnWriteProtect */
        printf("\r\nPFlash Page[128 ~ 255] is UnWriteProtect state, start to enable writeProtect...\r\n");
    #if REG_OR_OPTBYTE
        pWriteProtectConfig[0] = 0U;                                /* Page[0~127] UnWriteProtect */
        pWriteProtectConfig[1] = 0xFFFFFFFFU;                       /* Page[128~255] WriteProtect */
        rev = EFLASH_PFSetWriteProtection(pWriteProtectConfig);     /* Set Pflash page[0~127] UnWriteProtect, Page[128~255] WriteProtect */
    #else
        setPLWProtectStatus = 0U;                                   /* Page[0~127] UnWriteProtect */
        setPHWProtectStatus = 0xFFFFFFFFU;                          /* Page[128~255] WriteProtect */
        rev = EFLASH_SetWriteProtectionByReg(PFLASH, setPLWProtectStatus, setPHWProtectStatus); /* Set Pflash page[0~127] UnWriteProtect, Page[128~255] WriteProtect */
    #endif  
        
        if(EFLASH_STATUS_SUCCESS != rev)
        {
            printf("\r\n[%d]ERROR: Set Pflash Page[128 ~ 255] WriteProtect fail...\r\n", __LINE__);
        }
        else
        {
            printf("\r\nEnable Pflash Page[128 ~ 255] WriteProtect done...\r\n");
        }
    }
    EFLASH_LockCtrl();                                              /* Lock Flash */
    return rev;
}

/*!
 * @brief Job_DflashWriteProtect_Config
 *        This Function is set Dflash page[0~127] writeProtect status
 *        if Write protect is set on Dflash page[128~255], disable write protect; 
 *        if Write protect is unset on Dflash page[128~255], enable write protect;
 *
 * @param[in] none
 * @return operation status
 *        - EFLASH_STATUS_SUCCESS: Operation was successful
 *        - EFLASH_STATUS_ERROR:   Operation was failure
 *
 *
 */
EFLASH_StatusType Job_DflashWriteProtect_Config(void)
{
    EFLASH_StatusType rev = EFLASH_STATUS_ERROR;
  #if REG_OR_OPTBYTE /* Set Write protect optionbyte , take effect after resetting*/
    
    /* Dflash page[0~127] write protect controlled by dWriteProtectConfig[0], page[128~255] write protect controlled by dWriteProtectConfig[1],
       each bit controls the write protection state of 4 pages of pflash,  0: UnWriteProtect  1: WriteProtect */
    uint32_t dWriteProtectConfig[2] = {0};
    
  #else  /* Set Write protect by register , immediate effect and invalid after reset */
    
    /* Dflash page[0~127] write protect controlled by setDLWProtectStatus, page[128~255] write protect controlled by setDHWProtectStatus,
       each bit controls the write protection state of 4 pages of pflash, 0: UnWriteProtect  1: WriteProtect */
    uint32_t setDLWProtectStatus = 0U;
    uint32_t setDHWProtectStatus = 0U;
    
  #endif

    EFLASH_UnlockCtrl();                                         /* Unlock Flash */
    if(0xFFFFFFFFU == EFLASH_GetDWriteProRegLow())               /* Get Dflash Dage[0~127] WriteProtect Status */
    {
        /* Dflash LowArea(Page 0~127) is WriteProtect */
        printf("\r\nDFlash Page[128 ~ 255] is WriteProtect state, start to disable writeProtect...\r\n");
    #if REG_OR_OPTBYTE
        dWriteProtectConfig[0] = 0U;                            /* Page[0~127] UnWriteProtect */
        dWriteProtectConfig[1] = 0U;                            /* Page[128~255] UnWriteProtect */
        rev = EFLASH_DFSetWriteProtection(dWriteProtectConfig); /* Set all page UnWriteProtect */
    #else
        setDLWProtectStatus = 0U;                               /* Page[0~127] UnWriteProtect */
        setDHWProtectStatus = 0U;                               /* Page[128~255] UnWriteProtect */
        rev = EFLASH_SetWriteProtectionByReg(DFLASH, setDLWProtectStatus, setDHWProtectStatus); /* Set all page UnWriteProtect */
    #endif

        if(EFLASH_STATUS_SUCCESS != rev)
        {
            printf("\r\n[%d]ERROR: Set Dflash Page[128 ~ 255] UnWriteProtect fail...\r\n", __LINE__);
        }
        else
        {
            printf("\r\nDisable Pflash Dage[128 ~ 255] WriteProtect done...\r\n");
        }
    }
    else
    {
        /* Dflash LowArea(Page 128~255) is UnWriteProtect */
        printf("\r\nDFlash Page[128 ~ 255] is UnWriteProtect state, start to enable writeProtect...\r\n");
    #if REG_OR_OPTBYTE
        dWriteProtectConfig[0] = 0xFFFFFFFFU;                    /* Page[0~127] WriteProtect */
        dWriteProtectConfig[1] = 0U;                             /* Page[128~255] UnWriteProtect */
        rev = EFLASH_DFSetWriteProtection(dWriteProtectConfig);  /* Set Dflash page[0~127] WriteProtect, Page[128~255] UnWriteProtect */
    #else
        setDLWProtectStatus = 0xFFFFFFFFU;                       /* Page[0~127] WriteProtect */
        setDHWProtectStatus = 0U;                                /* Page[128~255] UnWriteProtect */
        rev = EFLASH_SetWriteProtectionByReg(DFLASH, setDLWProtectStatus, setDHWProtectStatus);  /* Set Dflash page[0~127] WriteProtect, Page[128~255] UnWriteProtect */
    #endif
        if(EFLASH_STATUS_SUCCESS != rev)
        {
            printf("\r\n[%d]ERROR: Set Dflash Page[0 ~ 127] WriteProtect fail...\r\n", __LINE__);
        }
        else
        {
            printf("\r\nEnable Dflash Page[0 ~ 127] WriteProtect done...\r\n");
        }
    }
    EFLASH_LockCtrl();                               /* Lock Flash */
    return rev;
}

/*!
 * @brief Job_Pflash_Write
 *        This Function is write test, This function is designed for write testing. If write protection is enabled, the write operation will fail.
 *
 * @param[in] none
 * @return operation status
 *        - EFLASH_STATUS_SUCCESS: Operation was successful
 *        - EFLASH_STATUS_ERROR:   Operation was failure
 *
 *
 */
EFLASH_StatusType Job_Pflash_Write(void)
{
    EFLASH_StatusType rev = EFLASH_STATUS_ERROR;
    uint32_t writeAndReadData = 0U;
    
    EFLASH_Read(PFLASH_PAGE_254, &writeAndReadData, 1);   /* read data to Read buff  */
    printf("\r\nRead addr[0x%08X] is [%08X]\r\n", PFLASH_PAGE_254, writeAndReadData);
    
    EFLASH_UnlockCtrl();                             /* Unlock Flash */
    rev = EFLASH_PageErase(PFLASH_PAGE_254);         /* Erase Flash by page */
    if(rev != EFLASH_STATUS_SUCCESS)
    {
        printf("\r\n[%d]ERROR: Erase Pflash addr[0x%08X ~ 0x%08X] fail, error code is [%d]...\r\n", \
                __LINE__, PFLASH_PAGE_254, PFLASH_PAGE_254+FLASH_PAGE_SIZE, rev);
    }
    else
    {
        /* Program Pflash */
        writeAndReadData += 1U;
        rev = EFLASH_PageProgram(PFLASH_PAGE_254, &writeAndReadData,  1); 
        if(rev != EFLASH_STATUS_SUCCESS)
        {
            printf("\r\n[%d]ERROR: Program Pflash addr[0x%08X ~ 0x%08X] fail, error code is [%d]...\r\n", \
                    __LINE__, PFLASH_PAGE_254, PFLASH_PAGE_254+FLASH_PAGE_SIZE, rev);
        }
        else 
        {
            printf("\r\nPflash Write done...\r\n");
        }
    }
    EFLASH_Read(PFLASH_PAGE_254, &writeAndReadData, 1);   /* read data to Read buff  */
    printf("\r\nRead addr[0x%08X] is [%08X]\r\n", PFLASH_PAGE_254, writeAndReadData);
    EFLASH_LockCtrl();                                    /* Lock Flash */
    return rev;
}

/*!
 * @brief Job_Dflash_Write
 *        This Function is write test, This function is designed for write testing. If write protection is enabled, the write operation will fail.
 *
 * @param[in] none
 * @return operation status
 *        - EFLASH_STATUS_SUCCESS: Operation was successful
 *        - EFLASH_STATUS_ERROR:   Operation was failure
 *
 *
 */
EFLASH_StatusType Job_Dflash_Write(void)
{
    EFLASH_StatusType rev = EFLASH_STATUS_ERROR;
    uint32_t writeAndReadData = 0U;
    
    EFLASH_Read(DFLASH_PAGE_1, &writeAndReadData, 1);    /* read data to Read buff  */
    printf("\r\nRead addr[0x%08X] is [%08X]\r\n", DFLASH_PAGE_1, writeAndReadData);
    
    EFLASH_UnlockCtrl();                                 /* Unlock Flash */
    rev = EFLASH_PageErase(DFLASH_PAGE_1);               /* Erase Flash by page */
    if(rev != EFLASH_STATUS_SUCCESS)
    {
        printf("\r\n[%d]ERROR: Erase Dflash addr[0x%08X ~ 0x%08X] fail, error code is [%d]...\r\n", \
                __LINE__, DFLASH_PAGE_1, DFLASH_PAGE_1+FLASH_PAGE_SIZE, rev);
    }
    else
    {
        /* Program Pflash */
        writeAndReadData += 1U;
        rev = EFLASH_PageProgram(DFLASH_PAGE_1, &writeAndReadData,  1); 
        if(rev != EFLASH_STATUS_SUCCESS)
        {
            printf("\r\n[%d]ERROR: Program Dflash addr[0x%08X ~ 0x%08X] fail, error code is [%d]...\r\n", \
                    __LINE__, DFLASH_PAGE_1, DFLASH_PAGE_1+FLASH_PAGE_SIZE, rev);
        }
        else 
        {
            printf("\r\nDflash Write done...\r\n");
        }
    }
    EFLASH_Read(DFLASH_PAGE_1, &writeAndReadData, 1);   /* read data to Read buff  */
    printf("\r\nRead addr[0x%08X] is [%08X]\r\n", DFLASH_PAGE_1, writeAndReadData);
    EFLASH_LockCtrl();                                  /* Lock Flash */
    return rev;
}

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