#ifndef	__ACM32F4__H
#define __ACM32F4__H

#define CHIP_FLASH_SIZE     0x7ffff
#define FLASH_PAGE_SIZE     0x200

#define SCU_RCR             *(unsigned int *)(0x40010800UL + 0x00)  
#define SCU_CCR1            *(unsigned int *)(0x40010800UL + 0x10) 
#define SCU_CCR2            *(unsigned int *)(0x40010800UL + 0x14)
#define SCU_RCHCR           *(unsigned int *)(0x40010800UL + 0x24) 

#define SCU_RCR_REMAP_IMP   (1UL << 16)
#define SCU_RCHCR_RCHRDY    (1UL << 9)
#define SCU_RCHCR_RCH_EN    (1UL << 0)
#define SCU_RCHCR_RCH_DIV   (1UL << 8)
#define SCU_CCR2_DIVDONE    (1UL << 31)

#define EFC_CTRL            *(unsigned int *)(0x00100000UL + 0x00)
#define EFC_SEC             *(unsigned int *)(0x00100000UL + 0x04)
#define EFC_TERASE          *(unsigned int *)(0x00100000UL + 0x0c)
#define EFC_TPROG           *(unsigned int *)(0x00100000UL + 0x10)
#define EFC_STATUS          *(unsigned int *)(0x00100000UL + 0x14)   
#define EFC_INTSTATUS       *(unsigned int *)(0x00100000UL + 0x18)   
#define EFC_INTEN           *(unsigned int *)(0x00100000UL + 0x2C)    
#define FMC_FLSTS_OVF_Msk   0x01
#define SCB_VTOR           *(unsigned int *)(0xE000E000UL + 0x0D00UL + 0x08)

#define EFC_CTRL_PAGE_ERASE_MODE        (1 << 1)
#define EFC_CTRL_PROGRAM_MODE           (1 << 0)

#define EFC_STATUS_NVR4_LOCK            (1 << 4)
#define EFC_STATUS_NVR3_LOCK            (1 << 3)
#define EFC_STATUS_NVR2_LOCK            (1 << 2)
#define EFC_STATUS_NVR1_LOCK            (1 << 1)
#define EFC_STATUS_EFLASH_RDY           (1 << 0)

//计算编程等待时间,默认时钟为64M
#define SYS_CLK             (64)
#define FLASH_PROG_DELAY    (12 * SYS_CLK)
#define FLASH_ERSAE_DELAY   (6 * 1000 * SYS_CLK)

//系统时钟配置
#define system_init()   do{                 \
    SCU_RCR |= SCU_RCR_REMAP_IMP;           \
    EFC_CTRL = (EFC_CTRL & ~(0x1F << 7)) | (8 << 7); \
    if(0 == (SCU_RCHCR & SCU_RCHCR_RCH_EN)) \
    {                                       \
        SCU_RCHCR |=  SCU_RCHCR_RCH_EN;     \
        while(0 == (SCU_RCHCR & SCU_RCHCR_RCHRDY)); \
    }                                       \
    SCU_CCR1 = 0;                           \
    SCU_RCHCR &= (~SCU_RCHCR_RCH_DIV);      \
    while(0 == (SCU_RCHCR & SCU_RCHCR_RCHRDY));    \
    SCU_CCR2 = 0x0000;                      \
    while((SCU_CCR2 & SCU_CCR2_DIVDONE) == 0x00);  \
    EFC_TPROG = FLASH_PROG_DELAY;           \
    EFC_TERASE = FLASH_ERSAE_DELAY;         \
}while(0)

#define flash_readywait(value)  do{     \
    unsigned int i;                     \
    i = value;                          \
    do{                                 \
        i --;                           \
        if((EFC_STATUS & EFC_STATUS_EFLASH_RDY) != 0) break; \
    }while(i);                          \
}while(0)

#define flash_program()    do{                  \
    unsigned int i;                             \
    EFC_CTRL |= EFC_CTRL_PROGRAM_MODE;          \
    for(i=0; i<FlashParameter.size; i += 4)     \
    {                                           \
        EFC_SEC = 0x55AAAA55;                   \
        *(unsigned int *)(FlashParameter.addr + i) = *((unsigned int *)(&FlashParameter.data[i])); \
        flash_readywait(FLASH_PROG_DELAY);      \
    }                                           \
    EFC_CTRL &= ~EFC_CTRL_PROGRAM_MODE;         \
    FlashParameter.status = 0;                  \
}while(0)

#define flash_erasepage()   do{                 \
    EFC_CTRL |= EFC_CTRL_PAGE_ERASE_MODE;       \
    EFC_SEC = 0x55AAAA55;                       \
    *(unsigned int *) FlashParameter.addr = 0x00; \
    flash_readywait(FLASH_ERSAE_DELAY);         \
    EFC_CTRL &= ~EFC_CTRL_PAGE_ERASE_MODE;      \
    FlashParameter.status = 0;                  \
}while(0)

#define flash_erasechip()   do{                 \
    unsigned int i;                             \
    EFC_CTRL |= EFC_CTRL_PAGE_ERASE_MODE;       \
    for(i=0; i<FlashParameter.size; i += FLASH_PAGE_SIZE)   \
    {                                           \
        EFC_SEC = 0x55AAAA55;                   \
        *(unsigned int *)(i) = 0x00;            \
        flash_readywait(FLASH_ERSAE_DELAY);     \
    }                                           \
    EFC_CTRL &= ~EFC_CTRL_PAGE_ERASE_MODE;      \
    FlashParameter.status = 0;                  \
}while(0)

#define flash_readchip()    do{}while(0)

#endif
