getPropertyValue('signatures', 'signature0'); $byteOne = $this->getPropertyValue('signatures', 'signature1'); $byteTwo = $this->getPropertyValue('signatures', 'signature2'); 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); return $signature; } return null; } public function getAvrFamily(): ?AvrFamily { 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; } public function getSupportedPhysicalInterfaces(): array { $physicalInterfacesByName = [ 'isp' => AvrPhysicalInterface::ISP, 'debugwire' => AvrPhysicalInterface::DEBUG_WIRE, 'updi' => AvrPhysicalInterface::UPDI, 'pdi' => AvrPhysicalInterface::PDI, 'jtag' => AvrPhysicalInterface::JTAG, ]; return array_filter( $physicalInterfacesByName, function(string $name) { return isset($this->physicalInterfacesByName[$name]); }, ARRAY_FILTER_USE_KEY ); } public function getSupportedDebugPhysicalInterfaces(): array { $physicalInterfacesByName = [ 'debugwire' => AvrPhysicalInterface::DEBUG_WIRE, 'updi' => AvrPhysicalInterface::UPDI, 'pdi' => AvrPhysicalInterface::PDI, 'jtag' => AvrPhysicalInterface::JTAG, ]; return array_filter( $physicalInterfacesByName, function(string $name) { return isset($this->physicalInterfacesByName[$name]); }, ARRAY_FILTER_USE_KEY ); } public function getTargetParameters(): TargetParameters { $output = new TargetParameters(); $registerMemorySegment = $this->getMemorySegment('data', 'regs'); if ($registerMemorySegment instanceof MemorySegment) { $output->gpRegisterSize = $registerMemorySegment->size; $output->gpRegisterStartAddress = $registerMemorySegment->startAddress; } $programMemoryAddressSpace = $this->addressSpacesById['prog'] ?? null; if ($programMemoryAddressSpace instanceof AddressSpace) { $output->flashSize = $programMemoryAddressSpace->size; $output->flashStartAddress = $programMemoryAddressSpace->startAddress; } $programMemorySegment = $this->getMemorySegment('prog', 'flash'); if ($programMemorySegment instanceof MemorySegment) { $output->flashPageSize = $programMemorySegment->pageSize; } $ramMemorySegment = $this->getMemorySegment('data', 'ram'); if ($ramMemorySegment instanceof MemorySegment) { $output->ramStartAddress = $ramMemorySegment->startAddress; $output->ramSize = $ramMemorySegment->size; } $eepromMemorySegment = $this->getMemorySegment( 'data', 'eeprom', 'eeprom' ); if ($eepromMemorySegment instanceof MemorySegment) { $output->eepromStartAddress = $eepromMemorySegment->startAddress; $output->eepromSize = $eepromMemorySegment->size; $output->eepromPageSize = $eepromMemorySegment->pageSize; } else if (isset($this->addressSpacesById['eeprom'])) { $eepromAddressSpace = $this->addressSpacesById['eeprom']; $output->eepromStartAddress = $eepromAddressSpace->startAddress; $eepromMemorySegment = $this->getMemorySegment('eeprom', 'eeprom'); if ($eepromMemorySegment instanceof MemorySegment) { $output->eepromSize = $eepromMemorySegment->size; $output->eepromPageSize = $eepromMemorySegment->pageSize; } } $eepromAddressRegister = $this->getModuleRegister( 'eeprom', 'eeprom', 'eear' ); if ($eepromAddressRegister instanceof Register) { $output->eepromAddressRegisterLow = $eepromAddressRegister->offset; $output->eepromAddressRegisterHigh = ($eepromAddressRegister->size == 2) ? $eepromAddressRegister->offset + 1 : $eepromAddressRegister->offset; } 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; } else { $stackPointerRegisterLow = $this->getModuleRegister( 'cpu', 'cpu', 'spl' ); if ($stackPointerRegisterLow instanceof Register) { $output->stackPointerRegisterLowAddress = $stackPointerRegisterLow->offset; $output->stackPointerRegisterSize = $stackPointerRegisterLow->size; } $stackPointerRegisterHigh = $this->getModuleRegister( 'cpu', 'cpu', 'sph' ); if ($stackPointerRegisterHigh instanceof Register) { $output->stackPointerRegisterSize += $stackPointerRegisterHigh->size; } } return $output; } 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; } 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; } 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; } 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; } 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(); if (is_null($this->getSignature())) { $failures[] = "Missing or incomplete AVR signature."; } $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'; } $targetParameters = $this->getTargetParameters(); if (is_null($targetParameters->stackPointerRegisterSize)) { $failures[] = 'Missing stack pointer register size.'; } if ($targetParameters->stackPointerRegisterSize > 2) { // The AVR architecture implementation in GDB expects all SP registers to be a maximum of two bytes in size. $failures[] = 'Stack pointer register size (' . $targetParameters->stackPointerRegisterSize . ') exceeds maximum (2).'; } if ($targetParameters->stackPointerRegisterSize < 1) { $failures[] = 'Stack pointer register size (' . $targetParameters->stackPointerRegisterSize . ') is less than 1.'; } if (is_null($targetParameters->stackPointerRegisterLowAddress)) { $failures[] = 'Missing stack pointer register start address.'; } if (is_null($targetParameters->statusRegisterStartAddress)) { $failures[] = 'Missing status register start address.'; } if (is_null($targetParameters->statusRegisterSize)) { $failures[] = 'Missing status register size.'; } else if ($targetParameters->statusRegisterSize > 1) { $failures[] = 'Status register size exceeds 1'; } if (is_null($targetParameters->flashSize)) { $failures[] = 'Missing flash size.'; } if (is_null($targetParameters->flashPageSize)) { $failures[] = 'Missing flash page size.'; } if (is_null($targetParameters->flashStartAddress)) { $failures[] = 'Missing flash start address.'; } if (is_null($targetParameters->ramStartAddress)) { $failures[] = 'Missing ram start address.'; } if (is_null($targetParameters->eepromSize)) { $failures[] = 'Missing eeprom size.'; } 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.'; } if (is_null($targetParameters->eepromPageSize)) { $failures[] = 'Missing eeprom page size.'; } if (is_null($targetParameters->eepromStartAddress)) { $failures[] = 'Missing eeprom start address.'; } if (in_array(AvrPhysicalInterface::DEBUG_WIRE, $debugPhysicalInterfaces)) { $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)) { $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.'; } } } if ( in_array(AvrPhysicalInterface::JTAG, $debugPhysicalInterfaces) && $family == AvrFamily::MEGA ) { $jtagParameters = $this->getJtagParameters(); if (is_null($jtagParameters->ocdRevision)) { $failures[] = 'Missing OCD revision.'; } if (is_null($jtagParameters->ocdDataRegister)) { $failures[] = 'Missing OCD data register address.'; } if (is_null($jtagParameters->spmcRegisterStartAddress)) { $failures[] = 'Missing store program memory control register start address.'; } if (is_null($jtagParameters->osccalAddress)) { $failures[] = 'Missing oscillator calibration register address.'; } 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)) { $pdiParameters = $this->getPdiParameters(); if (is_null($pdiParameters->appSectionPdiOffset)) { $failures[] = 'Missing app section PDI offset.'; } if (is_null($pdiParameters->bootSectionPdiOffset)) { $failures[] = 'Missing boot section PDI offset.'; } if (is_null($pdiParameters->ramPdiOffset)) { $failures[] = 'Missing datamem PDI offset.'; } if (is_null($pdiParameters->eepromPdiOffset)) { $failures[] = 'Missing eeprom PDI offset.'; } if (is_null($pdiParameters->userSignaturesPdiOffset)) { $failures[] = 'Missing user signatures PDI offset.'; } if (is_null($pdiParameters->productSignaturesPdiOffset)) { $failures[] = 'Missing product signatures PDI offset.'; } if (is_null($pdiParameters->lockRegistersPdiOffset)) { $failures[] = 'Missing lock registers PDI offset.'; } if (is_null($pdiParameters->nvmModuleBaseAddress)) { $failures[] = 'Missing NVM module base address.'; } if (is_null($pdiParameters->mcuModuleBaseAddress)) { $failures[] = 'Missing MCU module base address.'; } if (is_null($pdiParameters->appSectionStartAddress)) { $failures[] = 'Missing APP section start address'; } if (is_null($pdiParameters->appSectionSize)) { $failures[] = 'Missing APP section size'; } } if (in_array(AvrPhysicalInterface::UPDI, $debugPhysicalInterfaces)) { $updiParameters = $this->getUpdiParameters(); if (is_null($updiParameters->nvmModuleBaseAddress)) { $failures[] = 'Missing NVM base address.'; } if (is_null($updiParameters->programMemoryStartAddress)) { $failures[] = 'Missing UPDI program memory offset.'; } 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.'; } if (!is_null($targetParameters->flashPageSize) && $targetParameters->flashPageSize > 0xFFFF) { $failures[] = 'Flash page size exceeds maximum value for 16-bit unsigned integer.'; } if (is_null($updiParameters->ocdBaseAddress)) { $failures[] = 'Missing OCD base address.'; } else if ($updiParameters->ocdBaseAddress > 0xFFFF) { $failures[] = 'UPDI OCD base address exceeds maximum value for 16-bit unsigned integer.'; } if (is_null($updiParameters->signatureSegmentStartAddress)) { $failures[] = 'Missing signature segment start address.'; } if (is_null($updiParameters->fuseSegmentSize)) { $failures[] = 'Missing fuse segment size.'; } if (is_null($updiParameters->fuseSegmentStartAddress)) { $failures[] = 'Missing fuses segment start address.'; } if (is_null($updiParameters->lockbitsSegmentStartAddress)) { $failures[] = 'Missing lockbits segment start address.'; } } if ( in_array(AvrPhysicalInterface::JTAG, $debugPhysicalInterfaces) || in_array(AvrPhysicalInterface::UPDI, $debugPhysicalInterfaces) ) { if (empty($this->getFuseBitsDescriptor('eesave'))) { $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; } }