273 lines
9.1 KiB
C
273 lines
9.1 KiB
C
/**
|
|
* @file system_init.c
|
|
* @author Flagchip
|
|
* @brief interrupt configuration
|
|
* @version 0.1.0
|
|
* @date 2024-01-12
|
|
*
|
|
* @copyright Copyright (c) 2024 Flagchip Semiconductors Co., Ltd.
|
|
*
|
|
*/
|
|
|
|
/* ********************************************************************************
|
|
* Revision History:
|
|
*
|
|
* Version Date Author Descriptions
|
|
* --------- ---------- ------------ ---------------
|
|
* 0.1.0 2024-01-12 Flagchip038 First version for gcc, iar, keil, ghs data init
|
|
******************************************************************************** */
|
|
|
|
|
|
#include "system_init.h"
|
|
#include "fc7xxx_driver_fpu.h"
|
|
|
|
static void data_clear(uint32_t u32StartAddr, uint32_t u32EndAddr);
|
|
static void data_copy(uint32_t u32SourceAddr, uint32_t u32DestAddr, uint32_t u32DestEndAddr);
|
|
|
|
|
|
#define REG_VAL(addr) (*(volatile uint32 *)(addr))
|
|
#define REG_VAL_OFF(addr,offset) (*(volatile uint32 *)((addr)+(offset)))
|
|
#define WDOG0_BASE_ADDR 0x40022000U
|
|
#define WDOG1_BASE_ADDR 0x40433000U
|
|
#define SMC_STANDBY_CFG_ADDR 0x40045010U
|
|
#define SCM_BASE_ADDR 0x40072000U
|
|
#define RGM_BASE_ADDR 0x40046000U
|
|
#define PCC_STCU_ADDR 0x400241FCU
|
|
#define STCU_BASE_ADDR 0x4007F000U
|
|
|
|
#define DWT_CYCCNT_ADDR 0xE0001004U
|
|
#define DEMCR_ADDR 0xE000EDFCU
|
|
|
|
#define CPACR_ADDR 0xE000ED88U
|
|
|
|
static void wdog_disable(uint32 wdog_base)
|
|
{
|
|
uint32 u32ttt = 128;
|
|
uint32 u32First = 1;
|
|
/* if it is not first time configure wdog, unlock status only pending for 128 bus clock */
|
|
do {
|
|
/* check unlock active */
|
|
if (0U == (0x800u & REG_VAL(wdog_base)))
|
|
{
|
|
/* if unlock statue turn to 0, means not first time configuring wdog */
|
|
u32First = 0;
|
|
break;
|
|
}
|
|
} while (u32ttt--);
|
|
|
|
if (u32First == 0U)
|
|
{
|
|
/* only unlock=0, reconfig=1, can unlock wdog*/
|
|
|
|
/* waiting reconfiguration successful */
|
|
while (0U == (0x400u & REG_VAL(wdog_base)));
|
|
|
|
/* unlock wdog */
|
|
REG_VAL_OFF(wdog_base, 4) = 0x08181982;
|
|
/* waiting unlock active */
|
|
while (0U == (0x800u & REG_VAL(wdog_base)));
|
|
|
|
}
|
|
REG_VAL(wdog_base) = 0x2920;
|
|
REG_VAL_OFF(wdog_base, 8) = 0xF000;
|
|
/* waiting reconfiguration successful */
|
|
while (0U == (0x400u & REG_VAL(wdog_base)));
|
|
}
|
|
|
|
/**
|
|
* \brief System Initialization
|
|
*
|
|
*/
|
|
void System_Init(void)
|
|
{
|
|
/* only errata in debug mode */
|
|
/* if (0 != (0x01 & REG_VAL(0xE000EDF0))) */
|
|
{
|
|
/* --------------- Errata MCU debug Issue 1 lockstep lost start -------------- */
|
|
/* clear dwt counter to handle cpu0 lockstep error under debug */
|
|
REG_VAL(DEMCR_ADDR) = 0x01000000u; /* open TRCENA */
|
|
REG_VAL(DWT_CYCCNT_ADDR) = 0x0u; /* Clear DWT_CYCCNT */
|
|
/* ----------------- Errata MCU debug Issue 1 lockstep lost end -------------- */
|
|
}
|
|
|
|
uint32 u32ResetType = (REG_VAL_OFF(RGM_BASE_ADDR, 8));
|
|
/* external and power domain reset like bist/pin/por/jtag/sysap need to clear all ram */
|
|
if (0U != (u32ResetType & 0x89C3))
|
|
{
|
|
/* --------- Errata MCU debug Issue 2 for ITCM error hardfault start --------- */
|
|
/* ------------------ NVR must set ITCM initial auto enable ------------------ */
|
|
/* disable AXBS/CPU0 ECC */
|
|
REG_VAL_OFF(SCM_BASE_ADDR, 0x20) = 0x02AA8A2A;
|
|
REG_VAL_OFF(SCM_BASE_ADDR, 0x24) = 0x00002822;
|
|
REG_VAL_OFF(SCM_BASE_ADDR, 0x28) = 0x00000AAA;
|
|
|
|
/* STCU PCC Enable*/
|
|
REG_VAL(PCC_STCU_ADDR) = 0x00800000;
|
|
/* clear all itcm dtcm sram*/
|
|
REG_VAL_OFF(STCU_BASE_ADDR, 0x50) = 0xFFFFFFFF; /* reserved bit write non-effect */
|
|
if (0x01U == (u32ResetType & 0x01U)) /* only skip ram for standby wakeup */
|
|
{
|
|
/* Get SMC standby mode */
|
|
uint32 standbymode = REG_VAL(SMC_STANDBY_CFG_ADDR) & 0x03U;
|
|
/* config skip ram for special standby */
|
|
REG_VAL_OFF(STCU_BASE_ADDR, 0x48) = 1u | (standbymode << 16);
|
|
}
|
|
else
|
|
{
|
|
REG_VAL_OFF(STCU_BASE_ADDR, 0x48) = 1u;
|
|
}
|
|
|
|
while (0 == ((REG_VAL_OFF(STCU_BASE_ADDR, 0x4C)) & 2u)); /* wait busy */
|
|
while (0 == ((REG_VAL_OFF(STCU_BASE_ADDR, 0x4C)) & 1u)); /* wait done */
|
|
|
|
}
|
|
|
|
/* enable AXBS/CPU0 ECC after every reset */
|
|
REG_VAL_OFF(SCM_BASE_ADDR, 0x20) = 0x03FFCF3F;
|
|
REG_VAL_OFF(SCM_BASE_ADDR, 0x24) = 0x00003D33;
|
|
REG_VAL_OFF(SCM_BASE_ADDR, 0x28) = 0x00000FFF;
|
|
|
|
/* disable wdog 0 */
|
|
wdog_disable(WDOG0_BASE_ADDR);
|
|
|
|
/* disable wdog 1 */
|
|
wdog_disable(WDOG1_BASE_ADDR);
|
|
|
|
|
|
#if ((__FPU_PRESENT == 1) && (__FPU_USED == 1))
|
|
REG_VAL(CPACR_ADDR) = 0x00F00000u; /* set CP10, CP11 Full Access */
|
|
#endif /* ((__FPU_PRESENT == 1) && (__FPU_USED == 1)) */
|
|
|
|
/*
|
|
// disable wdog 0
|
|
*(volatile uint32 *)0x40022004 = 0x08181982;
|
|
while (0U == (0x800u & *(volatile uint32 *)0x40022000));
|
|
*(volatile uint32 *)0x40022000 = 0x2920;
|
|
*(volatile uint32 *)0x40022008 = 0xF000;
|
|
while (0U == (0x400u & *(volatile uint32 *)0x40022000));
|
|
|
|
// disable wdog 1
|
|
*(volatile uint32 *)0x40433004 = 0x08181982;
|
|
while (0U == (0x800u & *(volatile uint32 *)0x40433000));
|
|
*(volatile uint32 *)0x40433000 = 0x2920;
|
|
*(volatile uint32 *)0x40433008 = 0xF000;
|
|
while (0U == (0x400u & *(volatile uint32 *)0x40433000));
|
|
|
|
#if ((__FPU_PRESENT == 1) && (__FPU_USED == 1))
|
|
FPU_Enable(); // Enable FPU
|
|
#endif
|
|
*/
|
|
}
|
|
|
|
void Data_Init(void)
|
|
{
|
|
#if defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
|
|
extern uint32_t Load$$RW_m_dtcm$$Base;
|
|
extern uint32_t Image$$RW_m_dtcm$$Base;
|
|
extern uint32_t Image$$RW_m_dtcm$$Limit;
|
|
|
|
extern uint32_t Image$$RW_m_dtcm$$ZI$$Limit;
|
|
extern uint32_t Image$$RW_m_dtcm$$ZI$$Base;
|
|
|
|
extern uint32_t Image$$ARM_LIB_HEAP$$ZI$$Base;
|
|
extern uint32_t Image$$ARM_LIB_HEAP$$ZI$$Limit;
|
|
|
|
/* data/bss/heap clear */
|
|
data_clear((uint32_t)&Image$$RW_m_dtcm$$Base, (uint32_t)&Image$$RW_m_dtcm$$Limit);
|
|
data_clear((uint32_t)&Image$$RW_m_dtcm$$ZI$$Base, (uint32_t)&Image$$RW_m_dtcm$$ZI$$Limit);
|
|
data_clear((uint32_t)&Image$$ARM_LIB_HEAP$$ZI$$Base, (uint32_t)&Image$$ARM_LIB_HEAP$$ZI$$Limit);
|
|
|
|
/* data */
|
|
data_copy((uint32_t)&Load$$RW_m_dtcm$$Base, (uint32_t)&Image$$RW_m_dtcm$$Base, (uint32_t)&Image$$RW_m_dtcm$$Limit);
|
|
|
|
#elif defined(__GNUC__) || defined(__ghs__)
|
|
extern uint32 __rom_data_start[];
|
|
extern uint32 __ram_data_start[];
|
|
extern uint32 __ram_data_end[];
|
|
extern uint32 __bss_start[];
|
|
extern uint32 __bss_end[];
|
|
extern uint32 __rom_ncache_data_start[];
|
|
extern uint32 __ram_ncache_data_start[];
|
|
extern uint32 __ram_ncache_data_end[];
|
|
extern uint32 __ncache_bss_start[];
|
|
extern uint32 __ncache_bss_end[];
|
|
|
|
extern uint32_t __itcm_start[];
|
|
extern uint32_t __itcm_end[];
|
|
|
|
|
|
extern uint32_t __xcp_start[];
|
|
extern uint32_t __xcp_end[];
|
|
|
|
|
|
/* data clear */
|
|
data_clear((uint32_t)__ram_data_start, (uint32_t)__ram_data_end);
|
|
data_clear((uint32_t)__bss_start, (uint32_t)__bss_end);
|
|
data_clear((uint32_t)__ram_ncache_data_start, (uint32_t)__ram_ncache_data_end);
|
|
data_clear((uint32_t)__ncache_bss_start, (uint32_t)__ncache_bss_end);
|
|
|
|
data_clear((uint32_t)__itcm_start, (uint32_t)__itcm_end);
|
|
data_clear((uint32_t)__xcp_start, (uint32_t)__xcp_end);
|
|
|
|
/* data copy */
|
|
data_copy((uint32_t)__rom_data_start, (uint32_t)__ram_data_start, (uint32_t)__ram_data_end);
|
|
data_copy((uint32_t)__rom_ncache_data_start, (uint32_t)__ram_ncache_data_start, (uint32_t)__ram_ncache_data_end);
|
|
|
|
#elif defined(__ICCARM__)
|
|
#pragma section=".data"
|
|
#pragma section=".data_init"
|
|
#pragma section=".ncsram"
|
|
#pragma section=".ncsram_init"
|
|
#pragma section=".bss"
|
|
#pragma section="RAM_VECTOR"
|
|
#pragma section=".intvec"
|
|
|
|
data_clear((uint32_t)__section_begin(".bss"), (uint32_t)__section_end(".bss"));
|
|
|
|
data_copy((uint32_t)__section_begin(".data_init"), (uint32_t)__section_begin(".data"), (uint32_t)__section_end(".data"));
|
|
|
|
data_copy((uint32_t)__section_begin(".ncsram_init"), (uint32_t)__section_begin(".ncsram"), (uint32_t)__section_end(".ncsram"));
|
|
|
|
#endif
|
|
}
|
|
|
|
/* to avoid ecc issue, FC7240 clear ram with 64bits once after power on reset */
|
|
static void data_clear(uint32_t u32StartAddr, uint32_t u32EndAddr)
|
|
{
|
|
/* 64 bits align */
|
|
uint32_t u32AlignStart = u32StartAddr & 0xFFFFFFF8;
|
|
uint32_t u32AlignEnd = (u32EndAddr - u32AlignStart);
|
|
volatile uint64_t *pData = (uint64_t *)u32AlignStart;
|
|
|
|
/* 32 word Align */
|
|
uint32_t u32LeftCount = u32AlignEnd & 0x1Fu;
|
|
u32AlignEnd = u32EndAddr - u32LeftCount;
|
|
|
|
while ((uint32_t)pData < u32AlignEnd)
|
|
{
|
|
*pData++ = 0u;
|
|
*pData++ = 0u;
|
|
*pData++ = 0u;
|
|
*pData++ = 0u;
|
|
}
|
|
|
|
while ((uint32_t)pData < u32EndAddr)
|
|
{
|
|
*pData++ = 0u;
|
|
}
|
|
}
|
|
|
|
static void data_copy(uint32_t u32SourceAddr, uint32_t u32DestAddr, uint32_t u32DestEndAddr)
|
|
{
|
|
uint32_t *pSource = (uint32_t *)u32SourceAddr;
|
|
uint32_t *pDest = (uint32_t *)u32DestAddr;
|
|
|
|
while ((uint32_t)pDest < u32DestEndAddr)
|
|
{
|
|
*pDest = *pSource;
|
|
pDest++;
|
|
pSource++;
|
|
}
|
|
}
|
|
|