今年国庆完成了4个bootloader,前面介绍了2个,都是PIC32MZ的USB bootloader, 接着介绍2个PIC24 的USB bootloader, 首先是PIC24 USB CDC bootloader。PIC24 USB CDC bootloader 是我开发给我的PIC24FJ256GB106硬件板子的。
开发环境
1. IDE: MPLABX v4.01
2. Compiler: XC16, v1.11
3. Library&Example: c:/microchip_solutions_v2013-06-15/USB/Device-CDC-Basic Demo
这个PIC24 CDC bootloader 是在MLA_v2013-06-15的USB CDC basic demo的基础上修改而成。bootloader 占用空间从0x400开始, 长度= 0x1C00。 CDC bootloader模拟UART通信,一行一行接收串口发送过来的hex原文,然后对每行的hex原文进行解析,将里面的bin数据烧写到对应的地址上。整个的逻辑实现都在我写的Boot_DoProcess()函数中,函数代码如下。
uint8_t BOOT_DoProcess(uint8_t *buffer, uint16_t byteCount)
{
uint8_t i;
uint8_t bcount, recType;
DWORD_VAL pData;
uint8_t retVal = 0;
if (byteCount == 64)
{
return 1;
}
bcount = GetXbyte(buffer[LEN_NIBBLE1_INDEX],buffer[LEN_NIBBLE2_INDEX]);
if (!Checksum(buffer, bcount))
{
retVal = 2;
return retVal;
}
srcAddress.v[1] = GetXbyte(buffer[ADDRH_NIBBLE1_INDEX],buffer[ADDRH_NIBBLE2_INDEX]);
srcAddress.v[0] = GetXbyte(buffer[ADDRL_NIBBLE1_INDEX],buffer[ADDRL_NIBBLE2_INDEX]);
srcAddress.Val >>= 1;
recType = GetXbyte(buffer[TYPE_NIBBLE1_INDEX],buffer[TYPE_NIBBLE2_INDEX]);
switch(recType)
{
case LINEAR_ADDRESS:
srcAddress.v[3] = GetXbyte(buffer[TYPE_NIBBLE2_INDEX+1],buffer[TYPE_NIBBLE2_INDEX+2]);
srcAddress.v[2] = GetXbyte(buffer[TYPE_NIBBLE2_INDEX+3],buffer[TYPE_NIBBLE2_INDEX+4]);
retVal = 3;
break;
case DATA:
if ((srcAddress.Val >= BOOT_START_ADDRESS) && (srcAddress.Val < APPL_RESET_ADDRESS)) // boot protection, avoid to overlap
{
retVal = 4;
return retVal;
}
eraseAddress.Val = srcAddress.Val;
if ((srcAddress.Val % ERASE_BLOCK) == 0)
{
NVM_EraseBlock(eraseAddress.Val);
}
for (i=0; i < 2*bcount;)
{
pData.byte.LB = GetXbyte(buffer[TYPE_NIBBLE2_INDEX+1+i+0],buffer[TYPE_NIBBLE2_INDEX+1+i+1]);
pData.byte.HB = GetXbyte(buffer[TYPE_NIBBLE2_INDEX+1+i+2],buffer[TYPE_NIBBLE2_INDEX+1+i+3]);
pData.byte.UB = GetXbyte(buffer[TYPE_NIBBLE2_INDEX+1+i+4],buffer[TYPE_NIBBLE2_INDEX+1+i+5]);
pData.byte.MB = GetXbyte(buffer[TYPE_NIBBLE2_INDEX+1+i+6],buffer[TYPE_NIBBLE2_INDEX+1+i+7]);
unsigned int error = NVM_WriteWord(srcAddress.Val, pData.Val);
if ((error & 0x2000) > 0)
{
retVal = 5;
return retVal;
}
error = 0;
srcAddress.Val += 2;
i += 8;
}
//retVal = 1;
break;
case END:
retVal = 6;
break;
}
return retVal;
}
在main.c中ProcessIO()函数中调用Boot_DoProcess(). ProcessIO改动很大,代码如下。
void ProcessIO(void)
{
BYTE numBytesRead;
WORD status;
//Blink the LEDs according to the USB device status
BlinkUSBStatus();
// User Application USB tasks
if((USBDeviceState < CONFIGURED_STATE)||(USBSuspendControl==1)) return;
if(buttonPressed)
{
if(stringPrinted == FALSE)
{
if(mUSBUSARTIsTxTrfReady())
{
putrsUSBUSART("Button Pressed -- rn");
stringPrinted = TRUE;
}
}
}
else
{
stringPrinted = FALSE;
}
if(USBUSARTIsTxTrfReady())
{
numBytesRead = getsUSBUSART(USB_Out_Buffer,64);
if(numBytesRead != 0)
{
BYTE i;
BYTE j;
for(i=0;i
{
switch(USB_Out_Buffer[i])
{
case 0x0A:
case 0x0D:
USB_In_Buffer[i] = USB_Out_Buffer[i];
if (!BOOT_Handshake)
{
BOOT_Handshake = 1;
}
else
{
if ((BOOT_RecordSOF == 1) && (BOOT_RecordEOF == 0))
{
BOOT_RecordBuffer[BOOT_RecordCounter++] = USB_Out_Buffer[i];
BOOT_RecordEOF = 1;
for (j=0; j
{
BOOT_OperationBuffer[j] = BOOT_RecordBuffer[j];
}
BOOT_OperationCounter = BOOT_RecordCounter;
BOOT_RecordLineFlag = 1;
BOOT_RecordSOF = 0;
BOOT_RecordEOF = 0;
BOOT_RecordCounter = 0;
}
}
break;
case ':':
USB_In_Buffer[i] = USB_Out_Buffer[i];
if (BOOT_Handshake)
{
if (!BOOT_RecordSOF)
{
BOOT_RecordBuffer[BOOT_RecordCounter++] = USB_Out_Buffer[i];
BOOT_RecordSOF = 1;
}
}
break;
default:
USB_In_Buffer[i] = USB_Out_
『本文转载自网络,版权归原作者所有,如有侵权请联系删除』