diff --git a/build/scripts/TargetDescriptionFiles/AVR8/Avr8TargetDescriptionFile.php b/build/scripts/TargetDescriptionFiles/AVR8/Avr8TargetDescriptionFile.php deleted file mode 100644 index a1cb5208..00000000 --- a/build/scripts/TargetDescriptionFiles/AVR8/Avr8TargetDescriptionFile.php +++ /dev/null @@ -1,903 +0,0 @@ -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; - } -} diff --git a/build/scripts/TargetDescriptionFiles/AVR8/DebugWireParameters.php b/build/scripts/TargetDescriptionFiles/AVR8/DebugWireParameters.php deleted file mode 100644 index 2600a8db..00000000 --- a/build/scripts/TargetDescriptionFiles/AVR8/DebugWireParameters.php +++ /dev/null @@ -1,10 +0,0 @@ -fuseType = $fuseType; - } -} diff --git a/build/scripts/TargetDescriptionFiles/AVR8/JtagParameters.php b/build/scripts/TargetDescriptionFiles/AVR8/JtagParameters.php deleted file mode 100644 index d3a04509..00000000 --- a/build/scripts/TargetDescriptionFiles/AVR8/JtagParameters.php +++ /dev/null @@ -1,10 +0,0 @@ -targetFamily == TargetFamily::AVR_8) { - return new Avr8TargetDescriptionFile($filePath); - } - - return $tdf; - } - - /** - * Recursively finds all XML files within a given directory. - * - * @param string $dirPath - * @return \SplFileInfo[] - */ - public static function findXmlFiles(string $dirPath): array - { - $output = []; - - $directory = new \DirectoryIterator($dirPath); - foreach ($directory as $entry) { - if ($entry->isFile() && $entry->getExtension() == 'xml') { - $output[] = clone $entry; - - } else if ($entry->isDir() && !$entry->isDot()) { - $output = array_merge($output, self::findXmlFiles($entry->getPathname())); - } - } - - return $output; - } -} diff --git a/build/scripts/TargetDescriptionFiles/MemorySegment.php b/build/scripts/TargetDescriptionFiles/MemorySegment.php deleted file mode 100644 index d8991757..00000000 --- a/build/scripts/TargetDescriptionFiles/MemorySegment.php +++ /dev/null @@ -1,11 +0,0 @@ -filePath = $filePath; - $this->init(); - } - - protected function init() - { - if (!file_exists($this->filePath)) { - throw new Exception("Invalid TDF file path - file does not exist."); - } - - $xml = simplexml_load_file($this->filePath); - if ($xml === false) { - throw new Exception("Failed to parse TDF XML."); - } - - $this->xml = $xml; - - $device = $this->xml->device; - if (!empty($device)) { - $this->deviceAttributesByName = current((array)$device->attributes()); - - if (!empty($this->deviceAttributesByName['name'])) { - $this->targetName = $device['name']; - $this->configurationValue = strtolower($device['name']); - } - - if (!empty($this->deviceAttributesByName['family'])) { - $this->targetFamily = TargetFamily::tryFrom($device['family']); - } - } - - $this->loadVariants(); - $this->loadAddressSpaces(); - $this->loadPropertyGroups(); - $this->loadModules(); - $this->loadPeripheralModules(); - $this->loadPhysicalInterfaces(); - $this->loadPinouts(); - } - - protected function stringToInt(?string $value): ?int - { - if (is_null($value)) { - return null; - } - - return stristr($value, '0x') !== false - ? (int) hexdec($value) - : (strlen($value) > 0 ? (int) $value : null); - } - - protected function getPeripheralModuleRegisterGroupOffset( - string $moduleName, - string $instanceName, - string $registerGroupName - ): ?int { - if (isset($this->peripheralModulesByName[$moduleName])) { - $module = $this->peripheralModulesByName[$moduleName]; - - if (isset($module->instancesMappedByName[$instanceName])) { - $instance = $module->instancesMappedByName[$instanceName]; - - if (isset($instance->registerGroupsMappedByName[$registerGroupName])) { - return $instance->registerGroupsMappedByName[$registerGroupName]->offset; - } - } - } - - return null; - } - - protected function getPropertyValue(string $propertyGroupName, string $propertyName): ?string - { - if (isset($this->propertyGroupsByName[$propertyGroupName])) { - $propertyGroup = $this->propertyGroupsByName[$propertyGroupName]; - - if (isset($propertyGroup->propertiesMappedByName[$propertyName])) { - return $propertyGroup->propertiesMappedByName[$propertyName]->value; - } - } - - return null; - } - - protected function getMemorySegment( - string $addressSpaceId, - string $memorySegmentType, - ?string $memorySegmentName = null - ): ?MemorySegment { - if (isset($this->addressSpacesById[$addressSpaceId])) { - $addressSpace = $this->addressSpacesById[$addressSpaceId]; - - if (isset($addressSpace->memorySegmentsByTypeAndName[$memorySegmentType])) { - $memorySegmentsByName = $addressSpace->memorySegmentsByTypeAndName[$memorySegmentType]; - - return !is_null($memorySegmentName) - ? $memorySegmentsByName[$memorySegmentName] ?? null - : reset($memorySegmentsByName); - } - } - - return null; - } - - protected function getMemorySegmentSize( - string $addressSpaceId, - string $memorySegmentType, - ?string $memorySegmentName = null - ): ?int { - $memorySegment = $this->getMemorySegment($addressSpaceId, $memorySegmentType, $memorySegmentName); - return $memorySegment instanceof MemorySegment ? $this->stringToInt($memorySegment->size) : null; - } - - protected function getModuleRegister( - string $moduleName, - string $registerGroupName, - string $registerName - ): ?Register { - if (isset($this->modulesByName[$moduleName])) { - $module = $this->modulesByName[$moduleName]; - - if (isset($module->registerGroupsMappedByName[$registerGroupName])) { - return $module->registerGroupsMappedByName[$registerGroupName]->registersMappedByName[$registerName] - ?? null; - } - } - - return null; - } - - private function loadVariants(): void - { - $variantElements = $this->xml->xpath('variants/variant'); - foreach ($variantElements as $variantElement) { - $variantAttributes = $variantElement->attributes(); - $variant = new Variant(); - - if (!empty($variantAttributes['name'])) { - $variant->name = $variantAttributes['name']; - } - - if (!empty($variantAttributes['package'])) { - $variant->package = $variantAttributes['package']; - } - - if (!empty($variantAttributes['pinout'])) { - $variant->pinout = $variantAttributes['pinout']; - } - - $this->variants[] = $variant; - } - } - - private function loadAddressSpaces(): void - { - $addressSpaceElements = $this->xml->xpath('device/address-spaces/address-space'); - foreach ($addressSpaceElements as $addressSpaceElement) { - $addressSpaceAttrs = $addressSpaceElement->attributes(); - $addressSpace = new AddressSpace(); - - $addressSpace->id = isset($addressSpaceElement['id']) ? $addressSpaceElement['id'] : null; - if (is_null($addressSpace->id)) { - // All address spaces must have an ID - don't bother if one isn't found - continue; - } - - $addressSpace->name = isset($addressSpaceAttrs['name']) ? $addressSpaceAttrs['name'] : null; - $addressSpace->startAddress = isset($addressSpaceAttrs['start']) - ? $this->stringToInt($addressSpaceAttrs['start']) : null; - $addressSpace->size = isset($addressSpaceAttrs['size']) - ? $this->stringToInt($addressSpaceAttrs['size']) : null; - - $memorySegmentElements = $addressSpaceElement->xpath('memory-segment'); - foreach ($memorySegmentElements as $memorySegmentElement) { - $memorySegmentAttrs = $memorySegmentElement->attributes(); - $memorySegment = new MemorySegment(); - - $memorySegment->name = isset($memorySegmentAttrs['name']) ? $memorySegmentAttrs['name'] : null; - $memorySegment->startAddress = isset($memorySegmentAttrs['start']) - ? $this->stringToInt($memorySegmentAttrs['start']) : null; - $memorySegment->type = isset($memorySegmentAttrs['type']) ? $memorySegmentAttrs['type'] : null; - $memorySegment->size = isset($memorySegmentAttrs['size']) - ? $this->stringToInt($memorySegmentAttrs['size']) : null; - $memorySegment->pageSize = isset($memorySegmentAttrs['pagesize']) - ? $this->stringToInt($memorySegmentAttrs['pagesize']) : null; - - $addressSpace->memorySegmentsByTypeAndName[strtolower($memorySegment->type)] - [strtolower($memorySegment->name)] = $memorySegment; - } - - $this->addressSpacesById[strtolower($addressSpace->id)] = $addressSpace; - } - } - - private function loadPropertyGroups(): void - { - $propertyGroupElements = $this->xml->xpath('device/property-groups/property-group'); - foreach ($propertyGroupElements as $propertyGroupElement) { - $propertyGroupAttrs = $propertyGroupElement->attributes(); - $propertyGroup = new PropertyGroup(); - - $propertyGroup->name = isset($propertyGroupAttrs['name']) ? $propertyGroupAttrs['name'] : null; - if (empty($propertyGroup->name)) { - continue; - } - - $propertyElements = $propertyGroupElement->xpath('property'); - foreach ($propertyElements as $propertyElement) { - $propertyAttrs = $propertyElement->attributes(); - $property = new Property(); - - $property->name = isset($propertyAttrs['name']) ? $propertyAttrs['name'] : null; - if (empty($propertyGroup->name)) { - continue; - } - - $property->value = isset($propertyAttrs['value']) ? $propertyAttrs['value'] : null; - - $propertyGroup->propertiesMappedByName[strtolower($property->name)] = $property; - } - - $this->propertyGroupsByName[strtolower($propertyGroup->name)] = $propertyGroup; - } - } - - private function generateRegisterGroupFromElement(SimpleXMLElement $registerGroupElement): ?RegisterGroup - { - $registerGroupAttrs = $registerGroupElement->attributes(); - $registerGroup = new RegisterGroup(); - - $registerGroup->name = isset($registerGroupAttrs['name']) ? $registerGroupAttrs['name'] : null; - if (empty($registerGroup->name)) { - return null; - } - - $registerGroup->offset = isset($registerGroupAttrs['offset']) - ? $this->stringToInt($registerGroupAttrs['offset']) : null; - - $registerElements = $registerGroupElement->xpath('register'); - foreach ($registerElements as $registerElement) { - $registerAttrs = $registerElement->attributes(); - $register = new Register(); - - $register->name = isset($registerAttrs['name']) ? $registerAttrs['name'] : null; - if (empty($register->name)) { - continue; - } - - $register->offset = isset($registerAttrs['offset']) - ? $this->stringToInt($registerAttrs['offset']) : null; - $register->size = isset($registerAttrs['size']) - ? $this->stringToInt($registerAttrs['size']) : null; - - $bitFieldElements = $registerElement->xpath('bitfield'); - foreach ($bitFieldElements as $bitFieldElement) { - $bitFieldAttrs = $bitFieldElement->attributes(); - $bitField = new BitField(); - - $bitField->name = isset($bitFieldAttrs['name']) ? $bitFieldAttrs['name'] : null; - if (empty($bitField->name)) { - continue; - } - - $register->bitFieldsByName[strtolower($bitField->name)] = $bitField; - } - - $registerGroup->registersMappedByName[strtolower($register->name)] = $register; - } - - return $registerGroup; - } - - private function generateModuleFromElement(SimpleXMLElement $moduleElement): ?Module - { - $moduleAttrs = $moduleElement->attributes(); - $module = new Module(); - - $module->name = isset($moduleAttrs['name']) ? $moduleAttrs['name'] : null; - if (empty($module->name)) { - return null; - } - - $registerGroupElements = $moduleElement->xpath('register-group'); - foreach ($registerGroupElements as $registerGroupElement) { - $registerGroup = $this->generateRegisterGroupFromElement($registerGroupElement); - - if ($registerGroup instanceof RegisterGroup) { - $module->registerGroupsMappedByName[strtolower($registerGroup->name)] = $registerGroup; - } - } - - $instanceElements = $moduleElement->xpath('instance'); - foreach ($instanceElements as $instanceElement) { - $instanceAttrs = $instanceElement->attributes(); - $moduleInstance = new ModuleInstance(); - - $moduleInstance->name = isset($instanceAttrs['name']) ? $instanceAttrs['name'] : null; - if (empty($moduleInstance->name)) { - continue; - } - - $registerGroupElements = $instanceElement->xpath('register-group'); - foreach ($registerGroupElements as $registerGroupElement) { - $registerGroup = $this->generateRegisterGroupFromElement($registerGroupElement); - - if ($registerGroup instanceof RegisterGroup) { - $moduleInstance->registerGroupsMappedByName[strtolower($registerGroup->name)] = $registerGroup; - } - } - - $signalElements = $instanceElement->xpath('signals/signal'); - foreach ($signalElements as $signalElement) { - $signalAttrs = $signalElement->attributes(); - $signal = new Signal(); - - $signal->padName = isset($signalAttrs['pad']) ? $signalAttrs['pad'] : null; - $signal->function = isset($signalAttrs['function']) ? $signalAttrs['function'] : null; - $signal->index = isset($signalAttrs['index']) ? $this->stringToInt($signalAttrs['index']) : null; - - $moduleInstance->signals[] = $signal; - } - - $module->instancesMappedByName[strtolower($moduleInstance->name)] = $moduleInstance; - } - - return $module; - } - - private function loadModules(): void - { - $moduleElements = $this->xml->xpath('modules/module'); - foreach ($moduleElements as $moduleElement) { - $module = $this->generateModuleFromElement($moduleElement); - - if ($module instanceof Module) { - $this->modulesByName[strtolower($module->name)] = $module; - } - } - } - - private function loadPeripheralModules(): void - { - $moduleElements = $this->xml->xpath('device/peripherals/module'); - foreach ($moduleElements as $moduleElement) { - $module = $this->generateModuleFromElement($moduleElement); - - if ($module instanceof Module) { - $this->peripheralModulesByName[strtolower($module->name)] = $module; - } - } - } - - private function loadPhysicalInterfaces(): void - { - $interfaceElements = $this->xml->xpath('device/interfaces/interface'); - foreach ($interfaceElements as $interfaceElement) { - $interfaceAttrs = $interfaceElement->attributes(); - $physicalInterface = new PhysicalInterface(); - - $physicalInterface->name = isset($interfaceAttrs['name']) ? $interfaceAttrs['name'] : null; - if (empty($physicalInterface->name)) { - continue; - } - - $physicalInterface->type = isset($interfaceAttrs['type']) ? $interfaceAttrs['type'] : null; - - $this->physicalInterfacesByName[strtolower($physicalInterface->name)] = $physicalInterface; - } - } - - private function loadPinouts(): void - { - $pinoutElements = $this->xml->xpath('pinouts/pinout'); - foreach ($pinoutElements as $pinoutElement) { - $pinoutAttrs = $pinoutElement->attributes(); - $pinout = new Pinout(); - - $pinout->name = isset($pinoutAttrs['name']) ? $pinoutAttrs['name'] : null; - $pinout->function = isset($pinoutAttrs['function']) ? $pinoutAttrs['function'] : null; - $pinout->type = PinoutType::tryFrom($pinout->name); - - // Attempt to extract the number of expected pins for this pinout, from the pinout name - $expectedPinCount = filter_var($pinout->name, FILTER_SANITIZE_NUMBER_INT); - if (is_numeric($expectedPinCount)) { - $pinout->expectedPinCount = (int) $expectedPinCount; - } - - $pinElements = $pinoutElement->xpath('pin'); - foreach ($pinElements as $pinElement) { - $pinAttrs = $pinElement->attributes(); - $pin = new Pin(); - - $pin->pad = isset($pinAttrs['pad']) ? $pinAttrs['pad'] : null; - $pin->position = isset($pinAttrs['position']) ? $this->stringToInt($pinAttrs['position']) : null; - - $pinout->pins[] = $pin; - } - - $this->pinoutsMappedByName[strtolower($pinout->name)] = $pinout; - } - } - - public function validate(): array - { - $failures = []; - - if (empty($this->targetName)) { - $failures[] = 'Target name not found'; - } - - if (str_contains($this->targetName, ' ')) { - $failures[] = 'Target name cannot contain whitespaces'; - } - - if (empty($this->targetFamily)) { - $failures[] = 'Missing/invalid target family'; - } - - if (empty($this->variants)) { - $failures[] = 'Missing target variants'; - } - - foreach ($this->variants as $variant) { - $variantValidationFailures = $variant->validate(); - - if (!empty($variantValidationFailures)) { - $failures[] = 'Variant validation failures: ' . implode(", ", $variantValidationFailures); - } - - if (empty($this->pinoutsMappedByName[strtolower($variant->pinout)])) { - $failures[] = 'Pinout ("' . $variant->pinout . '") for variant "' . $variant->name . '" not found.'; - } - } - - if (empty($this->pinoutsMappedByName)) { - $failures[] = 'No pinouts found'; - } - - foreach ($this->pinoutsMappedByName as $pinout) { - if (!is_null($pinout->expectedPinCount)) { - if ($pinout->expectedPinCount != count($pinout->pins)) { - $failures[] = 'Pin count (' . count($pinout->pins) . ') for pinout "' . $pinout->name - . '" does not match expected pin count (' . $pinout->expectedPinCount . ')'; - } - - } else { - $failures[] = 'Could not deduce expected pin count for pinout "' . $pinout->name . '"'; - } - - if (in_array($pinout->type, [PinoutType::DIP, PinoutType::QFN, PinoutType::SOIC])) { - foreach ($pinout->pins as $index => $pin) { - if (is_null($pin->position)) { - $failures[] = 'Missing/invalid pin position for pin (index: ' . $index . ').'; - } - - if (is_null($pin->pad)) { - $failures[] = 'Missing/invalid pin pad for pin (index: ' . $index . ').'; - } - } - } - - if ( - in_array($pinout->type, [PinoutType::SOIC, PinoutType::DIP, PinoutType::SSOP]) - && count($pinout->pins) % 2 != 0 - ) { - $failures[] = 'DIP/SOIC/SSOP pinout (' . $pinout->name . ') pin count is not a multiple of two.'; - } - - if (in_array($pinout->type, [PinoutType::QFN, PinoutType::QFP]) && count($pinout->pins) % 4 != 0) { - $failures[] = 'QFP/QFN pinout (' . $pinout->name . ') pin count is not a multiple of four.'; - } - } - - return $failures; - } -} diff --git a/build/scripts/TargetDescriptionFiles/Variant.php b/build/scripts/TargetDescriptionFiles/Variant.php deleted file mode 100644 index 988b2010..00000000 --- a/build/scripts/TargetDescriptionFiles/Variant.php +++ /dev/null @@ -1,28 +0,0 @@ -name)) { - $failures[] = 'Name not found'; - } - - if ($this->name == "standard") { - $failures[] = 'Name set to "standard" - needs attention'; - } - - if (empty($this->package)) { - $failures[] = 'Package not found'; - } - - return $failures; - } -} diff --git a/build/scripts/Targets/TargetDescriptionFiles/AVR8/Avr8TargetDescriptionFile.php b/build/scripts/Targets/TargetDescriptionFiles/AVR8/Avr8TargetDescriptionFile.php new file mode 100644 index 00000000..17e9924d --- /dev/null +++ b/build/scripts/Targets/TargetDescriptionFiles/AVR8/Avr8TargetDescriptionFile.php @@ -0,0 +1,513 @@ +stringService = $stringService ?? new StringService(); + } + + public function getAdditionalDeviceAttributes(): array + { + return [ + 'avr-family' => $this->getAvrFamily()->value, + ]; + } + + public function getSignature(): ?Signature + { + $byteZero = $this->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->stringService->tryStringToInt($byteZero); + $signature->byteOne = $this->stringService->tryStringToInt($byteOne); + $signature->byteTwo = $this->stringService->tryStringToInt($byteTwo); + + return $signature; + } + + return null; + } + + public function getAvrFamily(): ?AvrFamily + { + return AvrFamily::tryFrom($this->deviceAttributesByName['avr-family']); + } + + public function getSupportedPhysicalInterfaces(): array + { + $physicalInterfacesByName = [ + 'isp' => AvrPhysicalInterface::ISP, + 'debugwire' => AvrPhysicalInterface::DEBUG_WIRE, + 'updi' => AvrPhysicalInterface::UPDI, + 'pdi' => AvrPhysicalInterface::PDI, + 'jtag' => AvrPhysicalInterface::JTAG, + ]; + + return array_filter(array_map( + fn (PhysicalInterface $interface): ?AvrPhysicalInterface + => $physicalInterfacesByName[strtolower($interface->name ?? '')] ?? null, + $this->physicalInterfaces + )); + } + + public function getSupportedDebugPhysicalInterfaces(): array + { + $physicalInterfacesByName = [ + 'debugwire' => AvrPhysicalInterface::DEBUG_WIRE, + 'updi' => AvrPhysicalInterface::UPDI, + 'pdi' => AvrPhysicalInterface::PDI, + 'jtag' => AvrPhysicalInterface::JTAG, + ]; + + return array_filter(array_map( + fn (PhysicalInterface $interface): ?AvrPhysicalInterface + => $physicalInterfacesByName[strtolower($interface->name ?? '')] ?? null, + $this->physicalInterfaces + )); + } + + public function getDebugWireParameters(): DebugWireParameters + { + $output = new DebugWireParameters(); + + $programMemorySegment = $this->getProgramMemorySegment(); + if ($programMemorySegment instanceof MemorySegment) { + $output->flashStartAddress = $programMemorySegment->startAddress; + $output->flashSize = $programMemorySegment->size; + $output->flashPageSize = $programMemorySegment->pageSize; + } + + $ramMemorySegment = $this->getRamSegment(); + if ($ramMemorySegment instanceof MemorySegment) { + $output->ramStartAddress = $ramMemorySegment->startAddress; + } + + $output->bootSections = $this->getBootSections(); + + $eepromMemorySegment = $this->getEepromSegment(); + if ($eepromMemorySegment instanceof MemorySegment) { + $output->eepromSize = $eepromMemorySegment->size; + $output->eepromPageSize = $eepromMemorySegment->pageSize; + } + + $output->ocdRevision = $this->stringService->tryStringToInt($this->getPropertyValue('ocd', 'ocd_revision')); + $output->ocdDataRegister = $this->stringService->tryStringToInt($this->getPropertyValue('ocd', 'ocd_datareg')); + + $eepromPeripheral = $this->getTargetPeripheral('eeprom'); + + if ($eepromPeripheral instanceof TargetPeripheral) { + $eepromAddressRegister = $eepromPeripheral->getRegister('eeprom', 'eear'); + + if ($eepromAddressRegister instanceof TargetRegister) { + $output->eepromAddressRegisterLow = $eepromAddressRegister->address; + $output->eepromAddressRegisterHigh = ($eepromAddressRegister->size == 2) + ? $eepromAddressRegister->address + 1 + : $eepromAddressRegister->address; + + } else { + $eepromAddressRegisterLow = $eepromPeripheral->getRegister('eeprom', 'eearl'); + $eepromAddressRegisterHigh = $eepromPeripheral->getRegister('eeprom', 'eearh'); + + if ($eepromAddressRegisterLow instanceof TargetRegister) { + $output->eepromAddressRegisterLow = $eepromAddressRegisterLow->address; + $output->eepromAddressRegisterHigh = $eepromAddressRegisterLow->address; + } + + if ($eepromAddressRegisterHigh instanceof TargetRegister) { + $output->eepromAddressRegisterHigh = $eepromAddressRegisterHigh->address; + } + } + + $eepromDataRegister = $eepromPeripheral->getRegister('eeprom', 'eedr'); + if ($eepromDataRegister instanceof TargetRegister) { + $output->eepromDataRegisterAddress = $eepromDataRegister->address; + } + + $eepromControlRegister = $eepromPeripheral->getRegister('eeprom', 'eecr'); + if ($eepromControlRegister instanceof TargetRegister) { + $output->eepromControlRegisterAddress = $eepromControlRegister->address; + } + } + + $cpuPeripheral = $this->getTargetPeripheral('cpu'); + + if ($cpuPeripheral instanceof TargetPeripheral) { + $spmcsRegister = $cpuPeripheral->getRegister('cpu', 'spmcsr') + ?? $cpuPeripheral->getRegister('cpu', 'spmcr'); + + if ($spmcsRegister instanceof TargetRegister) { + $output->spmcRegisterStartAddress = $spmcsRegister->address; + } + + $osccalRegister = $cpuPeripheral->getRegister('cpu', 'osccal') + ?? $cpuPeripheral->getRegister('cpu', 'osccal0') + ?? $cpuPeripheral->getRegister('cpu', 'osccal1') + ?? $cpuPeripheral->getRegister('cpu', 'fosccal') + ?? $cpuPeripheral->getRegister('cpu', 'sosccala'); + + if ($osccalRegister instanceof TargetRegister) { + $output->osccalAddress = $osccalRegister->address; + } + } + + if ($output->spmcRegisterStartAddress === null) { + $bootLoaderPeripheral = $this->getTargetPeripheral('boot_load'); + + if ($bootLoaderPeripheral instanceof TargetPeripheral) { + $spmcsRegister = $bootLoaderPeripheral->getRegister('boot_load', 'spmcr') + ?? $bootLoaderPeripheral->getRegister('boot_load', 'spmcsr'); + + if ($spmcsRegister instanceof TargetRegister) { + $output->spmcRegisterStartAddress = $spmcsRegister->address; + } + } + } + + return $output; + } + + public function getIspParameters(): IspParameters + { + $output = new IspParameters(); + + $output->programModeTimeout = $this->stringService->tryStringToInt( + $this->getPropertyValue('isp_interface', 'ispenterprogmode_timeout') + ); + $output->programModeStabilizationDelay = $this->stringService->tryStringToInt( + $this->getPropertyValue('isp_interface', 'ispenterprogmode_stabdelay') + ); + $output->programModeCommandExecutionDelay = $this->stringService->tryStringToInt( + $this->getPropertyValue('isp_interface', 'ispenterprogmode_cmdexedelay') + ); + $output->programModeSyncLoops = $this->stringService->tryStringToInt( + $this->getPropertyValue('isp_interface', 'ispenterprogmode_synchloops') + ); + $output->programModeByteDelay = $this->stringService->tryStringToInt( + $this->getPropertyValue('isp_interface', 'ispenterprogmode_bytedelay') + ); + $output->programModePollValue = $this->stringService->tryStringToInt( + $this->getPropertyValue('isp_interface', 'ispenterprogmode_pollvalue') + ); + $output->programModePollIndex = $this->stringService->tryStringToInt( + $this->getPropertyValue('isp_interface', 'ispenterprogmode_pollindex') + ); + $output->programModePreDelay = $this->stringService->tryStringToInt( + $this->getPropertyValue('isp_interface', 'ispleaveprogmode_predelay') + ); + $output->programModePostDelay = $this->stringService->tryStringToInt( + $this->getPropertyValue('isp_interface', 'ispleaveprogmode_postdelay') + ); + $output->readSignaturePollIndex = $this->stringService->tryStringToInt( + $this->getPropertyValue('isp_interface', 'ispreadsign_pollindex') + ); + $output->readFusePollIndex = $this->stringService->tryStringToInt( + $this->getPropertyValue('isp_interface', 'ispreadfuse_pollindex') + ); + $output->readLockPollIndex = $this->stringService->tryStringToInt( + $this->getPropertyValue('isp_interface', 'ispreadlock_pollindex') + ); + + return $output; + } + + public function getJtagParameters(): JtagParameters + { + $output = new JtagParameters(); + + $programMemorySegment = $this->getProgramMemorySegment(); + if ($programMemorySegment instanceof MemorySegment) { + $output->flashStartAddress = $programMemorySegment->startAddress; + $output->flashSize = $programMemorySegment->size; + $output->flashPageSize = $programMemorySegment->pageSize; + } + + $ramMemorySegment = $this->getRamSegment(); + if ($ramMemorySegment instanceof MemorySegment) { + $output->ramStartAddress = $ramMemorySegment->startAddress; + } + + $output->bootSections = $this->getBootSections(); + + $eepromMemorySegment = $this->getEepromSegment(); + if ($eepromMemorySegment instanceof MemorySegment) { + $output->eepromSize = $eepromMemorySegment->size; + $output->eepromPageSize = $eepromMemorySegment->pageSize; + } + + $output->ocdRevision = $this->stringService->tryStringToInt($this->getPropertyValue('ocd', 'ocd_revision')); + $output->ocdDataRegister = $this->stringService->tryStringToInt($this->getPropertyValue('ocd', 'ocd_datareg')); + + $eepromPeripheral = $this->getTargetPeripheral('eeprom'); + + if ($eepromPeripheral instanceof TargetPeripheral) { + $eepromAddressRegister = $eepromPeripheral->getRegister('eeprom', 'eear'); + + if ($eepromAddressRegister instanceof TargetRegister) { + $output->eepromAddressRegisterLow = $eepromAddressRegister->address; + $output->eepromAddressRegisterHigh = ($eepromAddressRegister->size == 2) + ? $eepromAddressRegister->address + 1 + : $eepromAddressRegister->address; + + } else { + $eepromAddressRegisterLow = $eepromPeripheral->getRegister('eeprom', 'eearl'); + $eepromAddressRegisterHigh = $eepromPeripheral->getRegister('eeprom', 'eearh'); + + if ($eepromAddressRegisterLow instanceof TargetRegister) { + $output->eepromAddressRegisterLow = $eepromAddressRegisterLow->address; + $output->eepromAddressRegisterHigh = $eepromAddressRegisterLow->address; + } + + if ($eepromAddressRegisterHigh instanceof TargetRegister) { + $output->eepromAddressRegisterHigh = $eepromAddressRegisterHigh->address; + } + } + + $eepromDataRegister = $eepromPeripheral->getRegister('eeprom', 'eedr'); + if ($eepromDataRegister instanceof TargetRegister) { + $output->eepromDataRegisterAddress = $eepromDataRegister->address; + } + + $eepromControlRegister = $eepromPeripheral->getRegister('eeprom', 'eecr'); + if ($eepromControlRegister instanceof TargetRegister) { + $output->eepromControlRegisterAddress = $eepromControlRegister->address; + } + } + + $cpuPeripheral = $this->getTargetPeripheral('cpu'); + + if ($cpuPeripheral instanceof TargetPeripheral) { + $spmcsRegister = $cpuPeripheral->getRegister('cpu', 'spmcsr') + ?? $cpuPeripheral->getRegister('cpu', 'spmcr'); + + if ($spmcsRegister instanceof TargetRegister) { + $output->spmcRegisterStartAddress = $spmcsRegister->address; + } + + $osccalRegister = $cpuPeripheral->getRegister('cpu', 'osccal') + ?? $cpuPeripheral->getRegister('cpu', 'osccal0') + ?? $cpuPeripheral->getRegister('cpu', 'osccal1') + ?? $cpuPeripheral->getRegister('cpu', 'fosccal') + ?? $cpuPeripheral->getRegister('cpu', 'sosccala'); + + if ($osccalRegister instanceof TargetRegister) { + $output->osccalAddress = $osccalRegister->address; + } + } + + if ($output->spmcRegisterStartAddress === null) { + $bootLoaderPeripheral = $this->getTargetPeripheral('boot_load'); + + if ($bootLoaderPeripheral instanceof TargetPeripheral) { + $spmcsRegister = $bootLoaderPeripheral->getRegister('boot_load', 'spmcr') + ?? $bootLoaderPeripheral->getRegister('boot_load', 'spmcsr'); + + if ($spmcsRegister instanceof TargetRegister) { + $output->spmcRegisterStartAddress = $spmcsRegister->address; + } + } + } + + return $output; + } + + public function getPdiParameters(): PdiParameters + { + $output = new PdiParameters(); + + $output->appSectionOffset = $this->stringService->tryStringToInt( + $this->getPropertyValue('pdi_interface', 'app_section_offset') + ); + $output->bootSectionOffset = $this->stringService->tryStringToInt( + $this->getPropertyValue('pdi_interface', 'boot_section_offset') + ); + $output->ramOffset = $this->stringService->tryStringToInt( + $this->getPropertyValue('pdi_interface', 'datamem_offset') + ); + $output->eepromOffset = $this->stringService->tryStringToInt( + $this->getPropertyValue('pdi_interface', 'eeprom_offset') + ); + $output->userSignaturesOffset = $this->stringService->tryStringToInt( + $this->getPropertyValue('pdi_interface', 'user_signatures_offset') + ); + $output->productSignaturesOffset = $this->stringService->tryStringToInt( + $this->getPropertyValue('pdi_interface', 'prod_signatures_offset') + ); + $output->fuseRegistersOffset = $this->stringService->tryStringToInt( + $this->getPropertyValue('pdi_interface', 'fuse_registers_offset') + ); + $output->lockRegistersOffset = $this->stringService->tryStringToInt( + $this->getPropertyValue('pdi_interface', 'lock_registers_offset') + ); + + $programMemorySegment = $this->getProgramMemorySegment(); + if ($programMemorySegment instanceof MemorySegment) { + $output->flashPageSize = $programMemorySegment->pageSize; + + $appSection = $programMemorySegment->getSection('app_section'); + if ($appSection instanceof MemorySegmentSection) { + $output->appSectionSize = $appSection->size; + } + + $bootSection = $programMemorySegment->getSection('boot_section'); + if ($bootSection instanceof MemorySegmentSection) { + $output->bootSectionSize = $bootSection->size; + } + } + + $eepromMemorySegment = $this->getEepromSegment(); + if ($eepromMemorySegment instanceof MemorySegment) { + $output->eepromSize = $eepromMemorySegment->size; + $output->eepromPageSize = $eepromMemorySegment->pageSize; + } + + $nvmModuleRegisterGroup = $this->getTargetRegisterGroup('nvm', 'nvm'); + if ($nvmModuleRegisterGroup instanceof TargetRegisterGroup) { + $output->nvmModuleBaseAddress = $nvmModuleRegisterGroup->baseAddress; + } + + $output->signatureOffset = $this->stringService->tryStringToInt( + $this->getPropertyValue('pdi_interface', 'signature_offset') + ); + + return $output; + } + + public function getUpdiParameters(): UpdiParameters + { + $output = new UpdiParameters(); + + $output->programMemoryOffset = $this->stringService->tryStringToInt( + $this->getPropertyValue('updi_interface', 'progmem_offset') + ); + + $programMemorySegment = $this->getProgramMemorySegment(); + if ($programMemorySegment instanceof MemorySegment) { + $output->flashSize = $programMemorySegment->size; + $output->flashPageSize = $programMemorySegment->pageSize; + } + + $eepromMemorySegment = $this->getEepromSegment(); + if ($eepromMemorySegment instanceof MemorySegment) { + $output->eepromStartAddress = $eepromMemorySegment->startAddress; + $output->eepromSize = $eepromMemorySegment->size; + $output->eepromPageSize = $eepromMemorySegment->pageSize; + } + + $output->nvmModuleBaseAddress = $this->getTargetRegisterGroup( + 'nvmctrl', + 'nvmctrl' + )->baseAddress ?? null; + + $output->ocdBaseAddress = $this->stringService->tryStringToInt( + $this->getPropertyValue('updi_interface', 'ocd_base_addr') + ); + + $signatureMemorySegment = $this->getMemorySegment( + 'data', + 'signatures' + ); + if ($signatureMemorySegment instanceof MemorySegment) { + $output->signatureSegmentStartAddress = $signatureMemorySegment->startAddress; + } + + $fuseMemorySegment = $this->getMemorySegment( + 'data', + 'fuses' + ); + if ($fuseMemorySegment instanceof MemorySegment) { + $output->fuseSegmentSize = $fuseMemorySegment->size; + $output->fuseSegmentStartAddress = $fuseMemorySegment->startAddress; + } + + $lockbitsMemorySegment = $this->getMemorySegment( + 'data', + 'lockbits' + ); + if ($lockbitsMemorySegment instanceof MemorySegment) { + $output->lockbitsSegmentStartAddress = $lockbitsMemorySegment->startAddress; + } + + return $output; + } + + public function getFuseBitsDescriptor(string $fuseBitFieldKey): ?FuseBitsDescriptor + { + $peripheral = $this->getTargetPeripheral('fuse') ?? $this->getTargetPeripheral('nvm'); + if ($peripheral instanceof TargetPeripheral) { + $fuseRegisterGroup = $peripheral->getRegisterGroup('fuse') + ?? $peripheral->getRegisterGroup('nvm_fuses'); + + if ($fuseRegisterGroup instanceof TargetRegisterGroup) { + foreach ($fuseRegisterGroup->registers as $fuseRegister) { + foreach ($fuseRegister->bitFields as $bitField) { + if ($bitField->key === $fuseBitFieldKey) { + return new FuseBitsDescriptor($fuseRegister->name); + } + } + } + } + } + + return null; + } + + private function getProgramMemorySegment(): ?MemorySegment + { + return $this->getMemorySegment('prog', 'internal_program_memory'); + } + + private function getRamSegment(): ?MemorySegment + { + return $this->getMemorySegment('data', 'internal_ram'); + } + + private function getEepromSegment(): ?MemorySegment + { + return $this->getMemorySegment('data', 'internal_eeprom') + ?? $this->getMemorySegment('eeprom', 'internal_eeprom'); + } + + private function getBootSections(): array + { + $output = []; + + $bootSectionPropertyGroups = $this->getPropertyGroup('boot_sections')->subPropertyGroups ?? []; + foreach ($bootSectionPropertyGroups as $propertyGroup) { + $output[] = new BootSection( + $this->stringService->tryStringToInt($propertyGroup->getPropertyValue('start_address')), + $this->stringService->tryStringToInt($propertyGroup->getPropertyValue('size')), + $this->stringService->tryStringToInt($propertyGroup->getPropertyValue('page_size')) + ); + } + + return $output; + } +} diff --git a/build/scripts/TargetDescriptionFiles/AVR8/AvrFamily.php b/build/scripts/Targets/TargetDescriptionFiles/AVR8/AvrFamily.php similarity index 76% rename from build/scripts/TargetDescriptionFiles/AVR8/AvrFamily.php rename to build/scripts/Targets/TargetDescriptionFiles/AVR8/AvrFamily.php index 1633a982..409d0bd7 100644 --- a/build/scripts/TargetDescriptionFiles/AVR8/AvrFamily.php +++ b/build/scripts/Targets/TargetDescriptionFiles/AVR8/AvrFamily.php @@ -1,5 +1,5 @@ startAddress = $startAddress; + $this->size = $size; + $this->pageSize = $pageSize; + } +} diff --git a/build/scripts/TargetDescriptionFiles/AVR8/TargetParameters.php b/build/scripts/Targets/TargetDescriptionFiles/AVR8/DebugWireParameters.php similarity index 50% rename from build/scripts/TargetDescriptionFiles/AVR8/TargetParameters.php rename to build/scripts/Targets/TargetDescriptionFiles/AVR8/DebugWireParameters.php index 40376149..301ff9b7 100644 --- a/build/scripts/TargetDescriptionFiles/AVR8/TargetParameters.php +++ b/build/scripts/Targets/TargetDescriptionFiles/AVR8/DebugWireParameters.php @@ -1,24 +1,26 @@ fuseType = strtolower($fuseType); + } +} diff --git a/build/scripts/TargetDescriptionFiles/AVR8/IspParameters.php b/build/scripts/Targets/TargetDescriptionFiles/AVR8/IspParameters.php similarity index 91% rename from build/scripts/TargetDescriptionFiles/AVR8/IspParameters.php rename to build/scripts/Targets/TargetDescriptionFiles/AVR8/IspParameters.php index eb77b41f..b8130d3a 100644 --- a/build/scripts/TargetDescriptionFiles/AVR8/IspParameters.php +++ b/build/scripts/Targets/TargetDescriptionFiles/AVR8/IspParameters.php @@ -1,5 +1,5 @@ byteZero) || is_null($this->byteOne) || is_null($this->byteTwo)) { + if ($this->byteZero === null || $this->byteOne === null || $this->byteTwo === null) { throw new \Exception("Cannot generate hex string of incomplete AVR8 target signature."); } diff --git a/build/scripts/TargetDescriptionFiles/AVR8/UpdiParameters.php b/build/scripts/Targets/TargetDescriptionFiles/AVR8/UpdiParameters.php similarity index 52% rename from build/scripts/TargetDescriptionFiles/AVR8/UpdiParameters.php rename to build/scripts/Targets/TargetDescriptionFiles/AVR8/UpdiParameters.php index 11cedcdb..8774e0ba 100644 --- a/build/scripts/TargetDescriptionFiles/AVR8/UpdiParameters.php +++ b/build/scripts/Targets/TargetDescriptionFiles/AVR8/UpdiParameters.php @@ -1,13 +1,17 @@ key = $key; + $this->startAddress = $startAddress; + $this->size = $size; + $this->endianness = $endianness; + } + + public function totalSegmentSize(): int + { + return array_sum( + array_map( + fn (MemorySegment $segment): int => (int) $segment->size, + $this->memorySegments + ) + ); + } + + public function segmentStartAddress(): int + { + return min( + array_map( + fn (MemorySegment $segment): int => (int) $segment->startAddress, + $this->memorySegments + ) + ); + } + + public function segmentEndAddress(): int + { + return max( + array_map( + fn (MemorySegment $segment): int => (int) $segment->startAddress + $segment->size - 1, + $this->memorySegments + ) + ); + } +} diff --git a/build/scripts/Targets/TargetDescriptionFiles/BitField.php b/build/scripts/Targets/TargetDescriptionFiles/BitField.php new file mode 100644 index 00000000..9f83ffaa --- /dev/null +++ b/build/scripts/Targets/TargetDescriptionFiles/BitField.php @@ -0,0 +1,35 @@ +key = $key; + $this->name = $name; + $this->description = $description; + $this->mask = $mask; + $this->access = $access; + } + + public function intersectsWith(BitField $other): bool + { + return + $this->mask !== null + && $other->mask !== null + && ($this->mask & $other->mask) !== 0 + ; + } +} diff --git a/build/scripts/Targets/TargetDescriptionFiles/MemorySegment.php b/build/scripts/Targets/TargetDescriptionFiles/MemorySegment.php new file mode 100644 index 00000000..9cb68ed1 --- /dev/null +++ b/build/scripts/Targets/TargetDescriptionFiles/MemorySegment.php @@ -0,0 +1,98 @@ +key = $key; + $this->name = $name; + $this->type = $type; + $this->startAddress = $startAddress; + $this->size = $size; + $this->pageSize = $pageSize; + $this->access = $access; + $this->sections = $sections; + } + + public function getSection(string $sectionId): ?MemorySegmentSection + { + foreach ($this->sections as $section) { + if ($section->key !== $sectionId) { + continue; + } + + return $section; + } + + return null; + } + + public function contains(MemorySegment $other): bool + { + $endAddress = !is_null($this->startAddress) && !is_null($this->size) + ? ($this->startAddress + $this->size - 1) : null; + $otherEndAddress = !is_null($other->startAddress) && !is_null($other->size) + ? ($other->startAddress + $other->size - 1) : null; + + return + $this->startAddress !== null + && $endAddress !== null + && $other->startAddress !== null + && $otherEndAddress !== null + && $this->startAddress <= $other->startAddress + && $endAddress >= $otherEndAddress + ; + } + + public function intersectsWith(MemorySegment $other): bool + { + $endAddress = !is_null($this->startAddress) && !is_null($this->size) + ? ($this->startAddress + $this->size - 1) : null; + $otherEndAddress = !is_null($other->startAddress) && !is_null($other->size) + ? ($other->startAddress + $other->size - 1) : null; + + return + $this->startAddress !== null + && $endAddress !== null + && $other->startAddress !== null + && $otherEndAddress !== null + && ( + ($other->startAddress <= $this->startAddress && $otherEndAddress >= $this->startAddress) + || ($other->startAddress >= $this->startAddress && $other->startAddress <= $endAddress) + ) + ; + } + + public function totalSectionSize(): int + { + return array_sum( + array_map( + fn (MemorySegmentSection $section): int => (int) $section->size, + $this->sections + ) + ); + } +} diff --git a/build/scripts/Targets/TargetDescriptionFiles/MemorySegmentSection.php b/build/scripts/Targets/TargetDescriptionFiles/MemorySegmentSection.php new file mode 100644 index 00000000..66a6d65a --- /dev/null +++ b/build/scripts/Targets/TargetDescriptionFiles/MemorySegmentSection.php @@ -0,0 +1,63 @@ +key = $key; + $this->name = $name; + $this->startAddress = $startAddress; + $this->size = $size; + $this->subSections = $subSections; + } + + public function contains(MemorySegment $other): bool + { + $endAddress = !is_null($this->startAddress) && !is_null($this->size) + ? ($this->startAddress + $this->size - 1) : null; + $otherEndAddress = !is_null($other->startAddress) && !is_null($other->size) + ? ($other->startAddress + $other->size - 1) : null; + + return + $this->startAddress !== null + && $endAddress !== null + && $other->startAddress !== null + && $otherEndAddress !== null + && $this->startAddress <= $other->startAddress + && $endAddress >= $otherEndAddress + ; + } + + public function intersectsWith(MemorySegmentSection $other): bool + { + $endAddress = !is_null($this->startAddress) && !is_null($this->size) + ? ($this->startAddress + $this->size - 1) : null; + $otherEndAddress = !is_null($other->startAddress) && !is_null($other->size) + ? ($other->startAddress + $other->size - 1) : null; + + return + $this->startAddress !== null + && $endAddress !== null + && $other->startAddress !== null + && $otherEndAddress !== null + && ( + ($other->startAddress <= $this->startAddress && $otherEndAddress >= $this->startAddress) + || ($other->startAddress >= $this->startAddress && $other->startAddress <= $endAddress) + ) + ; + } +} diff --git a/build/scripts/Targets/TargetDescriptionFiles/MemorySegmentType.php b/build/scripts/Targets/TargetDescriptionFiles/MemorySegmentType.php new file mode 100644 index 00000000..351180f2 --- /dev/null +++ b/build/scripts/Targets/TargetDescriptionFiles/MemorySegmentType.php @@ -0,0 +1,18 @@ +key = $key; + $this->name = $name; + $this->description = $description; + $this->registerGroups = $registerGroups; + } + + public function getRegisterGroup(array|string $keys): ?RegisterGroup + { + if (is_string($keys)) { + $keys = explode('.', $keys); + } + + $firstLevelSubGroupId = array_shift($keys); + foreach ($this->registerGroups as $registerGroup) { + if ($registerGroup->key === $firstLevelSubGroupId) { + return !empty($keys) ? $registerGroup->getSubGroup($keys) : $registerGroup; + } + } + + return null; + } +} diff --git a/build/scripts/Targets/TargetDescriptionFiles/Peripheral.php b/build/scripts/Targets/TargetDescriptionFiles/Peripheral.php new file mode 100644 index 00000000..59042f18 --- /dev/null +++ b/build/scripts/Targets/TargetDescriptionFiles/Peripheral.php @@ -0,0 +1,45 @@ +key = $key; + $this->name = $name; + $this->moduleKey = $moduleKey; + $this->registerGroupReferences = $registerGroupReferences; + $this->signals = $signals; + } + + public function getRegisterGroupReference(string $key): ?RegisterGroupReference + { + foreach ($this->registerGroupReferences as $reference) { + if ($reference->key === $key) { + return $reference; + } + } + + return null; + } +} diff --git a/build/scripts/Targets/TargetDescriptionFiles/PhysicalInterface.php b/build/scripts/Targets/TargetDescriptionFiles/PhysicalInterface.php new file mode 100644 index 00000000..0a4ae3ba --- /dev/null +++ b/build/scripts/Targets/TargetDescriptionFiles/PhysicalInterface.php @@ -0,0 +1,14 @@ +name = $name; + $this->type = $type; + } +} diff --git a/build/scripts/Targets/TargetDescriptionFiles/Pin.php b/build/scripts/Targets/TargetDescriptionFiles/Pin.php new file mode 100644 index 00000000..aed6e5c1 --- /dev/null +++ b/build/scripts/Targets/TargetDescriptionFiles/Pin.php @@ -0,0 +1,14 @@ +position = $position; + $this->pad = $pad; + } +} diff --git a/build/scripts/Targets/TargetDescriptionFiles/Pinout.php b/build/scripts/Targets/TargetDescriptionFiles/Pinout.php new file mode 100644 index 00000000..16d75b8f --- /dev/null +++ b/build/scripts/Targets/TargetDescriptionFiles/Pinout.php @@ -0,0 +1,30 @@ +key = $key; + $this->name = $name; + $this->type = $type; + $this->function = $function; + $this->pins = $pins; + } +} diff --git a/build/scripts/Targets/TargetDescriptionFiles/PinoutType.php b/build/scripts/Targets/TargetDescriptionFiles/PinoutType.php new file mode 100644 index 00000000..0917bd10 --- /dev/null +++ b/build/scripts/Targets/TargetDescriptionFiles/PinoutType.php @@ -0,0 +1,14 @@ +key = $key; + $this->value = $value; + } +} diff --git a/build/scripts/Targets/TargetDescriptionFiles/PropertyGroup.php b/build/scripts/Targets/TargetDescriptionFiles/PropertyGroup.php new file mode 100644 index 00000000..25dca433 --- /dev/null +++ b/build/scripts/Targets/TargetDescriptionFiles/PropertyGroup.php @@ -0,0 +1,57 @@ +key = $key; + $this->subPropertyGroups = $subPropertyGroups; + $this->properties = $properties; + } + + public function getSubGroup(array|string $subGroupKeys): ?PropertyGroup + { + if (is_string($subGroupKeys)) { + $subGroupKeys = explode('.', $subGroupKeys); + } + + $firstLevelSubGroupKey = array_shift($subGroupKeys); + foreach ($this->subPropertyGroups as $subGroup) { + if ($subGroup->key === $firstLevelSubGroupKey) { + return !empty($subGroupKeys) ? $subGroup->getSubGroup($subGroupKeys) : $subGroup; + } + } + + return null; + } + + public function getProperty(string $propertyKey): ?Property + { + foreach ($this->properties as $property) { + if ($property->key === $propertyKey) { + return $property; + } + } + + return null; + } + + public function getPropertyValue(string $propertyKey): ?string + { + return ($property = $this->getProperty($propertyKey)) instanceof Property ? $property->value : null; + } +} diff --git a/build/scripts/Targets/TargetDescriptionFiles/Register.php b/build/scripts/Targets/TargetDescriptionFiles/Register.php new file mode 100644 index 00000000..b975239e --- /dev/null +++ b/build/scripts/Targets/TargetDescriptionFiles/Register.php @@ -0,0 +1,63 @@ +key = $key; + $this->name = $name; + $this->description = $description; + $this->offset = $offset; + $this->size = $size; + $this->initialValue = $initialValue; + $this->access = $access; + $this->alternative = $alternative; + $this->bitFields = $bitFields; + } + + public function intersectsWith(Register $other): bool + { + $endAddress = !is_null($this->offset) && !is_null($this->size) + ? ($this->offset + $this->size - 1) : null; + $otherEndAddress = !is_null($other->offset) && !is_null($other->size) + ? ($other->offset + $other->size - 1) : null; + + return + $this->offset !== null + && $endAddress !== null + && $other->offset !== null + && $otherEndAddress !== null + && ( + ($other->offset <= $this->offset && $otherEndAddress >= $this->offset) + || ($other->offset >= $this->offset && $other->offset <= $endAddress) + ) + ; + } +} diff --git a/build/scripts/Targets/TargetDescriptionFiles/RegisterGroup.php b/build/scripts/Targets/TargetDescriptionFiles/RegisterGroup.php new file mode 100644 index 00000000..b92c4cce --- /dev/null +++ b/build/scripts/Targets/TargetDescriptionFiles/RegisterGroup.php @@ -0,0 +1,76 @@ +key = $key; + $this->name = $name; + $this->offset = $offset; + $this->registers = $registers; + $this->subGroups = $subGroups; + $this->subGroupReferences = $subGroupReferences; + } + + public function getRegister(array|string $keys): ?Register + { + if (is_string($keys)) { + $keys = explode('.', $keys); + } + + $registerKey = array_pop($keys); + $group = !empty($keys) > 1 ? $this->getSubGroup($keys) : $this; + + if ($group instanceof RegisterGroup) { + foreach ($group->registers as $register) { + if ($register->key === $registerKey) { + return $register; + } + } + } + + return null; + } + + public function getSubGroup(array|string $subGroupKeys): ?RegisterGroup + { + if (is_string($subGroupKeys)) { + $subGroupKeys = explode('.', $subGroupKeys); + } + + $firstLevelSubGroupKey = array_shift($subGroupKeys); + foreach ($this->subGroups as $subGroup) { + if ($subGroup->key === $firstLevelSubGroupKey) { + return !empty($subGroupKeys) ? $subGroup->getSubGroup($subGroupKeys) : $subGroup; + } + } + + return null; + } +} diff --git a/build/scripts/Targets/TargetDescriptionFiles/RegisterGroupReference.php b/build/scripts/Targets/TargetDescriptionFiles/RegisterGroupReference.php new file mode 100644 index 00000000..169ee385 --- /dev/null +++ b/build/scripts/Targets/TargetDescriptionFiles/RegisterGroupReference.php @@ -0,0 +1,27 @@ +key = $key; + $this->name = $name; + $this->registerGroupKey = $registerGroupKey; + $this->offset = $offset; + $this->description = $description; + } +} diff --git a/build/scripts/Targets/TargetDescriptionFiles/Services/StringService.php b/build/scripts/Targets/TargetDescriptionFiles/Services/StringService.php new file mode 100644 index 00000000..17be9613 --- /dev/null +++ b/build/scripts/Targets/TargetDescriptionFiles/Services/StringService.php @@ -0,0 +1,23 @@ +padId = $padId; + $this->index = $index; + $this->function = $function; + $this->group = $group; + $this->field = $field; + } +} diff --git a/build/scripts/Targets/TargetDescriptionFiles/TargetDescriptionFile.php b/build/scripts/Targets/TargetDescriptionFiles/TargetDescriptionFile.php new file mode 100644 index 00000000..afe57d06 --- /dev/null +++ b/build/scripts/Targets/TargetDescriptionFiles/TargetDescriptionFile.php @@ -0,0 +1,331 @@ +deviceAttributesByName['name'] ?? null; + } + + public function getFamily(): ?TargetFamily + { + return TargetFamily::tryFrom($this->deviceAttributesByName['family'] ?? null); + } + + public function getConfigurationValue(): ?string + { + return $this->deviceAttributesByName['configuration-value'] ?? null; + } + + public function getArchitecture(): ?string + { + return $this->deviceAttributesByName['architecture'] ?? null; + } + + public function getVendor(): ?string + { + return $this->deviceAttributesByName['vendor'] ?? null; + } + + public function getPropertyGroup(array|string $keys): ?PropertyGroup + { + if (is_string($keys)) { + $keys = explode('.', $keys); + } + + $firstLevelGroupKey = array_shift($keys); + foreach ($this->propertyGroups as $propertyGroup) { + if ($propertyGroup->key === $firstLevelGroupKey) { + return !empty($keys) ? $propertyGroup->getSubGroup($keys) : $propertyGroup; + } + } + + return null; + } + + public function getProperty(array|string $propertyGroupKeys, $propertyKey): ?Property + { + return ($propertyGroup = $this->getPropertyGroup($propertyGroupKeys)) instanceof PropertyGroup + ? $propertyGroup->getProperty($propertyKey) + : null; + } + + public function getPropertyValue(array|string $propertyGroupKeys, $propertyKey): ?string + { + return ($property = $this->getProperty($propertyGroupKeys, $propertyKey)) instanceof Property + ? $property->value + : null; + } + + public function getAddressSpace(string $key): ?AddressSpace + { + foreach ($this->addressSpaces as $addressSpace) { + if ($addressSpace->key != $key) { + continue; + } + + return $addressSpace; + } + + return null; + } + + public function getMemorySegment(string $addressSpaceKey, string $memorySegmentKey): ?MemorySegment + { + if (($addressSpace = $this->getAddressSpace($addressSpaceKey)) instanceof AddressSpace) { + foreach ($addressSpace->memorySegments as $memorySegment) { + if ($memorySegment->key !== $memorySegmentKey) { + continue; + } + + return $memorySegment; + } + } + + return null; + } + + public function getMemorySegmentsFromAnyAddressSpace(string $key): ?MemorySegment + { + foreach ($this->addressSpaces as $addressSpace) { + foreach ($addressSpace->memorySegments as $memorySegment) { + if ($memorySegment->key === $key) { + return $memorySegment; + } + } + } + + return null; + } + + public function getPeripheral(string $key): ?Peripheral + { + foreach ($this->peripherals as $peripheral) { + if ($peripheral->key === $key) { + return $peripheral; + } + } + + return null; + } + + /** + * Gets all peripherals of a particular module + * + * @param string $moduleKey + * @return Peripheral[] + */ + public function getPeripheralsOfModule(string $moduleKey): array + { + return array_filter( + $this->peripherals, + fn (Peripheral $peripheral): bool => $peripheral->moduleKey === $moduleKey + ); + } + + public function removePeripheral(string $key): void + { + $this->peripherals = array_filter( + $this->peripherals, + fn (Peripheral $peripheral): bool => $peripheral->key !== $key + ); + } + + public function getModule(string $key): ?Module + { + foreach ($this->modules as $module) { + if ($module->key === $key) { + return $module; + } + } + + return null; + } + + /** + * Will rename the key of the given module, and update all associated peripherals. + * + * @param Module $module + * @param string $newKey + * @return void + */ + public function renameModuleKey(Module $module, string $newKey): void + { + foreach ($this->getPeripheralsOfModule($module->key) as $peripheral) { + $peripheral->moduleKey = $newKey; + } + + $module->key = $newKey; + } + + public function getPinout(string $key): ?Pinout + { + foreach ($this->pinouts as $pinout) { + if ($pinout->key === $key) { + return $pinout; + } + } + + return null; + } + + public function getTargetPeripheral(string $peripheralKey): ?TargetPeripheral + { + $peripheral = $this->getPeripheral($peripheralKey); + return $peripheral instanceof Peripheral ? $this->targetPeripheralFromPeripheral($peripheral) : null; + } + + public function getTargetRegisterGroup(string $peripheralKey, array|string $registerGroupKeys): ?TargetRegisterGroup + { + $peripheral = $this->getPeripheral($peripheralKey); + return $peripheral instanceof Peripheral + ? $this->targetPeripheralFromPeripheral($peripheral)->getRegisterGroup($registerGroupKeys) + : null; + } + + public function getTargetRegister( + string $peripheralKey, + array|string $groupKeys, + array|string $registerKeys + ): ?TargetRegister { + return ($peripheral = $this->getPeripheral($peripheralKey)) instanceof Peripheral + ? $this->targetPeripheralFromPeripheral($peripheral)->getRegister($groupKeys, $registerKeys) + : null; + } + + public function resolveRegisterGroupReference( + RegisterGroupReference $registerGroupReference, + string $moduleKey + ): ?RegisterGroup { + $module = $this->getModule($moduleKey); + return $module instanceof Module ? $module->getRegisterGroup($registerGroupReference->registerGroupKey) : null; + } + + private function targetPeripheralFromPeripheral(Peripheral $peripheral): TargetPeripheral + { + $output = new TargetPeripheral($peripheral->name, []); + + foreach ($peripheral->registerGroupReferences as $registerGroupReference) { + $registerGroup = $this->resolveRegisterGroupReference($registerGroupReference, $peripheral->moduleKey); + if ($registerGroup instanceof RegisterGroup) { + $output->registerGroups[] = $this->targetRegisterGroupFromRegisterGroup( + $registerGroup, + $registerGroupReference->offset ?? 0, + $peripheral->moduleKey + ); + } + } + + return $output; + } + + private function targetRegisterGroupFromRegisterGroup( + RegisterGroup $registerGroup, + int $addressOffset, + string $moduleKey + ): TargetRegisterGroup { + $addressOffset += $registerGroup->offset ?? 0; + $output = new TargetRegisterGroup($registerGroup->key, $registerGroup->name, $addressOffset, [], []); + + foreach ($registerGroup->subGroups as $subGroup) { + $output->subGroups[] = $this->targetRegisterGroupFromRegisterGroup($subGroup, $addressOffset, $moduleKey); + } + + foreach ($registerGroup->subGroupReferences as $subGroupReference) { + $subGroup = $this->resolveRegisterGroupReference($subGroupReference, $moduleKey); + + if ($subGroup instanceof RegisterGroup) { + $output->subGroups[] = $this->targetRegisterGroupFromRegisterGroup( + $subGroup, + $addressOffset, + $moduleKey + ); + } + } + + foreach ($registerGroup->registers as $register) { + $output->registers[] = $this->targetRegisterFromRegister($register, $addressOffset); + } + + return $output; + } + + private function targetRegisterFromRegister(Register $register, int $addressOffset): TargetRegister + { + return new TargetRegister( + $register->key, + $register->name, + $addressOffset + $register->offset, + $register->size, + $register->description, + array_map( + fn (BitField $bitField): TargetRegisterBitField => $this->targetRegisterBitFieldFromBitField($bitField), + $register->bitFields + ) + ); + } + + private function targetRegisterBitFieldFromBitField(BitField $bitField): TargetRegisterBitField + { + return new TargetRegisterBitField( + $bitField->key, + $bitField->name, + $bitField->description, + $bitField->mask, + $bitField->access + ); + } +} diff --git a/build/scripts/TargetDescriptionFiles/TargetFamily.php b/build/scripts/Targets/TargetDescriptionFiles/TargetFamily.php similarity index 62% rename from build/scripts/TargetDescriptionFiles/TargetFamily.php rename to build/scripts/Targets/TargetDescriptionFiles/TargetFamily.php index 495ea1b7..67ed3188 100644 --- a/build/scripts/TargetDescriptionFiles/TargetFamily.php +++ b/build/scripts/Targets/TargetDescriptionFiles/TargetFamily.php @@ -1,5 +1,5 @@ name = $name; + $this->pinoutKey = $pinoutKey; + $this->package = $package; + } +} diff --git a/build/scripts/Targets/TargetPeripheral.php b/build/scripts/Targets/TargetPeripheral.php new file mode 100644 index 00000000..547a17ae --- /dev/null +++ b/build/scripts/Targets/TargetPeripheral.php @@ -0,0 +1,56 @@ + element in a + * TDF, meaning it only contains references to register groups and their respective offsets. Those register group + * references are unresolved, meaning you can't access any of the referenced group's registers or subgroups. + * + * This class represents a **resolved** target peripheral - meaning all the referenced register groups are resolved, + * along with their respective addresses. With this class, we can access all peripheral registers/register groups, and + * their absolute addresses. + * + * This class is constructed from a `TargetDescriptionFiles\Peripheral` object. + * @see TargetDescriptionFile::getTargetPeripheral() for more. + */ +class TargetPeripheral +{ + public ?string $name = null; + + /** @var TargetRegisterGroup[] */ + public array $registerGroups = []; + + public function __construct(?string $name, array $registerGroups) + { + $this->name = $name; + $this->registerGroups = $registerGroups; + } + + public function getRegisterGroup(array|string $keys): ?TargetRegisterGroup + { + if (is_string($keys)) { + $keys = explode('.', $keys); + } + + $firstLevelSubGroupId = array_shift($keys); + + foreach ($this->registerGroups as $registerGroup) { + if ($registerGroup->key === $firstLevelSubGroupId) { + return !empty($keys) ? $registerGroup->getSubGroup($keys) : $registerGroup; + } + } + + return null; + } + + public function getRegister(array|string $groupKeys, array|string $keys): ?TargetRegister + { + return ($group = $this->getRegisterGroup($groupKeys)) instanceof TargetRegisterGroup + ? ($register = $group->getRegister($keys)) instanceof TargetRegister ? $register : null + : null; + } +} diff --git a/build/scripts/Targets/TargetRegister.php b/build/scripts/Targets/TargetRegister.php new file mode 100644 index 00000000..b8f22ff4 --- /dev/null +++ b/build/scripts/Targets/TargetRegister.php @@ -0,0 +1,44 @@ + element in a TDF, + * which is part of some unresolved register group. + * + * This class represents a **resolved** target register, within a register group, within a target peripheral. With + * this class, we can access the absolute address of the register. + * + * This class is constructed from a `TargetDescriptionFiles\Register` object. + * @see TargetDescriptionFile::getTargetRegister() for more. + */ +class TargetRegister +{ + public ?string $key = null; + public ?string $name = null; + public ?int $address = null; + public ?int $size = null; + public ?string $description = null; + + /** @var TargetRegisterBitField[] */ + public array $bitFields; + + public function __construct( + ?string $key, + ?string $name, + ?int $address, + ?int $size, + ?string $description, + array $bitFields + ) { + $this->key = $key; + $this->name = $name; + $this->address = $address; + $this->size = $size; + $this->description = $description; + $this->bitFields = $bitFields; + } +} diff --git a/build/scripts/Targets/TargetRegisterBitField.php b/build/scripts/Targets/TargetRegisterBitField.php new file mode 100644 index 00000000..e6250296 --- /dev/null +++ b/build/scripts/Targets/TargetRegisterBitField.php @@ -0,0 +1,25 @@ +key = $key; + $this->name = $name; + $this->description = $description; + $this->mask = $mask; + $this->access = $access; + } +} diff --git a/build/scripts/Targets/TargetRegisterGroup.php b/build/scripts/Targets/TargetRegisterGroup.php new file mode 100644 index 00000000..10bbb7cd --- /dev/null +++ b/build/scripts/Targets/TargetRegisterGroup.php @@ -0,0 +1,75 @@ + element + * in a TDF. Any references to subgroups will be unresolved. + * + * This class represents a **resolved** target register group, within a target peripheral. With this class, we can + * access all subgroups, including referenced subgroups, along with their registers. + * + * This class is constructed from a `TargetDescriptionFiles\RegisterGroup` object. + * @see TargetDescriptionFile::getTargetRegisterGroup() for more. + */ +class TargetRegisterGroup +{ + public ?string $key = null; + public ?string $name = null; + public ?int $baseAddress = null; + + /** @var TargetRegisterGroup[] */ + public array $subGroups = []; + + /** @var TargetRegister[] */ + public array $registers = []; + + public function __construct(?string $key, ?string $name, ?int $baseAddress, array $subGroups, array $registers) + { + $this->key = $key; + $this->name = $name; + $this->baseAddress = $baseAddress; + $this->subGroups = $subGroups; + $this->registers = $registers; + } + + public function getRegister(array|string $keys): ?TargetRegister + { + if (is_string($keys)) { + $keys = explode('.', $keys); + } + + $registerKey = array_pop($keys); + $group = !empty($keys) > 1 ? $this->getSubGroup($keys) : $this; + + if ($group instanceof TargetRegisterGroup) { + foreach ($group->registers as $register) { + if ($register->key === $registerKey) { + return $register; + } + } + } + + return null; + } + + public function getSubGroup(array|string $subGroupKeys): ?TargetRegisterGroup + { + if (is_string($subGroupKeys)) { + $subGroupKeys = explode('.', $subGroupKeys); + } + + $firstLevelSubGroupKey = array_shift($subGroupKeys); + foreach ($this->subGroups as $subGroup) { + if ($subGroup->key === $firstLevelSubGroupKey) { + return !empty($subGroupKeys) ? $subGroup->getSubGroup($subGroupKeys) : $subGroup; + } + } + + return null; + } +}