⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bootload.c

📁 牛人张明峰写的bootloader。很有参考价值。和很多freescale的例子不太一样
💻 C
📖 第 1 页 / 共 2 页
字号:
   //State-machine for S19 line data processing
   switch (s19RecState) {     //switch to each possible state
      
      //State-0: wait for 1st leading 'S'
      case 0:
         if (dat!='S') return;
         else
            s19RecState = 1;  //'S' detected, check for next byte
         break;
      
      //State-1: check for 2nd data right afte leading 'S'
      case 1:
         //check to the data content
         switch (dat) {
            case '0':            //0 = begin of S19 file
               s19RecState = 3;  //switch to state-3 and wait for its completion
               break;
            case '3':            //3 = valid S19 code line
               s19RecCount = 0;  //reset counter
               s19RecState = 2;  //switch to state-2 for getting rest of data
               break;
            case '7':            //end of S19 file
               reBootFlag  = 1;  //re-boot enabled
               s19RecState = 3;  //switch to state-3 and wait for its completion
               break;
            default:             //invalid line
               s19RecState = 3;  //switch to state-3 and wait for its completion
               break;
         }
         break;
   
      //State-2: save for the rest of data in one S19 line
      case 2:             
         if ((dat>='0' && dat<='9') ||       //valid ASCII 0-9
             (dat>='A' && dat<='F')) {       //valid ASCII A-F
            if (s19RecCount>=MAX_S19_LINE)   //make sure no buffer overflow
               s19RecCount = 0;
            s19RecBuff[s19RecCount++] = dat; //save valid data to line buffer
         }
         else if (dat==0x00) {         //end of current S19 line detected
            LED_COMM_IN = LED_OFF;     //SCI data in-coming inactive
            dat = S19LineFormat();     //re-format the line and get back the checksum
            if (dat==0xff) {           //correct checksum
               tmpPtr = s19RecBuff;    //get the pointer of pay-load data
               num = *tmpPtr++;        //number of data byte in this line
               num--;                  //deduct the last byte which is the checksum
               num >>= 2;              //num/=4, number of 4-byte group
               datPtr = (void*)(*(unsigned long*)tmpPtr);   //get the Flash address intented to be programmed
               if (datPtr >= (void*)FLASH_PRG_ADDR) {       //address is in re-programable area
                  LED_PRG_BUSY = LED_ON;                    //turn LED on as start-of-programming
                  ((unsigned long*)tmpPtr)++;               //point to code data
                  num--;                                    //deduct 1 group of address 4-bytes
                  for (i=0;i<num;i++) {
                     FSTAT  = 0x30;                                     //clear FPVIOL & FACCERR, if any
                     *(unsigned long*)datPtr = *(unsigned long*)tmpPtr; //latch 4 bytes of data into flash array
                     prg = ((byte (*)(byte))codeInRam)(0x20);           //launch command for flash programming
                     ((unsigned long*)tmpPtr)++;                        //next group of data
                     ((unsigned long*)datPtr)++;                        //next flash address
                  }
                  LED_PRG_BUSY = LED_OFF;
               }
            }
            __SciSendData('.');     //echo back to PC asking for more data
            s19RecState = 0;        //reset state machine for next new line
         }
         break;
   
      //wait for completion of one S19 line
      //Echo back '.' to acknowledge once end-of-line detected
      case 3:       
         if (dat==0x00) {
            LED_COMM_IN = LED_OFF;     //SCI data in-coming inactive
            __SciSendData('.');        //echo back to PC asking for more data
            s19RecState = 0;           //reset state machine for next new line
            
            if (reBootFlag) {          //re-boot with new code now !!!
               asm(jmp 0xffffffff);    //Jump to illegal address will result a RESET!!!
            }
         }
         break;
      
      //invalid state, reset the state-machine
      default:
         s19RecState = 0;           //reset state for next new line
   }
}

//=============================================================================
// - Launch Flash programing command and wait for its completion
// - This routine is implemented in Flash memory but must be copied into RAM
//   and executed in RAM.
// - With the coding here the total length of this routine is less than 128 bytes
// - User must verify the length again if one makes any code additions for any
//   specific purposes
//=============================================================================
byte FlashCmdExec(byte cmd)
{
   //FSTAT_FACCERR = 1;         //clear any pending Flash error flag
   FCMD  = cmd;
   FSTAT_FCBEF   = 1;         //command launched and FCBEF cleared
   if (FSTAT_FPVIOL || FSTAT_FACCERR) { //exit if encounter any error
      return(0);                        //return with error flag
   }
   while(!FSTAT_FCCF) { //wait for FCCF=1
      __RESET_WATCHDOG();               
   }
   return(1);                           //return with success
}   

//=============================================================================
// - Copy ROM data into RAM buffer 'codeInRam'
// - Input: romPtr - byte pointer of ROM data
//          size   - no. of bytes need to be copied
// - Return: no. of data bytes actually copied
//=============================================================================
word CopyRom2Ram(byte* romPtr, word size)
{
   word i;
   
   if (size==0 || size>RAM_CODE_SIZE)
      return(0);  //no data copied
   
   //copy ROM data into RAM
   for (i=0;i<size;i++) {
      codeInRam[i] = *romPtr++;
   }
   
   return(i);     //return with no. of bytes copied
}
      
//=============================================================================
// - Erase all flash memory sectors except base vector table & bootload section
//   for new code download
// - FLASH_PRG_ADDR refers to the starting address to be erased
//=============================================================================
void FlashErase(void)
{
   byte sect, i;
   word w;
   
   sect = FLASH_PRG_ADDR/FLASH_PAGE_SIZE;       //get the starting sector number
   
   while(sect<128) {
      datPtr = (void*)(sect*FLASH_PAGE_SIZE);
      for (w=0;w<FLASH_PAGE_SIZE;w++) {         //verify if this sector is already blank
         if (((byte*)datPtr)[w] != 0xff) break; //found at least one byte was not blank
      }
      if (w<FLASH_PAGE_SIZE) {                  //this sector needs to be erased
         while (!FCDIV_FDIVLD) FCDIV = 39;
         while (!FSTAT_FCBEF) {;}
         FSTAT = 0x30;                          //clear FPVIOL & FACCERR, if any
         *(unsigned long*)datPtr = 0L;          //dummy write;
         i = ((byte (*)(byte))codeInRam)(0x40); //command for sector erase
      }
      sect++;
   }
}

//=============================================================================
// Check for TMP1 overflow and toggle LED
//=============================================================================
void TPM1OverflowChk(void)
{
   if (TPM1SC&0x80) {
      TPM1SC_TOF = 0;
      LED_BOOTLOADER = !LED_BOOTLOADER;
   }
}

//=============================================================================
// Boot-loader main routine
//=============================================================================
void BootLoader(void)
{
   //setup A7 stack pointer
   asm (lea      _SP_INIT, a7);
	//setup A6 dummy stackframe
   asm (movea.l  #0, a6);
   asm (link     a6, #0);
	//setup A5
   asm (lea      _SDA_BASE, a5);

   DisableInterrupts;      //disable all interrupt, no interrupt is allowed
   
   //Do all the initialization works
   InitBootLoad();         
   
   //Copy flash-command execution code into RAM
   CopyRom2Ram((byte*)FlashCmdExec, 128);

   //Erase all pages in reprogramable area
   FlashErase();           
   
   //Boot-loader main loop 
   for (;;) {
      __RESET_WATCHDOG();  //clear watchdog
      
      ReceiveS19Text();    //polling to process incoming data
      
      TPM1OverflowChk();   //polling to check timer
   }
}

//=============================================================================
// - Vector 1 - Reset vector
//
// - This portion of code will be executed right after reset.
// - The purpose is to check if it should go to normal code flow or get into
//   Boot-loader by checking key-press on PortD pin3 and validity of vector area
//=============================================================================
void interrupt VectorNumber_INITPC FirstHandChk(void)     
{
   //setup A7 stack pointer
   asm (lea      _SP_INIT, a7);
	//setup A6 dummy stackframe
   asm (movea.l  #0, a6);
   asm (link     a6, #0);
	//setup A5
   asm (lea      _SDA_BASE, a5);
   
   //setup PORTD3 for key-press detection
   PTDDD_PTDDD3 = 0;                //set PTD3 as input (key)
   
   // check if boot-loader function is activated by pressing PortD pin3
   // upon reset
   if (!PTDD_PTDD3) {                  //pin is low - possible key-press detected
      for (wTmp=0;wTmp<1024;wTmp++) {} //delay for key debouncing
      if (!PTDD_PTDD3) {               //double-check to confirm key-press
         asm (jmp BootLoader);         //Boot-loader activation confirmed, jump to Boot-loader routine
      }
   }
   
   //Boot-loader is not activated by key upon reset, 
   //Need to further verify if normal code flow exists
   //by checking 1st 16 bytes of data in remapped vector area
   datPtr = (void*)StartupEntry;    //get the starting address by referring to 1st entry in redirected vector map
   for (bTmp=0;bTmp<16;bTmp++) {    //check for consecutive 16 bytes
      if (*(byte*)datPtr != 0xff)   //break out if any one is not 0xff
         break;
      ((byte*)datPtr)++;
   }
   
   if (bTmp==16) {               //leading 16 bytes in vector map are all 0xff, vector map is invalid
      asm (jmp BootLoader);      //Jump to Boot-loader routine
   }
   
   //execute normal code follow
   asm (jmp StartupEntry);       //Jump to normal "startup" routine

}   

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -