//----------------------------------------------------------------------------- // FUNCTION: main // SCOPE: Bootloader application system function // DESCRIPTION: bootloader main function // RETURNS: 0 //----------------------------------------------------------------------------- int main(void) { volatile unsigned long loop_counter = 0; // counter of loop without received frame Byte enableBootMode = 0; // 0: enter APP, 1: enter BOOT mode, 2: enter verify mode DisableInterrupts; //WDG_Disable(); //watchdog can be enable or disabled in kinetis_sysinit.c INIT_CLOCKS_TO_MODULES; // init clock module Boot_Button_Init(); // init SW1 button (PTC3 port) on FRDM_KL26 board INIT_BOOT_LED; //condition for entering boot: if(((*(unsigned long*)(RELOCATED_VECTORS + 8)) == 0xffffffff) //1. no valid code in APP vector section, || Boot_StrCompare(( Byte*)APPOK_START_ADDRESS, str_app_ok, APPOK_LENGTH) == CHECK_FAIL //2."APP_OK" is wrong in address APPOK_START_ADDRESS. || ((GPIO_PDIR_REG(BOOT_PIN_ENABLE_GPIO_BASE) & (1 << BOOT_PIN_ENABLE_NUM)) == 0) //3. SW1 is pressed || (AppIDC == 0x0000000B)) //4. App request boot { enableBootMode = 1; // enable boot BOOT_LED_ON; AppIDC = 0; } else if (AppIDC == 0x0000000A) // App request verify { enableBootMode = 2; // enable verify mode BOOT_LED_ON; AppIDC = 0; } if(enableBootMode) { // if use external clock #ifdef USE_EXTERNAL_CLOCK Boot_Init_Clock( ); #endif PIN_INIT_AS_UART; // set PTA1/UART0_RX and PTA2/UART0_TX pins as UART UART_Initialization(); // init UART module } //////////////////////////////////////////////////////////////////////// //BOOT Model //////////////////////////////////////////////////////////////////////// while(enableBootMode) // enter boot or verify mode, execute all command from GUI { volatile Byte frame_start_flag = 0; // if frame header is received. 1: receive $, start to receive frame; 0: no $ received volatile Byte frame_length = 0xFF; // SCI received frame length, initialized as 0xFF volatile Byte data_length = 0; volatile Byte buff_index = 1; // receive buffer index for sci_buffer[] volatile Byte data_checked = 0; // check frame end 0xAA 0x55. 1: correct frame ; 0: wrong frame FLASH_Initialization(); sci_buffer[0] = UART_GetChar(); if( sci_buffer[0] == '$') //check frame header: whether it is '$' { loop_counter = 0; frame_start_flag = 1; } if(frame_start_flag == 1) { sci_buffer[1] = UART_GetChar(); // sci_buffer[1] is the station number UART_GetChar(); // sci_buffer[2] is reserved sci_buffer[3] = UART_GetChar(); // sci_buffer[3] is the Data length data_length = sci_buffer[3]; frame_length = 4 + sci_buffer[3] + 2; // frame_length = frame head + data + frame end buff_index = 4; while(data_length --) sci_buffer[buff_index ++] = UART_GetChar(); sci_buffer[buff_index ++] = UART_GetChar(); // frame end. It should be 0xAA sci_buffer[buff_index ++] = UART_GetChar(); // frame end. It should be 0x55 frame_start_flag = 0; } if((sci_buffer[frame_length-2] == 0xAA) && (sci_buffer[frame_length-1] == 0x55)) //Check if Frame end is correct { data_checked = 1; // Correct frame received. } // all the data in frame was correctly received (data_checked = 1) above, now perform frame analysis below. // sci_buffer[] now is switched to tx buffer if(data_checked == 1) { Byte i = 0; Byte j = 0; Byte s19length = 0; Byte s19buffer[WR_BLOCK_BYTE]; //extract app file burning code from received frame, store them to s19buffer[] WDG_Refresh(); switch(sci_buffer[4]) { case 'I': // receive 'I' command, send version information to UART i = 4; while((sci_buffer[i] = Identifier[i-4]) !='\0') //assign chip part number info to sci_buffer[] { i++; } sci_buffer[3] = i - 4; // tx data length in one frame Boot_Send(sci_buffer); if(enableBootMode == 1) // if in boot mode FLASH_EraseSector((LWord)APPOK_START_ADDRESS); //erase APP_OK break; case 'E': // receive 'E' command, erase sector, then send confirm frame to UART Boot_ReadAddress(); if(!( FLASH_EraseSector(address.complete))) { sci_buffer[3] = 00; Boot_Send(sci_buffer); } break; case'W': // receive 'W' command, extract app burning code, program flash. then send confirm frame to UART Boot_ReadAddress(); s19length = sci_buffer[8]; for(j=0,i=9;j<s19length;j++,i++) // extract the prepared writing data from sci_buff[] to S19buffer[] { s19buffer[j] = sci_buffer[i]; } if(!(FLASH_ProgramSectionByLongs (address.complete, (LWord*)s19buffer, s19length/4))) { sci_buffer[3] = 00; Boot_Send(sci_buffer); break; } case'R': // receive 'R' command, read out the memory data, then send the data in frame to UART Boot_ReadAddress(); s19length = sci_buffer[8]; for(i=0;i<s19length;i++) { sci_buffer[i + 4] = ((Byte*)(address.complete))[i]; } sci_buffer[3] = s19length; Boot_Send(sci_buffer); break; case'G': // receive 'G' command, go to app. if(enableBootMode == 1) FLASH_ProgramSectionByLongs ((LWord)APPOK_START_ADDRESS, (LWord*)str_app_ok, APPOK_LENGTH/4); Boot_Cpu_SystemReset( ); // if we want to jump to user application, we need to deinitialize used modules and switch MCG back to FEI mode break; default : break; }// end switch(sci_buffer[4]) frame_start_flag = 0; for (buff_index = 0; buff_index<FRAME_BUFF_LENGTH; buff_index++) // clear sci_buffer[] sci_buffer[buff_index] = 0; }// end if(data_checked == 1) loop_counter ++; if(loop_counter >= 10 && enableBootMode == 2) // 100 * timeout of UART_GetChar(); { Boot_Cpu_SystemReset( ); } }// end while(enableBootMode) // deinitialization of used modules UART_Deinitialization(); DEINIT_BOOT_LED; DEINIT_CLOCKS_TO_MODULES; // relocate vector table SCB_VTOR = RELOCATED_VECTORS; AppIDC = 0; // Jump to user application JumpToUserApplication(*((unsigned long*)RELOCATED_VECTORS), *((unsigned long*)(RELOCATED_VECTORS+4))); return 0; } // end main
//----------------------------------------------------------------------------- // FUNCTION: main // SCOPE: Bootloader application system function // DESCRIPTION: bootloader main function // RETURNS: 0 //----------------------------------------------------------------------------- int main(void) { volatile unsigned long loop_counter = 0; // counter of loop without received frame Byte enableBootMode = 0; // 0: enter APP, 1: enter BOOT mode, 2: enter verify mode //Byte s19buffer[WR_BLOCK_BYTE] = {1}; //extract app file burning code from received frame, store them to s19buffer[] DisableInterrupts; INIT_CLOCKS_TO_MODULES; // init clock module Boot_Button_Init(); // init SW3 button (PTC3 port) on FRDM_K22 board INIT_BOOT_LED; // condition for entering boot: if(((*(unsigned long*)(RELOCATED_VECTORS + 8)) == 0xffffffff) //1. no valid code in APP vector section, || Boot_StrCompare(( Byte*)APPOK_START_ADDRESS, str_app_ok, APPOK_LENGTH) == CHECK_FAIL //2."APP_OK" is wrong in address APPOK_START_ADDRESS. || ((GPIO_PDIR_REG(BOOT_PIN_ENABLE_GPIO_BASE) & (1 << BOOT_PIN_ENABLE_NUM)) == 0) //3. SW1 is pressed || (AppIDC == 0x0000000B)) //4. App request boot { enableBootMode = 1; // enable boot BOOT_LED_ON; AppIDC = 0; } else if (AppIDC == 0x0000000A) // App request verify { enableBootMode = 2; // enable verify mode BOOT_LED_ON; AppIDC = 0; } if(enableBootMode) { // if use external clock #ifdef USE_EXTERNAL_CLOCK Boot_Init_Clock(); #endif PIN_INIT_AS_UART; // set PTEA1/UART1_RX and PTE0/UART1_TX pins as UART UART_Initialization(); // init UART module } //////////////////////////////////////////////////////////////////////// //BOOT Model //////////////////////////////////////////////////////////////////////// while(enableBootMode) // enter boot or verify mode, execute all command from GUI { volatile Byte frame_start_flag = 0; // if frame header is received. 1: receive $, start to receive frame; 0: no $ received volatile Byte frame_length = 0xFF; // SCI received frame length, initialized as 0xFF volatile Byte data_length = 0; volatile Byte buff_index = 1; // receive buffer index for sci_buffer[] volatile Byte data_checked = 0; // check frame end 0xAA 0x55. 1: correct frame ; 0: wrong frame WDG_Refresh(); FLASH_Initialization(); sci_buffer[0] = UART_GetChar(); if( sci_buffer[0] == '$') //check frame header: whether it is '$' { loop_counter = 0; frame_start_flag = 1; } if(frame_start_flag == 1) { sci_buffer[1] = UART_GetChar(); // sci_buffer[1] is the station number UART_GetChar(); // sci_buffer[2] is reserved sci_buffer[3] = UART_GetChar(); // sci_buffer[3] is the Data length data_length = sci_buffer[3]; frame_length = 4 + sci_buffer[3] + 2; // frame_length = frame head + data + frame end buff_index = 4; while(data_length --) sci_buffer[buff_index ++] = UART_GetChar(); sci_buffer[buff_index ++] = UART_GetChar(); // frame end. It should be 0xAA sci_buffer[buff_index ++] = UART_GetChar(); // frame end. It should be 0x55 frame_start_flag = 0; } if((sci_buffer[frame_length-2] == 0xAA) && (sci_buffer[frame_length-1] == 0x55)) //Check if Frame end is correct { data_checked = 1; // Correct frame received. } // all the data in frame was correctly received (data_checked = 1) above, now perform frame analysis below. // sci_buffer[] now is switched to tx buffer if(data_checked == 1) { Byte i = 0; Byte j = 0; Byte burn_data_length = 0; Byte s19buffer[WR_BLOCK_BYTE]; //extract app file burning code from received frame, store them to s19buffer[] //WDG_Refresh(); switch(sci_buffer[4]) { case 'I': // receive 'I' command, send version information to UART i = 4; while((sci_buffer[i] = MCU_Identification.targ_name[i-4]) !='\0') //assign chip part number info to sci_buffer[] { i++; } sci_buffer[i++] = '#'; j = i; while((sci_buffer[i] = MCU_Identification.Boot_version[i-j]) !='\0') //assign bootloader version info to sci_buffer[] { i++; } sci_buffer[i++] = '#'; sci_buffer[i++] = (MCU_Identification.wrblk & 0xFF00)>>8; //assign write block size sci_buffer[i++] = MCU_Identification.wrblk & 0x00FF; sci_buffer[i++] = (MCU_Identification.erblk & 0xFF00)>>8; //assign erase block size sci_buffer[i++] = MCU_Identification.erblk & 0x00FF; sci_buffer[i++] = MCU_Identification.addr_limit.Bytes.hl; //assign MCU Flash end address sci_buffer[i++] = MCU_Identification.addr_limit.Bytes.lh; sci_buffer[i++] = MCU_Identification.addr_limit.Bytes.ll; sci_buffer[i++] = MCU_Identification.dontcare_addrl.Bytes.hl; //assign bootloader dont care memory start adddress sci_buffer[i++] = MCU_Identification.dontcare_addrl.Bytes.lh; sci_buffer[i++] = MCU_Identification.dontcare_addrl.Bytes.ll; sci_buffer[i++] = MCU_Identification.dontcare_addrh.Bytes.hl; //assign bootloader dont care memory end adddress sci_buffer[i++] = MCU_Identification.dontcare_addrh.Bytes.lh; sci_buffer[i++] = MCU_Identification.dontcare_addrh.Bytes.ll; sci_buffer[i++] = MCU_Identification.relocated_vectors.Bytes.hl; //assign bootloader start adddress sci_buffer[i++] = MCU_Identification.relocated_vectors.Bytes.lh; sci_buffer[i++] = MCU_Identification.relocated_vectors.Bytes.ll; sci_buffer[i++] = MCU_Identification.targ_core; // target is M4 core sci_buffer[3] = i - 4; // tx data length in one frame Boot_Send(sci_buffer); if(enableBootMode == 1) // if in boot mode FLASH_EraseSector((LWord)APPOK_START_ADDRESS); //erase APP_OK WDG_Refresh(); break; case 'E': // receive 'E' command, erase sector, then send confirm frame to UART Boot_ReadAddress(); if(!( FLASH_EraseSector(address.complete))) { sci_buffer[3] = 00; Boot_Send(sci_buffer); } WDG_Refresh(); break; case'W': // receive 'W' command, extract app burning code, program flash. then send confirm frame to UART Boot_ReadAddress(); burn_data_length = sci_buffer[8]; for(j=0,i=9;j<burn_data_length;j++,i++) // extract the prepared writing data from sci_buff[] to S19buffer[] { s19buffer[j] = sci_buffer[i]; } if(!(FLASH_ProgramSectionByLongs (address.complete, (LWord*)s19buffer, burn_data_length/4))) { sci_buffer[3] = 00; Boot_Send(sci_buffer); } WDG_Refresh(); break; case'R': // receive 'R' command, read out the memory data, then send the data in frame to UART Boot_ReadAddress(); burn_data_length = sci_buffer[8]; for(i=0;i<burn_data_length;i++) { sci_buffer[i + 4] = ((Byte*)(address.complete))[i]; } sci_buffer[3] = burn_data_length; Boot_Send(sci_buffer); WDG_Refresh(); break; case'G': // receive 'G' command, go to app. if(enableBootMode == 1) FLASH_ProgramSectionByLongs ((LWord)APPOK_START_ADDRESS, (LWord*)str_app_ok, APPOK_LENGTH/4); //BOOT_LED_OFF; NVIC_SystemReset(); break; default : break; }// end switch(sci_buffer[4]) frame_start_flag = 0; for (buff_index = 0; buff_index<FRAME_BUFF_LENGTH; buff_index++) // clear sci_buffer[] sci_buffer[buff_index] = 0; }// end if(data_checked == 1) loop_counter ++; if(loop_counter >= 10 && enableBootMode == 2) // 100 * timeout of UART_GetChar(); { NVIC_SystemReset(); } }// end while(enableBootMode)