system_gd32e10x.c分析

/*!
    \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 */

到底用哪個,需要仔細確認的!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章