From cadeca0812bff5d242bce48d7ee83630d153b481 Mon Sep 17 00:00:00 2001 From: Nav Date: Sun, 28 May 2023 02:17:20 +0100 Subject: [PATCH] Tidied AVR8 TDF validation script --- build/scripts/Avr8TargetDescriptionFiles.php | 11 +- .../AVR8/Avr8TargetDescriptionFile.php | 1253 +++++++++-------- .../AVR8/DebugWireParameters.php | 10 + .../AVR8/IspParameters.php | 18 + .../AVR8/JtagParameters.php | 10 + .../AVR8/PdiParameters.php | 20 + .../AVR8/TargetParameters.php | 24 + .../AVR8/UpdiParameters.php | 14 + .../TargetDescriptionFile.php | 94 +- .../ValidateAvr8TargetDescriptionFiles.php | 4 +- 10 files changed, 826 insertions(+), 632 deletions(-) create mode 100644 build/scripts/TargetDescriptionFiles/AVR8/DebugWireParameters.php create mode 100644 build/scripts/TargetDescriptionFiles/AVR8/IspParameters.php create mode 100644 build/scripts/TargetDescriptionFiles/AVR8/JtagParameters.php create mode 100644 build/scripts/TargetDescriptionFiles/AVR8/PdiParameters.php create mode 100644 build/scripts/TargetDescriptionFiles/AVR8/TargetParameters.php create mode 100644 build/scripts/TargetDescriptionFiles/AVR8/UpdiParameters.php diff --git a/build/scripts/Avr8TargetDescriptionFiles.php b/build/scripts/Avr8TargetDescriptionFiles.php index 77527a32..0fe53b92 100644 --- a/build/scripts/Avr8TargetDescriptionFiles.php +++ b/build/scripts/Avr8TargetDescriptionFiles.php @@ -72,10 +72,11 @@ foreach ($avrTdfs as $avrTdf) { $relativeDestinationFilePath .= "/" . strtoupper($avrTdf->targetArchitecture); } - if (!empty($avrTdf->family)) { + $avrFamily = $avrTdf->getFamily(); + if (!empty($avrFamily)) { // Group by family - $destinationFilePath .= "/" . str_replace([' '] , '_', strtoupper($avrTdf->family)); - $relativeDestinationFilePath .= "/" . str_replace([' '] , '_', strtoupper($avrTdf->family)); + $destinationFilePath .= "/" . str_replace([' '] , '_', strtoupper($avrFamily)); + $relativeDestinationFilePath .= "/" . str_replace([' '] , '_', strtoupper($avrFamily)); } if (!file_exists($destinationFilePath)) { @@ -87,14 +88,14 @@ foreach ($avrTdfs as $avrTdf) { // Copy TDF to build location if (copy($avrTdf->filePath, $destinationFilePath) === false) { - print "FATAL ERROR: Failed to TDF file to " . $destinationFilePath . "\n"; + print "FATAL ERROR: Failed to copy TDF file to " . $destinationFilePath . "\n"; print "Aborting\n"; exit(1); } $tdfMapping[$id] = [ 'name' => $strippedTargetName, - 'signature' => $avrTdf->signature->toHex(), + 'signature' => $avrTdf->getSignature()->toHex(), 'tdfPath' => $relativeDestinationFilePath, ]; } diff --git a/build/scripts/TargetDescriptionFiles/AVR8/Avr8TargetDescriptionFile.php b/build/scripts/TargetDescriptionFiles/AVR8/Avr8TargetDescriptionFile.php index 3eae1d0c..afc8e449 100644 --- a/build/scripts/TargetDescriptionFiles/AVR8/Avr8TargetDescriptionFile.php +++ b/build/scripts/TargetDescriptionFiles/AVR8/Avr8TargetDescriptionFile.php @@ -1,10 +1,19 @@ xml->device; - if (empty($device)) { - return; + 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->stringToInt($byteZero); + $signature->byteOne = $this->stringToInt($byteOne); + $signature->byteTwo = $this->stringToInt($byteTwo); + + return $signature; } - $deviceAttributes = $device->attributes(); + return null; + } - if (!empty($deviceAttributes['family'])) { - if (stristr($deviceAttributes['family'], 'xmega') !== false) { - $this->family = self::AVR8_FAMILY_XMEGA; + public function getFamily(): ?string + { + if (!empty($this->deviceAttributesByName['family'])) { + if (stristr($this->deviceAttributesByName['family'], 'xmega') !== false) { + return self::AVR8_FAMILY_XMEGA; - } else if (stristr($deviceAttributes['family'], 'tiny') !== false) { - $this->family = self::AVR8_FAMILY_TINY; + } else if (stristr($this->deviceAttributesByName['family'], 'tiny') !== false) { + return self::AVR8_FAMILY_TINY; - } else if (stristr($deviceAttributes['family'], 'mega') !== false) { - $this->family = self::AVR8_FAMILY_MEGA; + } else if (stristr($this->deviceAttributesByName['family'], 'mega') !== false) { + return self::AVR8_FAMILY_MEGA; - } else if (strtolower(trim($deviceAttributes['family'])) == 'avr da') { - $this->family = self::AVR8_FAMILY_DA; + } else if (strtolower(trim($this->deviceAttributesByName['family'])) == 'avr da') { + return self::AVR8_FAMILY_DA; - } else if (strtolower(trim($deviceAttributes['family'])) == 'avr db') { - $this->family = self::AVR8_FAMILY_DB; + } else if (strtolower(trim($this->deviceAttributesByName['family'])) == 'avr db') { + return self::AVR8_FAMILY_DB; - } else if (strtolower(trim($deviceAttributes['family'])) == 'avr dd') { - $this->family = self::AVR8_FAMILY_DD; + } else if (strtolower(trim($this->deviceAttributesByName['family'])) == 'avr dd') { + return self::AVR8_FAMILY_DD; - } else if (strtolower(trim($deviceAttributes['family'])) == 'avr ea') { - $this->family = self::AVR8_FAMILY_EA; - - } else { - $this->family = self::AVR8_FAMILY_OTHER; + } else if (strtolower(trim($this->deviceAttributesByName['family'])) == 'avr ea') { + return self::AVR8_FAMILY_EA; } } - if (isset($this->physicalInterfacesByName['isp'])) { - $this->physicalInterfaces[] = self::AVR8_PHYSICAL_INTERFACE_ISP; + return self::AVR8_FAMILY_OTHER; + } + + public function getSupportedPhysicalInterfaces(): array + { + $physicalInterfacesByName = [ + 'isp' => self::AVR8_PHYSICAL_INTERFACE_ISP, + 'debugwire' => self::AVR8_PHYSICAL_INTERFACE_DEBUG_WIRE, + 'updi' => self::AVR8_PHYSICAL_INTERFACE_UPDI, + 'pdi' => self::AVR8_PHYSICAL_INTERFACE_PDI, + 'jtag' => self::AVR8_PHYSICAL_INTERFACE_JTAG, + ]; + + return array_filter( + $physicalInterfacesByName, + function(string $name) { + return isset($this->physicalInterfacesByName[$name]); + }, + ARRAY_FILTER_USE_KEY + ); + } + + public function getSupportedDebugPhysicalInterfaces(): array + { + $physicalInterfacesByName = [ + 'debugwire' => self::AVR8_PHYSICAL_INTERFACE_DEBUG_WIRE, + 'updi' => self::AVR8_PHYSICAL_INTERFACE_UPDI, + 'pdi' => self::AVR8_PHYSICAL_INTERFACE_PDI, + 'jtag' => self::AVR8_PHYSICAL_INTERFACE_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; } - if (isset($this->physicalInterfacesByName['debugwire'])) { - $this->debugPhysicalInterfaces[] = self::AVR8_PHYSICAL_INTERFACE_DEBUG_WIRE; - $this->physicalInterfaces[] = self::AVR8_PHYSICAL_INTERFACE_DEBUG_WIRE; + $programMemoryAddressSpace = $this->addressSpacesById['prog'] ?? null; + if ($programMemoryAddressSpace instanceof AddressSpace) { + $output->flashSize = $programMemoryAddressSpace->size; + $output->flashStartAddress = $programMemoryAddressSpace->startAddress; } - if (isset($this->physicalInterfacesByName['updi'])) { - $this->debugPhysicalInterfaces[] = self::AVR8_PHYSICAL_INTERFACE_UPDI; - $this->physicalInterfaces[] = self::AVR8_PHYSICAL_INTERFACE_UPDI; - - } else if (isset($this->physicalInterfacesByName['pdi'])) { - $this->debugPhysicalInterfaces[] = self::AVR8_PHYSICAL_INTERFACE_PDI; - $this->physicalInterfaces[] = self::AVR8_PHYSICAL_INTERFACE_PDI; + $programMemorySegment = $this->getMemorySegment('prog', 'flash'); + if ($programMemorySegment instanceof MemorySegment) { + $output->flashPageSize = $programMemorySegment->pageSize; } - if (isset($this->physicalInterfacesByName['jtag'])) { - $this->debugPhysicalInterfaces[] = self::AVR8_PHYSICAL_INTERFACE_JTAG; - $this->physicalInterfaces[] = self::AVR8_PHYSICAL_INTERFACE_JTAG; + $ramMemorySegment = $this->getMemorySegment('data', 'ram'); + if ($ramMemorySegment instanceof MemorySegment) { + $output->ramStartAddress = $ramMemorySegment->startAddress; + $output->ramSize = $ramMemorySegment->size; } - $signaturePropertyGroup = $this->propertyGroupsByName['signatures'] ?? null; - if (!empty($signaturePropertyGroup)) { - $this->signature = new Signature(); + $eepromMemorySegment = $this->getMemorySegment( + 'data', + 'eeprom', + 'eeprom' + ); + if ($eepromMemorySegment instanceof MemorySegment) { + $output->eepromStartAddress = $eepromMemorySegment->startAddress; + $output->eepromSize = $eepromMemorySegment->size; + $output->eepromPageSize = $eepromMemorySegment->pageSize; - if (isset($signaturePropertyGroup->propertiesMappedByName['signature0'])) { - $this->signature->byteZero = $this->stringToInt( - $signaturePropertyGroup->propertiesMappedByName['signature0']->value - ); - } - - if (isset($signaturePropertyGroup->propertiesMappedByName['signature1'])) { - $this->signature->byteOne = $this->stringToInt( - $signaturePropertyGroup->propertiesMappedByName['signature1']->value - ); - } - - if (isset($signaturePropertyGroup->propertiesMappedByName['signature2'])) { - $this->signature->byteTwo = $this->stringToInt( - $signaturePropertyGroup->propertiesMappedByName['signature2']->value - ); - } - } - - $ispParamPropertyGroup = $this->propertyGroupsByName['isp_interface'] ?? null; - if (!empty($ispParamPropertyGroup)) { - if (isset($ispParamPropertyGroup->propertiesMappedByName['ispenterprogmode_timeout'])) { - $this->ispProgramModeTimeout = $this->stringToInt( - $ispParamPropertyGroup->propertiesMappedByName['ispenterprogmode_timeout']->value - ); - } - - if (isset($ispParamPropertyGroup->propertiesMappedByName['ispenterprogmode_stabdelay'])) { - $this->ispProgramModeStabilizationDelay = $this->stringToInt( - $ispParamPropertyGroup->propertiesMappedByName['ispenterprogmode_stabdelay']->value - ); - } - - if (isset($ispParamPropertyGroup->propertiesMappedByName['ispenterprogmode_cmdexedelay'])) { - $this->ispProgramModeCommandExecutionDelay = $this->stringToInt( - $ispParamPropertyGroup->propertiesMappedByName['ispenterprogmode_cmdexedelay']->value - ); - } - - if (isset($ispParamPropertyGroup->propertiesMappedByName['ispenterprogmode_synchloops'])) { - $this->ispProgramModeSyncLoops = $this->stringToInt( - $ispParamPropertyGroup->propertiesMappedByName['ispenterprogmode_synchloops']->value - ); - } - - if (isset($ispParamPropertyGroup->propertiesMappedByName['ispenterprogmode_bytedelay'])) { - $this->ispProgramModeByteDelay = $this->stringToInt( - $ispParamPropertyGroup->propertiesMappedByName['ispenterprogmode_bytedelay']->value - ); - } - - if (isset($ispParamPropertyGroup->propertiesMappedByName['ispenterprogmode_pollvalue'])) { - $this->ispProgramModePollValue = $this->stringToInt( - $ispParamPropertyGroup->propertiesMappedByName['ispenterprogmode_pollvalue']->value - ); - } - - if (isset($ispParamPropertyGroup->propertiesMappedByName['ispenterprogmode_pollindex'])) { - $this->ispProgramModePollIndex = $this->stringToInt( - $ispParamPropertyGroup->propertiesMappedByName['ispenterprogmode_pollindex']->value - ); - } - - if (isset($ispParamPropertyGroup->propertiesMappedByName['ispleaveprogmode_predelay'])) { - $this->ispProgramModePreDelay = $this->stringToInt( - $ispParamPropertyGroup->propertiesMappedByName['ispleaveprogmode_predelay']->value - ); - } - - if (isset($ispParamPropertyGroup->propertiesMappedByName['ispleaveprogmode_postdelay'])) { - $this->ispProgramModePostDelay = $this->stringToInt( - $ispParamPropertyGroup->propertiesMappedByName['ispleaveprogmode_postdelay']->value - ); - } - - if (isset($ispParamPropertyGroup->propertiesMappedByName['ispreadsign_pollindex'])) { - $this->ispReadSignaturePollIndex = $this->stringToInt( - $ispParamPropertyGroup->propertiesMappedByName['ispreadsign_pollindex']->value - ); - } - if (isset($ispParamPropertyGroup->propertiesMappedByName['ispreadfuse_pollindex'])) { - $this->ispReadFusePollIndex = $this->stringToInt( - $ispParamPropertyGroup->propertiesMappedByName['ispreadfuse_pollindex']->value - ); - } - if (isset($ispParamPropertyGroup->propertiesMappedByName['ispreadlock_pollindex'])) { - $this->ispReadLockPollIndex = $this->stringToInt( - $ispParamPropertyGroup->propertiesMappedByName['ispreadlock_pollindex']->value - ); - } - } - - $progAddressSpace = $this->addressSpacesById['prog'] ?? null; - if (!empty($progAddressSpace)) { - $this->flashSize = $progAddressSpace->size; - $this->flashStartAddress = $progAddressSpace->startAddress; - - $firstFlashMemorySegment = reset($progAddressSpace->memorySegmentsByTypeAndName['flash']); - $appFlashMemorySegment = $progAddressSpace->memorySegmentsByTypeAndName['flash']['app_section'] ?? null; - $bootSectionMemorySegment = $progAddressSpace->memorySegmentsByTypeAndName['flash']['boot_section_1'] - ?? $progAddressSpace->memorySegmentsByTypeAndName['flash']['boot_section'] ?? null; - - if (!empty($firstFlashMemorySegment)) { - $this->flashPageSize = $firstFlashMemorySegment->pageSize; - } - - if (!empty($appFlashMemorySegment)) { - $this->appSectionStartAddress = $appFlashMemorySegment->startAddress; - $this->appSectionSize = $appFlashMemorySegment->size; - } - - if (!empty($bootSectionMemorySegment)) { - $this->bootSectionSize = $bootSectionMemorySegment->size; - $this->bootSectionStartAddress = $bootSectionMemorySegment->startAddress; - } - } - - $dataAddressSpace = $this->addressSpacesById['data'] ?? null; - if (!empty($dataAddressSpace)) { - $ramMemorySegments = $dataAddressSpace->memorySegmentsByTypeAndName['ram'] ?? null; - $registerMemorySegments = $dataAddressSpace->memorySegmentsByTypeAndName['regs'] ?? null; - - if (!empty($ramMemorySegments)) { - $ramMemorySegment = reset($ramMemorySegments); - $this->ramSize = $ramMemorySegment->size; - $this->ramStartAddress = $ramMemorySegment->startAddress; - } - - if (!empty($registerMemorySegments)) { - $registerMemorySegment = reset($registerMemorySegments); - $this->gpRegisterSize = $registerMemorySegment->size; - $this->gpRegisterStartAddress = $registerMemorySegment->startAddress; - } - - if (isset($dataAddressSpace->memorySegmentsByTypeAndName['eeprom']['eeprom'])) { - $eepromMemorySegment = $dataAddressSpace->memorySegmentsByTypeAndName['eeprom']['eeprom']; - $this->eepromStartAddress = $eepromMemorySegment->startAddress; - $this->eepromSize = $eepromMemorySegment->size; - $this->eepromPageSize = $eepromMemorySegment->pageSize; - } - } - - if ( - (is_null($this->eepromSize) || is_null($this->eepromPageSize) || is_null($this->eepromStartAddress)) - && isset($this->addressSpacesById['eeprom']) - ) { + } else if (isset($this->addressSpacesById['eeprom'])) { $eepromAddressSpace = $this->addressSpacesById['eeprom']; - $eepromMemorySegments = $eepromAddressSpace->memorySegmentsByTypeAndName['eeprom'] ?? null; - $this->eepromStartAddress = $eepromAddressSpace->startAddress; + $output->eepromStartAddress = $eepromAddressSpace->startAddress; - if (!empty($eepromMemorySegments)) { - $eepromMemorySegment = reset($eepromMemorySegments); - $this->eepromSize = $eepromMemorySegment->size; - $this->eepromPageSize = $eepromMemorySegment->pageSize; + $eepromMemorySegment = $this->getMemorySegment('eeprom', 'eeprom'); + if ($eepromMemorySegment instanceof MemorySegment) { + $output->eepromSize = $eepromMemorySegment->size; + $output->eepromPageSize = $eepromMemorySegment->pageSize; } } - if (isset($this->propertyGroupsByName['ocd'])) { - $ocdProperties = $this->propertyGroupsByName['ocd']->propertiesMappedByName; + $eepromAddressRegister = $this->getModuleRegister( + 'eeprom', + 'eeprom', + 'eear' + ); + if ($eepromAddressRegister instanceof Register) { + $output->eepromAddressRegisterLow = $eepromAddressRegister->offset; + $output->eepromAddressRegisterHigh = ($eepromAddressRegister->size == 2) + ? $eepromAddressRegister->offset + 1 + : $eepromAddressRegister->offset; - $this->ocdRevision = isset($ocdProperties['ocd_revision']) ? (int) $ocdProperties['ocd_revision']->value : null; - $this->ocdDataRegister = isset($ocdProperties['ocd_datareg']) - ? $this->stringToInt($ocdProperties['ocd_datareg']->value) : null; - } + } else { + $eepromAddressRegisterLow = $this->getModuleRegister( + 'eeprom', + 'eeprom', + 'eearl' + ); + if ($eepromAddressRegisterLow instanceof Register) { + $output->eepromAddressRegisterLow = $eepromAddressRegisterLow->offset; + $output->eepromAddressRegisterHigh = $eepromAddressRegisterLow->offset; + } - if (isset($this->modulesByName['cpu'])) { - $cpuModule = $this->modulesByName['cpu']; - - if (isset($cpuModule->registerGroupsMappedByName['cpu'])) { - $cpuRegisterGroup = $cpuModule->registerGroupsMappedByName['cpu']; - - if (isset($cpuRegisterGroup->registersMappedByName['sreg'])) { - $statusRegister = $cpuRegisterGroup->registersMappedByName['sreg']; - $this->statusRegisterSize = $statusRegister->size; - $this->statusRegisterStartAddress = $statusRegister->offset; - } - - if (isset($cpuRegisterGroup->registersMappedByName['sp'])) { - $stackPointerRegister = $cpuRegisterGroup->registersMappedByName['sp']; - $this->stackPointerRegisterSize = $stackPointerRegister->size; - $this->stackPointerRegisterLowAddress = $stackPointerRegister->offset; - - } else { - if (isset($cpuRegisterGroup->registersMappedByName['spl'])) { - $stackPointerLowRegister = $cpuRegisterGroup->registersMappedByName['spl']; - $this->stackPointerRegisterSize = $stackPointerLowRegister->size; - $this->stackPointerRegisterLowAddress = $stackPointerLowRegister->offset; - - if (isset($cpuRegisterGroup->registersMappedByName['sph'])) { - $stackPointerHighRegister = $cpuRegisterGroup->registersMappedByName['sph']; - $this->stackPointerRegisterSize += $stackPointerHighRegister->size; - } - } - } - - if (isset($cpuRegisterGroup->registersMappedByName['spmcsr'])) { - $spmcsRegister = $cpuRegisterGroup->registersMappedByName['spmcsr']; - $this->spmcRegisterStartAddress = $spmcsRegister->offset; - - } else if (isset($cpuRegisterGroup->registersMappedByName['spmcr'])) { - $spmcRegister = $cpuRegisterGroup->registersMappedByName['spmcr']; - $this->spmcRegisterStartAddress = $spmcRegister->offset; - - } else { - if (isset($this->modulesByName['boot_load']) - && isset($this->modulesByName['boot_load']->registerGroupsMappedByName['boot_load']) - ) { - $bootLoadedModule = $this->modulesByName['boot_load']; - $bootLoaderRegisterGroup = $bootLoadedModule->registerGroupsMappedByName['boot_load']; - - if (isset($bootLoaderRegisterGroup->registersMappedByName['spmcr'])) { - $spmcRegister = $bootLoaderRegisterGroup->registersMappedByName['spmcr']; - $this->spmcRegisterStartAddress = $spmcRegister->offset; - - } else if (isset($bootLoaderRegisterGroup->registersMappedByName['spmcsr'])) { - $spmcsRegister = $bootLoaderRegisterGroup->registersMappedByName['spmcsr']; - $this->spmcRegisterStartAddress = $spmcsRegister->offset; - } - } - } - - $osccalRegister = $cpuRegisterGroup->registersMappedByName['osccal'] - ?? $cpuRegisterGroup->registersMappedByName['osccal0'] - ?? $cpuRegisterGroup->registersMappedByName['osccal1'] - ?? $cpuRegisterGroup->registersMappedByName['fosccal'] - ?? $cpuRegisterGroup->registersMappedByName['sosccala'] ?? null; - - if (!is_null($osccalRegister)) { - $this->osccalAddress = $osccalRegister->offset; - } + $eepromAddressRegisterHigh = $this->getModuleRegister( + 'eeprom', + 'eeprom', + 'eearh' + ); + if ($eepromAddressRegisterHigh instanceof Register) { + $output->eepromAddressRegisterHigh = $eepromAddressRegisterHigh->offset; } } - if (isset($this->modulesByName['eeprom'])) { - $eepromModule = $this->modulesByName['eeprom']; + $eepromDataRegister = $this->getModuleRegister( + 'eeprom', + 'eeprom', + 'eedr' + ); + if ($eepromDataRegister instanceof Register) { + $output->eepromDataRegisterAddress = $eepromDataRegister->offset; + } - if (isset($eepromModule->registerGroupsMappedByName['eeprom'])) { - $eepromRegisterGroup = $eepromModule->registerGroupsMappedByName['eeprom']; + $eepromControlRegister = $this->getModuleRegister( + 'eeprom', + 'eeprom', + 'eecr' + ); + if ($eepromControlRegister instanceof Register) { + $output->eepromControlRegisterAddress = $eepromControlRegister->offset; + } - if (isset($eepromRegisterGroup->registersMappedByName['eear'])) { - $eearRegister = $eepromRegisterGroup->registersMappedByName['eear']; - $this->eepromAddressRegisterLow = $eearRegister->offset; - $this->eepromAddressRegisterHigh = ($eearRegister->size == 2) - ? $eearRegister->offset + 1 : $eearRegister->offset; + $statusRegister = $this->getModuleRegister( + 'cpu', + 'cpu', + 'sreg' + ); + if ($statusRegister instanceof Register) { + $output->statusRegisterStartAddress = $statusRegister->offset; + $output->statusRegisterSize = $statusRegister->size; + } - } else { - if (isset($eepromRegisterGroup->registersMappedByName['eearl'])) { - $eearlRegister = $eepromRegisterGroup->registersMappedByName['eearl']; - $this->eepromAddressRegisterLow = $eearlRegister->offset; + $stackPointerRegister = $this->getModuleRegister( + 'cpu', + 'cpu', + 'sp' + ); + if ($stackPointerRegister instanceof Register) { + $output->stackPointerRegisterLowAddress = $stackPointerRegister->offset; + $output->stackPointerRegisterSize = $stackPointerRegister->size; - if (isset($eepromRegisterGroup->registersMappedByName['eearh'])) { - $eearhRegister = $eepromRegisterGroup->registersMappedByName['eearh']; - $this->eepromAddressRegisterHigh = $eearhRegister->offset; + } else { + $stackPointerRegisterLow = $this->getModuleRegister( + 'cpu', + 'cpu', + 'spl' + ); + if ($stackPointerRegisterLow instanceof Register) { + $output->stackPointerRegisterLowAddress = $stackPointerRegisterLow->offset; + $output->stackPointerRegisterSize = $stackPointerRegisterLow->size; + } - } else { - $this->eepromAddressRegisterHigh = $eearlRegister->offset; - } - - } - } - - if (isset($eepromRegisterGroup->registersMappedByName['eedr'])) { - $eedrRegister = $eepromRegisterGroup->registersMappedByName['eedr']; - $this->eepromDataRegisterAddress = $eedrRegister->offset; - } - - if (isset($eepromRegisterGroup->registersMappedByName['eecr'])) { - $eecrRegister = $eepromRegisterGroup->registersMappedByName['eecr']; - $this->eepromControlRegisterAddress = $eecrRegister->offset; - } + $stackPointerRegisterHigh = $this->getModuleRegister( + 'cpu', + 'cpu', + 'sph' + ); + if ($stackPointerRegisterHigh instanceof Register) { + $output->stackPointerRegisterSize += $stackPointerRegisterHigh->size; } } - if (isset($this->propertyGroupsByName['pdi_interface'])) { - $pdiInterfacePropertyGroup = $this->propertyGroupsByName['pdi_interface']; - $pdiInterfacePropertiesByName = $pdiInterfacePropertyGroup->propertiesMappedByName; + return $output; + } - if (isset($pdiInterfacePropertiesByName['app_section_offset'])) { - $this->appSectionPdiOffset = isset($pdiInterfacePropertiesByName['app_section_offset']->value) - ? $this->stringToInt($pdiInterfacePropertiesByName['app_section_offset']->value) : null; - } + public function getDebugWireParameters(): DebugWireParameters + { + $output = new DebugWireParameters(); - if (isset($pdiInterfacePropertiesByName['boot_section_offset'])) { - $this->bootSectionPdiOffset = isset($pdiInterfacePropertiesByName['boot_section_offset']->value) - ? $this->stringToInt($pdiInterfacePropertiesByName['boot_section_offset']->value) : null; - } + $output->ocdRevision = $this->stringToInt( + $this->getPropertyValue('ocd', 'ocd_revision') + ); + $output->ocdDataRegister = $this->stringToInt( + $this->getPropertyValue('ocd', 'ocd_datareg') + ); - if (isset($pdiInterfacePropertiesByName['datamem_offset'])) { - $this->ramPdiOffset = isset($pdiInterfacePropertiesByName['datamem_offset']->value) - ? $this->stringToInt($pdiInterfacePropertiesByName['datamem_offset']->value) : null; - } - - if (isset($pdiInterfacePropertiesByName['eeprom_offset'])) { - $this->eepromPdiOffset = isset($pdiInterfacePropertiesByName['eeprom_offset']->value) - ? $this->stringToInt($pdiInterfacePropertiesByName['eeprom_offset']->value) : null; - } - - if (isset($pdiInterfacePropertiesByName['user_signatures_offset'])) { - $this->userSignaturesPdiOffset = isset($pdiInterfacePropertiesByName['user_signatures_offset']->value) - ? $this->stringToInt($pdiInterfacePropertiesByName['user_signatures_offset']->value) : null; - } - - if (isset($pdiInterfacePropertiesByName['prod_signatures_offset'])) { - $this->productSignaturesPdiOffset = isset($pdiInterfacePropertiesByName['prod_signatures_offset']->value) - ? $this->stringToInt($pdiInterfacePropertiesByName['prod_signatures_offset']->value) : null; - } - - if (isset($pdiInterfacePropertiesByName['fuse_registers_offset'])) { - $this->fuseRegistersPdiOffset = isset($pdiInterfacePropertiesByName['fuse_registers_offset']->value) - ? $this->stringToInt($pdiInterfacePropertiesByName['fuse_registers_offset']->value) : null; - } - - if (isset($pdiInterfacePropertiesByName['lock_registers_offset'])) { - $this->lockRegistersPdiOffset = isset($pdiInterfacePropertiesByName['lock_registers_offset']->value) - ? $this->stringToInt($pdiInterfacePropertiesByName['lock_registers_offset']->value) : null; - } - - if (isset($this->peripheralModulesByName['nvm'])) { - $nvmModule = $this->peripheralModulesByName['nvm']; - - if (isset($nvmModule->instancesMappedByName['nvm'])) { - $nvmInstance = $nvmModule->instancesMappedByName['nvm']; - - if (isset($nvmInstance->registerGroupsMappedByName['nvm'])) { - $this->nvmModuleBaseAddress = $nvmInstance->registerGroupsMappedByName['nvm']->offset; - } - } - } - - if (isset($this->peripheralModulesByName['mcu'])) { - $mcuModule = $this->peripheralModulesByName['mcu']; - - if (isset($mcuModule->instancesMappedByName['mcu'])) { - $mcuInstance = $mcuModule->instancesMappedByName['mcu']; - - if (isset($mcuInstance->registerGroupsMappedByName['mcu'])) { - $this->mcuModuleBaseAddress = $mcuInstance->registerGroupsMappedByName['mcu']->offset; - } - } - } + $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; } - if (in_array(Avr8TargetDescriptionFile::AVR8_PHYSICAL_INTERFACE_UPDI, $this->debugPhysicalInterfaces)) { - if (isset($this->peripheralModulesByName['nvmctrl'])) { - $nvmModule = $this->peripheralModulesByName['nvmctrl']; - - if (isset($nvmModule->instancesMappedByName['nvmctrl'])) { - $nvmInstance = $nvmModule->instancesMappedByName['nvmctrl']; - - if (isset($nvmInstance->registerGroupsMappedByName['nvmctrl'])) { - $this->nvmModuleBaseAddress = $nvmInstance->registerGroupsMappedByName['nvmctrl']->offset; - } - } - } - - if (isset($this->propertyGroupsByName['updi_interface'])) { - $updiInterfacePropertyGroup = $this->propertyGroupsByName['updi_interface']; - $updiInterfacePropertiesByName = $updiInterfacePropertyGroup->propertiesMappedByName; - - if (isset($updiInterfacePropertiesByName['ocd_base_addr'])) { - $this->ocdBaseAddress = isset($updiInterfacePropertiesByName['ocd_base_addr']->value) - ? $this->stringToInt($updiInterfacePropertiesByName['ocd_base_addr']->value) : null; - } - - if (isset($updiInterfacePropertiesByName['progmem_offset'])) { - $this->programMemoryUpdiStartAddress = isset($updiInterfacePropertiesByName['progmem_offset']->value) - ? $this->stringToInt($updiInterfacePropertiesByName['progmem_offset']->value) : null; - } - } - - if (!is_null($dataAddressSpace)) { - if (isset($dataAddressSpace->memorySegmentsByTypeAndName['signatures']['signatures'])) { - $signatureMemSegment = $dataAddressSpace->memorySegmentsByTypeAndName['signatures']['signatures']; - $this->signatureSegmentSize = isset($signatureMemSegment->size) - ? $this->stringToInt($signatureMemSegment->size) : null; - - $this->signatureSegmentStartAddress = isset($signatureMemSegment->startAddress) - ? $this->stringToInt($signatureMemSegment->startAddress) : null; - } - - if (isset($dataAddressSpace->memorySegmentsByTypeAndName['fuses']['fuses'])) { - $fusesMemSegment = $dataAddressSpace->memorySegmentsByTypeAndName['fuses']['fuses']; - $this->fuseSegmentSize = isset($fusesMemSegment->size) - ? $this->stringToInt($fusesMemSegment->size) : null; - - $this->fuseSegmentStartAddress = isset($fusesMemSegment->startAddress) - ? $this->stringToInt($fusesMemSegment->startAddress) : null; - } - - if (isset($dataAddressSpace->memorySegmentsByTypeAndName['lockbits']['lockbits'])) { - $lockbitsMemSegment = $dataAddressSpace->memorySegmentsByTypeAndName['lockbits']['lockbits']; - $this->lockbitsSegmentStartAddress = isset($lockbitsMemSegment->startAddress) - ? $this->stringToInt($lockbitsMemSegment->startAddress) : null; - } - } + $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 @@ -595,63 +583,162 @@ class Avr8TargetDescriptionFile extends TargetDescriptionFile { $failures = parent::validate(); - if (is_null($this->signature) - || is_null($this->signature->byteZero) - || is_null($this->signature->byteOne) - || is_null($this->signature->byteTwo) - ) { + if (is_null($this->getSignature())) { $failures[] = "Missing or incomplete AVR signature."; } - if (is_null($this->debugPhysicalInterfaces)) { + $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; } - if (is_null($this->family) || $this->family == self::AVR8_FAMILY_OTHER) { + $family = $this->getFamily(); + if (is_null($family) || $family == self::AVR8_FAMILY_OTHER) { $failures[] = 'Unknown AVR8 family'; } - if (in_array(self::AVR8_PHYSICAL_INTERFACE_DEBUG_WIRE, $this->debugPhysicalInterfaces)) { - if (!isset($this->physicalInterfacesByName['isp'])) { + $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(self::AVR8_PHYSICAL_INTERFACE_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(self::AVR8_PHYSICAL_INTERFACE_ISP, $physicalInterfaces)) { $failures[] = 'Missing ISP interface for debugWire target.'; } - if (is_null($this->ispProgramModeTimeout)) { + if (is_null($ispParameters->programModeTimeout)) { $failures[] = 'Missing ispenterprogmode_timeout ISP parameter.'; } - if (is_null($this->ispProgramModeStabilizationDelay)) { + + if (is_null($ispParameters->programModeStabilizationDelay)) { $failures[] = 'Missing ispenterprogmode_stabdelay ISP parameter.'; } - if (is_null($this->ispProgramModeCommandExecutionDelay)) { + + if (is_null($ispParameters->programModeCommandExecutionDelay)) { $failures[] = 'Missing ispenterprogmode_cmdexedelay ISP parameter.'; } - if (is_null($this->ispProgramModeSyncLoops)) { + + if (is_null($ispParameters->programModeSyncLoops)) { $failures[] = 'Missing ispenterprogmode_synchloops ISP parameter.'; } - if (is_null($this->ispProgramModeByteDelay)) { + + if (is_null($ispParameters->programModeByteDelay)) { $failures[] = 'Missing ispenterprogmode_bytedelay ISP parameter.'; } - if (is_null($this->ispProgramModePollValue)) { + + if (is_null($ispParameters->programModePollValue)) { $failures[] = 'Missing ispenterprogmode_pollvalue ISP parameter.'; } - if (is_null($this->ispProgramModePollIndex)) { + + if (is_null($ispParameters->programModePollIndex)) { $failures[] = 'Missing ispenterprogmode_pollindex ISP parameter.'; } - if (is_null($this->ispProgramModePreDelay)) { + + if (is_null($ispParameters->programModePreDelay)) { $failures[] = 'Missing ispleaveprogmode_predelay ISP parameter.'; } - if (is_null($this->ispProgramModePostDelay)) { + + if (is_null($ispParameters->programModePostDelay)) { $failures[] = 'Missing ispleaveprogmode_postdelay ISP parameter.'; } - if (is_null($this->ispReadSignaturePollIndex)) { + + if (is_null($ispParameters->readSignaturePollIndex)) { $failures[] = 'Missing ispreadsign_pollindex ISP parameter.'; } - if (is_null($this->ispReadFusePollIndex)) { + + if (is_null($ispParameters->readFusePollIndex)) { $failures[] = 'Missing ispreadfuse_pollindex ISP parameter.'; } - if (is_null($this->ispReadLockPollIndex)) { + + if (is_null($ispParameters->readLockPollIndex)) { $failures[] = 'Missing ispreadlock_pollindex ISP parameter.'; } @@ -672,152 +759,95 @@ class Avr8TargetDescriptionFile extends TargetDescriptionFile } } - if (is_null($this->stackPointerRegisterLowAddress)) { - $failures[] = 'Missing stack pointer register start address.'; - } - - if ($this->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 (' . $this->stackPointerRegisterSize . ') exceeds maximum (2).'; - } - - if ($this->stackPointerRegisterSize < 1) { - $failures[] = 'Stack pointer register size (' . $this->stackPointerRegisterSize . ') is less than 1.'; - } - - if (is_null($this->stackPointerRegisterSize)) { - $failures[] = 'Missing stack pointer register size.'; - } - - if (is_null($this->statusRegisterStartAddress)) { - $failures[] = 'Missing status register start address.'; - } - - if (is_null($this->statusRegisterSize)) { - $failures[] = 'Missing status register size.'; - - } else if ($this->statusRegisterSize > 1) { - $failures[] = 'Status register size exceeds 1'; - } - - if (is_null($this->flashSize)) { - $failures[] = 'Missing flash size.'; - } - - if (is_null($this->flashPageSize)) { - $failures[] = 'Missing flash page size.'; - } - - if (is_null($this->flashStartAddress)) { - $failures[] = 'Missing flash start address.'; - } - - if (is_null($this->ramStartAddress)) { - $failures[] = 'Missing ram start address.'; - } - - if (is_null($this->eepromSize)) { - $failures[] = 'Missing eeprom size.'; - } - - if ($this->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($this->eepromPageSize)) { - $failures[] = 'Missing eeprom page size.'; - } - - if (is_null($this->eepromStartAddress)) { - $failures[] = 'Missing eeprom start address.'; - } - if ( - in_array(self::AVR8_PHYSICAL_INTERFACE_DEBUG_WIRE, $this->debugPhysicalInterfaces) - || ( - in_array(self::AVR8_PHYSICAL_INTERFACE_JTAG, $this->debugPhysicalInterfaces) - && $this->family == self::AVR8_FAMILY_MEGA - ) + in_array(self::AVR8_PHYSICAL_INTERFACE_JTAG, $debugPhysicalInterfaces) + && $family == self::AVR8_FAMILY_MEGA ) { - if (is_null($this->ocdRevision)) { + $jtagParameters = $this->getJtagParameters(); + + if (is_null($jtagParameters->ocdRevision)) { $failures[] = 'Missing OCD revision.'; } - if (is_null($this->ocdDataRegister)) { + if (is_null($jtagParameters->ocdDataRegister)) { $failures[] = 'Missing OCD data register address.'; } - if (is_null($this->spmcRegisterStartAddress)) { + if (is_null($jtagParameters->spmcRegisterStartAddress)) { $failures[] = 'Missing store program memory control register start address.'; } - if (is_null($this->osccalAddress)) { + 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(self::AVR8_PHYSICAL_INTERFACE_PDI, $this->debugPhysicalInterfaces)) { - if (is_null($this->appSectionPdiOffset)) { + if (in_array(self::AVR8_PHYSICAL_INTERFACE_PDI, $debugPhysicalInterfaces)) { + $pdiParameters = $this->getPdiParameters(); + + if (is_null($pdiParameters->appSectionPdiOffset)) { $failures[] = 'Missing app section PDI offset.'; } - if (is_null($this->bootSectionPdiOffset)) { + if (is_null($pdiParameters->bootSectionPdiOffset)) { $failures[] = 'Missing boot section PDI offset.'; } - if (is_null($this->ramPdiOffset)) { + if (is_null($pdiParameters->ramPdiOffset)) { $failures[] = 'Missing datamem PDI offset.'; } - if (is_null($this->eepromPdiOffset)) { + if (is_null($pdiParameters->eepromPdiOffset)) { $failures[] = 'Missing eeprom PDI offset.'; } - if (is_null($this->userSignaturesPdiOffset)) { + if (is_null($pdiParameters->userSignaturesPdiOffset)) { $failures[] = 'Missing user signatures PDI offset.'; } - if (is_null($this->productSignaturesPdiOffset)) { + if (is_null($pdiParameters->productSignaturesPdiOffset)) { $failures[] = 'Missing product signatures PDI offset.'; } - if (is_null($this->lockRegistersPdiOffset)) { + if (is_null($pdiParameters->lockRegistersPdiOffset)) { $failures[] = 'Missing lock registers PDI offset.'; } - if (is_null($this->nvmModuleBaseAddress)) { + if (is_null($pdiParameters->nvmModuleBaseAddress)) { $failures[] = 'Missing NVM module base address.'; } - if (is_null($this->mcuModuleBaseAddress)) { + if (is_null($pdiParameters->mcuModuleBaseAddress)) { $failures[] = 'Missing MCU module base address.'; } - if (is_null($this->appSectionStartAddress)) { + if (is_null($pdiParameters->appSectionStartAddress)) { $failures[] = 'Missing APP section start address'; } - if (is_null($this->appSectionSize)) { + if (is_null($pdiParameters->appSectionSize)) { $failures[] = 'Missing APP section size'; } } - if (in_array(Avr8TargetDescriptionFile::AVR8_PHYSICAL_INTERFACE_UPDI, $this->debugPhysicalInterfaces)) { - if (is_null($this->nvmModuleBaseAddress)) { + if (in_array(Avr8TargetDescriptionFile::AVR8_PHYSICAL_INTERFACE_UPDI, $debugPhysicalInterfaces)) { + $updiParameters = $this->getUpdiParameters(); + if (is_null($updiParameters->nvmModuleBaseAddress)) { $failures[] = 'Missing NVM base address.'; } - if (is_null($this->programMemoryUpdiStartAddress)) { + if (is_null($updiParameters->programMemoryStartAddress)) { $failures[] = 'Missing UPDI program memory offset.'; - } else if ($this->programMemoryUpdiStartAddress > 0xFFFFFF) { + } 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. @@ -825,56 +855,37 @@ class Avr8TargetDescriptionFile extends TargetDescriptionFile $failures[] = 'UPDI program memory offset exceeds maximum value for 24-bit unsigned integer.'; } - if (!is_null($this->flashPageSize) && $this->flashPageSize > 0xFFFF) { + if (!is_null($targetParameters->flashPageSize) && $targetParameters->flashPageSize > 0xFFFF) { $failures[] = 'Flash page size exceeds maximum value for 16-bit unsigned integer.'; } - if (is_null($this->ocdBaseAddress)) { + if (is_null($updiParameters->ocdBaseAddress)) { $failures[] = 'Missing OCD base address.'; - } else if ($this->ocdBaseAddress > 0xFFFF) { + } else if ($updiParameters->ocdBaseAddress > 0xFFFF) { $failures[] = 'UPDI OCD base address exceeds maximum value for 16-bit unsigned integer.'; } - if (is_null($this->signatureSegmentStartAddress)) { + if (is_null($updiParameters->signatureSegmentStartAddress)) { $failures[] = 'Missing signature segment start address.'; } - if (is_null($this->fuseSegmentSize)) { + if (is_null($updiParameters->fuseSegmentSize)) { $failures[] = 'Missing fuse segment size.'; } - if (is_null($this->fuseSegmentStartAddress)) { + if (is_null($updiParameters->fuseSegmentStartAddress)) { $failures[] = 'Missing fuses segment start address.'; } - if (is_null($this->fuseSegmentSize)) { - $failures[] = 'Missing fuses segment size.'; - } - - if (is_null($this->lockbitsSegmentStartAddress)) { + if (is_null($updiParameters->lockbitsSegmentStartAddress)) { $failures[] = 'Missing lockbits segment start address.'; } } if ( - in_array(Avr8TargetDescriptionFile::AVR8_PHYSICAL_INTERFACE_JTAG, $this->debugPhysicalInterfaces) - && $this->family == self::AVR8_FAMILY_MEGA - ) { - 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(Avr8TargetDescriptionFile::AVR8_PHYSICAL_INTERFACE_JTAG, $this->debugPhysicalInterfaces) - || in_array(Avr8TargetDescriptionFile::AVR8_PHYSICAL_INTERFACE_UPDI, $this->debugPhysicalInterfaces) + in_array(Avr8TargetDescriptionFile::AVR8_PHYSICAL_INTERFACE_JTAG, $debugPhysicalInterfaces) + || in_array(Avr8TargetDescriptionFile::AVR8_PHYSICAL_INTERFACE_UPDI, $debugPhysicalInterfaces) ) { if (empty($this->getFuseBitsDescriptor('eesave'))) { $failures[] = 'Could not find EESAVE fuse bit field for JTAG/UPDI target.'; diff --git a/build/scripts/TargetDescriptionFiles/AVR8/DebugWireParameters.php b/build/scripts/TargetDescriptionFiles/AVR8/DebugWireParameters.php new file mode 100644 index 00000000..2600a8db --- /dev/null +++ b/build/scripts/TargetDescriptionFiles/AVR8/DebugWireParameters.php @@ -0,0 +1,10 @@ +xml->device; if (!empty($device)) { - $deviceAttributes = $device->attributes(); + $this->deviceAttributesByName = current((array)$device->attributes()); - if (!empty($deviceAttributes['name'])) { + if (!empty($this->deviceAttributesByName['name'])) { $this->targetName = $device['name']; } - if (!empty($deviceAttributes['architecture'])) { + if (!empty($this->deviceAttributesByName['architecture'])) { $this->targetArchitecture = stristr($device['architecture'], 'avr') !== false ? self::ARCHITECTURE_AVR8 : $device['architecture']; } @@ -85,13 +88,96 @@ class TargetDescriptionFile $this->loadPinouts(); } - protected function stringToInt(string $value): ?int + 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'); diff --git a/build/scripts/ValidateAvr8TargetDescriptionFiles.php b/build/scripts/ValidateAvr8TargetDescriptionFiles.php index ab595a2f..af7e7c0e 100644 --- a/build/scripts/ValidateAvr8TargetDescriptionFiles.php +++ b/build/scripts/ValidateAvr8TargetDescriptionFiles.php @@ -16,7 +16,7 @@ foreach ($avr8Tdfs as $targetDescriptionFile) { print "\033[31m"; print "Validation for " . $targetDescriptionFile->filePath . " failed.\n"; - print count($validationFailures) . " errors found:\n"; + print count($validationFailures) . " error(s) found:\n"; print implode("\n", $validationFailures); print "\n\n"; print "\033[0m"; @@ -31,5 +31,5 @@ foreach ($avr8Tdfs as $targetDescriptionFile) { print "\n\n"; print "Validated " . count($avr8Tdfs) . " TDFs. "; print (($failedValidationCount > 0) ? "\033[31m" : "\033[32m"); -print $failedValidationCount . " failures." . "\033[0m" . "\n"; +print $failedValidationCount . " failure(s)." . "\033[0m" . "\n"; echo "Done\n";