/*----------------------------------------------------------------------------*/ int nxp_verify_hex(ASerialPort_t* aPort, ADeviceNXP_t* aDevice) { int test, loop, wait, count, index = 0, length = 0; char hexchk[COUNT_HEXSTR_BUFF]; /* no need to check end-of-record line! */ if(aDevice->linehex->type==0x01) return 0; aDevice->command = NXP_ISP_CHECK; aDevice->subcommand = CHECK_DATA; aDevice->beg_hi = aDevice->linehex->address; aDevice->end_lo = aDevice->linehex->address+aDevice->linehex->count-1; count = aDevice->linehex->count*2; wait = NXP_CHECK_EQ_INDEX+1+NXP_CHECK_BUFF_EXT+count; /* send data read command */ test = nxp_check_data(aPort, aDevice); if(test) return HEX_ERROR_GENERAL; /* wait for data */ test = nxp_get_wait(aPort,hexchk,COUNT_HEXSTR_BUFF,wait); if(test) return HEX_ERROR_ACK; /* get length */ while(hexchk[length]) length++; if(length<NXP_CHECK_EQ_INDEX+1) return HEX_ERROR_LENGTH; #ifdef MY1DEBUG printf("[DEBUG0] {%s},{%s}\n",hexchk,aDevice->linehex->hexstr); #endif /* check address */ test = get_hexword(&hexchk[index]); if(test!=aDevice->linehex->address) return HEX_ERROR_INVALID; /* check '=' sign */ if(hexchk[NXP_CHECK_EQ_INDEX]!='=') return HEX_ERROR_INVALID; /* check data */ index=NXP_CHECK_EQ_INDEX+1; if((length-index)<count) return HEX_ERROR_LENGTH; #ifdef MY1DEBUG printf("[DEBUGX] "); #endif count = 0; /* now, count error */ for(loop=0;loop<aDevice->linehex->count;loop++) { test = get_hexbyte(&hexchk[index]); if(test!=aDevice->linehex->data[loop]) count++; index += 2; #ifdef MY1DEBUG printf("([%02X|%02X]{%d})",test,aDevice->linehex->data[loop],count); #endif } #ifdef MY1DEBUG printf("\n"); #endif return count; }
/* ========================================================================= */ uint8 check_checksum(uint8 *hex, uint8 reclen) { uint8 checksum = 0; uint8 i; // add all byte values, incl. checksum! for (i=0; i <= (reclen + HEX_HEADER_LEN); i++) { checksum += get_hexbyte(hex); hex += 2; } // checksum is zero if checksum is correct return (checksum); }
/*----------------------------------------------------------------------------*/ int nxp_check_hex(char* hexstr, ALineHEX_t* linehex) { int length = 0, loop = 0, type; int count, address, checksum, test, temp; /* find length, filter newline! */ while(hexstr[length]) { linehex->hexstr[length] = hexstr[length]; if(hexstr[length]=='\n'||hexstr[length]=='\r') { hexstr[length] = 0x0; linehex->hexstr[length] = 0x0; break; } length++; if(length>COUNT_HEXSTR_CHAR) return HEX_ERROR_LENGTH; } /* check valid length */ if(length<9) return HEX_ERROR_LENGTH; /* check first char */ if(hexstr[loop++]!=':') return HEX_ERROR_NOCOLON; /* get data count */ count = get_hexbyte(&hexstr[loop]); checksum = count&0x0FF; loop += 2; /* get address - highbyte */ test = get_hexbyte(&hexstr[loop]); checksum += test&0xFF; loop += 2; address = (test&0xFF)<<8; /* get address - lowbyte */ test = get_hexbyte(&hexstr[loop]); checksum += test&0xFF; loop += 2; address |= (test&0xFF); /* get record type for checksum calc */ type = get_hexbyte(&hexstr[loop]); checksum += type&0xFF; loop += 2; /* check EOF type? */ if(type!=0x00&&type!=0x01) return HEX_ERROR_NOTDATA; /* save data if requested */ if(linehex) { linehex->count = count; linehex->type = type; linehex->address = address; linehex->lastaddr = address + count - 1 + type; /* count=0 @ type=1! */ } /* get data */ for(temp=0;temp<count;temp++) { if(loop>=(length-2)) return HEX_ERROR_LENGTH; test = get_hexbyte(&hexstr[loop]); if(linehex) linehex->data[temp] = test&0xFF; checksum += test&0xFF; loop += 2; } /* get checksum */ if(loop!=(length-2)) return HEX_ERROR_LENGTH; test = get_hexbyte(&hexstr[loop]); /* calculate and verify checksum */ checksum = ~checksum + 1; if((test&0xFF)!=(checksum&0xFF)) return HEX_ERROR_CHECKSUM; /* returns record type */ return type; }
/* ========================================================================= */ void bootloader(void) { uint32 addr; uint16 addr_low; uint8 addr_high = 0; uint8 reclen; uint8 rectype; uint8 idx; uint8 buffer[HEX_LINE_LEN_MAX]; uint8 ch; bool hexend = 0; #if getenv("FLASH_ERASE_SIZE")>2 uint16 next_addr = 0; #endif /* until end of HEX file */ while(hexend == 0) { /* get one line of the HEX file via RS232 until we receive CR or */ /* we reached the end of the buffer */ idx = 0; do { /* get one byte */ ch = getch(); /* save to buffer */ buffer[idx] = ch; /* increment buffer index */ idx++; } while(ch != 0x0A); /* get record length */ reclen = get_hexbyte(&buffer[HEX_LEN_START]); /* check for proper checksum */ if (check_checksum(&buffer[HEX_LEN_START], reclen) != 0) { /* checkum error - send negative acknowledge */ putc(NAK); } else { /* checkum ok */ /* get address */ addr_low = make16(get_hexbyte(&buffer[HEX_ADDR_START]), get_hexbyte(&buffer[HEX_ADDR_START+2])); /* make 32 bit address */ addr = make32(addr_high, addr_low); /* get record type */ rectype = get_hexbyte(&buffer[HEX_TYPE_START]); if (rectype == HEX_DATA_REC) { /* only program code memory */ if ((addr_high < 0x30) && (addr >= RESET_VECTOR)) { for (idx=0; idx < reclen; idx++) { buffer[idx] = get_hexbyte(&buffer[HEX_DATA_START+(idx*2)]); } #if getenv("FLASH_ERASE_SIZE") > getenv("FLASH_WRITE_SIZE") #if defined(__PCM__) if ((addr_low!=next_addr)&&(addr_low&(getenv("FLASH_ERASE_SIZE")-1)!=0)) #else if ((addr_low!=next_addr)&&(addr_low&(getenv("FLASH_ERASE_SIZE")/2-1)!=0)) #endif erase_program_eeprom(addr); next_addr = addr_low + 1; #endif write_program_memory(addr, buffer, reclen); } } else if (rectype == HEX_EOF_REC) { hexend = 1; } else if (rectype == HEX_EXTADDR_REC) { /* to save resources, only take lower byte - this */ /* allows 24 bit addresses => enough for PIC18F */ //addr_high = make16(get_hexbyte(&buffer[HEX_DATA_START]), // get_hexbyte(&buffer[HEX_DATA_START+2])); addr_high = get_hexbyte(&buffer[HEX_DATA_START+2]); } /* send positive acknowledge */ putc(ACK); } } }