From 72e9c64715eb5ed7b2bd0fe4575fb3600d50c818 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Wed, 23 Feb 2022 17:40:00 +0100 Subject: [PATCH 01/10] Added test for os-specific config options --- arduino/cores/board_test.go | 41 +++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/arduino/cores/board_test.go b/arduino/cores/board_test.go index 3eeb35d16a2..1e78f1167fe 100644 --- a/arduino/cores/board_test.go +++ b/arduino/cores/board_test.go @@ -340,6 +340,47 @@ func TestBoardOptions(t *testing.T) { // fmt.Print(string(data)) } +func TestOSSpecificBoardOptions(t *testing.T) { + boardWihOSSpecificOptionProperties := properties.NewMap() + boardWihOSSpecificOptionProperties.Set("menu.UploadSpeed.115200", "115200") + boardWihOSSpecificOptionProperties.Set("menu.UploadSpeed.115200.upload.speed", "115200") + boardWihOSSpecificOptionProperties.Set("menu.UploadSpeed.9600", "9600") + boardWihOSSpecificOptionProperties.Set("menu.UploadSpeed.9600.upload.speed", "9600") + boardWihOSSpecificOptionProperties.Set("menu.UploadSpeed.57600", "57600") + boardWihOSSpecificOptionProperties.Set("menu.UploadSpeed.57600.upload.speed", "57600") + boardWihOSSpecificOptionProperties.Set("menu.UploadSpeed.230400", "230400") + boardWihOSSpecificOptionProperties.Set("menu.UploadSpeed.230400.macosx", "230400") + boardWihOSSpecificOptionProperties.Set("menu.UploadSpeed.230400.upload.speed", "230400") + boardWihOSSpecificOptionProperties.Set("menu.UploadSpeed.256000.windows", "256000") + boardWihOSSpecificOptionProperties.Set("menu.UploadSpeed.256000.upload.speed", "256000") + boardWihOSSpecificOptionProperties.Set("menu.UploadSpeed.460800", "460800") + boardWihOSSpecificOptionProperties.Set("menu.UploadSpeed.460800.macosx", "460800") + boardWihOSSpecificOptionProperties.Set("menu.UploadSpeed.460800.upload.speed", "460800") + boardWihOSSpecificOptionProperties.Set("menu.UploadSpeed.512000.windows", "512000") + boardWihOSSpecificOptionProperties.Set("menu.UploadSpeed.512000.upload.speed", "512000") + boardWihOSSpecificOptionProperties.Set("menu.UploadSpeed.921600", "921600") + boardWihOSSpecificOptionProperties.Set("menu.UploadSpeed.921600.upload.speed", "921600") + + boardWithOSSpecificOptions := &Board{ + BoardID: "test", + Properties: boardWihOSSpecificOptionProperties, + PlatformRelease: &PlatformRelease{ + Platform: &Platform{ + Architecture: "test", + Package: &Package{ + Name: "test", + }, + }, + Menus: properties.NewFromHashmap(map[string]string{ + "UploadSpeed": "Upload Speed", + }), + }, + } + + _, err := boardWithOSSpecificOptions.GeneratePropertiesForConfiguration("UploadSpeed=256000") + require.Error(t, err) +} + func TestBoardMatching(t *testing.T) { brd01 := &Board{ Properties: properties.NewFromHashmap(map[string]string{ From c48573a453121dc791b62dceb6e5691e494ff9eb Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Tue, 22 Feb 2022 18:13:34 +0100 Subject: [PATCH 02/10] Build board config options structures only once and cache them --- arduino/cores/board.go | 50 +++++++++++++++++++++++++++--------------- 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/arduino/cores/board.go b/arduino/cores/board.go index 3195fb8f14f..0504e8b0b68 100644 --- a/arduino/cores/board.go +++ b/arduino/cores/board.go @@ -24,10 +24,12 @@ import ( // Board represents a board loaded from an installed platform type Board struct { - BoardID string - Properties *properties.Map `json:"-"` - PlatformRelease *PlatformRelease `json:"-"` - identificationProperties []*properties.Map + BoardID string + Properties *properties.Map `json:"-"` + PlatformRelease *PlatformRelease `json:"-"` + configOptions *properties.Map + configOptionValues map[string]*properties.Map + identificationProperties []*properties.Map } // HasUsbID returns true if the board match the usb vid and pid parameters @@ -64,29 +66,41 @@ func (b *Board) String() string { return b.FQBN() } +func (b *Board) buildConfigOptionsStructures() { + if b.configOptions != nil { + return + } + + b.configOptions = properties.NewMap() + allConfigs := b.Properties.SubTree("menu") + for _, option := range allConfigs.FirstLevelKeys() { + b.configOptions.Set(option, b.PlatformRelease.Menus.Get(option)) + } + + b.configOptionValues = map[string]*properties.Map{} + for configName, options := range allConfigs.FirstLevelOf() { + b.configOptionValues[configName] = properties.NewMap() + for _, value := range options.FirstLevelKeys() { + if label, ok := options.GetOk(value); ok { + b.configOptionValues[configName].Set(value, label) + } + } + } +} + // GetConfigOptions returns an OrderedMap of configuration options for this board. // The returned map will have key and value as option id and option name, respectively. func (b *Board) GetConfigOptions() *properties.Map { - res := properties.NewMap() - menu := b.Properties.SubTree("menu") - for _, option := range menu.FirstLevelKeys() { - res.Set(option, b.PlatformRelease.Menus.Get(option)) - } - return res + b.buildConfigOptionsStructures() + return b.configOptions } // GetConfigOptionValues returns an OrderedMap of possible values for a specific configuratio options // for this board. The returned map will have key and value as option value and option value name, // respectively. func (b *Board) GetConfigOptionValues(option string) *properties.Map { - res := properties.NewMap() - menu := b.Properties.SubTree("menu").SubTree(option) - for _, value := range menu.FirstLevelKeys() { - if label, ok := menu.GetOk(value); ok { - res.Set(value, label) - } - } - return res + b.buildConfigOptionsStructures() + return b.configOptionValues[option] } // GetBuildProperties returns the build properties and the build From db2a3d15bb8945b80c886daa5797b782cc49b680 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Wed, 23 Feb 2022 10:36:17 +0100 Subject: [PATCH 03/10] Board's build options properties are now calculated only once and cached --- arduino/cores/board.go | 68 ++++++++++++++++++------------------- arduino/cores/board_test.go | 8 +++++ 2 files changed, 41 insertions(+), 35 deletions(-) diff --git a/arduino/cores/board.go b/arduino/cores/board.go index 0504e8b0b68..8b3e596ebb2 100644 --- a/arduino/cores/board.go +++ b/arduino/cores/board.go @@ -24,12 +24,14 @@ import ( // Board represents a board loaded from an installed platform type Board struct { - BoardID string - Properties *properties.Map `json:"-"` - PlatformRelease *PlatformRelease `json:"-"` - configOptions *properties.Map - configOptionValues map[string]*properties.Map - identificationProperties []*properties.Map + BoardID string + Properties *properties.Map `json:"-"` + PlatformRelease *PlatformRelease `json:"-"` + configOptions *properties.Map + configOptionValues map[string]*properties.Map + configOptionProperties map[string]*properties.Map + defaultConfig *properties.Map + identificationProperties []*properties.Map } // HasUsbID returns true if the board match the usb vid and pid parameters @@ -78,11 +80,16 @@ func (b *Board) buildConfigOptionsStructures() { } b.configOptionValues = map[string]*properties.Map{} - for configName, options := range allConfigs.FirstLevelOf() { - b.configOptionValues[configName] = properties.NewMap() - for _, value := range options.FirstLevelKeys() { - if label, ok := options.GetOk(value); ok { - b.configOptionValues[configName].Set(value, label) + b.configOptionProperties = map[string]*properties.Map{} + b.defaultConfig = properties.NewMap() + for option, optionProps := range allConfigs.FirstLevelOf() { + b.configOptionValues[option] = properties.NewMap() + values := optionProps.FirstLevelKeys() + b.defaultConfig.Set(option, values[0]) + for _, value := range values { + if label, ok := optionProps.GetOk(value); ok { + b.configOptionValues[option].Set(value, label) + b.configOptionProperties[option+"="+value] = optionProps.SubTree(value) } } } @@ -106,38 +113,29 @@ func (b *Board) GetConfigOptionValues(option string) *properties.Map { // GetBuildProperties returns the build properties and the build // platform for the Board with the configuration passed as parameter. func (b *Board) GetBuildProperties(userConfigs *properties.Map) (*properties.Map, error) { - // Clone user configs because they are destroyed during iteration - userConfigs = userConfigs.Clone() + b.buildConfigOptionsStructures() + + // Override default configs with user configs + config := b.defaultConfig.Clone() + config.Merge(userConfigs) // Start with board's base properties buildProperties := b.Properties.Clone() // Add all sub-configurations one by one (a config is: option=value) - menu := b.Properties.SubTree("menu") - for _, option := range menu.FirstLevelKeys() { - optionMenu := menu.SubTree(option) - userValue, haveUserValue := userConfigs.GetOk(option) - if haveUserValue { - userConfigs.Remove(option) - if !optionMenu.ContainsKey(userValue) { - return nil, fmt.Errorf(tr("invalid value '%[1]s' for option '%[2]s'"), userValue, option) - } - } else { - // apply default - userValue = optionMenu.FirstLevelKeys()[0] - } - - optionsConf := optionMenu.SubTree(userValue) - buildProperties.Merge(optionsConf) - } - // Check for residual invalid options... - if invalidKeys := userConfigs.Keys(); len(invalidKeys) > 0 { - invalidOption := invalidKeys[0] - if invalidOption == "" { + for option, value := range config.AsMap() { + if option == "" { return nil, fmt.Errorf(tr("invalid empty option found")) } - return nil, fmt.Errorf(tr("invalid option '%s'"), invalidOption) + if _, ok := b.configOptions.GetOk(option); !ok { + return nil, fmt.Errorf(tr("invalid option '%s'"), option) + } + optionsConf, ok := b.configOptionProperties[option+"="+value] + if !ok { + return nil, fmt.Errorf(tr("invalid value '%[1]s' for option '%[2]s'"), value, option) + } + buildProperties.Merge(optionsConf) } return buildProperties, nil diff --git a/arduino/cores/board_test.go b/arduino/cores/board_test.go index 1e78f1167fe..41f3cf2a970 100644 --- a/arduino/cores/board_test.go +++ b/arduino/cores/board_test.go @@ -59,6 +59,7 @@ var boardUno = &Board{ Name: "arduino", }, }, + Menus: properties.NewMap(), }, } @@ -114,6 +115,9 @@ var boardMega = &Board{ Name: "arduino", }, }, + Menus: properties.NewFromHashmap(map[string]string{ + "cpu": "Processor", + }), }, } @@ -154,6 +158,10 @@ var boardWatterottTiny841 = &Board{ Name: "watterott", }, }, + Menus: properties.NewFromHashmap(map[string]string{ + "core": "Core", + "info": "Info", + }), }, } From c921d0c5defe558f7f439c2ba45266c643221380 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Wed, 23 Feb 2022 17:29:01 +0100 Subject: [PATCH 04/10] Added tests for config options ordering It required insertion of test data with the properties.Set method to preserve ordering. --- arduino/cores/board_test.go | 482 +++++++++++++++++++----------------- 1 file changed, 249 insertions(+), 233 deletions(-) diff --git a/arduino/cores/board_test.go b/arduino/cores/board_test.go index 41f3cf2a970..e42f57125d4 100644 --- a/arduino/cores/board_test.go +++ b/arduino/cores/board_test.go @@ -22,36 +22,40 @@ import ( "github.com/stretchr/testify/require" ) +var boardUnoProperties = properties.NewMap() + +func init() { + boardUnoProperties.Set("name", "Arduino/Genuino Uno") + boardUnoProperties.Set("vid.0", "0x2341") + boardUnoProperties.Set("pid.0", "0x0043") + boardUnoProperties.Set("vid.1", "0x2341") + boardUnoProperties.Set("pid.1", "0x0001") + boardUnoProperties.Set("vid.2", "0x2A03") + boardUnoProperties.Set("pid.2", "0x0043") + boardUnoProperties.Set("vid.3", "0x2341") + boardUnoProperties.Set("pid.3", "0x0243") + boardUnoProperties.Set("upload.tool", "avrdude") + boardUnoProperties.Set("upload.protocol", "arduino") + boardUnoProperties.Set("upload.maximum_size", "32256") + boardUnoProperties.Set("upload.maximum_data_size", "2048") + boardUnoProperties.Set("upload.speed", "115200") + boardUnoProperties.Set("bootloader.tool", "avrdude") + boardUnoProperties.Set("bootloader.low_fuses", "0xFF") + boardUnoProperties.Set("bootloader.high_fuses", "0xDE") + boardUnoProperties.Set("bootloader.extended_fuses", "0xFD") + boardUnoProperties.Set("bootloader.unlock_bits", "0x3F") + boardUnoProperties.Set("bootloader.lock_bits", "0x0F") + boardUnoProperties.Set("bootloader.file", "optiboot/optiboot_atmega328.hex") + boardUnoProperties.Set("build.mcu", "atmega328p") + boardUnoProperties.Set("build.f_cpu", "16000000L") + boardUnoProperties.Set("build.board", "AVR_UNO") + boardUnoProperties.Set("build.core", "arduino") + boardUnoProperties.Set("build.variant", "standard") +} + var boardUno = &Board{ - BoardID: "uno", - Properties: properties.NewFromHashmap(map[string]string{ - "name": "Arduino/Genuino Uno", - "vid.0": "0x2341", - "pid.0": "0x0043", - "vid.1": "0x2341", - "pid.1": "0x0001", - "vid.2": "0x2A03", - "pid.2": "0x0043", - "vid.3": "0x2341", - "pid.3": "0x0243", - "upload.tool": "avrdude", - "upload.protocol": "arduino", - "upload.maximum_size": "32256", - "upload.maximum_data_size": "2048", - "upload.speed": "115200", - "bootloader.tool": "avrdude", - "bootloader.low_fuses": "0xFF", - "bootloader.high_fuses": "0xDE", - "bootloader.extended_fuses": "0xFD", - "bootloader.unlock_bits": "0x3F", - "bootloader.lock_bits": "0x0F", - "bootloader.file": "optiboot/optiboot_atmega328.hex", - "build.mcu": "atmega328p", - "build.f_cpu": "16000000L", - "build.board": "AVR_UNO", - "build.core": "arduino", - "build.variant": "standard", - }), + BoardID: "uno", + Properties: boardUnoProperties, PlatformRelease: &PlatformRelease{ Platform: &Platform{ Architecture: "avr", @@ -63,51 +67,56 @@ var boardUno = &Board{ }, } +var boardMegaProperties = properties.NewMap() + +func init() { + boardMegaProperties.Set("name", "Arduino/Genuino Mega or Mega 2560") + boardMegaProperties.Set("vid.0", "0x2341") + boardMegaProperties.Set("pid.0", "0x0010") + boardMegaProperties.Set("vid.1", "0x2341") + boardMegaProperties.Set("pid.1", "0x0042") + boardMegaProperties.Set("vid.2", "0x2A03") + boardMegaProperties.Set("pid.2", "0x0010") + boardMegaProperties.Set("vid.3", "0x2A03") + boardMegaProperties.Set("pid.3", "0x0042") + boardMegaProperties.Set("vid.4", "0x2341") + boardMegaProperties.Set("pid.4", "0x0210") + boardMegaProperties.Set("vid.5", "0x2341") + boardMegaProperties.Set("pid.5", "0x0242") + boardMegaProperties.Set("upload.tool", "avrdude") + boardMegaProperties.Set("upload.maximum_data_size", "8192") + boardMegaProperties.Set("bootloader.tool", "avrdude") + boardMegaProperties.Set("bootloader.low_fuses", "0xFF") + boardMegaProperties.Set("bootloader.unlock_bits", "0x3F") + boardMegaProperties.Set("bootloader.lock_bits", "0x0F") + boardMegaProperties.Set("build.f_cpu", "16000000L") + boardMegaProperties.Set("build.core", "arduino") + boardMegaProperties.Set("build.variant", "mega") + boardMegaProperties.Set("build.board", "AVR_MEGA2560") + boardMegaProperties.Set("menu.cpu.atmega2560", "ATmega2560 (Mega 2560)") + boardMegaProperties.Set("menu.cpu.atmega2560.upload.protocol", "wiring") + boardMegaProperties.Set("menu.cpu.atmega2560.upload.maximum_size", "253952") + boardMegaProperties.Set("menu.cpu.atmega2560.upload.speed", "115200") + boardMegaProperties.Set("menu.cpu.atmega2560.bootloader.high_fuses", "0xD8") + boardMegaProperties.Set("menu.cpu.atmega2560.bootloader.extended_fuses", "0xFD") + boardMegaProperties.Set("menu.cpu.atmega2560.bootloader.file", "stk500v2/stk500boot_v2_mega2560.hex") + boardMegaProperties.Set("menu.cpu.atmega2560.build.mcu", "atmega2560") + boardMegaProperties.Set("menu.cpu.atmega2560.build.board", "AVR_MEGA2560") + boardMegaProperties.Set("menu.cpu.atmega1280", "ATmega1280") + boardMegaProperties.Set("menu.cpu.atmega1280.upload.protocol", "arduino") + boardMegaProperties.Set("menu.cpu.atmega1280.upload.maximum_size", "126976") + boardMegaProperties.Set("menu.cpu.atmega1280.upload.speed", "57600") + boardMegaProperties.Set("menu.cpu.atmega1280.bootloader.high_fuses", "0xDA") + boardMegaProperties.Set("menu.cpu.atmega1280.bootloader.extended_fuses", "0xF5") + boardMegaProperties.Set("menu.cpu.atmega1280.bootloader.file", "atmega/ATmegaBOOT_168_atmega1280.hex") + boardMegaProperties.Set("menu.cpu.atmega1280.build.mcu", "atmega1280") + boardMegaProperties.Set("menu.cpu.atmega1280.build.board", "AVR_MEGA") +} + var boardMega = &Board{ - BoardID: "mega", - Properties: properties.NewFromHashmap(map[string]string{ - "name": "Arduino/Genuino Mega or Mega 2560", - "vid.0": "0x2341", - "pid.0": "0x0010", - "vid.1": "0x2341", - "pid.1": "0x0042", - "vid.2": "0x2A03", - "pid.2": "0x0010", - "vid.3": "0x2A03", - "pid.3": "0x0042", - "vid.4": "0x2341", - "pid.4": "0x0210", - "vid.5": "0x2341", - "pid.5": "0x0242", - "upload.tool": "avrdude", - "upload.maximum_data_size": "8192", - "bootloader.tool": "avrdude", - "bootloader.low_fuses": "0xFF", - "bootloader.unlock_bits": "0x3F", - "bootloader.lock_bits": "0x0F", - "build.f_cpu": "16000000L", - "build.core": "arduino", - "build.variant": "mega", - "build.board": "AVR_MEGA2560", - "menu.cpu.atmega2560": "ATmega2560 (Mega 2560)", - "menu.cpu.atmega2560.upload.protocol": "wiring", - "menu.cpu.atmega2560.upload.maximum_size": "253952", - "menu.cpu.atmega2560.upload.speed": "115200", - "menu.cpu.atmega2560.bootloader.high_fuses": "0xD8", - "menu.cpu.atmega2560.bootloader.extended_fuses": "0xFD", - "menu.cpu.atmega2560.bootloader.file": "stk500v2/stk500boot_v2_mega2560.hex", - "menu.cpu.atmega2560.build.mcu": "atmega2560", - "menu.cpu.atmega2560.build.board": "AVR_MEGA2560", - "menu.cpu.atmega1280": "ATmega1280", - "menu.cpu.atmega1280.upload.protocol": "arduino", - "menu.cpu.atmega1280.upload.maximum_size": "126976", - "menu.cpu.atmega1280.upload.speed": "57600", - "menu.cpu.atmega1280.bootloader.high_fuses": "0xDA", - "menu.cpu.atmega1280.bootloader.extended_fuses": "0xF5", - "menu.cpu.atmega1280.bootloader.file": "atmega/ATmegaBOOT_168_atmega1280.hex", - "menu.cpu.atmega1280.build.mcu": "atmega1280", - "menu.cpu.atmega1280.build.board": "AVR_MEGA", - }), + BoardID: "mega", + Properties: boardMegaProperties, + PlatformRelease: &PlatformRelease{ Platform: &Platform{ Architecture: "avr", @@ -121,36 +130,41 @@ var boardMega = &Board{ }, } +var boardWatterottTiny841Properties = properties.NewMap() + +func init() { + boardWatterottTiny841Properties.Set("name", "ATtiny841 (8 MHz)") + boardWatterottTiny841Properties.Set("menu.core.arduino", "Standard Arduino") + boardWatterottTiny841Properties.Set("menu.core.arduino.build.core", "arduino:arduino") + boardWatterottTiny841Properties.Set("menu.core.arduino.build.variant", "tiny14") + boardWatterottTiny841Properties.Set("menu.core.spencekonde", "ATtiny841 (by Spence Konde)") + boardWatterottTiny841Properties.Set("menu.core.spencekonde.build.core", "tiny841") + boardWatterottTiny841Properties.Set("menu.core.spencekonde.build.variant", "tiny14") + boardWatterottTiny841Properties.Set("menu.info.info", "Press Reset, when Uploading is shown.") + boardWatterottTiny841Properties.Set("vid.0", "0x16D0") + boardWatterottTiny841Properties.Set("pid.0", "0x0753") + boardWatterottTiny841Properties.Set("bootloader.tool", "avrdude") + boardWatterottTiny841Properties.Set("bootloader.low_fuses", "0xE2") + boardWatterottTiny841Properties.Set("bootloader.high_fuses", "0xDD") + boardWatterottTiny841Properties.Set("bootloader.extended_fuses", "0xFE") + boardWatterottTiny841Properties.Set("bootloader.unlock_bits", "0xFF") + boardWatterottTiny841Properties.Set("bootloader.lock_bits", "0xFF") + boardWatterottTiny841Properties.Set("bootloader.file", "micronucleus-t841.hex") + boardWatterottTiny841Properties.Set("upload.tool", "micronucleus") + boardWatterottTiny841Properties.Set("upload.protocol", "usb") + boardWatterottTiny841Properties.Set("upload.wait_for_upload_port", "false") + boardWatterottTiny841Properties.Set("upload.use_1200bps_touch", "false") + boardWatterottTiny841Properties.Set("upload.disable_flushing", "false") + boardWatterottTiny841Properties.Set("upload.maximum_size", "6500") + boardWatterottTiny841Properties.Set("build.mcu", "attiny841") + boardWatterottTiny841Properties.Set("build.f_cpu", "8000000L") + boardWatterottTiny841Properties.Set("build.board", "AVR_ATTINY841") + +} + var boardWatterottTiny841 = &Board{ - BoardID: "attiny841", - Properties: properties.NewFromHashmap(map[string]string{ - "name": "ATtiny841 (8 MHz)", - "menu.core.arduino": "Standard Arduino", - "menu.core.arduino.build.core": "arduino:arduino", - "menu.core.arduino.build.variant": "tiny14", - "menu.core.spencekonde": "ATtiny841 (by Spence Konde)", - "menu.core.spencekonde.build.core": "tiny841", - "menu.core.spencekonde.build.variant": "tiny14", - "menu.info.info": "Press Reset, when Uploading is shown.", - "vid.0": "0x16D0", - "pid.0": "0x0753", - "bootloader.tool": "avrdude", - "bootloader.low_fuses": "0xE2", - "bootloader.high_fuses": "0xDD", - "bootloader.extended_fuses": "0xFE", - "bootloader.unlock_bits": "0xFF", - "bootloader.lock_bits": "0xFF", - "bootloader.file": "micronucleus-t841.hex", - "upload.tool": "micronucleus", - "upload.protocol": "usb", - "upload.wait_for_upload_port": "false", - "upload.use_1200bps_touch": "false", - "upload.disable_flushing": "false", - "upload.maximum_size": "6500", - "build.mcu": "attiny841", - "build.f_cpu": "8000000L", - "build.board": "AVR_ATTINY841", - }), + BoardID: "attiny841", + Properties: boardWatterottTiny841Properties, PlatformRelease: &PlatformRelease{ Platform: &Platform{ Architecture: "avr", @@ -194,111 +208,114 @@ func TestBoard(t *testing.T) { } func TestBoardOptions(t *testing.T) { - expConf2560 := properties.NewFromHashmap(map[string]string{ - "bootloader.extended_fuses": "0xFD", - "bootloader.file": "stk500v2/stk500boot_v2_mega2560.hex", - "bootloader.high_fuses": "0xD8", - "bootloader.lock_bits": "0x0F", - "bootloader.low_fuses": "0xFF", - "bootloader.tool": "avrdude", - "bootloader.unlock_bits": "0x3F", - "build.board": "AVR_MEGA2560", - "build.core": "arduino", - "build.f_cpu": "16000000L", - "build.mcu": "atmega2560", - "build.variant": "mega", - "menu.cpu.atmega1280": "ATmega1280", - "menu.cpu.atmega1280.bootloader.extended_fuses": "0xF5", - "menu.cpu.atmega1280.bootloader.file": "atmega/ATmegaBOOT_168_atmega1280.hex", - "menu.cpu.atmega1280.bootloader.high_fuses": "0xDA", - "menu.cpu.atmega1280.build.board": "AVR_MEGA", - "menu.cpu.atmega1280.build.mcu": "atmega1280", - "menu.cpu.atmega1280.upload.maximum_size": "126976", - "menu.cpu.atmega1280.upload.protocol": "arduino", - "menu.cpu.atmega1280.upload.speed": "57600", - "menu.cpu.atmega2560": "ATmega2560 (Mega 2560)", - "menu.cpu.atmega2560.bootloader.extended_fuses": "0xFD", - "menu.cpu.atmega2560.bootloader.file": "stk500v2/stk500boot_v2_mega2560.hex", - "menu.cpu.atmega2560.bootloader.high_fuses": "0xD8", - "menu.cpu.atmega2560.build.board": "AVR_MEGA2560", - "menu.cpu.atmega2560.build.mcu": "atmega2560", - "menu.cpu.atmega2560.upload.maximum_size": "253952", - "menu.cpu.atmega2560.upload.protocol": "wiring", - "menu.cpu.atmega2560.upload.speed": "115200", - "name": "Arduino/Genuino Mega or Mega 2560", - "pid.0": "0x0010", - "pid.1": "0x0042", - "pid.2": "0x0010", - "pid.3": "0x0042", - "pid.4": "0x0210", - "pid.5": "0x0242", - "upload.maximum_data_size": "8192", - "upload.maximum_size": "253952", - "upload.protocol": "wiring", - "upload.speed": "115200", - "upload.tool": "avrdude", - "vid.0": "0x2341", - "vid.1": "0x2341", - "vid.2": "0x2A03", - "vid.3": "0x2A03", - "vid.4": "0x2341", - "vid.5": "0x2341", - }) + expConf2560 := properties.NewMap() + expConf2560.Set("bootloader.extended_fuses", "0xFD") + expConf2560.Set("bootloader.file", "stk500v2/stk500boot_v2_mega2560.hex") + expConf2560.Set("bootloader.high_fuses", "0xD8") + expConf2560.Set("bootloader.lock_bits", "0x0F") + expConf2560.Set("bootloader.low_fuses", "0xFF") + expConf2560.Set("bootloader.tool", "avrdude") + expConf2560.Set("bootloader.unlock_bits", "0x3F") + expConf2560.Set("build.board", "AVR_MEGA2560") + expConf2560.Set("build.core", "arduino") + expConf2560.Set("build.f_cpu", "16000000L") + expConf2560.Set("build.mcu", "atmega2560") + expConf2560.Set("build.variant", "mega") + expConf2560.Set("menu.cpu.atmega1280", "ATmega1280") + expConf2560.Set("menu.cpu.atmega1280.bootloader.extended_fuses", "0xF5") + expConf2560.Set("menu.cpu.atmega1280.bootloader.file", "atmega/ATmegaBOOT_168_atmega1280.hex") + expConf2560.Set("menu.cpu.atmega1280.bootloader.high_fuses", "0xDA") + expConf2560.Set("menu.cpu.atmega1280.build.board", "AVR_MEGA") + expConf2560.Set("menu.cpu.atmega1280.build.mcu", "atmega1280") + expConf2560.Set("menu.cpu.atmega1280.upload.maximum_size", "126976") + expConf2560.Set("menu.cpu.atmega1280.upload.protocol", "arduino") + expConf2560.Set("menu.cpu.atmega1280.upload.speed", "57600") + expConf2560.Set("menu.cpu.atmega2560", "ATmega2560 (Mega 2560)") + expConf2560.Set("menu.cpu.atmega2560.bootloader.extended_fuses", "0xFD") + expConf2560.Set("menu.cpu.atmega2560.bootloader.file", "stk500v2/stk500boot_v2_mega2560.hex") + expConf2560.Set("menu.cpu.atmega2560.bootloader.high_fuses", "0xD8") + expConf2560.Set("menu.cpu.atmega2560.build.board", "AVR_MEGA2560") + expConf2560.Set("menu.cpu.atmega2560.build.mcu", "atmega2560") + expConf2560.Set("menu.cpu.atmega2560.upload.maximum_size", "253952") + expConf2560.Set("menu.cpu.atmega2560.upload.protocol", "wiring") + expConf2560.Set("menu.cpu.atmega2560.upload.speed", "115200") + expConf2560.Set("name", "Arduino/Genuino Mega or Mega 2560") + expConf2560.Set("pid.0", "0x0010") + expConf2560.Set("pid.1", "0x0042") + expConf2560.Set("pid.2", "0x0010") + expConf2560.Set("pid.3", "0x0042") + expConf2560.Set("pid.4", "0x0210") + expConf2560.Set("pid.5", "0x0242") + expConf2560.Set("upload.maximum_data_size", "8192") + expConf2560.Set("upload.maximum_size", "253952") + expConf2560.Set("upload.protocol", "wiring") + expConf2560.Set("upload.speed", "115200") + expConf2560.Set("upload.tool", "avrdude") + expConf2560.Set("vid.0", "0x2341") + expConf2560.Set("vid.1", "0x2341") + expConf2560.Set("vid.2", "0x2A03") + expConf2560.Set("vid.3", "0x2A03") + expConf2560.Set("vid.4", "0x2341") + expConf2560.Set("vid.5", "0x2341") conf2560, err := boardMega.GeneratePropertiesForConfiguration("cpu=atmega2560") require.NoError(t, err, "generating cpu=atmega2560 configuration") require.EqualValues(t, expConf2560.AsMap(), conf2560.AsMap(), "configuration for cpu=atmega2560") - - expConf1280 := properties.NewFromHashmap(map[string]string{ - "bootloader.extended_fuses": "0xF5", - "bootloader.file": "atmega/ATmegaBOOT_168_atmega1280.hex", - "bootloader.high_fuses": "0xDA", - "bootloader.lock_bits": "0x0F", - "bootloader.low_fuses": "0xFF", - "bootloader.tool": "avrdude", - "bootloader.unlock_bits": "0x3F", - "build.board": "AVR_MEGA", - "build.core": "arduino", - "build.f_cpu": "16000000L", - "build.mcu": "atmega1280", - "build.variant": "mega", - "menu.cpu.atmega1280": "ATmega1280", - "menu.cpu.atmega1280.bootloader.extended_fuses": "0xF5", - "menu.cpu.atmega1280.bootloader.file": "atmega/ATmegaBOOT_168_atmega1280.hex", - "menu.cpu.atmega1280.bootloader.high_fuses": "0xDA", - "menu.cpu.atmega1280.build.board": "AVR_MEGA", - "menu.cpu.atmega1280.build.mcu": "atmega1280", - "menu.cpu.atmega1280.upload.maximum_size": "126976", - "menu.cpu.atmega1280.upload.protocol": "arduino", - "menu.cpu.atmega1280.upload.speed": "57600", - "menu.cpu.atmega2560": "ATmega2560 (Mega 2560)", - "menu.cpu.atmega2560.bootloader.extended_fuses": "0xFD", - "menu.cpu.atmega2560.bootloader.file": "stk500v2/stk500boot_v2_mega2560.hex", - "menu.cpu.atmega2560.bootloader.high_fuses": "0xD8", - "menu.cpu.atmega2560.build.board": "AVR_MEGA2560", - "menu.cpu.atmega2560.build.mcu": "atmega2560", - "menu.cpu.atmega2560.upload.maximum_size": "253952", - "menu.cpu.atmega2560.upload.protocol": "wiring", - "menu.cpu.atmega2560.upload.speed": "115200", - "name": "Arduino/Genuino Mega or Mega 2560", - "pid.0": "0x0010", - "pid.1": "0x0042", - "pid.2": "0x0010", - "pid.3": "0x0042", - "pid.4": "0x0210", - "pid.5": "0x0242", - "upload.maximum_data_size": "8192", - "upload.maximum_size": "126976", - "upload.protocol": "arduino", - "upload.speed": "57600", - "upload.tool": "avrdude", - "vid.0": "0x2341", - "vid.1": "0x2341", - "vid.2": "0x2A03", - "vid.3": "0x2A03", - "vid.4": "0x2341", - "vid.5": "0x2341", - }) + require.EqualValues(t, map[string]string{"cpu": "Processor"}, boardMega.GetConfigOptions().AsMap()) + require.EqualValues(t, map[string]string{ + "atmega1280": "ATmega1280", + "atmega2560": "ATmega2560 (Mega 2560)", + }, boardMega.GetConfigOptionValues("cpu").AsMap()) + require.EqualValues(t, map[string]string{"cpu": "atmega2560"}, boardMega.defaultConfig.AsMap()) + expConf1280 := properties.NewMap() + expConf1280.Set("bootloader.extended_fuses", "0xF5") + expConf1280.Set("bootloader.file", "atmega/ATmegaBOOT_168_atmega1280.hex") + expConf1280.Set("bootloader.high_fuses", "0xDA") + expConf1280.Set("bootloader.lock_bits", "0x0F") + expConf1280.Set("bootloader.low_fuses", "0xFF") + expConf1280.Set("bootloader.tool", "avrdude") + expConf1280.Set("bootloader.unlock_bits", "0x3F") + expConf1280.Set("build.board", "AVR_MEGA") + expConf1280.Set("build.core", "arduino") + expConf1280.Set("build.f_cpu", "16000000L") + expConf1280.Set("build.mcu", "atmega1280") + expConf1280.Set("build.variant", "mega") + expConf1280.Set("menu.cpu.atmega1280", "ATmega1280") + expConf1280.Set("menu.cpu.atmega1280.bootloader.extended_fuses", "0xF5") + expConf1280.Set("menu.cpu.atmega1280.bootloader.file", "atmega/ATmegaBOOT_168_atmega1280.hex") + expConf1280.Set("menu.cpu.atmega1280.bootloader.high_fuses", "0xDA") + expConf1280.Set("menu.cpu.atmega1280.build.board", "AVR_MEGA") + expConf1280.Set("menu.cpu.atmega1280.build.mcu", "atmega1280") + expConf1280.Set("menu.cpu.atmega1280.upload.maximum_size", "126976") + expConf1280.Set("menu.cpu.atmega1280.upload.protocol", "arduino") + expConf1280.Set("menu.cpu.atmega1280.upload.speed", "57600") + expConf1280.Set("menu.cpu.atmega2560", "ATmega2560 (Mega 2560)") + expConf1280.Set("menu.cpu.atmega2560.bootloader.extended_fuses", "0xFD") + expConf1280.Set("menu.cpu.atmega2560.bootloader.file", "stk500v2/stk500boot_v2_mega2560.hex") + expConf1280.Set("menu.cpu.atmega2560.bootloader.high_fuses", "0xD8") + expConf1280.Set("menu.cpu.atmega2560.build.board", "AVR_MEGA2560") + expConf1280.Set("menu.cpu.atmega2560.build.mcu", "atmega2560") + expConf1280.Set("menu.cpu.atmega2560.upload.maximum_size", "253952") + expConf1280.Set("menu.cpu.atmega2560.upload.protocol", "wiring") + expConf1280.Set("menu.cpu.atmega2560.upload.speed", "115200") + expConf1280.Set("name", "Arduino/Genuino Mega or Mega 2560") + expConf1280.Set("pid.0", "0x0010") + expConf1280.Set("pid.1", "0x0042") + expConf1280.Set("pid.2", "0x0010") + expConf1280.Set("pid.3", "0x0042") + expConf1280.Set("pid.4", "0x0210") + expConf1280.Set("pid.5", "0x0242") + expConf1280.Set("upload.maximum_data_size", "8192") + expConf1280.Set("upload.maximum_size", "126976") + expConf1280.Set("upload.protocol", "arduino") + expConf1280.Set("upload.speed", "57600") + expConf1280.Set("upload.tool", "avrdude") + expConf1280.Set("vid.0", "0x2341") + expConf1280.Set("vid.1", "0x2341") + expConf1280.Set("vid.2", "0x2A03") + expConf1280.Set("vid.3", "0x2A03") + expConf1280.Set("vid.4", "0x2341") + expConf1280.Set("vid.5", "0x2341") conf1280, err := boardMega.GeneratePropertiesForConfiguration("cpu=atmega1280") require.NoError(t, err, "generating cpu=atmega1280 configuration") require.EqualValues(t, expConf1280.AsMap(), conf1280.AsMap(), "configuration for cpu=atmega1280") @@ -309,36 +326,35 @@ func TestBoardOptions(t *testing.T) { _, err = boardUno.GeneratePropertiesForConfiguration("cpu=atmega1280") require.Error(t, err, "generating cpu=atmega1280 configuration") - expWatterott := properties.NewFromHashmap(map[string]string{ - "bootloader.extended_fuses": "0xFE", - "bootloader.file": "micronucleus-t841.hex", - "bootloader.high_fuses": "0xDD", - "bootloader.lock_bits": "0xFF", - "bootloader.low_fuses": "0xE2", - "bootloader.tool": "avrdude", - "bootloader.unlock_bits": "0xFF", - "build.board": "AVR_ATTINY841", - "build.core": "tiny841", - "build.f_cpu": "8000000L", - "build.mcu": "attiny841", - "build.variant": "tiny14", - "menu.core.arduino": "Standard Arduino", - "menu.core.arduino.build.core": "arduino:arduino", - "menu.core.arduino.build.variant": "tiny14", - "menu.core.spencekonde": "ATtiny841 (by Spence Konde)", - "menu.core.spencekonde.build.core": "tiny841", - "menu.core.spencekonde.build.variant": "tiny14", - "menu.info.info": "Press Reset, when Uploading is shown.", - "name": "ATtiny841 (8 MHz)", - "pid.0": "0x0753", - "upload.disable_flushing": "false", - "upload.maximum_size": "6500", - "upload.protocol": "usb", - "upload.tool": "micronucleus", - "upload.use_1200bps_touch": "false", - "upload.wait_for_upload_port": "false", - "vid.0": "0x16D0", - }) + expWatterott := properties.NewMap() + expWatterott.Set("bootloader.extended_fuses", "0xFE") + expWatterott.Set("bootloader.file", "micronucleus-t841.hex") + expWatterott.Set("bootloader.high_fuses", "0xDD") + expWatterott.Set("bootloader.lock_bits", "0xFF") + expWatterott.Set("bootloader.low_fuses", "0xE2") + expWatterott.Set("bootloader.tool", "avrdude") + expWatterott.Set("bootloader.unlock_bits", "0xFF") + expWatterott.Set("build.board", "AVR_ATTINY841") + expWatterott.Set("build.core", "tiny841") + expWatterott.Set("build.f_cpu", "8000000L") + expWatterott.Set("build.mcu", "attiny841") + expWatterott.Set("build.variant", "tiny14") + expWatterott.Set("menu.core.arduino", "Standard Arduino") + expWatterott.Set("menu.core.arduino.build.core", "arduino:arduino") + expWatterott.Set("menu.core.arduino.build.variant", "tiny14") + expWatterott.Set("menu.core.spencekonde", "ATtiny841 (by Spence Konde)") + expWatterott.Set("menu.core.spencekonde.build.core", "tiny841") + expWatterott.Set("menu.core.spencekonde.build.variant", "tiny14") + expWatterott.Set("menu.info.info", "Press Reset, when Uploading is shown.") + expWatterott.Set("name", "ATtiny841 (8 MHz)") + expWatterott.Set("pid.0", "0x0753") + expWatterott.Set("upload.disable_flushing", "false") + expWatterott.Set("upload.maximum_size", "6500") + expWatterott.Set("upload.protocol", "usb") + expWatterott.Set("upload.tool", "micronucleus") + expWatterott.Set("upload.use_1200bps_touch", "false") + expWatterott.Set("upload.wait_for_upload_port", "false") + expWatterott.Set("vid.0", "0x16D0") confWatterott, err := boardWatterottTiny841.GeneratePropertiesForConfiguration("core=spencekonde,info=info") require.NoError(t, err, "generating core=spencekonde,info=info configuration") require.EqualValues(t, expWatterott.AsMap(), confWatterott.AsMap(), "generating core=spencekonde,info=info configuration") From baecc789347c132a38cd267a79a30bceea7224f0 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Wed, 23 Feb 2022 23:41:27 +0100 Subject: [PATCH 05/10] Renamed some variables to improve code readability --- arduino/cores/packagemanager/loader.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/arduino/cores/packagemanager/loader.go b/arduino/cores/packagemanager/loader.go index 298669186fb..462576255ab 100644 --- a/arduino/cores/packagemanager/loader.go +++ b/arduino/cores/packagemanager/loader.go @@ -458,27 +458,27 @@ func (pm *Builder) loadBoards(platform *cores.PlatformRelease) error { } boardsTxtPath := platform.InstallDir.Join("boards.txt") - boardsProperties, err := properties.LoadFromPath(boardsTxtPath) + allBoardsProperties, err := properties.LoadFromPath(boardsTxtPath) if err != nil { return err } boardsLocalTxtPath := platform.InstallDir.Join("boards.local.txt") - if localProperties, err := properties.SafeLoadFromPath(boardsLocalTxtPath); err == nil { - boardsProperties.Merge(localProperties) + if boardsLocalProperties, err := properties.SafeLoadFromPath(boardsLocalTxtPath); err == nil { + allBoardsProperties.Merge(boardsLocalProperties) } else { return err } - platform.Menus = boardsProperties.SubTree("menu") + platform.Menus = allBoardsProperties.SubTree("menu") // Build to boards structure following the boards.txt board ordering - for _, boardID := range boardsProperties.FirstLevelKeys() { + for _, boardID := range allBoardsProperties.FirstLevelKeys() { if boardID == "menu" { // This is not a board id so we remove it to correctly set all other boards properties continue } - boardProperties := boardsProperties.SubTree(boardID) + boardProperties := allBoardsProperties.SubTree(boardID) var board *cores.Board if !platform.PluggableDiscoveryAware { convertVidPidIdentificationPropertiesToPluggableDiscovery(boardProperties) From 14a424b84d5e769725a43ebdb24d33f212a5b207 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Thu, 24 Feb 2022 00:05:39 +0100 Subject: [PATCH 06/10] Added board config identification subroutines --- arduino/cores/board.go | 39 +++++++++++- arduino/cores/board_test.go | 78 ++++++++++++++++++++++++ arduino/cores/packagemanager/identify.go | 9 +++ 3 files changed, 125 insertions(+), 1 deletion(-) diff --git a/arduino/cores/board.go b/arduino/cores/board.go index 8b3e596ebb2..c5cd73daafd 100644 --- a/arduino/cores/board.go +++ b/arduino/cores/board.go @@ -165,7 +165,7 @@ func (b *Board) GetIdentificationProperties() []*properties.Map { } // IsBoardMatchingIDProperties returns true if the board match the given -// identification properties +// upload port identification properties func (b *Board) IsBoardMatchingIDProperties(query *properties.Map) bool { // check checks if the given set of properties p match the "query" check := func(p *properties.Map) bool { @@ -191,3 +191,40 @@ func (b *Board) IsBoardMatchingIDProperties(query *properties.Map) bool { func GetMonitorSettings(protocol string, boardProperties *properties.Map) *properties.Map { return boardProperties.SubTree("monitor_port." + protocol) } + +// IdentifyBoardConfiguration returns the configuration of the board that can be +// deduced from the given upload port identification properties +func (b *Board) IdentifyBoardConfiguration(query *properties.Map) *properties.Map { + // check checks if the given set of properties p match the "query" + check := func(p *properties.Map) bool { + for k, v := range p.AsMap() { + if !strings.EqualFold(query.Get(k), v) { + return false + } + } + return true + } + checkAll := func(allP []*properties.Map) bool { + for _, p := range allP { + if check(p) { + return true + } + } + return false + } + + res := properties.NewMap() + for _, option := range b.GetConfigOptions().Keys() { + values := b.GetConfigOptionValues(option).Keys() + + for _, value := range values { + config := option + "=" + value + configProps := b.configOptionProperties[config] + + if checkAll(configProps.ExtractSubIndexSets("upload_port")) { + res.Set(option, value) + } + } + } + return res +} diff --git a/arduino/cores/board_test.go b/arduino/cores/board_test.go index e42f57125d4..a0665e26c5f 100644 --- a/arduino/cores/board_test.go +++ b/arduino/cores/board_test.go @@ -554,3 +554,81 @@ func TestBoardMatching(t *testing.T) { "lemons": "XXX", }))) } + +func TestBoardConfigMatching(t *testing.T) { + brd01 := &Board{ + Properties: properties.NewFromHashmap(map[string]string{ + "upload_port.pid": "0x0010", + "upload_port.vid": "0x2341", + "menu.cpu.atmega1280": "ATmega1280", + "menu.cpu.atmega1280.upload_port.cpu": "atmega1280", + "menu.cpu.atmega1280.build_cpu": "atmega1280", + "menu.cpu.atmega2560": "ATmega2560", + "menu.cpu.atmega2560.upload_port.cpu": "atmega2560", + "menu.cpu.atmega2560.build_cpu": "atmega2560", + "menu.mem.1k": "1KB", + "menu.mem.1k.upload_port.mem": "1", + "menu.mem.1k.build_mem": "1024", + "menu.mem.2k": "2KB", + "menu.mem.2k.upload_port.1.mem": "2", + "menu.mem.2k.upload_port.2.ab": "ef", + "menu.mem.2k.upload_port.2.cd": "gh", + "menu.mem.2k.build_mem": "2048", + }), + PlatformRelease: &PlatformRelease{ + Platform: &Platform{ + Architecture: "avr", + Package: &Package{ + Name: "arduino", + }, + }, + Menus: properties.NewFromHashmap(map[string]string{ + "cpu": "Processor", + "mem": "Memory", + }), + }, + } + + type m map[string]string + type Test struct { + testName string + identificationProps map[string]string + configOutput map[string]string + } + + tests := []Test{ + {"Simple", + m{"pid": "0x0010", "vid": "0x2341"}, + m{}}, + {"WithConfig1", + m{"pid": "0x0010", "vid": "0x2341", "cpu": "atmega2560"}, + m{"cpu": "atmega2560"}}, + {"WithConfig2", + m{"pid": "0x0010", "vid": "0x2341", "cpu": "atmega1280"}, + m{"cpu": "atmega1280"}}, + {"WithDoubleConfig1", + m{"pid": "0x0010", "vid": "0x2341", "cpu": "atmega1280", "mem": "1"}, + m{"cpu": "atmega1280", "mem": "1k"}}, + {"WithDoubleConfig2", + m{"pid": "0x0010", "vid": "0x2341", "cpu": "atmega1280", "ab": "ef"}, + m{"cpu": "atmega1280"}}, + {"WithDoubleConfig3", + m{"pid": "0x0010", "vid": "0x2341", "cpu": "atmega1280", "ab": "ef", "cd": "gh"}, + m{"cpu": "atmega1280", "mem": "2k"}}, + {"WithIncompleteIdentificationProps", + m{"cpu": "atmega1280"}, + nil}, + } + for _, test := range tests { + t.Run(test.testName, func(t *testing.T) { + identificationProps := properties.NewFromHashmap(test.identificationProps) + if test.configOutput != nil { + require.True(t, brd01.IsBoardMatchingIDProperties(identificationProps)) + config := brd01.IdentifyBoardConfiguration(identificationProps) + require.EqualValues(t, test.configOutput, config.AsMap()) + } else { + require.False(t, brd01.IsBoardMatchingIDProperties(identificationProps)) + } + }) + } +} diff --git a/arduino/cores/packagemanager/identify.go b/arduino/cores/packagemanager/identify.go index b785bf02263..fb7d7d6f1de 100644 --- a/arduino/cores/packagemanager/identify.go +++ b/arduino/cores/packagemanager/identify.go @@ -35,3 +35,12 @@ func (pme *Explorer) IdentifyBoard(idProps *properties.Map) []*cores.Board { return foundBoards } + +// IdentifyBoardConfiguration returns a set of identification properties for configuration options +// of a board. +func (pm *PackageManager) IdentifyBoardConfiguration(idProps *properties.Map, board *cores.Board) *properties.Map { + if idProps.Size() == 0 { + return properties.NewMap() + } + return board.IdentifyBoardConfiguration(idProps) +} From ccceb6c5ae38ed1585446dbe68425c6509cdcb78 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Thu, 24 Feb 2022 12:22:16 +0100 Subject: [PATCH 07/10] Added board config detection in 'commands.identify' function --- commands/board/list.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/commands/board/list.go b/commands/board/list.go index 1a81a187f85..13f1dbd05ad 100644 --- a/commands/board/list.go +++ b/commands/board/list.go @@ -27,6 +27,7 @@ import ( "time" "github.com/arduino/arduino-cli/arduino" + "github.com/arduino/arduino-cli/arduino/cores" "github.com/arduino/arduino-cli/arduino/cores/packagemanager" "github.com/arduino/arduino-cli/arduino/discovery" "github.com/arduino/arduino-cli/arduino/httpclient" @@ -124,13 +125,19 @@ func identify(pme *packagemanager.Explorer, port *discovery.Port) ([]*rpc.BoardL // first query installed cores through the Package Manager logrus.Debug("Querying installed cores for board identification...") for _, board := range pme.IdentifyBoard(port.Properties) { + fqbn, err := cores.ParseFQBN(board.FQBN()) + if err != nil { + return nil, &arduino.InvalidFQBNError{Cause: err} + } + fqbn.Configs = board.IdentifyBoardConfiguration(port.Properties) + // We need the Platform maintaner for sorting so we set it here platform := &rpc.Platform{ Maintainer: board.PlatformRelease.Platform.Package.Maintainer, } boards = append(boards, &rpc.BoardListItem{ Name: board.Name(), - Fqbn: board.FQBN(), + Fqbn: fqbn.String(), Platform: platform, }) } From 1bcdd33255293129cfa80f1b5fb6d016cfdd3c3a Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Fri, 14 Oct 2022 15:07:55 +0200 Subject: [PATCH 08/10] Updated docs --- docs/pluggable-discovery-specification.md | 64 +++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/docs/pluggable-discovery-specification.md b/docs/pluggable-discovery-specification.md index e713cb98cdb..e68a4a421b2 100644 --- a/docs/pluggable-discovery-specification.md +++ b/docs/pluggable-discovery-specification.md @@ -377,3 +377,67 @@ myboard.upload_port.1.apples=40 will match on both `pears=20, apples=30` and `pears=30, apples=40` but not `pears=20, apples=40`, in that sense each "set" of identification properties is independent from each other and cannot be mixed for port matching. + +#### Identification of board options + +The board identification can also identify [custom board options](platform-specification.md#custom-board-options) if the +corresponding `upload_port` properties are defined: + +``` +BOARDNAME.menu.MENUNAME.MENUOPTION.upload_port.IDENTIFIER=Value +BOARDNAME.menu.MENUNAME.MENUOPTION.upload_port.#.IDENTIFIER=Value +``` + +a discovery tools capable of detecting which menu options where used could report properties to match those lines. Let's +see an example to clarify it, in the following `boards.txt`: + +``` +myboard.upload_port.pid=0x0010 +myboard.upload_port.vid=0x2341 +myboard.menu.cpu.atmega1280=ATmega1280 +myboard.menu.cpu.atmega1280.upload_port.c=atmega1280 <--- identification property for cpu=atmega1280 +myboard.menu.cpu.atmega1280.build_cpu=atmega1280 +myboard.menu.cpu.atmega2560=ATmega2560 +myboard.menu.cpu.atmega2560.upload_port.c=atmega2560 <--- identification property for cpu=atmega2560 +myboard.menu.cpu.atmega2560.build_cpu=atmega2560 +myboard.menu.mem.1k=1KB +myboard.menu.mem.1k.upload_port.mem=1 <--- identification property for mem=1k +myboard.menu.mem.1k.build_mem=1024 +myboard.menu.mem.2k=2KB +myboard.menu.mem.2k.upload_port.1.mem=2 <------ identification property for mem=2k (case 1) +myboard.menu.mem.2k.upload_port.2.ab=ef <---\ +myboard.menu.mem.2k.upload_port.2.cd=gh <---+-- identification property for mem=2k (case 2) +myboard.menu.mem.2k.build_mem=2048 +``` + +we have a board called `myboard` with two custom menu options `cpu` and `mem`. The discovery may provide extra +identification properties to determine the custom menu options of the connected board, for example the following +properties: + +``` +vid=0x0010 +pid=0x2341 +c=atmega2560 +``` + +will match the FQBN `mypackage:avr:myboard:cpu=atmega2560` becuase of the property `c=atmega2560`. The identification +properties: + +``` +vid=0x0010 +pid=0x2341 +c=atmega2560 +mem=2 +``` + +will match the FQBN `mypackage:avr:myboard:cpu=atmega2560,mem=2k`. The identification properties: + +``` +vid=0x0010 +pid=0x2341 +c=atmega2560 +ab=ef +cd=gh +``` + +will match the FQBN `mypackage:avr:myboard:cpu=atmega2560,mem=2k` too (they will match the second set for `mem=2k`). From d0ebfd755b645a536c393334ac16c32145e81bb6 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Mon, 17 Oct 2022 11:00:12 +0200 Subject: [PATCH 09/10] Apply suggestions from code review Co-authored-by: per1234 --- docs/pluggable-discovery-specification.md | 40 +++++++++++++++-------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/docs/pluggable-discovery-specification.md b/docs/pluggable-discovery-specification.md index e68a4a421b2..16d196c5bf0 100644 --- a/docs/pluggable-discovery-specification.md +++ b/docs/pluggable-discovery-specification.md @@ -380,16 +380,26 @@ will match on both `pears=20, apples=30` and `pears=30, apples=40` but not `pear #### Identification of board options -The board identification can also identify [custom board options](platform-specification.md#custom-board-options) if the -corresponding `upload_port` properties are defined: +[Custom board options](platform-specification.md#custom-board-options) can also be identified. + +Identification property values are associated with a custom board option by the board definition in +[`boards.txt`](platform-specification.md#boardstxt). Two formats are available. + +If only a single set of identification properties are associated with the option: + +``` +BOARD_ID.menu.MENU_ID.OPTION_ID.upload_port.PORT_PROPERTY_KEY=PORT_PROPERTY_VALUE +``` + +If one or more sets of identification properties are associated with the option, an index number is used for each set: ``` -BOARDNAME.menu.MENUNAME.MENUOPTION.upload_port.IDENTIFIER=Value -BOARDNAME.menu.MENUNAME.MENUOPTION.upload_port.#.IDENTIFIER=Value +BOARD_ID.menu.MENU_ID.OPTION_ID.upload_port.SET_INDEX.PORT_PROPERTY_KEY=PORT_PROPERTY_VALUE ``` -a discovery tools capable of detecting which menu options where used could report properties to match those lines. Let's -see an example to clarify it, in the following `boards.txt`: +If multiple identification properties are associated within a set, all must match for the option to be identified. + +Let's see an example to clarify it, in the following `boards.txt`: ``` myboard.upload_port.pid=0x0010 @@ -410,9 +420,9 @@ myboard.menu.mem.2k.upload_port.2.cd=gh <---+-- identifica myboard.menu.mem.2k.build_mem=2048 ``` -we have a board called `myboard` with two custom menu options `cpu` and `mem`. The discovery may provide extra -identification properties to determine the custom menu options of the connected board, for example the following -properties: +we have a board called `myboard` with two custom menu options `cpu` and `mem`. + +A port with the following identification properties: ``` vid=0x0010 @@ -420,8 +430,9 @@ pid=0x2341 c=atmega2560 ``` -will match the FQBN `mypackage:avr:myboard:cpu=atmega2560` becuase of the property `c=atmega2560`. The identification -properties: +will be identified as FQBN `mypackage:avr:myboard:cpu=atmega2560` because of the property `c=atmega2560`. + +A port with the following identification properties: ``` vid=0x0010 @@ -430,7 +441,9 @@ c=atmega2560 mem=2 ``` -will match the FQBN `mypackage:avr:myboard:cpu=atmega2560,mem=2k`. The identification properties: +will be identified as FQBN `mypackage:avr:myboard:cpu=atmega2560,mem=2k`. + +A port with the following identification properties: ``` vid=0x0010 @@ -440,4 +453,5 @@ ab=ef cd=gh ``` -will match the FQBN `mypackage:avr:myboard:cpu=atmega2560,mem=2k` too (they will match the second set for `mem=2k`). +will be identified as FQBN `mypackage:avr:myboard:cpu=atmega2560,mem=2k` too (they will match the second identification +properties set for `mem=2k`). From 024597e331e612748ae2ee39058cece2d04039fd Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Tue, 18 Oct 2022 17:35:36 +0200 Subject: [PATCH 10/10] Fixed comment --- arduino/cores/packagemanager/identify.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arduino/cores/packagemanager/identify.go b/arduino/cores/packagemanager/identify.go index fb7d7d6f1de..22d8382cd67 100644 --- a/arduino/cores/packagemanager/identify.go +++ b/arduino/cores/packagemanager/identify.go @@ -36,8 +36,8 @@ func (pme *Explorer) IdentifyBoard(idProps *properties.Map) []*cores.Board { return foundBoards } -// IdentifyBoardConfiguration returns a set of identification properties for configuration options -// of a board. +// IdentifyBoardConfiguration returns the configuration of the board that can be +// deduced from the given upload port identification properties func (pm *PackageManager) IdentifyBoardConfiguration(idProps *properties.Map, board *cores.Board) *properties.Map { if idProps.Size() == 0 { return properties.NewMap() pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy