/**************************************************************************//**
 * @file     sys.c
 * @version  V1.00
 * $Revision: 1 $
 * $Date: 14/07/30 10:00a $
 * @brief    N572 Series SYS driver source file
 *
 * @note
 * Copyright (C) 2014 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/

#include "N572.h"

/** @addtogroup N572_Device_Driver N572 Device Driver
  @{
*/
	
/** @addtogroup N572_SYS_Driver SYS Driver
  @{
*/
	
/** @addtogroup N572_SYS_EXPORTED_FUNCTIONS SYS Exported Functions
  @{
*/

/**
  * @brief  This function configure BOD function.
  *         Configure set Brown-out voltage level.
  *         Enable Brown-out function
  * @param  u32BODLevel is Brown-out voltage level. Including :
  *         - \ref SYS_BODCTL_BODVL_2_7V
  *         - \ref SYS_BODCTL_BODVL_3_0V
  *
  * @return None
  */
void SYS_EnableBOD(uint32_t u32BODLevel)
{
	uint8_t u8Lock;
	
	u8Lock = SYS_Unlock();
    SYS->BODCTL = (SYS->BODCTL&~(SYS_BODCTL_BOD_VL_Msk))|(u32BODLevel|SYS_BODCTL_BOD_EN_Msk);
	SYS_Lock(u8Lock);
}

/**
  * @brief  This function disable BOD function.
  * @return None
  */
void SYS_DisableBOD(void)
{
	uint8_t u8Lock;
	
	u8Lock = SYS_Unlock();
    SYS->BODCTL &= ~SYS_BODCTL_BOD_EN_Msk;
	SYS_Lock(u8Lock);
}

/**
  * @brief  This function clear the selected system reset source
  * @param  u32Src is system reset source
  * @return None
  */
void SYS_ClearResetSrc(uint32_t u32Src)
{
    SYS->RSTSTS |= u32Src;
}

/**
  * @brief  This function get the system reset source register value
  * @return Reset source
  */
uint32_t SYS_GetResetSrc(void)
{
    return (SYS->RSTSTS);
}

/**
  * @brief  This function check register write-protection bit setting
  * @return 0: Write-protection function is disabled.
  *         1: Write-protection function is enabled.
  */
uint32_t SYS_IsRegLocked(void)
{
    return ( SYS->REGLCTL == SYS_REGLCTL_REGLCTL_Msk? 0:1 );
}

/**
  * @brief  This function enable register write-protection function
  * @return None
  * @details To lock the protected register to forbid write access
  */
void SYS_LockReg(void)
{
    SYS->REGLCTL = 0;
}

/**
  * @brief  This function disable register write-protection function
  * @return None
  * @details To unlock the protected register to allow write access
  */
void SYS_UnlockReg(void)
{
    while(SYS->REGLCTL != SYS_REGLCTL_REGLCTL_Msk) 
	{
        SYS->REGLCTL = 0x59;
        SYS->REGLCTL = 0x16;
        SYS->REGLCTL = 0x88;
    }
}

/**
  * @brief  This function enable register write-protection function or not according to input lock optin.
  * @param  u8Lock is lock option. 1 represents to lock protected register. 0 represents not to lock protected register.
  * @return None
  * @details To lock the protected register to forbid write access
  */
void SYS_Lock(uint8_t u8Lock)
{
	if ( u8Lock )
		SYS->REGLCTL = 0;
}

/**
  * @brief  This function disable register write-protection function and return previous lock state before calling this function.
  * @return 1: represent the previous state is locked, 0: represent the previous state is unlocked.
  * @details To unlock the protected register to allow write access
  */
uint8_t SYS_Unlock(void)
{
	if ( ((SYS->REGLCTL)&SYS_REGLCTL_REGLCTL_Msk) == 1 )
		return 0;
	
    while(SYS->REGLCTL != SYS_REGLCTL_REGLCTL_Msk) 
	{
        SYS->REGLCTL = 0x59;
        SYS->REGLCTL = 0x16;
        SYS->REGLCTL = 0x88;
    }

	return 1;
}

/**
  * @brief  This function get product ID.
  * @return Product ID
  */
uint32_t  SYS_ReadPDID(void)
{
    return SYS->PDID;
}

/**
  * @brief  This function reset chip.
  * @return None
  */
void SYS_ResetChip(void)
{
	uint8_t u8Lock;
	
	u8Lock = SYS_Unlock();
    SYS->IPRST0 |= SYS_IPRST0_CHIPRST_Msk;
	SYS_Lock(u8Lock);
}

/**
  * @brief  This function reset CPU.
  * @return None
  */
void SYS_ResetCPU(void)
{
	uint8_t u8Lock;
	
	u8Lock = SYS_Unlock();
    SYS->IPRST0 |= SYS_IPRST0_CPURST_Msk;
	SYS_Lock(u8Lock);
}

/**
  * @brief  This function reset selected modules.
  * @param  u32ModuleIndex is module index. Including :
  * - \ref CHIP_RST
  * - \ref CPU_RST
  * - \ref GPIO_RST
  * - \ref TMR0_RST
  * - \ref TMR1_RST
  * - \ref TMR2_RST
  * - \ref APU_RST
  * - \ref TMRF_RST
  * - \ref SPI0_RST
  * - \ref SPI1_RST
  * - \ref PWM_RST
  * - \ref ADC_RST
  * @return None
  */
void SYS_ResetModule(uint32_t u32ModuleIndex)
{
	uint8_t u8Lock;
	
	u8Lock = SYS_Unlock();
    *(volatile uint32_t *)((uint32_t)&(SYS->IPRST0) + (u32ModuleIndex>>24)) |= 1<<(u32ModuleIndex & 0x00ffffff);
    *(volatile uint32_t *)((uint32_t)&(SYS->IPRST0) + (u32ModuleIndex>>24)) &= ~(1<<(u32ModuleIndex & 0x00ffffff));
	SYS_Lock(u8Lock);
}

/**
  * @brief  This function sets RAM wait state control for CPU accessing RAM.
  * @param  u32RamWaitState is RAM wait state. It can be one of the following :
  * - \ref SYS_IPRST0_RAMWS_ZERO_WAIT represents no wait state.
  * - \ref SYS_IPRST0_RAMWS_1HCLK_WAIT represents 1 HCLK clock wait state.
  * @return None
  */
void SYS_SetRamWaitSate(uint32_t u32RamWaitState)
{
	uint8_t u8Lock;
	
	u8Lock = SYS_Unlock();
	SYS->IPRST0 = (SYS->IPRST0&(~SYS_IPRST0_RAMWS_Msk))|u32RamWaitState;
	SYS_Lock(u8Lock);
}

/**
  * @brief  This function sets CPU wait state control for CPU accessing flash memory.
  * @param  u32CpuWaitState is CPU wait state. It can be one of the following :
  * - \ref SYS_IPRST0_CPUWS_ZERO_WAIT represents no wait state.
  * - \ref SYS_IPRST0_CPUWS_1HCLK_WAIT represents 1 HCLK clock wait state.
  * @return None
  */
void SYS_SetCpuWaiState(uint32_t u32CpuWaitState)
{
	uint8_t u8Lock;
	
	u8Lock = SYS_Unlock();
	SYS->IPRST0 = (SYS->IPRST0&(~SYS_IPRST0_CPUWS_Msk))|u32CpuWaitState;
	SYS_Lock(u8Lock);
}

/**
  * @brief  This function sets RAM adn CPU wait state control for CPU accessing RAM and accessing flash memory.
  * @param  u32RamWaitState is RAM wait state. It can be one of the following :
  * - \ref SYS_IPRST0_RAMWS_ZERO_WAIT represents no wait state.
  * - \ref SYS_IPRST0_RAMWS_1HCLK_WAIT represents 1 HCLK clock wait state.
  * @param  u32CpuWaitState is CPU wait state. It can be one of the following :
  * - \ref SYS_IPRST0_CPUWS_ZERO_WAIT represents no wait state.
  * - \ref SYS_IPRST0_CPUWS_1HCLK_WAIT represents 1 HCLK clock wait state.
  * @return None
  */
void SYS_SetRamCpuWaitState(uint32_t u32RamWaitState, uint32_t u32CpuWaitState)
{
	uint8_t u8Lock;
	
	u8Lock = SYS_Unlock();
	SYS->IPRST0 = (SYS->IPRST0&(~(SYS_IPRST0_RAMWS_Msk|SYS_IPRST0_CPUWS_Msk)))|(u32RamWaitState)|(u32CpuWaitState);
	SYS_Lock(u8Lock);
}

/**
  * @brief  This function disables LVR(Low Voltage Reset) function.
  * @return None
  */
void SYS_DisableLVR(void)
{
	uint8_t u8Lock;
	
	u8Lock = SYS_Unlock();
	SYS->BODCTL &= ~SYS_BODCTL_LVR_EN_Msk;
	SYS_Lock(u8Lock);
}

/**
  * @brief  This function enables LVR(Low Voltage Reset) function. The chip will be reset at detecting low voltage.
  * @return None
  */
void SYS_EnableLVR(void)
{
	uint8_t u8Lock;
	
	u8Lock = SYS_Unlock();
	SYS->BODCTL |= SYS_BODCTL_LVR_EN_Msk;
	SYS_Lock(u8Lock);
}
/**
  * @brief  This function disables POR(Power On Reset) function. This can avoid power noise to cause the POR active again!
  * @return None
  */
void SYS_DisablePOR(void)
{
	uint8_t u8Lock;
	
	u8Lock = SYS_Unlock();
	SYS->PORCTL = 0x5AA5;
	SYS_Lock(u8Lock);
}
/**
  * @brief  This function enables POR(Power On Reset) function.
  * @return None
  */
void SYS_EnablePOR(void)
{
	uint8_t u8Lock;
	
	u8Lock = SYS_Unlock();
	SYS->PORCTL = 0x0000;
	SYS_Lock(u8Lock);
}


/*@}*/ /* end of group N572_SYS_EXPORTED_FUNCTIONS */

/*@}*/ /* end of group N572_SYS_Driver */

/*@}*/ /* end of group N572_Device_Driver */

/*** (C) COPYRIGHT 2014 Nuvoton Technology Corp. ***/
