Skip to content

Proposal: Amend 'standard practice' config defaults model #3152

@kenbell

Description

@kenbell

The current standard practice for default configuration in TinyGo (and drivers) is:

  1. Expose a Config struct
  2. Expose a Configure(Config) method
  3. In Configure see if individual fields are uninitialized and if so, set defaults

This is causing a few problems:

  • The rules for what uninitialized means aren't clear. For integer-derived fields is 0 default, or did the caller explicitly want the 0 value? Should the driver/peripheral logic always make sure 0 is used only for uninitialized even when the underlying hardware uses 0 specifically?
  • In the machine package it causes backwards dependencies where board-agnostic code (e.g. for a family of chips) depends on board-specific code (default I2C pins)

Proposal

  1. For all drivers and peripherals where useful defaults are needed, expose a DefaultConfig variable that has those defaults present. This should be a non pointer variable
  2. Document the correct way to get defaults is xxx.Configure(yyy.DefaultConfig)
  3. After some period (may be a release or two of TinyGo), strip all the logic trying to handle uninitialized config fields

How would this look?

To take the I2C pin defaults, currently calling code typically looks like this:

machine.I2C0.Configure(machine.I2CConfig{})

That would now look like this:

machine.I2C0.Configure(machine.DefaultI2C0Config)

For code that wants to just set 'some' of the peripheral config fields, it currently looks like this:

machine.I2C0.Configure(machine.I2CConfig{Frequency: 100000})

That would now look like this:

cfg := machine.DefaultI2C0Config
cfg.Frequency = 100000
machine.I2C0.Configure(cfg)

The implementation would be something like this:

// in board_feather_rp2040.go

const (
	I2C0_SDA_PIN = GPIO24
	I2C0_SCL_PIN = GPIO25

	I2C1_SDA_PIN = GPIO2
	I2C1_SCL_PIN = GPIO3
)

var (
	DefaultI2C0Config = I2CConfig {Frequency: 100_000, SDA: I2C0_SDA_PIN, SCL: I2C0_SCL_PIN}
	DefaultI2C1Config = I2CConfig {Frequency: 100_000, SDA: I2C1_SDA_PIN, SCL: I2C1_SCL_PIN}
)

// in machine_rp2040_i2c.go

func (i2c *I2C) Configure(config I2CConfig) error {

	// Config default logic stripped from here

	config.SDA.Configure(PinConfig{PinI2C})
	config.SCL.Configure(PinConfig{PinI2C})
	return i2c.init(config)
}

A similar approach could be taken for drivers in https://github.com/tinygo-org/drivers

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions