新唐51单片机 boot 代码

为了方便代码的升级,常常会在代码里面增加自动升级代码的部分单片机的内部的 FLASH 。将 FLASH 分成 LDROM 和 APPROM。

LDROM

LDROM是加载引导

APPROM

 APROM是应用程序

解决方案

在开机的时候我们检测是否要升级程序,如果不用升级就直接跳转到 APPROM 里面,在新唐的单片机里面是通过软件复位跳转到APPROM在 arm 的架构里面在不同的 Flash 上面是通过跳转指令直接跳转到应用程序


code

/*---------------------------------------------------------------------------------------------------------*/
/*                                                                                                         */
/* Copyright(c) 2018 Nuvoton Technology Corp. All rights reserved.                                         */
/*                                                                                                         */
/*---------------------------------------------------------------------------------------------------------*/


//***********************************************************************************************************
//  File Function: ML51 UART0 ISP demo code
//***********************************************************************************************************
#include "ML51.H"
/************************************************************************************************************
*    Main function 
************************************************************************************************************/

#pragma save
#pragma optimize (8)
void IAP_goSet(void)
{
    TA=0xAA;
    TA=0x55;
    IAPTRG|=SET_BIT0;
}

void IAP_Enable(void)
{
    TA=0xAA;
    TA=0x55;
    CHPCON|=SET_BIT0;
}    

void IAP_uEnable(void)
{
    TA=0xAA;
    TA=0x55;
    IAPUEN|=SET_BIT0;
}

void IAP_clrCHPCON(void)
{
    TA=0xAA;
    TA=0x55;
    CHPCON&=CLR_BIT6;
}

void ISP_Reboot2Approm(void)
{
    TA=0xAA;
    TA=0x55;
  CHPCON = 0x00;                  
    TA=0xAA;
    TA=0x55;
  CHPCON = 0x80;    //set boot from AP
}
#pragma restore



#undef set_IAPTRG_IAPGO
#define set_IAPTRG_IAPGO      IAP_goSet()           

#undef set_CHPCON_IAPEN
#define set_CHPCON_IAPEN      IAP_Enable()    

#undef set_IAPUEN_APUEN
#define set_IAPUEN_APUEN      IAP_uEnable()    

#undef clr_CHPCON_IAPFF
#define clr_CHPCON_IAPFF      IAP_clrCHPCON()    

void main (void)
{

  //uart initial for ISP programmer GUI, always use 115200 baudrate
  SFRS=0x01;P1UP|=SET_BIT5;
   
  UART0_ini_115200();
  TM0_ini();

  g_timer0Over=0;
  g_timer0Counter=5000;
  g_progarmflag=0;
  
  if (P1 & (1<<5))
    goto _APROM;
 
while(1)
{
        if(bUartDataReady == TRUE)
        {
          EA=0; //DISABLE ALL INTERRUPT                  
          if(g_progarmflag==1)
          {
            for(count=8;count<64;count++)
            {
              IAPCN = BYTE_PROGRAM_AP;          //program byte
              IAPAL = flash_address&0xff;
              IAPAH = (flash_address>>8)&0xff;
              IAPFD=uart_rcvbuf[count];
              set_IAPTRG_IAPGO;
          
              IAPCN = BYTE_READ_AP;              //program byte verify
              set_IAPTRG_IAPGO;
              if(IAPFD!=uart_rcvbuf[count])
              while(1);                          
              if (CHPCON==0x43)              //if error flag set, program error stop ISP
              while(1);
              
              g_totalchecksum=g_totalchecksum+uart_rcvbuf[count];
              flash_address++;
  
              if(flash_address==AP_size)
              {
                g_progarmflag=0;
                 goto END_2;          
              }
            } 
END_2:                
            Package_checksum();
            uart_txbuf[8]=g_totalchecksum&0xff;
            uart_txbuf[9]=(g_totalchecksum>>8)&0xff;
            Send_64byte_To_UART0();
                        
            if (g_progarmflag == 0)
            {
                goto _APROM;
            }
        }
                        
          switch(uart_rcvbuf[0])
          {                
            case CMD_CONNECT:
            case CMD_SYNC_PACKNO:
            {
              Package_checksum();
              Send_64byte_To_UART0();    
              g_timer0Counter=0; //clear timer 0 for no reset
              g_timer0Over=0;
            break;
            }
                        
            case CMD_RUN_APROM:            
            {
              goto _APROM;
            break;
            }

            case CMD_UPDATE_APROM:            
            {
              set_CHPCON_IAPEN;
              set_IAPUEN_APUEN;
              IAPFD = 0xFF;          //Erase must set IAPFD = 0xFF
              IAPCN = PAGE_ERASE_AP;
              AP_size=0;
              AP_size=uart_rcvbuf[12];
              AP_size|=(uart_rcvbuf[13]<<8);  
              for(flash_address=0x0000;flash_address>8)&0xff;
                IAPFD=uart_rcvbuf[count];

                clr_CHPCON_IAPFF;
                set_IAPTRG_IAPGO;                              
      
                IAPCN = BYTE_READ_AP;                //program byte verify
                set_IAPTRG_IAPGO;                          
                if(IAPFD!=uart_rcvbuf[count])
                while(1);          
                if (CHPCON==0x43)                //if error flag set, program error stop ISP
                while(1);
                
                g_totalchecksum=g_totalchecksum+uart_rcvbuf[count];
                flash_address++;
                
                if(flash_address==AP_size)
                {
                  g_progarmflag=0;
                   goto END_1;          
                }
              }
END_1:                
              Package_checksum();
              uart_txbuf[8]=g_totalchecksum&0xff;
              uart_txbuf[9]=(g_totalchecksum>>8)&0xff;
              Send_64byte_To_UART0();  
              break;
            }
          }  
          bUartDataReady = FALSE;
          bufhead = 0;            
          EA=1;
      }
      //For connect timer out  
      if(g_timer0Over==1)
      {       
       goto _APROM;
      }
            
      //for uart time out or buffer error
       if(g_timer1Over==1)
      {       
       if((bufhead<64)&&(bufhead>0)||(bufhead>64))
       {
         bufhead=0;         
       }
      }  

}   

_APROM:
    ISP_Reboot2Approm();
    while(1);  
}




对部分代码的说明

#pragma save
#pragma optimize (8)
/*.
.  中间的代码的优化等级设计为8,其他代码的优化等级在后面会进行恢复
.*/
#pragma restore

遇到问题的总结

  • 1.单片机设置成上拉模式需要时间,如果初始化完成就去检测会检测不到
  SFRS=0x01;
  P1UP|=SET_BIT5;
   
  UART0_ini_115200();
  TM0_ini();

  g_timer0Over=0;
  g_timer0Counter=5000;
  g_progarmflag=0;
  
  if (P1 & (1<<5))
    goto _APROM;

上面代码的功能是开机的时候进行检测按键是否已经按下,如果没有按下直接进行软件复位 ,这里面的判断加载初始话后面的主要原因是为了等待内部上拉,如果直接加在

  SFRS=0x01;
  P1UP|=SET_BIT5;

后面就会出现错误

  • 2 编译器的优化等级太高的时候对于连续的赋值会出现被优化的情况,这样连续的赋值在大多数情况下是可以被优化的,但是当这些和硬件的'时序有关的时候,硬件之间的通信就会出现不正常的现象。
#pragma optimize (8)
void IAP_goSet(void)
{
    TA=0xAA;
    TA=0x55;
    IAPTRG|=SET_BIT0;
}
...

和时序有关的代码可以适当的降低优先级

里面的代码是根据新唐的支持包进行修改的,为了节省空间,将里面的部分的功能删除,最后将代码的空间缩小到 1K 以内

你可能感兴趣的:(c)