自己用C語言寫PIC32 serial bootloader
從15年12月份以來我的空余時間都在折騰15年底買的PIC32MZ EC Starter kit。并陸續(xù)寫了十多篇隨筆記錄我折騰的歷程。最近新完成的是用C語言實現(xiàn)了PIC32的UART bootloader, 采用串口通信,適用于Microchip的PIC32MZ EC,稍作對應(yīng)的修改也可適用于PIC32MX, PIC32MZ EF等。Uart bootloader是用XC32編譯的,電腦端的通信軟件是用超級終端--HyperTerminal (也可以使用SecureCRT). 和之前我寫的HyperBootloader_PIC16/PIC18/dsPIC很類似,算是一個家族系列之一。為保證家族特性,我命其名為HyperBootloader_PIC32
BOOTLOADER PLACEMENT
HyperBootloader_PIC32 序放在引導(dǎo)閃存存儲器中,如下圖所示。
BOOTLOADER LINKER SCRIPT
由于需要將bootloader放置在特定位置,我們不能使用默認(rèn)的linker script. 我們需要修改linker script來放置bootloader, 以下是修改后的主要部分。
_RESET_ADDR=0xBFC00000;_BEV_EXCPT_ADDR=0xBFC00380;_DBG_EXCPT_ADDR=0xBFC00480;_SIMPLE_TLB_REFILL_EXCPT_ADDR=_ebase_address+0;_CACHE_ERR_EXCPT_ADDR=_ebase_address+0x100;_GEN_EXCPT_ADDR=_ebase_address+0x180;/**************************************************************************MemoryRegions**Memoryregionswithoutattributescannotbeusedfororphanedsections.*Onlysectionsspecificallyassignedtotheseregionscanbeallocated*intotheseregions.**TheDebugexceptionvectorislocatedat0x9FC00480.**Theconfig_sectionsareusedtolocatetheconfigwordsat*theirabsoluteaddresses.*************************************************************************/MEMORY{/*Bootloaderusercode:OnlyintheLowerBootAlias*/kseg0_program_mem(rx):ORIGIN=0x9FC02000,LENGTH=0xDF00/*LowerBootAliaslast(5th)page:Notused*/kseg0_lba_last_page(rx):ORIGIN=0x9FC10000,LENGTH=0x4000/*InterruptVectortable*/kseg0_boot_mem:ORIGIN=0x9FC01000,LENGTH=0x1000/*ResetandCStartupmodule*/kseg1_boot_mem:ORIGIN=0xBFC00000,LENGTH=0x480/*CacheTLBInitializationTable*/kseg1_boot_mem_4B0:ORIGIN=0xBFC004B0,LENGTH=0xB50
BOOTLOADER MAIN CODE
修改后的linker script加到bootloader的項目中后,接著是bootloader的coding,以下是bootloader code的主要部分
if(linereceived){for(ix=0;ix=(EraseAddr.Val+PAGE_SIZE)){EraseAddr.Val=(SourceAddr.Val/PAGE_SIZE)*PAGE_SIZE;NVMErasePage(EraseAddr.Val);}linereceived=0;for(ix=0;ix<2*bcount;){pData.byte.LB=GetXbyte(frameBuffer[TYPE_NIBBLE2_INDEX+1+ix+0],frameBuffer[TYPE_NIBBLE2_INDEX+1+ix+1]);pData.byte.HB=GetXbyte(frameBuffer[TYPE_NIBBLE2_INDEX+1+ix+2],frameBuffer[TYPE_NIBBLE2_INDEX+1+ix+3]);pData.byte.UB=GetXbyte(frameBuffer[TYPE_NIBBLE2_INDEX+1+ix+4],frameBuffer[TYPE_NIBBLE2_INDEX+1+ix+5]);pData.byte.MB=GetXbyte(frameBuffer[TYPE_NIBBLE2_INDEX+1+ix+6],frameBuffer[TYPE_NIBBLE2_INDEX+1+ix+7]);unsignedinterror=NVMWriteWord(SourceAddr.Val,pData.Val);if((error&0x3000)>0)Uart_Putc('N');//fordebugerror=0;SourceAddr.Val+=4;ix+=8;if(linereceived)Uart_Putc('X');//fordebug}Checksum();//Buf_Init();break;caseEND:Checksum();U1MODE=0x0;U1STA=0x0;TRISCSET=0x2000;/*RC13Input*/LATCCLR=0x6000;/*ClearLATC*/IPC28CLR=0x1F00;/*ClearIPC28*/IEC3bits.U1RXIE=0;/*ClearIEC3*/(*((void(*)(void))USER_APP_RESET_ADDRESS))();break;}linereceived=0;incrbytes=0;}