#ifndef	__STM32F10x__H
#define __STM32F10x__H

#define UNLOCK_KEY0                ((unsigned int)0x45670123U)                          /*!< FMC/OB unlock key 0 */
#define UNLOCK_KEY1                ((unsigned int)0xCDEF89ABU)                          /*!< FMC/OB unlock key 1 */
#define SLP_UNLOCK_KEY0            ((unsigned int)0x04152637U)                          /*!< SLP unlock key 0 */
#define SLP_UNLOCK_KEY1            ((unsigned int)0xBCAD9E8FU)                          /*!< SLP unlock key 1 */


#define FLASH_PAGE_SIZE     (0x200U)
#define FMC_BASE            (0x40020000U + 0x2000U)
#define RCC_BASE            (0x40020000U + 0x1000U)
#define PWR_BASE            (0x40000000U + 0x7000U)

#define FMC_ACR             *(unsigned int *)(FMC_BASE + 0x00)
#define FMC_KEYR            *(unsigned int *)(FMC_BASE + 0x04)
#define FMC_OPTKEYR         *(unsigned int *)(FMC_BASE + 0x08)					/*!< FMC option bytes unlock key register */
#define FMC_SR              *(unsigned int *)(FMC_BASE + 0x0C)         			/*!< FMC status register */
#define FMC_CR              *(unsigned int *)(FMC_BASE + 0x10)                 	/*!< FMC control register */
#define FMC_AR              *(unsigned int *)(FMC_BASE + 0x14)                 	/*!< FMC address register */
#define FMC_OBR             *(unsigned int *)(FMC_BASE + 0x1C)                 	/*!< FMC option bytes status register */
#define FMC_WRPR            *(unsigned int *)(FMC_BASE + 0x20)                 	/*!< FMC erase/program protection register */

#define SCB_VTOR            *(unsigned int *)(0xE000ED08)                  		/*!< SCB_VTOR */

#define RCC_CR	            *(unsigned int *)(RCC_BASE + 0x00)
#define RCC_CFGR            *(unsigned int *)(RCC_BASE + 0x04)
#define RCC_CIR	            *(unsigned int *)(RCC_BASE + 0x08)
#define RCC_APB2RSTR  		*(unsigned int *)(RCC_BASE + 0x0c)
#define RCC_APB1RSTR  		*(unsigned int *)(RCC_BASE + 0x10)
#define RCC_AHBENR			*(unsigned int *)(RCC_BASE + 0x14)
#define RCC_APB2ENR			*(unsigned int *)(RCC_BASE + 0x18)
#define RCC_APB1ENR			*(unsigned int *)(RCC_BASE + 0x1c)
#define RCC_CFGR2           *(unsigned int *)(RCC_BASE + 0x2C) 

#define RCC_CFG_AHBPRES_DIV1    0x00
#define RCC_CFG_APBPRES_DIV1    0x00  

#define FMC_FLAG        0x34
#define FMC_STS_BUSY    (1 << 0)
//#define FMC_STS_FSTAT   (1 << 15)
#define FMC_STS_PGERR   (1 << 2) 
//#define FMC_STS_PGAERR  (1 << 3)
#define FMC_STS_WRPERR  (1 << 4)
#define FMC_STS_EOP     (1 << 5)

#define FMC_CTRL_LOCK   (1 << 7)
#define FMC_CTRL_START  (1 << 6)
#define FMC_CTRL_MER    (1 << 2)
#define FMC_CTRL_PER    (1 << 1)
#define FMC_CTRL_PG     (1 << 0)

#define FMC_TIMEOUT_COUNT   (0x01000000U) 

#define system_init()   do{ \
	RCC_APB2RSTR 	= 0x00;	\
  	RCC_APB1RSTR 	= 0x00;	\
  	RCC_AHBENR 		= 0x14;	\
  	RCC_APB2ENR 	= 0x00;	\
  	RCC_APB1ENR 	= 0x00;	\
  	RCC_CR 			|= 0x01;\
  	RCC_CFGR        = 0x00;	\
  	RCC_CIR 		= 0x00;	\
}while(0)

#define flash_unlock()  do{         \
    if((FMC_CR & FMC_CTRL_LOCK) != 0) \
    {                               \
        FMC_KEYR = UNLOCK_KEY0;      \
        FMC_KEYR = UNLOCK_KEY1;      \
    }                               \
}while(0)
#define flash_lock()    do{     \
    FMC_CR |= FMC_CTRL_LOCK;  \
}while(0)

#define flash_flagClr() FMC_SR = FMC_FLAG

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

#define flash_program()    do{                  \
    unsigned int i;                             \
    flash_unlock();                             \
    for(i=0; i<FlashParameter.size; i += 2)     \
    {                                           \
        flash_flagClr();                        \
        flash_readywait(FMC_TIMEOUT_COUNT);     \
        if((FMC_SR & FMC_STS_BUSY) == 0)       \
        {                                       \
            FMC_CR |= FMC_CTRL_PG;            \
            *(unsigned short *)(FlashParameter.addr + i) = *((unsigned short *)(&FlashParameter.data[i]));                    \
            flash_readywait(FMC_TIMEOUT_COUNT); \
            FMC_CR &= ~FMC_CTRL_PG;           \
        }                                       \
    }                                           \
    flash_lock();                               \
    FlashParameter.status = 0;                  \
}while(0)

#define flash_erasepage()   do{         \
    flash_unlock();                     \
    flash_flagClr();                    \
    flash_readywait(FMC_TIMEOUT_COUNT); \
    FMC_CR |= FMC_CTRL_PER;           \
    FMC_AR = FlashParameter.addr;     \
    FMC_CR |= FMC_CTRL_START;         \
    flash_readywait(FMC_TIMEOUT_COUNT); \
    FMC_CR &= ~FMC_CTRL_PER;          \
    flash_lock();                       \
    FlashParameter.status = 0;          \
}while(0)

#define flash_erasechip()   do{         \
    flash_unlock();                     \
    flash_flagClr();                    \
    flash_readywait(FMC_TIMEOUT_COUNT); \
    FMC_CR |= FMC_CTRL_MER;           \
    FMC_AR = FlashParameter.addr;     \
    FMC_CR |= FMC_CTRL_START;         \
    flash_readywait(FMC_TIMEOUT_COUNT); \
    FMC_CR &= ~FMC_CTRL_MER;          \
    flash_lock();                       \
    FlashParameter.status = 0;          \
}while(0)

#define	flash_readchip()	do{	\
	FlashParameter.Result = 1;	\
}while(0)

#endif
