/*!
\brief setup the microcontroller system, initialize the system
\param[in] none
\param[out] none
\retval none
*/
void SystemInit (void)
{
/* FPU settings */
/* 如果要使用戶FPU,則在gd32e10x.h中定義__FPU_PRESENT ,看供應商提供的文檔中有關於FPU設置的方法 */
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */
#endif
/* reset the RCU clock configuration to the default reset state */
/* Set IRC8MEN bit */
/*
下面對復位和時鐘單元的部分寄存器進行初始化。這裏對RCU_CTL這個寄存器做置位,來啓動IRC 8M RC振盪器
系統啓動的時候就默認用8M的RC振盪器來工作,至於後面時鐘怎麼選,後面再說。
不過想一下前面彙編程序是在system init之前是怎麼執行的?比如其中有堆棧的空間SPACE,這個SPACE是怎麼做的
當時都沒有時鐘,可能還是要了解一下啓動過程
*/
RCU_CTL |= RCU_CTL_IRC8MEN;
/* Reset CFG0 and CFG1 registers */
RCU_CFG0 = 0x00000000U;
RCU_CFG1 = 0x00000000U;
/* Reset HXTALEN, CKMEN, PLLEN, PLL1EN and PLL2EN bits */
RCU_CTL &= ~(RCU_CTL_PLLEN |RCU_CTL_PLL1EN | RCU_CTL_PLL2EN | RCU_CTL_CKMEN | RCU_CTL_HXTALEN);
/* disable all interrupts */
RCU_INT = 0x00ff0000U;
/* reset HXTALBPS bit */
RCU_CTL &= ~(RCU_CTL_HXTALBPS);//高速晶體振盪器(HXTAL)時鐘旁路模式
/* configure the system clock source, PLL Multiplier, AHB/APBx prescalers and Flash settings */
system_clock_config();//這裏我用的是PLL倍頻出的48M,最終調用的system_clock_48m_irc8m,這裏其實就是初始化PLL,等待PLL穩定下來提供穩定的時鐘源
//下面是重點,下面單獨說
#ifdef VECT_TAB_SRAM
nvic_vector_table_set(NVIC_VECTTAB_RAM,VECT_TAB_OFFSET);
#else
nvic_vector_table_set(NVIC_VECTTAB_FLASH,VECT_TAB_OFFSET);
#endif
}
對於RCU部分,可以看下RCU在整個EFM32 芯片中的位置,通過AHB和ARM Cortex-M4進行通信
AHB(Advanced High performance Bus)系統總線,高級性能總線和APB(Advanced Peripheral Bus)外圍總線
#ifdef VECT_TAB_SRAM
nvic_vector_table_set(NVIC_VECTTAB_RAM,VECT_TAB_OFFSET);
#else
nvic_vector_table_set(NVIC_VECTTAB_FLASH,VECT_TAB_OFFSET);
#endif
VECT_TAB_SRAM
這裏是關於NVIC的一些內容,NVIC (Nested Vectored Interrupt Controller).
這裏從上面圖中就可以看出NVIC是Cortex-M4內部集成的,注意它和我們經常用到的外部中斷控制器EXIT的區別。
這裏不多說,只說這裏關於宏的選擇:
在SPEC上我們看到關於NVIC的說明
對於硬件上boot0 和boot1的引腳電平,可以選擇不同的引導源
注意這句話:片上SRAM存儲空間的起始地址是0x2000 0000,當他被選擇爲引導源時,在應用程序初始化代碼中,
你必須使用NVIC異常表和偏移寄存器來將向量表重定向到SRAM中。
這裏看下我們硬件的選擇
BOOT0是接地,電平是0,所以引導源是主FLash存儲器,這個宏應該不要定義,看看代碼確實沒有定義。
在看代碼本身
其中的宏:
/* constants definitions */
/* set the RAM and FLASH base address */
#define NVIC_VECTTAB_RAM ((uint32_t)0x20000000) /*!< RAM base address */
#define NVIC_VECTTAB_FLASH ((uint32_t)0x08000000) /*!< Flash base address */
RAM的地址被映射爲0x20000000
FLash基地址是0x80000000
這裏可以對應SPEC上
再看
/* Vector Table base offset */
#define VECT_TAB_OFFSET 0x0000 /* This value must be a multiple of 0x200. */
這個是你比如說flash上的偏移地址,前面說的基地址,如果你有bootloader,bootloader的空間是0x200,那麼你這裏就要把bootloader的偏移給加上,加上之後纔是你的APP的最終基地址。
之前在開發的時候,這裏默認寫的是0x2000,但是我又沒有bootloader,導致一直有問題,一旦設置中斷就出現問題,但是我當時設置的是外部中斷,不知道爲什麼影響到這裏,外部的和內部的NVIC應該在一起的吧,我想
後續:
#include "gd32e10x.h" 這個頭文件被包含在此Sytem_gd32e10x.c源文件中,注意其中的設置
有的宏是需要在編譯器中或者代碼中定義的,定義之後才能和你的板子匹配
比如說.h文件中的
/* define value of high speed crystal oscillator (HXTAL) in Hz */
#if !defined HXTAL_VALUE
#ifdef GD32E103V_EVAL
#define HXTAL_VALUE ((uint32_t)8000000) /*!< value of the external oscillator in Hz */
#define HXTAL_VALUE_8M HXTAL_VALUE
#elif defined(GD32E103R_START) || defined(GD32E103C_START) || defined(GD32E103T_START)
#define HXTAL_VALUE ((uint32_t)25000000) /*!< value of the external oscillator in Hz */
#define HXTAL_VALUE_25M HXTAL_VALUE
#else
#error "Please select the target board type used in your application (in gd32e10x.h file)"
#endif
#endif /* high speed crystal oscillator value */
到底用哪個,需要仔細確認的!