You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@mynewt.apache.org by "paul@wrada.com" <pa...@wrada.com> on 2016/03/28 20:46:43 UTC

sysid etc.

This is a discussion on how we identify devices (peripherals or internal MCU devices) through the HAL (Hardware abstraction layer).

A picture is posted to jira here.

https://issues.apache.org/jira/secure/attachment/12795673/hal_drawing.pdf

Here is the gist of the design.

A BSP defines a set of SYSID (System IDS).  This is an enumeration of all the devices that the system has.  Remembers, the system includes the built in MCU peripherals and also the external peripherals.  The BSP puts these system ids into /hw/bsp/include/bsp/bsp_sysid.h

An Example for Arduino might be:

Enum SystemDeviceDescriptor {
     ARDUINO_ANALOG0,   ARDUINO_ANALOG1,     ARDUINO_ANALOG2,     ARDUINO_ANALOG3,     ARDUINO_ANALOG4,     ARDUINO_ANALOG5,
     ARDUINO_DIGITAL0,     ARDUINO_DIGITAL1,     ARDUINO_DIGITAL2,     ARDUINO_DIGITAL3,     ARDUINO_DIGITAL4,     ARDUINO_DIGITAL5,
     ARDUINO_DIGITAL6,     ARDUINO_DIGITAL7,     ARDUINO_DIGITAL8,     ARDUINO_DIGITAL9,     ARDUINO_DIGITAL10,     ARDUINO_DIGITAL11,
     ARDUINO_DIGITAL12,     ARDUINO_DIGITAL13,
     ARDUINO_UART,
     ARDUINO_SPI,
     ARDUINO_PWM8,     ARDUINO_PWM9,     ARDUINO_PWM10,     ARDUINO_PWM11,     ARDUINO_PWM12,     ARDUINO_PWM13,
}

An example for a fictitious weather monitor which has two analog temp sensors, flash storage, a SPI bus with two peripherals, a clock and a display each activate with a different digital chip select.  NOTE: Its likely this would have more digital lines for power saving, battery control etc.

Enum SystemDeviceDescriptor {
WEATHERMON_ANALOG_TEMP_INDOOR,
WEATHERMON_ANALOG_TEMP_OUTDOOR,
WEATHERMON_FLASH,
WEATHERMON_SPI,
WEATHERMON_DIG_CLOCK_CS,
WEATHERMON_DIG_DISPLAY_CS,
...
};

A few NOTES.   This is not necessarily a mapping of PINS.  For example, the UART uses D0 and D1.  PWM8 Uses D8 etc. SO there will be conflicts if apps try to use certain combinations.  We haven't designed a pinmux API, but I think that will live underneath this.   In general though, the BSP designer will be making the tradeoffs about which devices are used in the system.  Since this largely depends on how the pins of the MCU are assigned, there won't be too many overlaps with this list, but in general, there will be some.

It was a design decision to include all the system devices within a single SYSID space (just one enum).  An alternative could have had a separate enum for each HAL.  This decision was made for two reasons. One, to keep all the BSP devices easily accessible in the same place. This means that APP designers don't need to learn or know that much to use the devices.  The tradeoff here is that is may not be as obvious which device is which HAL.   The convention to make device identification easier is to use descriptive names like above.  Two, to make it clear that in a BSP (as opposed to MCU), the BSP designer is making tradeoffs to support only some functionality depending on the schematic.  Generally, the MCUs have tons of pinmux flexibility with more internal devices than there are accessible pins.

The SYSID is used in only one place in the HAL.  Each HAL interface has a hal_xxx_init function which takes the SYSID of the device and returns a device object to the application.  The benefit of this is that the application does not need to statically pick a specific MCU object. This allows the application or library flexibility to work across multiple different platforms (which is the main goal of a HAL).

The rest of the HAL interface is invisible to the application or library.  Below is a description of how its recommended to work for the MCU or peripheral designer but is a convention only.

The MCU or peripheral implementation implements the hal_xxx_int.h driver API plus one extra function.   By convention the prototype for this function is stored in mcu/hal_xxx.h or periph/hal_xxx.h

The header file includes a single function to create a device of this type and the configuration structure to go with it.  Typically, this function will take some configuration options which are typically a constant structure (so it doesn't use any RAM space).  For example, for an ADC device it might look like this.  This configuration structure is where pin mappings or choices would go (if there are any).


/* this structure is passed to the BSP for configuration options */
enum samd_adc_reference_voltage {
DEVICE_ID_ADC_REFERENCE_INT1V,
DEVICE_ID_ADC_REFERENCE_INTVCC0,
DEVICE_ID_ADC_REFERENCE_INTVCC1,
DEVICE_ID_ADC_REFERENCE_AREFA ,
DEVICE_ID_ADC_REFERENCE_AREFB,
};

/* this device supports 6 channels */
enum samd_adc_analog_channel {
    ANALOG_CHANNEL_0 = 0,    ANALOG_CHANNEL_1,    ANALOG_CHANNEL_2,    ANALOG_CHANNEL_3,    ANALOG_CHANNEL_4,    ANALOG_CHANNEL_5,    ANALOG_CHANNEL_5,
    ANALOG_CHANNEL_6, ... , ANALOG_CHANNEL_18, ANALOG_CHANNEL_19, ANALOG_CHANNEL_20, ANALOG_CHANNEL_TEMP, ANALOG_CHANNEL_DAC,
};

struct samd21_adc_config {
    enum samd_adc_analog_channel    analog_channels;
    enum samd_adc_reference_voltage volt;
    int                             voltage_mvolts;
};

/* This creates a new ADC object for this ADC source */
struct hal_adc_device_s *
samd21_adc_create(const struct samd21_adc_config *pconfig);