Files
BloomPatched/build/scripts/TargetDescriptionFiles/AVR8/Avr8TargetDescriptionFile.php

904 lines
33 KiB
PHP
Raw Normal View History

<?php
namespace Bloom\BuildScripts\TargetDescriptionFiles\Avr8;
2023-05-28 02:17:20 +01:00
use Bloom\BuildScripts\TargetDescriptionFiles\AddressSpace;
use Bloom\BuildScripts\TargetDescriptionFiles\MemorySegment;
use Bloom\BuildScripts\TargetDescriptionFiles\Register;
use Bloom\BuildScripts\TargetDescriptionFiles\TargetDescriptionFile;
require_once __DIR__ . "/../TargetDescriptionFile.php";
require_once __DIR__ . "/AvrFamily.php";
require_once __DIR__ . "/AvrPhysicalInterface.php";
require_once __DIR__ . "/Signature.php";
2023-05-28 02:17:20 +01:00
require_once __DIR__ . "/TargetParameters.php";
require_once __DIR__ . "/DebugWireParameters.php";
require_once __DIR__ . "/IspParameters.php";
require_once __DIR__ . "/JtagParameters.php";
require_once __DIR__ . "/PdiParameters.php";
require_once __DIR__ . "/UpdiParameters.php";
require_once __DIR__ . "/FuseBitsDescriptor.php";
class Avr8TargetDescriptionFile extends TargetDescriptionFile
{
2023-05-28 02:17:20 +01:00
public function getSignature(): ?Signature
{
$byteZero = $this->getPropertyValue('signatures', 'signature0');
$byteOne = $this->getPropertyValue('signatures', 'signature1');
$byteTwo = $this->getPropertyValue('signatures', 'signature2');
2023-05-28 02:17:20 +01:00
if (!empty($byteZero) && !empty($byteOne) && !empty($byteTwo)) {
$signature = new Signature();
$signature->byteZero = $this->stringToInt($byteZero);
$signature->byteOne = $this->stringToInt($byteOne);
$signature->byteTwo = $this->stringToInt($byteTwo);
2023-05-28 02:17:20 +01:00
return $signature;
}
2023-05-28 02:17:20 +01:00
return null;
}
public function getAvrFamily(): ?AvrFamily
2023-05-28 02:17:20 +01:00
{
if (!empty($this->deviceAttributesByName['avr-family'])) {
if (stristr($this->deviceAttributesByName['avr-family'], 'xmega') !== false) {
return AvrFamily::XMEGA;
} else if (stristr($this->deviceAttributesByName['avr-family'], 'tiny') !== false) {
return AvrFamily::TINY;
} else if (stristr($this->deviceAttributesByName['avr-family'], 'mega') !== false) {
return AvrFamily::MEGA;
} else if (strtolower(trim($this->deviceAttributesByName['avr-family'])) == 'avr da') {
return AvrFamily::DA;
} else if (strtolower(trim($this->deviceAttributesByName['avr-family'])) == 'avr db') {
return AvrFamily::DB;
} else if (strtolower(trim($this->deviceAttributesByName['avr-family'])) == 'avr dd') {
return AvrFamily::DD;
} else if (strtolower(trim($this->deviceAttributesByName['avr-family'])) == 'avr ea') {
return AvrFamily::EA;
}
}
return null;
2023-05-28 02:17:20 +01:00
}
2023-05-28 02:17:20 +01:00
public function getSupportedPhysicalInterfaces(): array
{
$physicalInterfacesByName = [
'isp' => AvrPhysicalInterface::ISP,
'debugwire' => AvrPhysicalInterface::DEBUG_WIRE,
'updi' => AvrPhysicalInterface::UPDI,
'pdi' => AvrPhysicalInterface::PDI,
'jtag' => AvrPhysicalInterface::JTAG,
2023-05-28 02:17:20 +01:00
];
return array_filter(
$physicalInterfacesByName,
function(string $name) {
return isset($this->physicalInterfacesByName[$name]);
},
ARRAY_FILTER_USE_KEY
);
}
2023-05-28 02:17:20 +01:00
public function getSupportedDebugPhysicalInterfaces(): array
{
$physicalInterfacesByName = [
'debugwire' => AvrPhysicalInterface::DEBUG_WIRE,
'updi' => AvrPhysicalInterface::UPDI,
'pdi' => AvrPhysicalInterface::PDI,
'jtag' => AvrPhysicalInterface::JTAG,
2023-05-28 02:17:20 +01:00
];
return array_filter(
$physicalInterfacesByName,
function(string $name) {
return isset($this->physicalInterfacesByName[$name]);
},
ARRAY_FILTER_USE_KEY
);
}
2023-05-28 02:17:20 +01:00
public function getTargetParameters(): TargetParameters
{
$output = new TargetParameters();
2023-05-28 02:17:20 +01:00
$registerMemorySegment = $this->getMemorySegment('data', 'regs');
if ($registerMemorySegment instanceof MemorySegment) {
$output->gpRegisterSize = $registerMemorySegment->size;
$output->gpRegisterStartAddress = $registerMemorySegment->startAddress;
}
2023-05-28 02:17:20 +01:00
$programMemoryAddressSpace = $this->addressSpacesById['prog'] ?? null;
if ($programMemoryAddressSpace instanceof AddressSpace) {
$output->flashSize = $programMemoryAddressSpace->size;
$output->flashStartAddress = $programMemoryAddressSpace->startAddress;
}
2023-05-28 02:17:20 +01:00
$programMemorySegment = $this->getMemorySegment('prog', 'flash');
if ($programMemorySegment instanceof MemorySegment) {
$output->flashPageSize = $programMemorySegment->pageSize;
}
2023-05-28 02:17:20 +01:00
$ramMemorySegment = $this->getMemorySegment('data', 'ram');
if ($ramMemorySegment instanceof MemorySegment) {
$output->ramStartAddress = $ramMemorySegment->startAddress;
$output->ramSize = $ramMemorySegment->size;
}
2023-05-28 02:17:20 +01:00
$eepromMemorySegment = $this->getMemorySegment(
'data',
'eeprom',
'eeprom'
);
if ($eepromMemorySegment instanceof MemorySegment) {
$output->eepromStartAddress = $eepromMemorySegment->startAddress;
$output->eepromSize = $eepromMemorySegment->size;
$output->eepromPageSize = $eepromMemorySegment->pageSize;
2023-05-28 02:17:20 +01:00
} else if (isset($this->addressSpacesById['eeprom'])) {
$eepromAddressSpace = $this->addressSpacesById['eeprom'];
$output->eepromStartAddress = $eepromAddressSpace->startAddress;
2023-05-28 02:17:20 +01:00
$eepromMemorySegment = $this->getMemorySegment('eeprom', 'eeprom');
if ($eepromMemorySegment instanceof MemorySegment) {
$output->eepromSize = $eepromMemorySegment->size;
$output->eepromPageSize = $eepromMemorySegment->pageSize;
}
}
2023-05-28 02:17:20 +01:00
$eepromAddressRegister = $this->getModuleRegister(
'eeprom',
'eeprom',
'eear'
);
if ($eepromAddressRegister instanceof Register) {
$output->eepromAddressRegisterLow = $eepromAddressRegister->offset;
$output->eepromAddressRegisterHigh = ($eepromAddressRegister->size == 2)
? $eepromAddressRegister->offset + 1
: $eepromAddressRegister->offset;
2023-05-28 02:17:20 +01:00
} else {
$eepromAddressRegisterLow = $this->getModuleRegister(
'eeprom',
'eeprom',
'eearl'
);
if ($eepromAddressRegisterLow instanceof Register) {
$output->eepromAddressRegisterLow = $eepromAddressRegisterLow->offset;
$output->eepromAddressRegisterHigh = $eepromAddressRegisterLow->offset;
}
$eepromAddressRegisterHigh = $this->getModuleRegister(
'eeprom',
'eeprom',
'eearh'
);
if ($eepromAddressRegisterHigh instanceof Register) {
$output->eepromAddressRegisterHigh = $eepromAddressRegisterHigh->offset;
}
}
$eepromDataRegister = $this->getModuleRegister(
'eeprom',
'eeprom',
'eedr'
);
if ($eepromDataRegister instanceof Register) {
$output->eepromDataRegisterAddress = $eepromDataRegister->offset;
}
$eepromControlRegister = $this->getModuleRegister(
'eeprom',
'eeprom',
'eecr'
);
if ($eepromControlRegister instanceof Register) {
$output->eepromControlRegisterAddress = $eepromControlRegister->offset;
}
$statusRegister = $this->getModuleRegister(
'cpu',
'cpu',
'sreg'
);
if ($statusRegister instanceof Register) {
$output->statusRegisterStartAddress = $statusRegister->offset;
$output->statusRegisterSize = $statusRegister->size;
}
$stackPointerRegister = $this->getModuleRegister(
'cpu',
'cpu',
'sp'
);
if ($stackPointerRegister instanceof Register) {
$output->stackPointerRegisterLowAddress = $stackPointerRegister->offset;
$output->stackPointerRegisterSize = $stackPointerRegister->size;
2023-05-28 02:17:20 +01:00
} else {
$stackPointerRegisterLow = $this->getModuleRegister(
'cpu',
'cpu',
'spl'
);
if ($stackPointerRegisterLow instanceof Register) {
$output->stackPointerRegisterLowAddress = $stackPointerRegisterLow->offset;
$output->stackPointerRegisterSize = $stackPointerRegisterLow->size;
}
2023-05-28 02:17:20 +01:00
$stackPointerRegisterHigh = $this->getModuleRegister(
'cpu',
'cpu',
'sph'
);
if ($stackPointerRegisterHigh instanceof Register) {
$output->stackPointerRegisterSize += $stackPointerRegisterHigh->size;
}
}
2023-05-28 02:17:20 +01:00
return $output;
}
2023-05-28 02:17:20 +01:00
public function getDebugWireParameters(): DebugWireParameters
{
$output = new DebugWireParameters();
$output->ocdRevision = $this->stringToInt(
$this->getPropertyValue('ocd', 'ocd_revision')
);
$output->ocdDataRegister = $this->stringToInt(
$this->getPropertyValue('ocd', 'ocd_datareg')
);
$spmcsRegister = $this->getModuleRegister(
'cpu',
'cpu',
'spmcsr'
) ?? $this->getModuleRegister(
'cpu',
'cpu',
'spmcr'
) ?? $this->getModuleRegister(
'boot_load',
'boot_load',
'spmcr'
) ?? $this->getModuleRegister(
'boot_load',
'boot_load',
'spmcsr'
);
if ($spmcsRegister instanceof Register) {
$output->spmcRegisterStartAddress = $spmcsRegister->offset;
}
$osccalRegister = $this->getModuleRegister(
'cpu',
'cpu',
'osccal'
) ?? $this->getModuleRegister(
'cpu',
'cpu',
'osccal0'
) ?? $this->getModuleRegister(
'cpu',
'cpu',
'osccal1'
) ?? $this->getModuleRegister(
'cpu',
'cpu',
'fosccal'
) ?? $this->getModuleRegister(
'cpu',
'cpu',
'sosccala'
);
if ($osccalRegister instanceof Register) {
$output->osccalAddress = $osccalRegister->offset;
}
return $output;
}
2023-05-28 02:17:20 +01:00
public function getIspParameters(): IspParameters
{
$output = new IspParameters();
$output->programModeTimeout = $this->stringToInt(
$this->getPropertyValue('isp_interface', 'ispenterprogmode_timeout')
);
$output->programModeStabilizationDelay = $this->stringToInt(
$this->getPropertyValue('isp_interface', 'ispenterprogmode_stabdelay')
);
$output->programModeCommandExecutionDelay = $this->stringToInt(
$this->getPropertyValue('isp_interface', 'ispenterprogmode_cmdexedelay')
);
$output->programModeSyncLoops = $this->stringToInt(
$this->getPropertyValue('isp_interface', 'ispenterprogmode_synchloops')
);
$output->programModeByteDelay = $this->stringToInt(
$this->getPropertyValue('isp_interface', 'ispenterprogmode_bytedelay')
);
$output->programModePollValue = $this->stringToInt(
$this->getPropertyValue('isp_interface', 'ispenterprogmode_pollvalue')
);
$output->programModePollIndex = $this->stringToInt(
$this->getPropertyValue('isp_interface', 'ispenterprogmode_pollindex')
);
$output->programModePreDelay = $this->stringToInt(
$this->getPropertyValue('isp_interface', 'ispleaveprogmode_predelay')
);
$output->programModePostDelay = $this->stringToInt(
$this->getPropertyValue('isp_interface', 'ispleaveprogmode_postdelay')
);
$output->readSignaturePollIndex = $this->stringToInt(
$this->getPropertyValue('isp_interface', 'ispreadsign_pollindex')
);
$output->readFusePollIndex = $this->stringToInt(
$this->getPropertyValue('isp_interface', 'ispreadfuse_pollindex')
);
$output->readLockPollIndex = $this->stringToInt(
$this->getPropertyValue('isp_interface', 'ispreadlock_pollindex')
);
return $output;
}
2023-05-28 02:17:20 +01:00
public function getJtagParameters(): JtagParameters
{
$output = new JtagParameters();
$output->ocdRevision = $this->stringToInt(
$this->getPropertyValue('ocd', 'ocd_revision')
);
$output->ocdDataRegister = $this->stringToInt(
$this->getPropertyValue('ocd', 'ocd_datareg')
);
$spmcsRegister = $this->getModuleRegister(
'cpu',
'cpu',
'spmcsr'
) ?? $this->getModuleRegister(
'cpu',
'cpu',
'spmcr'
) ?? $this->getModuleRegister(
'boot_load',
'boot_load',
'spmcr'
) ?? $this->getModuleRegister(
'boot_load',
'boot_load',
'spmcsr'
);
if ($spmcsRegister instanceof Register) {
$output->spmcRegisterStartAddress = $spmcsRegister->offset;
}
$osccalRegister = $this->getModuleRegister(
'cpu',
'cpu',
'osccal'
) ?? $this->getModuleRegister(
'cpu',
'cpu',
'osccal0'
) ?? $this->getModuleRegister(
'cpu',
'cpu',
'osccal1'
) ?? $this->getModuleRegister(
'cpu',
'cpu',
'fosccal'
) ?? $this->getModuleRegister(
'cpu',
'cpu',
'sosccala'
);
if ($osccalRegister instanceof Register) {
$output->osccalAddress = $osccalRegister->offset;
}
return $output;
}
2023-05-28 02:17:20 +01:00
public function getPdiParameters(): PdiParameters
{
$output = new PdiParameters();
$applicationSectionMemorySegment = $this->getMemorySegment(
'prog',
'flash',
'app_section'
);
if ($applicationSectionMemorySegment instanceof MemorySegment) {
$output->appSectionStartAddress = $applicationSectionMemorySegment->startAddress;
$output->appSectionSize = $applicationSectionMemorySegment->size;
}
$bootSectionMemorySegment = $this->getMemorySegment(
'prog',
'flash',
'boot_section_1'
) ?? $this->getMemorySegment(
'prog',
'flash',
'boot_section'
);
if ($bootSectionMemorySegment instanceof MemorySegment) {
$output->bootSectionStartAddress = $bootSectionMemorySegment->startAddress;
$output->bootSectionSize = $bootSectionMemorySegment->size;
}
$output->appSectionPdiOffset = $this->stringToInt(
$this->getPropertyValue('pdi_interface', 'app_section_offset')
);
$output->bootSectionPdiOffset = $this->stringToInt(
$this->getPropertyValue('pdi_interface', 'boot_section_offset')
);
$output->ramPdiOffset = $this->stringToInt(
$this->getPropertyValue('pdi_interface', 'datamem_offset')
);
$output->eepromPdiOffset = $this->stringToInt(
$this->getPropertyValue('pdi_interface', 'eeprom_offset')
);
$output->userSignaturesPdiOffset = $this->stringToInt(
$this->getPropertyValue('pdi_interface', 'user_signatures_offset')
);
$output->productSignaturesPdiOffset = $this->stringToInt(
$this->getPropertyValue('pdi_interface', 'prod_signatures_offset')
);
$output->fuseRegistersPdiOffset = $this->stringToInt(
$this->getPropertyValue('pdi_interface', 'fuse_registers_offset')
);
$output->lockRegistersPdiOffset = $this->stringToInt(
$this->getPropertyValue('pdi_interface', 'lock_registers_offset')
);
$output->nvmModuleBaseAddress = $this->getPeripheralModuleRegisterGroupOffset(
'nvm',
'nvm',
'nvm'
);
$output->mcuModuleBaseAddress = $this->getPeripheralModuleRegisterGroupOffset(
'mcu',
'mcu',
'mcu'
);
return $output;
}
2023-05-28 02:17:20 +01:00
public function getUpdiParameters(): UpdiParameters
{
$output = new UpdiParameters();
$output->nvmModuleBaseAddress = $this->getPeripheralModuleRegisterGroupOffset(
'nvmctrl',
'nvmctrl',
'nvmctrl'
);
$output->ocdBaseAddress = $this->stringToInt(
$this->getPropertyValue('updi_interface', 'ocd_base_addr')
);
$output->programMemoryStartAddress = $this->stringToInt(
$this->getPropertyValue('updi_interface', 'progmem_offset')
);
$signatureMemorySegment = $this->getMemorySegment(
'data',
'signatures',
'signatures'
);
if ($signatureMemorySegment instanceof MemorySegment) {
$output->signatureSegmentSize = $signatureMemorySegment->size;
$output->signatureSegmentStartAddress = $signatureMemorySegment->startAddress;
}
$fuseMemorySegment = $this->getMemorySegment(
'data',
'fuses',
'fuses'
);
if ($fuseMemorySegment instanceof MemorySegment) {
$output->fuseSegmentSize = $fuseMemorySegment->size;
$output->fuseSegmentStartAddress = $fuseMemorySegment->startAddress;
}
$lockbitsMemorySegment = $this->getMemorySegment(
'data',
'lockbits',
'lockbits'
);
if ($lockbitsMemorySegment instanceof MemorySegment) {
$output->lockbitsSegmentStartAddress = $lockbitsMemorySegment->startAddress;
}
return $output;
}
public function getFuseBitsDescriptor(string $fuseBitName): ?FuseBitsDescriptor
{
$fuseModule = $this->modulesByName['fuse'] ?? null;
if (!empty($fuseModule)) {
$fuseRegisterGroup = $fuseModule->registerGroupsMappedByName['fuse'] ?? null;
if (empty($fuseRegisterGroup)) {
$fuseRegisterGroup = $fuseModule->registerGroupsMappedByName['nvm_fuses'] ?? null;
}
if (!empty($fuseRegisterGroup)) {
foreach ($fuseRegisterGroup->registersMappedByName as $fuseType => $fuseRegister) {
if (isset($fuseRegister->bitFieldsByName[$fuseBitName])) {
return new FuseBitsDescriptor($fuseType);
}
}
}
}
// Try the NVM module
$nvmModule = $this->modulesByName['nvm'] ?? null;
if (!empty($nvmModule)) {
$fuseRegisterGroup = $nvmModule->registerGroupsMappedByName['nvm_fuses'] ?? null;
if (!empty($fuseRegisterGroup)) {
foreach ($fuseRegisterGroup->registersMappedByName as $fuseType => $fuseRegister) {
if (isset($fuseRegister->bitFieldsByName[$fuseBitName])) {
return new FuseBitsDescriptor($fuseType);
}
}
}
}
return null;
}
public function validate(): array
{
$failures = parent::validate();
2023-05-28 02:17:20 +01:00
if (is_null($this->getSignature())) {
$failures[] = "Missing or incomplete AVR signature.";
}
2023-05-28 02:17:20 +01:00
$physicalInterfaces = $this->getSupportedPhysicalInterfaces();
$debugPhysicalInterfaces = $this->getSupportedDebugPhysicalInterfaces();
if (empty($debugPhysicalInterfaces)) {
$failures[] = 'Target does not support any known AVR8 debug interface - the TDF will need to be deleted.'
. ' Aborting validation.';
return $failures;
}
$family = $this->getAvrFamily();
if (is_null($family)) {
$failures[] = 'Unknown AVR8 family';
}
2023-05-28 02:17:20 +01:00
$targetParameters = $this->getTargetParameters();
2023-05-28 02:17:20 +01:00
if (is_null($targetParameters->stackPointerRegisterSize)) {
$failures[] = 'Missing stack pointer register size.';
}
2023-05-28 02:17:20 +01:00
if ($targetParameters->stackPointerRegisterSize > 2) {
// The AVR architecture implementation in GDB expects all SP registers to be a maximum of two bytes in size.
2023-05-28 02:17:20 +01:00
$failures[] = 'Stack pointer register size (' . $targetParameters->stackPointerRegisterSize . ') exceeds maximum (2).';
}
2023-05-28 02:17:20 +01:00
if ($targetParameters->stackPointerRegisterSize < 1) {
$failures[] = 'Stack pointer register size (' . $targetParameters->stackPointerRegisterSize . ') is less than 1.';
}
2023-05-28 02:17:20 +01:00
if (is_null($targetParameters->stackPointerRegisterLowAddress)) {
$failures[] = 'Missing stack pointer register start address.';
}
2023-05-28 02:17:20 +01:00
if (is_null($targetParameters->statusRegisterStartAddress)) {
$failures[] = 'Missing status register start address.';
}
2023-05-28 02:17:20 +01:00
if (is_null($targetParameters->statusRegisterSize)) {
$failures[] = 'Missing status register size.';
2023-05-28 02:17:20 +01:00
} else if ($targetParameters->statusRegisterSize > 1) {
$failures[] = 'Status register size exceeds 1';
}
2023-05-28 02:17:20 +01:00
if (is_null($targetParameters->flashSize)) {
$failures[] = 'Missing flash size.';
}
2023-05-28 02:17:20 +01:00
if (is_null($targetParameters->flashPageSize)) {
$failures[] = 'Missing flash page size.';
}
2023-05-28 02:17:20 +01:00
if (is_null($targetParameters->flashStartAddress)) {
$failures[] = 'Missing flash start address.';
}
2023-05-28 02:17:20 +01:00
if (is_null($targetParameters->ramStartAddress)) {
$failures[] = 'Missing ram start address.';
}
2023-05-28 02:17:20 +01:00
if (is_null($targetParameters->eepromSize)) {
$failures[] = 'Missing eeprom size.';
}
2023-05-28 02:17:20 +01:00
if ($targetParameters->eepromSize < 64) {
/*
* All AVR8 targets supported by Bloom have at least 64 bytes of EEPROM. This is assumed in some areas of
* Bloom's code.
*
* The purpose of this check is to remind me to address those areas of Bloom's code before adding support
* for an AVR8 target with no EEPROM.
*/
$failures[] = 'Unexpected eeprom size.';
}
2023-05-28 02:17:20 +01:00
if (is_null($targetParameters->eepromPageSize)) {
$failures[] = 'Missing eeprom page size.';
}
2023-05-28 02:17:20 +01:00
if (is_null($targetParameters->eepromStartAddress)) {
$failures[] = 'Missing eeprom start address.';
}
if (in_array(AvrPhysicalInterface::DEBUG_WIRE, $debugPhysicalInterfaces)) {
2023-05-28 02:17:20 +01:00
$debugWireParameters = $this->getDebugWireParameters();
$ispParameters = $this->getIspParameters();
if (is_null($debugWireParameters->ocdRevision)) {
$failures[] = 'Missing OCD revision.';
}
if (is_null($debugWireParameters->ocdDataRegister)) {
$failures[] = 'Missing OCD data register address.';
}
if (is_null($debugWireParameters->spmcRegisterStartAddress)) {
$failures[] = 'Missing store program memory control register start address.';
}
if (is_null($debugWireParameters->osccalAddress)) {
$failures[] = 'Missing oscillator calibration register address.';
}
if (!in_array(AvrPhysicalInterface::ISP, $physicalInterfaces)) {
2023-05-28 02:17:20 +01:00
$failures[] = 'Missing ISP interface for debugWire target.';
}
if (is_null($ispParameters->programModeTimeout)) {
$failures[] = 'Missing ispenterprogmode_timeout ISP parameter.';
}
if (is_null($ispParameters->programModeStabilizationDelay)) {
$failures[] = 'Missing ispenterprogmode_stabdelay ISP parameter.';
}
if (is_null($ispParameters->programModeCommandExecutionDelay)) {
$failures[] = 'Missing ispenterprogmode_cmdexedelay ISP parameter.';
}
if (is_null($ispParameters->programModeSyncLoops)) {
$failures[] = 'Missing ispenterprogmode_synchloops ISP parameter.';
}
if (is_null($ispParameters->programModeByteDelay)) {
$failures[] = 'Missing ispenterprogmode_bytedelay ISP parameter.';
}
if (is_null($ispParameters->programModePollValue)) {
$failures[] = 'Missing ispenterprogmode_pollvalue ISP parameter.';
}
if (is_null($ispParameters->programModePollIndex)) {
$failures[] = 'Missing ispenterprogmode_pollindex ISP parameter.';
}
if (is_null($ispParameters->programModePreDelay)) {
$failures[] = 'Missing ispleaveprogmode_predelay ISP parameter.';
}
if (is_null($ispParameters->programModePostDelay)) {
$failures[] = 'Missing ispleaveprogmode_postdelay ISP parameter.';
}
if (is_null($ispParameters->readSignaturePollIndex)) {
$failures[] = 'Missing ispreadsign_pollindex ISP parameter.';
}
if (is_null($ispParameters->readFusePollIndex)) {
$failures[] = 'Missing ispreadfuse_pollindex ISP parameter.';
}
if (is_null($ispParameters->readLockPollIndex)) {
$failures[] = 'Missing ispreadlock_pollindex ISP parameter.';
}
$dwenFuseBitDescriptor = $this->getFuseBitsDescriptor('dwen');
if (empty($dwenFuseBitDescriptor)) {
$failures[] = 'Could not find DWEN fuse bit field for debugWire target.';
} else {
static $validFuseTypes = [
FuseBitsDescriptor::FUSE_TYPE_LOW,
FuseBitsDescriptor::FUSE_TYPE_HIGH,
FuseBitsDescriptor::FUSE_TYPE_EXTENDED,
];
if (!in_array($dwenFuseBitDescriptor->fuseType, $validFuseTypes)) {
$failures[] = 'Invalid/unknown fuse byte type for DWEN fuse bit.';
}
}
}
2023-05-07 16:52:29 +01:00
if (
in_array(AvrPhysicalInterface::JTAG, $debugPhysicalInterfaces)
&& $family == AvrFamily::MEGA
) {
2023-05-28 02:17:20 +01:00
$jtagParameters = $this->getJtagParameters();
if (is_null($jtagParameters->ocdRevision)) {
$failures[] = 'Missing OCD revision.';
}
2023-05-28 02:17:20 +01:00
if (is_null($jtagParameters->ocdDataRegister)) {
$failures[] = 'Missing OCD data register address.';
}
2023-05-28 02:17:20 +01:00
if (is_null($jtagParameters->spmcRegisterStartAddress)) {
$failures[] = 'Missing store program memory control register start address.';
}
2023-05-28 02:17:20 +01:00
if (is_null($jtagParameters->osccalAddress)) {
$failures[] = 'Missing oscillator calibration register address.';
}
2023-05-28 02:17:20 +01:00
if (empty($this->getFuseBitsDescriptor('ocden'))) {
$failures[] = 'Could not find OCDEN fuse bit field for JTAG target.';
}
if (empty($this->getFuseBitsDescriptor('jtagen'))) {
$failures[] = 'Could not find JTAGEN fuse bit field for JTAG target.';
}
}
if (in_array(AvrPhysicalInterface::PDI, $debugPhysicalInterfaces)) {
2023-05-28 02:17:20 +01:00
$pdiParameters = $this->getPdiParameters();
if (is_null($pdiParameters->appSectionPdiOffset)) {
$failures[] = 'Missing app section PDI offset.';
}
2023-05-28 02:17:20 +01:00
if (is_null($pdiParameters->bootSectionPdiOffset)) {
$failures[] = 'Missing boot section PDI offset.';
}
2023-05-28 02:17:20 +01:00
if (is_null($pdiParameters->ramPdiOffset)) {
$failures[] = 'Missing datamem PDI offset.';
}
2023-05-28 02:17:20 +01:00
if (is_null($pdiParameters->eepromPdiOffset)) {
$failures[] = 'Missing eeprom PDI offset.';
}
2023-05-28 02:17:20 +01:00
if (is_null($pdiParameters->userSignaturesPdiOffset)) {
$failures[] = 'Missing user signatures PDI offset.';
}
2023-05-28 02:17:20 +01:00
if (is_null($pdiParameters->productSignaturesPdiOffset)) {
$failures[] = 'Missing product signatures PDI offset.';
}
2023-05-28 02:17:20 +01:00
if (is_null($pdiParameters->lockRegistersPdiOffset)) {
$failures[] = 'Missing lock registers PDI offset.';
}
2023-05-28 02:17:20 +01:00
if (is_null($pdiParameters->nvmModuleBaseAddress)) {
2022-06-02 23:06:39 +01:00
$failures[] = 'Missing NVM module base address.';
}
2023-05-28 02:17:20 +01:00
if (is_null($pdiParameters->mcuModuleBaseAddress)) {
$failures[] = 'Missing MCU module base address.';
}
2023-05-28 02:17:20 +01:00
if (is_null($pdiParameters->appSectionStartAddress)) {
$failures[] = 'Missing APP section start address';
}
2023-05-28 02:17:20 +01:00
if (is_null($pdiParameters->appSectionSize)) {
$failures[] = 'Missing APP section size';
}
}
if (in_array(AvrPhysicalInterface::UPDI, $debugPhysicalInterfaces)) {
2023-05-28 02:17:20 +01:00
$updiParameters = $this->getUpdiParameters();
if (is_null($updiParameters->nvmModuleBaseAddress)) {
$failures[] = 'Missing NVM base address.';
}
2023-05-28 02:17:20 +01:00
if (is_null($updiParameters->programMemoryStartAddress)) {
$failures[] = 'Missing UPDI program memory offset.';
2023-05-28 02:17:20 +01:00
} else if ($updiParameters->programMemoryStartAddress > 0xFFFFFF) {
/*
* Due to size constraints of EDBG AVR8 parameters for UPDI sessions, the program memory offset must
* fit into a 24-bit integer.
*/
$failures[] = 'UPDI program memory offset exceeds maximum value for 24-bit unsigned integer.';
}
2023-05-28 02:17:20 +01:00
if (!is_null($targetParameters->flashPageSize) && $targetParameters->flashPageSize > 0xFFFF) {
$failures[] = 'Flash page size exceeds maximum value for 16-bit unsigned integer.';
}
2023-05-28 02:17:20 +01:00
if (is_null($updiParameters->ocdBaseAddress)) {
$failures[] = 'Missing OCD base address.';
2023-05-28 02:17:20 +01:00
} else if ($updiParameters->ocdBaseAddress > 0xFFFF) {
$failures[] = 'UPDI OCD base address exceeds maximum value for 16-bit unsigned integer.';
}
2023-05-28 02:17:20 +01:00
if (is_null($updiParameters->signatureSegmentStartAddress)) {
$failures[] = 'Missing signature segment start address.';
}
2023-05-28 02:17:20 +01:00
if (is_null($updiParameters->fuseSegmentSize)) {
$failures[] = 'Missing fuse segment size.';
}
2023-05-28 02:17:20 +01:00
if (is_null($updiParameters->fuseSegmentStartAddress)) {
$failures[] = 'Missing fuses segment start address.';
}
2023-05-28 02:17:20 +01:00
if (is_null($updiParameters->lockbitsSegmentStartAddress)) {
$failures[] = 'Missing lockbits segment start address.';
}
}
if (
in_array(AvrPhysicalInterface::JTAG, $debugPhysicalInterfaces)
|| in_array(AvrPhysicalInterface::UPDI, $debugPhysicalInterfaces)
2023-05-26 23:36:21 +01:00
) {
if (empty($this->getFuseBitsDescriptor('eesave'))) {
2023-05-26 23:36:21 +01:00
$failures[] = 'Could not find EESAVE fuse bit field for JTAG/UPDI target.';
}
}
$portPeripheralModule = $this->peripheralModulesByName['port'] ?? null;
if (empty($portPeripheralModule)) {
$failures[] = 'PORT peripheral module not found.';
} else {
$portModule = $this->modulesByName['port'];
foreach ($portPeripheralModule->instancesMappedByName as $portName => $portInstance) {
if (strlen($portName) === 5 && strpos($portName, "port") === 0) {
$portSuffix = substr($portName, strlen($portName) - 1, 1);
if (empty($portInstance->signals)) {
$failures[] = 'No signals defined for port ' . $portInstance->name . ' in PORT peripheral module.';
}
if (empty($portModule->registerGroupsMappedByName['port' . $portSuffix])) {
if (empty($portModule->registerGroupsMappedByName['port']->registersMappedByName['dir'])) {
$failures[] = 'Could not find PORT register group in PORT module, for port '
. $portName . ', using suffix ' . $portSuffix;
}
}
}
}
}
return $failures;
}
}