ARM固件开发(LPC1768启动初始化代码)

 一、复位

ARM启动中需要配置上电复位功能,因为这样才能确保上电之后程序处于初始状态而并非程序指针未知。通常启动代码编译器自带,而程序入口基本上都是以复位中断开始。

下面这一段启动代码会自动调用两个函数,分别是

SystemInit   系统上电初始化,主要进行时钟、锁相环等核心部分的配置

main            系统上电初始化之后,调用main函数,用户无需返回main函数

; Reset Handler

Reset_Handler   PROC
                EXPORT  Reset_Handler             [WEAK]
                IMPORT  SystemInit
                IMPORT  __main
                LDR     R0, =SystemInit
                BLX     R0
                LDR     R0, =__main
                BX      R0
                ENDP

二、SystemInit系统上电初始化

SystemInit仅仅是一个函数名称,所以在不同的环境下可能名字不同。

//LPC175X-6X
#if 1
void SystemInit(void){
    
      //Flash Accelerator Configuration register
    LPC_SC->FLASHCFG = ((0x05ul << 12) & (~(0x003f))) | 0x003a;     
    //Set system timers for each component  
#if (FPCLK / (FCCLK / 4)) == 1
    LPC_SC->PCLKSEL0 = 0x00000000;           /*  PCLK is 1/4 CCLK            */
    LPC_SC->PCLKSEL1 = 0x00000000;
#endif                                       /*  (FPCLK / (FCCLK / 4))       */
#if (FPCLK / (FCCLK / 4)) == 2
    LPC_SC->PCLKSEL0 = 0xAAAAAAAA;           /*  PCLK is 1/2 CCLK            */
    LPC_SC->PCLKSEL1 = 0xAAAAAAAA;   
#endif                                       /*  (FPCLK / (FCCLK / 4))       */
#if (FPCLK / (FCCLK / 4)) == 4
    LPC_SC->PCLKSEL0 = 0x55555555;           /*  PCLK is the same as CCLK    */
    LPC_SC->PCLKSEL1 = 0x55555555;      
#endif                                       /*  (FPCLK / (FCCLK / 4))       */
    //Selects the CPU clock as the CLKOUT source
      LPC_SC->CLKOUTCFG = 0;  
                                            
    /*     Close PLL           */
    if ((LPC_SC->PLL0STAT >> 24) == 1) {
        LPC_SC->PLL0CON = 1;                 //  Enable PLL, disconnected    
        LPC_SC->PLL0FEED = 0xAA;
        LPC_SC->PLL0FEED = 0x55;
    }
    LPC_SC->PLL0CON = 0;                     //  Disable PLL, disconnected   
    LPC_SC->PLL0FEED = 0xAA;
    LPC_SC->PLL0FEED = 0x55;
    while(LPC_SC->PLL0STAT & (3 << 24));                                               
    /*     PLL clock      */
      //Enable mainOSC,1MHz~20MHz 
    LPC_SC->SCS = (LPC_SC->SCS) | 0x20;
    //wait for The main oscillator is ready
    while ((LPC_SC->SCS & (1ul << 6)) == 0) ;
    LPC_SC->CLKSRCSEL = 0x01;//select main OSC as the PLL clock source 
    LPC_SC->PLL0CFG   = (((PLL_NVALUE - 1) << 16) | (PLL_MVALUE - 1));    
    LPC_SC->PLL0FEED  = 0xAA;  /*  Enable but disconnect PLL   */
    LPC_SC->PLL0FEED  = 0x55; 
    LPC_SC->PLL0CON   = 1;//PLL0 Enable
    LPC_SC->PLL0FEED  = 0xAA;  //  Enable but disconnect PLL 
    LPC_SC->PLL0FEED  = 0x55;  
    while ((LPC_SC->PLL0STAT & (1ul << 26)) == 0);
    
    //CPU Clock Configuration register
    LPC_SC->CCLKCFG = (FCCO / FCCLK) - 1;   
    
    while (((LPC_SC->PLL0STAT & (1ul << 26)) == 0)); /*  Check lock bit status       */
    while (((LPC_SC->PLL0STAT & 0x00007FFF) != (PLL_MVALUE - 1)) && 
           (((LPC_SC->PLL0STAT & 0x00FF0000) >> 16) != (PLL_NVALUE - 1)));
    
    LPC_SC->PLL0CON  = 3;         /*  connect the PLL             */
    LPC_SC->PLL0FEED = 0xAA;
    LPC_SC->PLL0FEED = 0x55;       
      //Wait until the PLL is connected                           
    while ((LPC_SC->PLL0STAT & (1ul << 25)) == 0);
                                                                      
    /*     USB clock      */    
#if FUSBCLK_EN
#if (FCCO % (FUSBCLK * 2)) == 0
    LPC_SC->PLL1CON   = 0;
    LPC_SC->PLL1FEED  = 0xaa;
    LPC_SC->PLL1FEED  = 0x55;        
    LPC_SC->USBCLKCFG = (FCCO / (FUSBCLK)) - 1; 
#else
    LPC_SC->PLL1CON  = 1;
    LPC_SC->PLL1CFG  =  ((FUSBCLK / FOSC) - 1) | (1 << 5);
    LPC_SC->PLL1FEED = 0xaa;
    LPC_SC->PLL1FEED = 0x55;
    while ((LPC_SC->PLL1STAT & (1 << 10)) == 0) { }
    LPC_SC->PLL1CON  = 3;
    LPC_SC->PLL1FEED = 0xaa;
    LPC_SC->PLL1FEED = 0x55;
#endif
#endif
                                          
    /*     flash accesses    */ 
      //Flash accesses use 1 CPU clock. Use for up to 20 MHz CPU clock.
#if FCCLK <= 20000000 
    LPC_SC->FLASHCFG = ((0x01ul << 12) & (~(0x003f))) | 0x003a;                 
#endif                                                                 
      //Flash accesses use 2 CPU clocks. Use for up to 40 MHz CPU clock.
#if FCCLK > 20000000 && FCCLK <= 40000000
    LPC_SC->FLASHCFG = ((0x02ul << 12) & (~(0x003f))) | 0x003a;                 
#endif                                                                  
      //Flash accesses use 3 CPU clocks. Use for up to 60 MHz CPU clock.
#if FCCLK > 40000000 && FCCLK <= 60000000
    LPC_SC->FLASHCFG = ((0x03ul << 12) & (~(0x003f))) | 0x003a;                
#endif                                                                 
      //Flash accesses use 4 CPU clocks.  Use for up to 80 MHz CPU clock.
#if FCCLK > 60000000 && FCCLK <= 80000000
    LPC_SC->FLASHCFG = ((0x04ul << 12) & (~(0x003f))) | 0x003a;               
#endif                                                                 
    //Flash accesses use 5 CPU clocks.  Use for up to 100 MHz CPU clock
#if FCCLK > 80000000 && FCCLK <= 100000000
    LPC_SC->FLASHCFG = ((0x05ul << 12) & (~(0x003f))) | 0x003a;               
#endif  

    IO_init();
    NVIC_ICER0  = 0xffffffff;
    NVIC_ICER1 |= 0x00000007;
    Interrupt_Enable();
}
#endif

三、main用户函数

main函数根据用户编程,一般执行步骤是初始化各个模块资源,然后进入后台循环任务。

//最简化的main函数,没有任何任务
int main(void)
{
  while(1)
  {

  }
}
/*
*********************************************************************************************** * * Description: * * Arguments : * Returns : ************************************************************************************************/ int main(void) { ErrType err; INT8U receive_buf[128],para_buf[128]; u_BusPacket pkt; TKIT_MSG Msg; //TKIT init #ifdef __APP_CODE__ SystemVectorRemap(0x00030000); TKIT_Init( TKITMODE_APP ); #else //BOOT code SystemVectorRemap(0x00000000); TKIT_Init( TKITMODE_BOOT ); #endif //__APP_CODE__ //检查文件系统以及升级文件 #if TKIT_FATFS_EN && KIT_SDCARD_EN while( SD_Exist ) { //建立系统文件夹 err = t_FatSysCheck(FAT_ROOT); if( TKIT_SUCCESS==err )err = t_fat_PathCheck(FAT_ROOT_PATH, TRUE); if( TKIT_SUCCESS==err )err = t_fat_PathCheck(FAT_PATH_DEVICE, TRUE); if( TKIT_SUCCESS==err )err = t_fat_PathCheck(FAT_PATH_SYS, TRUE); //检测升级文件 if( TRUE==b_FileFirmwareCheck(FAT_PATH_SYS,"AM-AM",FALSE,FALSE) ) { Printf("\t<FirmwareCheck>Find available app code in disk[%s]\r\n",FAT_PATH_SYS); #ifndef __APP_CODE__ b_FileFirmwareCheck(FAT_PATH_SYS,"AM-AM10",TRUE,TRUE); #endif } else { Printf("\t<FirmwareCheck>Can't find available app code in disk[%s]\r\n",FAT_PATH_SYS); } break; } #endif //TKIT_FATFS_EN //Bootloader检测是否需要跳转 #ifndef __APP_CODE__ Printf("\t<main>Bootloader check app code and jump...\r\n"); pkt.Alt.Port = BUS_PORT_ALL; TKIT_ErrUpdate( t_TKIT_AppCheck( TKIT_DLY_3S, &pkt ) ); #endif //__APP_CODE__ //启动所有前台任务 Printf("\t<main>TKIT task init and start.\r\n"); TKIT_TaskStart(); Task_Init(); //创建一个任务,每隔1S执行一次 TKIT_TaskCreateTimer("Task isr",Task_Isr, NULL, TKIT_DLY_1S ); //创建一个消息,系统每隔1S自动触发 Msg = TKIT_MsgCreate( NULL,TKIT_DLY_1S); while( 1 ) { Task(); //LED if( TKIT_MsgPend(Msg,NULL,0) ) { TKIT_IO_SetBurstCnt(IO_LED_CORE,1);//Pend message success } //If terminal enable if( Terminal_EnableCheck() ) { if( ReadsExt(receive_buf,para_buf) ) { Terminal_Handler(receive_buf,para_buf); } } //选择通信接口 //接收一个帧 pkt.Alt.Port = BUS_PORT_USB | BUS_PORT_AT | BUS_PORT_TCP; if( FALSE==Terminal_EnableCheck() ) { pkt.Alt.Port |= BUS_PORT_UART; } if( i_ProBus_ReadPkt(&pkt,TKIT_DLY_10MS) ) { //Printf("\t<main>Received command:%04X, Data len=%d\r\n",pkt.Alt.Cmd.u16,pkt.Alt.DataSize.u32 ); t_ProBus_CmdHandler( &pkt ); //Printf("\t<main>Received command handler finished. Return len:%d\r\n\r\n",pkt.Alt.DataSize.u32 ); TKIT_IO_SetBurstCnt(IO_LED_CORE,1); } else if( BUS_PORT_UART&pkt.Alt.Port && i_ProBus_ReadPktBuffer() ) { if( 0==std_StringCmpExtLen("admin%ADMIN",(char*)pkt.byte,5 ) ) { Terminal_Enable(TRUE); PrintWelcome(); } } #if DHCP_EN do_dhcp(); //DHCP测试程序 #endif ////////END FOR ///////////////// }//end while }

四、启动流程串口演示

(演示了代码启动,然后用户程序执行了手动跳转)

猜你喜欢

转载自www.cnblogs.com/lewismotion/p/11811610.html