自己用C语言写PIC32 serial bootloader
扫描二维码
随时随地手机看文章
从15年12月份以来我的空余时间都在折腾15年底买的PIC32MZ EC Starter kit。并陆续写了十多篇随笔记录我折腾的历程。最近新完成的是用C语言实现了PIC32的UART bootloader, 采用串口通信,适用于Microchip的PIC32MZ EC,稍作对应的修改也可适用于PIC32MX, PIC32MZ EF等。Uart bootloader是用XC32编译的,电脑端的通信软件是用超级终端--HyperTerminal (也可以使用SecureCRT). 和之前我写的HyperBootloader_PIC16/PIC18/dsPIC很类似,算是一个家族系列之一。为保证家族特性,我命其名为HyperBootloader_PIC32
BOOTLOADER PLACEMENT
HyperBootloader_PIC32 序放在引导闪存存储器中,如下图所示。
BOOTLOADER LINKER SCRIPT
由于需要将bootloader放置在特定位置,我们不能使用默认的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;}