使用TLE984X系列MCU进行产品开发,开发过程中参考官方例程配置SCU-CGU函数。 CGU全称为Clock Generation Unit(时钟产生单元),使用官方工具箱配置时钟,模式为内部振荡器PLL,产生25MHz时钟信号。 配置完成后,生成工程文件,可找遍了整个工程文件,也没有看到SCU初始化单元是怎么被执行的。 下面是部分代码:
复制int main(void) { /* Initialization of hardware modules based on Config Wizard configuration */ TLE_Init();//函数初始化,包含SCU初始化函数 /***************************************************************************** ** Place your application code here ** *****************************************************************************/ /***************************************************************************** ** Main endless loop ** *****************************************************************************/ for (;;) { /* Main watchdog1 (WDT1) service */ // (void)WDT1_Service(); /*************************************************************************** ** Place your application code here ** ***************************************************************************/ } 复制void TLE_Init(void) { //#ifdef RTE_DEVICE_SDK_SCU SCU_Init();//SCU初始化函数 //#endif //#ifdef RTE_DEVICE_SDK_PMU PMU_Init(); //#endif //#ifdef RTE_DEVICE_SDK_ADC1 // ADC1_Init(); //#endif //#ifdef RTE_DEVICE_SDK_ADC2 // ADC2_Init(); //#endif //#ifdef RTE_DEVICE_SDK_CCU6 // CCU6_Init(); //#endif //#ifdef RTE_DEVICE_SDK_GPT12E // GPT12E_Init(); //#endif //#ifdef RTE_DEVICE_SDK_TRX TRX_Init(); //#endif //#ifdef RTE_DEVICE_SDK_HS // HS1_Init(); //#if (UC_FEAT_HS > 1u) // HS2_Init(); //#endif //#endif //#ifdef RTE_DEVICE_SDK_LS // LS1_Init(); // LS2_Init(); //#endif //#ifdef RTE_DEVICE_SDK_MON // MONx_Init(); //#endif //#ifdef RTE_DEVICE_SDK_PORT PORT_Init(); //#endif //#ifdef RTE_DEVICE_SDK_SSC // SSC1_Init(); // SSC2_Init(); //#endif //#ifdef RTE_DEVICE_SDK_TIMER2X TIMER2_Init(); TIMER21_Init(); //#endif //#ifdef RTE_DEVICE_SDK_UART // UART1_Init(); // UART2_Init(); //#endif //#ifdef RTE_DEVICE_SDK_INT // INT_Init(); //#endif } 复制void SCU_Init(void) { /*************************************************************************** ** System Clock Output Control ** ***************************************************************************/ SCU->COCON.reg = (uint32) (SCU_COCON); /*************************************************************************** ** Module Pin Select ** **************************************************************************/ #ifdef SCU_MODPISEL SCU->MODPISEL.reg = (uint32) SCU_MODPISEL; #endif #ifdef SCU_MODPISEL1 SCU->MODPISEL1.reg = (uint8) SCU_MODPISEL1; #endif #ifdef SCU_MODPISEL2 SCU->MODPISEL2.reg = (uint8) SCU_MODPISEL2; #endif #ifdef SCU_MODPISEL3 SCU->MODPISEL3.reg = (uint8) SCU_MODPISEL3; #endif SCU->GPT12PISEL.reg = (uint8) SCU_GPT12PISEL; }第三段代码中,只是配置了fsys的分频及选择外部中断口,没有任何关于时钟源的选择及时钟配置相关的代码。 百思不得其解(对启动文件未曾了解),使用keil工具进行Debug,将断点打在PC初始位置,PC:0x00000000,按下F10单步调试,指针会在当前汇编代码中逐步执行,且PC会跳转至SystemInit函数中执行。
PC初始化
SCU配置初始化函数
复制void SCU_ClkInit(void) { sint32 int_was_mask; /* disable all interrupts */ int_was_mask = CMSIS_Irq_Dis(); /*************************************************************************** ** NVM Protection Control ** **************************************************************************/ #if (SCU_NVM_BOOT_PROT == 1u) (void)user_nvm_protect_set((uint32) SCU_NVM_PROT_PW, NVM_PASSWORD_SEGMENT_BOOT); #endif #if (SCU_NVM_CODE_PROT == 1u) (void)user_nvm_protect_set((uint32) SCU_NVM_PROT_PW, NVM_PASSWORD_SEGMENT_CODE); #endif #if (SCU_NVM_DATA_PROT == 1u) (void)user_nvm_protect_set((uint32) SCU_NVM_PROT_PW, NVM_PASSWORD_SEGMENT_DATA); #endif /*************************************************************************** ** PLL/SYSCLK Control ** **************************************************************************/ SCU->NMICON.bit.NMIPLL = 0u; /* enable XTAL1/2 pins */ SCU_OpenPASSWD(); SCU->MODPISEL1.reg = (uint32)(SCU_MODPISEL1 & SCU_MODPISEL1_XTAL12EN_Msk); SCU->PASSWD.reg = PASSWD_Close; /* select LP_CLK */ SCU_OpenPASSWD(); SCU->SYSCON0.bit.SYSCLKSEL = 2u; SCU_ClosePASSWD(); /* Oscillator Select */ SCU_OpenPASSWD(); SCU->OSC_CON.reg = (uint32)SCU_OSC_CON;// SCU_ClosePASSWD(); SCU_OpenPASSWD(); SCU->PLL_CON.reg = (uint32) SCU_PLL_CON; SCU_ClosePASSWD(); SCU_OpenPASSWD(); SCU->CMCON1.reg = (uint32) SCU_CMCON1; SCU_ClosePASSWD(); SCU->PLL_CON.bit.RESLD = 1u; /* set PLL_CON.bit.VCOBYP=0 */ SCU->PLL_CON.reg=(SCU->PLL_CON.reg&~SCU_PLL_CON_VCOBYP_Msk)|SCU_PLL_CON_UNPROT_VCOBYP_Msk; /* set PLL_CON.bit.OSCDISC=0 */ SCU->PLL_CON.reg=(SCU->PLL_CON.reg&~SCU_PLL_CON_OSCDISC_Msk)|SCU_PLL_CON_UNPROT_OSCDISC_Msk; while (u1_Field_Rd32(&SCU->PLL_CON.reg, (uint8)SCU_PLL_CON_LOCK_Pos, SCU_PLL_CON_LOCK_Msk) == (uint8)0) { } SCU_OpenPASSWD(); /* 0u << 6u */ SCU->SYSCON0.reg = 0u;//PLL OUT signal SCU_ClosePASSWD(); SCU->NMISRCLR.bit.FNMIPLLC = 1u; /*************************************************************************** ** Analog Clock Control ** ***************************************************************************/ /* set factor for MI_CLK and Filt_CLK*/ SCU->APCLK.reg = (uint32) SCU_APCLK; /* apply setting by toggling APCLK_SET */ SCU_OpenPASSWD(); SCU->APCLK_CTRL.bit.APCLK_SET = 1u; SCU_ClosePASSWD(); CMSIS_NOP(); SCU_OpenPASSWD(); SCU->APCLK_CTRL.bit.APCLK_SET = 0u; SCU_ClosePASSWD(); /* enable interrupts */ if (int_was_mask == 0) { CMSIS_Irq_En(); } } 复制Reset_Handler PROC EXPORT Reset_Handler [WEAK] IMPORT SystemInit IMPORT __main LDR R0, =SystemInit BLX R0 LDR R0, =__main BX R0 ENDP于是,进一步分析,并且对启动文件中部分代码做了一番分析。 程序在执行main函数之前,会先执行启动文件,启动文件中可以处理函数,并使用LDR,将该函数的地址放入R0通用寄存器,再使用BLX指令跳转执行。 执行后再使用LDR进入main函数,程序便进入主函数开始执行。
启动文件部分代码
Debug过程中,遇到一个问题,LDR指令存入R0寄存器的地址,与函数名的地址不符合。 比如systemInit函数在R0寄存器中存入的地址为0x110004D5,但通过watch窗口看到的地址是0x110004D4,小编试过其他函数,均是一样的情况,R0存入的地址比实际的地址+1。
Debug地址不同
免责声明:文章内容来自互联网,本站不对其真实性负责,也不承担任何法律责任,如有侵权等情况,请与本站联系删除。
转载请注明出处:使用TLE984X系列MCU进行产品开发 https://www.yhzz.com.cn/a/4320.html