[资料工具] NV32 系统初始化函数-Sysinit

[复制链接]
 楼主| hanzhen654 发表于 2020-2-23 20:06 | 显示全部楼层 |阅读模式
NV32 的系统初始化函数,配置 FLASH 等待周期,管脚复用,时钟选择等。
  1. void sysinit (void)
  2. {
  3. SIM_ConfigType sSIMConfig = {{0},0};
  4. ICS_ConfigType sICSConfig = {0};
  5. global_pass_count = 0;
  6. global_fail_count = 0;
  7. EFMCR &=0xFFFF0001; // 设置 FLASH 等待周期,注: 此处需修正
  8. #if defined(TRIM_IRC)
  9. ICS_Trim(ICS_TRIM_VALUE);//粗略的 TRIM 值校准, 若不使用此值则使用内部出厂 40M 主频
  10. #endif




 楼主| hanzhen654 发表于 2020-2-23 20:06 | 显示全部楼层
  1. /*
  2. 定义一些功能管脚的设置,比如禁用复位脚 RESET,以及 SWD 调试,通过宏定义的方式
  3. RST 脚与 NMI 脚在上电后只能配置一次, 第二次即视为无效
  4. 注:要考虑到这些管脚复用的问题,在 Sysinit 函数中,必须一开始就要禁用
  5. */
  6. #if defined(DISABLE_RST)
  7. sSIMConfig.sBits.bDisableRESET = 1;//禁用 RST 脚
  8. #endif
  9. #if defined(DISABLE_SWD)
  10. sSIMConfig.sBits.bDisableSWD = 1;//禁用 SWD 调试,注:慎用, 禁用则上电后不可再通过 SWD 调试
  11. #endif
  12. #if defined(SPI0_PINREMAP)
  13. sSIMConfig.u32PinSel |= SIM_PINSEL_SPI0PS_MASK;
  14. #endif


 楼主| hanzhen654 发表于 2020-2-23 20:07 | 显示全部楼层
  1. /* 输出总线时钟,定义为管脚 PH2 输出 */
  2. #if defined(OUTPUT_BUSCLK)
  3. sSIMConfig.sBits.bEnableCLKOUT = 1;
  4. #endif
  5. #if defined(DISABLE_NMI)
  6. sSIMConfig.sBits.bDisableNMI = 1;//禁用不可屏蔽中断的管脚 PB4
  7. #endif
  8. /* 使能部分模块的时钟信号 */
  9. sSIMConfig.u32SCGC|=SIM_SCGC_SWD_MASK|SIM_SCGC_FLASH_MASK|
  10. SIM_SCGC_UART0_MASK | SIM_SCGC_UART1_MASK | SIM_SCGC_UART2_MASK;
  11. /*初始化 SIM 模块*/
  12. SIM_Init(&sSIMConfig);
  13. #if defined(XOSC_STOP_ENABLE)
  14. sICSConfig.oscConfig.bStopEnable = 1;
  15. #endif
  16. #if defined(CRYST_HIGH_GAIN)
  17. sICSConfig.oscConfig.bGain = 1;
  18. #endif
  19. #if (EXT_CLK_FREQ_KHZ >=4000)
  20. sICSConfig.oscConfig.bRange = 1; //OSC_CR[RANGE]置位
  21. #endif
  22. sICSConfig.oscConfig.bEnable = 1; //使能 OSC
  23. sICSConfig.u32ClkFreq = EXT_CLK_FREQ_KHZ;
  24. #if defined(USE_FEE) //选择外部晶振时钟,常用的两种时钟模式为 FEE 和 FEI
  25. sICSConfig.u8ClkMode = ICS_CLK_MODE_FEE;
  26. #elif defined(USE_FBE_OSC)
  27. sICSConfig.u8ClkMode = ICS_CLK_MODE_FBE_OSC;
  28. #elif defined(USE_FEE_OSC)
  29. sICSConfig.u8ClkMode = ICS_CLK_MODE_FEE_OSC;
  30. #elif defined(USE_FBILP)
  31. sICSConfig.u8ClkMode = ICS_CLK_MODE_FBILP;
  32. #elif defined(USE_FBELP)
  33. sICSConfig.u8ClkMode = ICS_CLK_MODE_FBELP;
  34. #endif
  35. /*初始化 ICS 模块 */
  36. ICS_Init(&sICSConfig);
  37. /* 初始化 UART 打印串口输出 */
  38. UART_InitPrint();
  39. #if defined(PRINT_SYS_LOG)
  40. print_sys_log(); //打印系统相关的信息
  41. #endif
  42. }


 楼主| hanzhen654 发表于 2020-2-23 20:08 | 显示全部楼层
头文件 NV32Config.h 的说明
系统所使用的一些宏定义,以及时钟模式的选择

  1. #ifndef _NVxx_CONFIG_H_
  2. #define _NVxx_CONFIG_H_
  3. #include <stdint.h>
  4. #define CPU_NV32
  5. #define TEST
  6. /* 是否使用定义的 TRIM 值来校准内部 IRC,若注释则使用出厂校准的 TRIM 值出厂校准至 31.25K-1280
  7. 倍频->40M */
  8. //#define TRIM_IRC
  9. #define ICS_TRIM_VALUE 0x50 //由是否定义 TRIM_IRC 决定, 此值粗略为 40M
  10. #define SPI0_PINREMAP //SPI0 的 SCK、 MOSI、 MISO 和 PCS 映射到 PE0、 PE1、 PE2 和 PE3 上
  11. #define ENABLE_WDOG //禁用看门狗,但允许其更新配置
  12. /*! 禁用 NMI 中断输入引脚-PB4,该引脚建议布板外接 4.7K-10K 的上拉,以及上电时该引脚不可为低(若不
  13. 使用 NMI 功能) */
  14. #define DISABLE_NMI
  15. /*! 定义是否打印系统相关信息 */
  16. #define PRINT_SYS_LOG
  17. /*! 定义是否输出系统时钟,输出引脚为 PH2 */
  18. //#define OUTPUT_BUSCLK




 楼主| hanzhen654 发表于 2020-2-23 20:09 | 显示全部楼层
根据所选的时钟模式,及时钟分频系数确定最终的总线时钟 BUSCLK 和系统/内核时钟 ICSOUT
内部时钟 FEI 模式:内核/系统时钟=IRC*1280/BDIV :总线时钟=IRC*1280/BDIV/BUSDIV外部时钟 FEE 模式:内核/系统时钟=晶振/RDIV*1280/BDIV :总线时钟=晶振/RDIV*1280/BDIV/BUSDIV
其他时钟模式频率的计算请参考:库函数说明及参考手册 ICS 部分  


  1. /*! 定义时钟的时钟模式以及频率 */
  2. //#define USE_FEE //使用外部时钟 FEE 模式, 频率参考晶体振荡器
  3. //#define USE_FEE_OSC //使用外部时钟输入 OSC 模式, 频率参考 EXTAL-PB7
  4. #define USE_FEI //使用系统内部时钟 40M 作为主频
  5. //#define USE_FBELP //外部旁路低功耗模式, 禁用倍频环 FLL, 频率直接由晶振提供
  6. //#define USE_FBE_OSC
  7. /*! 定义 BDIV 分频系数 (BDIV) */
  8. /*
  9. * BDIV_ENCODE: 0 1 2 3 4 5 6 7
  10. *
  11. * BDIV--分频系数: 1 2 4 8 16 32 64 128
  12. */
  13. #define BDIV_ENCODE 0 //BDIV 分频系数为 1
  14. /*! 定义 BUSDIV 分频系数(BUSDIV) */
  15. /*
  16. * BUSDIV_ENCODE 0 1
  17. *
  18. * BUSCLK=ICSOUT/x 1 2
  19. */
  20. //此处建议不要修改,即系统/内核时钟=总线时钟
  21. #define BUSDIV_ENCODE 0 //总线时钟=ICSOUT/1
  22. /*! 若使用外部晶振,则需要定义外部晶振频率, 如下使用板载 10M 晶振*/
  23. //#define EXT_CLK_FREQ_KHZ 32 /* in KHz */
  24. //#define EXT_CLK_FREQ_KHZ 4000 /* in KHz */
  25. //#define EXT_CLK_FREQ_KHZ 8000 /* in KHz */
  26. #define EXT_CLK_FREQ_KHZ 10000 /* in KHz */
  27. //#define EXT_CLK_FREQ_KHZ 16000 /* in KHz */
  28. //#define EXT_CLK_FREQ_KHZ 20000 /* in KHz */


 楼主| hanzhen654 发表于 2020-2-23 20:14 | 显示全部楼层
  1. 例:使用 FEI 模式
  2. 内核时钟/系统时钟 = ICSOUT=31.25K*1280/1=40M,
  3. 总线时钟 = BUSCLK = ICSOUT/1 = 40M
  4. /* 定义总线时钟主频 */
  5. //一、前提:若定义使用 FEI 内部时钟
  6. #if defined(USE_FEI)
  7. #define BUS_CLK_HZ 40000000L //#define BDIV_ENCODE 0 //BDIV 分频系数为 1
  8. //#define BUS_CLK_HZ 20000000L //#define BDIV_ENCODE 1 //BDIV 分频系数为 2
  9. //#define BUS_CLK_HZ 10000000L //#define BDIV_ENCODE 2 //BDIV 分频系数为 4
  10. //二、前提:若定义使用外部时钟的模式,以下情况为使用通用 FEE 模式,关于其他模式的使用参见手册及
  11. 库函数说明
  12. #elif (EXT_CLK_FREQ_KHZ == 10000)
  13. #define BUS_CLK_HZ 25000000L //#define BDIV_ENCODE 1 //BDIV 分频系数为 2
  14. //NV32F100x 的主频需在 40M 以内
  15. #elif (EXT_CLK_FREQ_KHZ == 16000)
  16. #define BUS_CLK_HZ 25000000L //#define BDIV_ENCODE 1 //BDIV 分频系数为 2
  17. //NV32F100x 的主频需在 40M 以内
  18. #elif (EXT_CLK_FREQ_KHZ == 8000)


 楼主| hanzhen654 发表于 2020-2-23 20:14 | 显示全部楼层
  1. /*! 定义所使用 UART 口的波特率 */
  2. #define UART_PRINT_BITRATE 115200 //UART 波特率
  3. /*! 定义所使用的 UART 口,开发板上默认使用 UART1 口 */
  4. #define TERM_PORT UART1
  5. /*! 板载 LED */
  6. #define LED0_Init() GPIOB->PDDR |= (1<<25) //初始化
  7. #define LED0_Toggle() GPIOB->PTOR = (1<<25) //翻转
  8. #define LED0_On() GPIOB->PCOR = (1<<25) //置位
  9. #define LED0_Off() GPIOB->PSOR = (1<<25) //清零
  10. #define LED1_Init() GPIOB->PDDR |= (1<<26)
  11. #define LED1_Toggle() GPIOB->PTOR = (1<<26)
  12. #define LED1_On() GPIOB->PCOR = (1<<26)
  13. #define LED1_Off() GPIOB->PSOR = (1<<26)
  14. #define LED2_Init() GPIOB->PDDR |= (1<<7)
  15. #define LED2_Toggle() GPIOB->PTOR = (1<<7)
  16. #define LED2_On() GPIOB->PCOR = (1<<7)
  17. #define LED2_Off() GPIOB->PSOR = (1<<7)
  18. #endif /* NVxx_CONFIG_H_ */


 楼主| hanzhen654 发表于 2020-2-23 20:15 | 显示全部楼层
初始化过程中的管脚复用
以 PA5 脚为例,讲解一下在系统初始化过程中的管脚复用问题首先通过看 NV32 的管脚分配图
720425e526cef3f41c.png
我们可以直观的看出,此管脚上默认优先级最高的就是复位功能,类于这种系统级的功能用来管脚复用的
情况还有很多种,比如 NMI, SWD 功能所在引脚的管脚复用,都需要在系统初始化函数 Sysinit 中进行配
置。
1.在 Sysinit.c 中的 sysinit 函数中初始化 SIM 模块的结构体: SIM_ConfigType sSIMConfig = {{0},0};
2.利用模块化编程的思想,若宏定义 DISABLE_RST 这个参数,则禁用 RESET 脚,即给对应的结构体变量
赋值,对应的引脚参数参看 SIM 章节的 SIM_SOPT 系统选项寄存器的详细信息。
#if defined(DISABLE_RST)
sSIMConfig.sBits.bDisableRESET = 1;//禁用 RESET 脚
#endif
再比如,要禁用 NMI 引脚功能,作为普通 IO 口,和禁用 RESET 管脚同样的方法,进行 DISABLE_NMI
宏定义即可,即在文件开头#define DISABLE_NMI
#if defined(DISABLE_NMI)
sSIMConfig.sBits.bDisableNMI = 1;//禁用不可屏蔽中断的管脚 PB4
#endif
3.进行其他相关的配置以后,通过结构体传参进行 SIM 模块的初始化: SIM_Init(&sSIMConfig);具体的 SIM
模块的功能和函数见 NV32F100x 参考手册和 SIM 模块的相关说明
 楼主| hanzhen654 发表于 2020-2-23 20:16 | 显示全部楼层
使用 FEE 外部晶振作为系统时钟
.在 NV32Config.h 文件中定义 #define USE_FEE(此时#define USE_FEI 应当被注释掉)
2.定义外部晶振的频率,单位为 KHZ,如开发板上的晶振为 10M,即为 10000KHZ,则同样在 NV32Config.h
定义为 #define EXT_CLK_FREQ_KHZ 10000
3.计算出所要得到的总线时钟,即先分频,而后倍频(1280 倍),外部时钟分频在 ICS.c 中查找到 void
ICS_SetClkDivider(uint32_t u32ClkFreqKHz);这个函数,根据对应所选的晶振,来配置相应的分频关系
case 10000L:
/* 开发上为 10MHz 的晶振 */
ICS->C1 = (ICS->C1 & ~(ICS_C1_RDIV_MASK)) | ICS_C1_RDIV(3);
break;
 楼主| hanzhen654 发表于 2020-2-23 20:16 | 显示全部楼层
参考如下表格进行分频
778825e526d3673f54.png
 楼主| hanzhen654 发表于 2020-2-23 20:17 | 显示全部楼层
在 syinit 函数中我们定义了,超过 4MHZ,则将 OSC_CR[RANGE]置位,目的就是为了能将分频后的频率限制
在红色字体以内
#if (EXT_CLK_FREQ_KHZ >=4000)
sICSConfig.oscConfig.bRange = 1; /* 高范围模式 */
#endif
所以超过 4MHZ 的话,选择右边的分频位,例程中的为外接 10MHZ 晶振
*首先分频位选择 3,即 512 分频,ICS->C1 = (ICS->C1 & ~(ICS_C1_RDIV_MASK)) | ICS_C1_RDIV(3)
再倍频 1280,BDIV_ENCODE 设置为 1 即配置 BDIV 为 2
得到内核/系统时钟为:BUS_CLOCK=10000000/512*1280/2=25MHZ (NV32F100x 的内核/系统时钟不得超过 40M)
得到总线频率为 25MHZ,在 NV32Config.h 中定义
#elif (EXT_CLK_FREQ_KHZ == 10000)
#define BUS_CLK_HZ 25000000L
 楼主| hanzhen654 发表于 2020-2-23 20:26 | 显示全部楼层
使用 FEI 内部时钟作为系统时钟
1 在 NV32Config.h 文件中定义 #define USE_FEI(此时#define USE_FEE 应当被注释掉)
2.在芯片量产的时候,内部振荡器 IRC 校准至 31.25K。 1280 倍频后达到 40MHZ(此处作修改, NV32F100x 的
系统时钟不得超过 40M)
例程包中 BDIV_ENCODE 设置为 0 即配置 BDIV 为分频系数 1, 系统时钟为 40MHz
例程包中 BDIV_ENCODE 设置为 1 即配置 BDIV 为分频系数 2, 系统时钟为 20MHz
选择内部时钟源分频,在 ICS.c 中找到函数 void ICS_Init(ICS_ConfigType *pConfig);
 楼主| hanzhen654 发表于 2020-2-23 20:26 | 显示全部楼层
ICS_C2 寄存器的 BDIV 位
882515e526f86982f3.png
 楼主| hanzhen654 发表于 2020-2-23 20:27 | 显示全部楼层
关于看门狗的启用与禁用
Start.c 文件中的 void SystemInit( void );函数定义了看门狗的使能和禁用 ,当宏定义 #define
ENABLE_WDOG 时看门狗关闭, 但允许其更新; 否则看门狗关闭, 并后续配置无效。
598330983 发表于 2020-3-4 21:26 | 显示全部楼层
习惯了一种风格后,就淡定了。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

73

主题

1766

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部