205 lines
8.3 KiB
C++
205 lines
8.3 KiB
C++
/************************************************************************
|
|
* Copyright (c) 2009-2011, Microchip Technology Inc.
|
|
*
|
|
* Microchip licenses this software to you solely for use with Microchip
|
|
* products. The software is owned by Microchip and its licensors, and
|
|
* is protected under applicable copyright laws. All rights reserved.
|
|
*
|
|
* SOFTWARE IS PROVIDED "AS IS." MICROCHIP EXPRESSLY DISCLAIMS ANY
|
|
* WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING BUT
|
|
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
* FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. IN NO EVENT SHALL
|
|
* MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR
|
|
* CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, HARM TO YOUR
|
|
* EQUIPMENT, COST OF PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY
|
|
* OR SERVICES, ANY CLAIMS BY THIRD PARTIES (INCLUDING BUT NOT LIMITED
|
|
* TO ANY DEFENSE THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION,
|
|
* OR OTHER SIMILAR COSTS.
|
|
*
|
|
* To the fullest extent allowed by law, Microchip and its licensors
|
|
* liability shall not exceed the amount of fees, if any, that you
|
|
* have paid directly to Microchip to use this software.
|
|
*
|
|
* MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE
|
|
* OF THESE TERMS.
|
|
*
|
|
* Author Date Comment
|
|
*************************************************************************
|
|
* E. Schlunder 2010/02/01 Loading config bit fields/settings added.
|
|
* E. Schlunder 2009/04/14 Initial code ported from VB app.
|
|
* F. Schlunder 2011/06/13 Minor changes for USB HID Bootloader use.
|
|
************************************************************************/
|
|
|
|
#include "Device.h"
|
|
|
|
Device::Device(DeviceData *data)
|
|
{
|
|
deviceData = data;
|
|
|
|
setUnknown();
|
|
}
|
|
|
|
void Device::setUnknown(void)
|
|
{
|
|
family = Unknown;
|
|
|
|
bytesPerAddressFLASH = 1;
|
|
bytesPerAddressEEPROM = 1;
|
|
bytesPerAddressConfig = 1;
|
|
|
|
bytesPerWordEEPROM = 1;
|
|
bytesPerWordConfig = 2;
|
|
bytesPerWordFLASH = 2;
|
|
}
|
|
|
|
bool Device::hasEeprom(void)
|
|
{
|
|
DeviceData::MemoryRange range;
|
|
foreach(range, deviceData->ranges)
|
|
{
|
|
if(range.type == EEPROM_MEMORY)
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool Device::hasConfig(void)
|
|
{
|
|
DeviceData::MemoryRange range;
|
|
foreach(range, deviceData->ranges)
|
|
{
|
|
if(range.type == CONFIG_MEMORY)
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//This method is useful for hex file parsing. This function checks if the address indicated in the hex
|
|
//file line is contained in one of the programmable regions (ex: flash, eeprom, config words, etc.), as
|
|
//specified by the USB device, (from the query response that we received earlier). If the address
|
|
//from the hex file is contained in the programmable device address range, this function returns
|
|
//bool includedInProgrammableRange = true, with the type set to the programmable region type
|
|
//(which can be determined based on the address and the query response). This function also returns
|
|
//the new effective device address (not from the .hex file, which is a raw linear byte address, but the
|
|
//effective address the device should load into its self programming address registers, in order to
|
|
//program the contents [PIC24 uses a 16-bit word addressed flash array, so the hex file addresses
|
|
//don't match the microcontroller addresses]).
|
|
//This function also returns bool addressWasEndofRange = true, if the input hexAddress corresponded
|
|
//to the very last byte of the last address of the programmable memory region that the hexAddress
|
|
//corresponded to. Otherwise this value returns false. This provides an easy check later to
|
|
//know when an end of a region has been completed during hex file parsing.
|
|
unsigned int Device::GetDeviceAddressFromHexAddress(unsigned int hexAddress, DeviceData* pData, unsigned char& type, bool& includedInProgrammableRange, bool& addressWasEndofRange, unsigned int& bytesPerAddressAndType, unsigned int& endDeviceAddressofRegion, unsigned char*& pPCRAMBuffer)
|
|
{
|
|
DeviceData::MemoryRange range;
|
|
unsigned int flashAddress = hexAddress / bytesPerAddressFLASH;
|
|
unsigned int eepromAddress = hexAddress / bytesPerAddressEEPROM;
|
|
unsigned int configAddress = hexAddress / bytesPerAddressConfig;
|
|
unsigned char* pRAMDataBuffer;
|
|
unsigned int byteOffset;
|
|
|
|
|
|
//Loop for each of the previously identified programmable regions, based on the results of the
|
|
//previous Query device response packet.
|
|
foreach(range, pData->ranges)
|
|
{
|
|
//Find what address range the hex address seems to contained within (if any, could be none, in
|
|
//the case the .hex file contains info that is not part of the bootloader re-programmable region of flash).
|
|
if((range.type == PROGRAM_MEMORY) && (flashAddress >= range.start) && (flashAddress < range.end))
|
|
{
|
|
includedInProgrammableRange = true;
|
|
if(range.start != 0)
|
|
{
|
|
byteOffset = ((flashAddress - range.start) * bytesPerAddressFLASH) + (hexAddress % bytesPerAddressFLASH);
|
|
pRAMDataBuffer = range.pDataBuffer + byteOffset;
|
|
pPCRAMBuffer = pRAMDataBuffer;
|
|
}
|
|
else
|
|
{
|
|
pPCRAMBuffer = 0;
|
|
}
|
|
|
|
type = PROGRAM_MEMORY;
|
|
bytesPerAddressAndType = bytesPerAddressFLASH;
|
|
endDeviceAddressofRegion = range.end;
|
|
//Check if this was the very last byte of the very last address of the region.
|
|
//We can determine this, using the below check.
|
|
if((flashAddress == (range.end - 1)) && ((hexAddress % bytesPerAddressFLASH) == (bytesPerAddressFLASH - 1)))
|
|
{
|
|
addressWasEndofRange = true;
|
|
}
|
|
else
|
|
{
|
|
addressWasEndofRange = false;
|
|
}
|
|
return flashAddress;
|
|
}
|
|
|
|
if((range.type == EEPROM_MEMORY) && (eepromAddress >= range.start) && (eepromAddress < range.end))
|
|
{
|
|
includedInProgrammableRange = true;
|
|
if(range.start != 0)
|
|
{
|
|
byteOffset = ((eepromAddress - range.start) * bytesPerAddressEEPROM) + (hexAddress % bytesPerAddressEEPROM);
|
|
pRAMDataBuffer = range.pDataBuffer + byteOffset;
|
|
pPCRAMBuffer = pRAMDataBuffer;
|
|
}
|
|
else
|
|
{
|
|
pPCRAMBuffer = 0;
|
|
}
|
|
type = EEPROM_MEMORY;
|
|
bytesPerAddressAndType = bytesPerAddressEEPROM;
|
|
endDeviceAddressofRegion = range.end;
|
|
//Check if this was the very last byte of the very last address of the region.
|
|
//We can determine this, using the below check.
|
|
if((eepromAddress == (range.end - 1)) && ((eepromAddress % bytesPerAddressEEPROM) == (bytesPerAddressEEPROM - 1)))
|
|
{
|
|
addressWasEndofRange = true;
|
|
}
|
|
else
|
|
{
|
|
addressWasEndofRange = false;
|
|
}
|
|
return eepromAddress;
|
|
}
|
|
|
|
if((range.type == CONFIG_MEMORY) && (configAddress >= range.start) && (configAddress < range.end))
|
|
{
|
|
includedInProgrammableRange = true;
|
|
if(range.start != 0)
|
|
{
|
|
byteOffset = ((configAddress - range.start) * bytesPerAddressConfig) + (hexAddress % bytesPerAddressConfig);
|
|
pRAMDataBuffer = range.pDataBuffer + byteOffset;
|
|
pPCRAMBuffer = pRAMDataBuffer;
|
|
}
|
|
else
|
|
{
|
|
pPCRAMBuffer = 0;
|
|
}
|
|
type = CONFIG_MEMORY;
|
|
bytesPerAddressAndType = bytesPerAddressConfig;
|
|
endDeviceAddressofRegion = range.end;
|
|
//Check if this was the very last byte of the very last address of the region.
|
|
//We can determine this, using the below check.
|
|
if((configAddress == (range.end - 1)) && ((configAddress % bytesPerAddressConfig) == (bytesPerAddressConfig - 1)))
|
|
{
|
|
addressWasEndofRange = true;
|
|
}
|
|
else
|
|
{
|
|
addressWasEndofRange = false;
|
|
}
|
|
return configAddress;
|
|
}
|
|
}
|
|
|
|
//If we get to here, that means the hex file address that was passed in was not included in any of the
|
|
//device's reported programmable memory regions.
|
|
includedInProgrammableRange = false;
|
|
addressWasEndofRange = false;
|
|
pPCRAMBuffer = 0;
|
|
return 0;
|
|
}
|