Spi device tree source code

From Wiki at Neela Nurseries
Jump to: navigation, search

Device_tree_from_scratch   ::   Spi_device_tree_source_code   ::   Pico-sdk_studies


2022-08-11 Thursday
Keywords: YAML conditional logic :: YAML schemas


^ Overview

Notes on SPI device tree source, with goal to add SPI device to modified RPi Pico DTS files, which build firmware to run on Sparkfun DEV-18288 board. As of 2022-08-19 Friday we have device tree source for SPI and DMA peripherals of the RP2040 compiling correctly in a small project, github hosted at [1]. The compilation involves `dtc` or similar reading the device node's "compatible" property value and finding a bindings file in YAML format. The device tree compiler then checks that the given node contains all required properties which are called out in the given compatible's bindings file, and correct data types as well. ( The build process was able to report a mal-formed device address, "dma0@5000000" should be "dma0@50000000". ) So this tells us that while Zephyr RTOS Project does not use device tree source to generate device tree blobs, there is yet great debugging and correctness assurance benefit to using device tree to describe a system's or product's hardware.

So as of this 8-19 Friday it now appears that crafting the wrapping code between Zephyr device model API pointers and third party driver code will be the harder part of the effort to bring up DMA and full SPI functionality on MCUs not yet supported by Zephyr RTOS.

RPi Pico SDK offers a starting point to understand needed wrapper code between Zephyr and Pico DMA driver, in their hello_dma sample app.

Nordic Semi provides a list of some sixty hardware makers and bindings files to their hardware at their Nordic device tree bindings index page. nordic-semi--device-bindings-index


Though Ted wouldn't normally include links in an overview section, another important starting point to understand device tree to describe SPI peripherals is at this github link to a SPI dts bindings file:


^ TO DO

Following are questions to answer, topic areas to research . . .


^ SPI dts examples from Zephyr boards

In Zephyr RTOS' supported board dts files we find SPI peripherals defined for several boards. Here are excerpts

Excerpt 1 - zephyr/boards/arm/sparkfun_thing_plus_nrf9160/sparkfun_thing_plus_nrf9160_common.dts


142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162


&spi3 {
        compatible = "nordic,nrf-spim";
        status = "okay";
        cs-gpios = <&gpio0 7 GPIO_ACTIVE_LOW>;
        pinctrl-0 = <&spi3_default>;
        pinctrl-1 = <&spi3_sleep>;
        pinctrl-names = "default", "sleep";
        w25q32jv: w25q32jv@0 {
                compatible = "jedec,spi-nor";
                label = "W25Q32JV";
                reg = <0>;
                spi-max-frequency = <40000000>;
                wp-gpios = <&gpio0 8 GPIO_ACTIVE_LOW>;
                hold-gpios = <&gpio0 10 GPIO_ACTIVE_LOW>;
                size = <0x2000000>;
                has-dpd;
                t-enter-dpd = <3000>;
                t-exit-dpd = <30000>;
                jedec-id = [ ef 40 16 ];
        };
};

a
 81         spi3_default: spi3_default {
 82                 group1 {
 83                         psels = <NRF_PSEL(SPIM_SCK, 0, 11)>,
 84                                 <NRF_PSEL(SPIM_MOSI, 0, 9)>,
 85                                 <NRF_PSEL(SPIM_MISO, 0, 28)>;
 86                 };
 87         };
 88 
 89         spi3_sleep: spi3_sleep {
 90                 group1 {
 91                         psels = <NRF_PSEL(SPIM_SCK, 0, 11)>,
 92                                 <NRF_PSEL(SPIM_MOSI, 0, 9)>,
 93                                 <NRF_PSEL(SPIM_MISO, 0, 28)>;
 94                         low-power-enable;
 95                 };
 96         };

^ edit point dts excerpt 2

Excerpt 2 - zephyr/boards/arm/96b_carbon_nrf51/96b_carbon_nrf51.dts and 96b_carbon_nrf51-pinctrl.dtsi

47
48
49
50
51
52
53
54
55
56
&spi1 {
        compatible = "nordic,nrf-spis";
        status = "okay";
        def-char = <0x00>;

        pinctrl-0 = <&spi1_default>;
        pinctrl-names = "default";
        bt-hci@0 {
                compatible = "zephyr,bt-hci-spi-slave";
                reg = <0>;
                irq-gpios = <&gpio0 28 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>;
        };
};
37
38
39
40
41
42
43
44
        spi1_default: spi1_default {
                group1 {
                        psels = <NRF_PSEL(SPIS_SCK, 0, 7)>,
                                <NRF_PSEL(SPIS_MOSI, 0, 0)>,
                                <NRF_PSEL(SPIS_MISO, 0, 30)>,
                                <NRF_PSEL(SPIS_CSN, 0, 25)>;
                };
        };

^ edit point dts excerpt 3

Excerpt 3 - zephyr/boards/arm/stm32l562e_dk/stm32l562e_dk_common.dts and stm32l562e_dk_common.dtsi


Looks like pin control names value 'default'
may be defined in Kconfig.default for this board . . .
114
115
116
117
118
119
120
121
122
123
124
125
126
127
&spi1 {
        pinctrl-0 = <&spi1_sck_pg2 &spi1_miso_pg3 &spi1_mosi_pg4>;
        pinctrl-names = "default";
        cs-gpios = <&gpiog 5 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>;
        status = "okay";

        spbtle-rf@0 {
                compatible = "zephyr,bt-hci-spi";
                reg = <0>;
                irq-gpios = <&gpiog 6 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>;
                reset-gpios = <&gpiog 8 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
                spi-max-frequency = <2000000>;
                label = "SPBTLE-RF";
        };
};

^ edit point dts excerpt 4

Excerpt 4 -





^ edit point dts excerpt 5

Excerpt 5 -







^ RPi Pico dts in Zephyr 3.1.0

From the zephyr/boards/arm/rpi_pico/doc/index.rst file there's no mention of SPI support, though SPI peripherals exist in the RP2040. Zephyr has a RP2040 dts file that covers some on chip peripherals. RaspberryPi's restructured text document does not mention SPI support either:


 37      Raspberry Pi Pico (Image courtesy of Raspberry Pi)
 38 
 39 Supported Features
 40 ==================
 41 
 42 The rpi_pico board configuration supports the following
 43 hardware features:
 44 
 45 .. list-table::
 46    :header-rows: 1
 47 
 48    * - Peripheral
 49      - Kconfig option
 50      - Devicetree compatible
 51    * - NVIC
 52      - N/A
 53      - :dtcompatible:`arm,v6m-nvic`
 54    * - UART
 55      - :kconfig:option:`CONFIG_SERIAL`
 56      - :dtcompatible:`rpi,pico-uart`
 57    * - GPIO
 58      - :kconfig:option:`CONFIG_GPIO`
 59      - :dtcompatible:`rpi,pico-gpio`
 60    * - I2C
 61      - :kconfig:option:`CONFIG_I2C`
 62      - :dtcompatible:`snps,designware-i2c`
 63    * - USB Device
 64      - :kconfig:option:`CONFIG_USB_DEVICE_STACK`
 65      - :dtcompatible:`raspberrypi,pico-usbd`
 66    * - HWINFO
 67      - :kconfig:option:`CONFIG_HWINFO`
 68      - N/A
 69 
 70 Programming and Debugging
 71 *************************
 72 
 73 Flashing

There is a clue here on line 62 "- :dtcompatible:`snps,designware-i2c`". This is for I2C, but a search via startpage.com for "snps,designware-spi" gives a first or near first result of:

This still leaves the open question, where are RPi Pico's I2C and SPI driver implementations in Zephyr RTOS release 3.1.0?


^ YAML device bindings files

2022-08-16 NEED to combine some of this section with . . . need to create a local page for yaml file schemas and yaml syntax.

To support a typical development kit or custom board with multiple peripherals we need a device bindings file comparable to this ... bindings file:

  1. ~/projects-sandbox/workspace-for-rpi/zephyr/boards/arm/nrf9160dk_nrf9160/nrf9160dk_nrf9160.yaml
identifier: nrf9160dk_nrf9160
name: nRF9160-DK-NRF9160
type: mcu 
arch: arm 
toolchain:
  - gnuarmemb
  - xtools
  - zephyr
ram: 88
flash: 256 
supported:
  - arduino_gpio
  - arduino_i2c
  - gpio
  - i2c
  - pwm
  - spi
  - watchdog
  - counter

Or possibly this bindings file by Jared Wolff of Circuit Dojo:

A more involved and documented dts bindings file is available from a git repo of STMicro. The following SPI controller bindings file contains an example of what appears to be YAML conditional logic at line 170:


^ STMicro device tree SPI documentation

The following STMicro article goes into good detail on their SPI controllers in STM32Fxx family parts, and even gives device tree excerpts. These apparently are used in Linux based projects where Linux kernel and OS run on a 32-bit ST MCU.

A device tree excerpt from the first link just above:

spi1: spi@44004000 {
	#address-cells = <1>;
	#size-cells = <0>;
	compatible = "st,stm32h7-spi";
	reg = <0x44004000 0x400>;
	interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
	clocks = <&rcc SPI1_K>;
	resets = <&rcc SPI1_R>;
	dmas = <&dmamux1 37 0x400 0x05>,
	       <&dmamux1 38 0x400 0x05>;
	dma-names = "rx", "tx";
	power-domains = <&pd_core>;
	status = "disabled";
};

Warning white.png Warning
This device tree part is related to STM32 microprocessors. It must be kept as is, without being modified by the end-user. 

Some further excerpts from STMicro SPI and dts documentation, which explain some required and some optional device tree node attribute value pairs. This may be the most useful documentation yet to describe how to craft dts for a newer or otherwise "not dts supported" processor:

3 DT configuration↑

This hardware description is a combination of the STM32 microprocessor device tree files (.dtsi extension) and board device tree files (.dts extension). See the Device tree for an explanation of the device tree file split.

STM32CubeMX can be used to generate the board device tree. Refer to How to configure the DT using STM32CubeMX for more details.
3.1 DT configuration (STM32 level)↑

At device level, each SPI controller is declared as follows:

spi1: spi@44004000 {
	#address-cells = <1>;
	#size-cells = <0>;
	compatible = "st,stm32h7-spi";
	reg = <0x44004000 0x400>;
	interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
	clocks = <&rcc SPI1_K>;
	resets = <&rcc SPI1_R>;
	dmas = <&dmamux1 37 0x400 0x05>,
	       <&dmamux1 38 0x400 0x05>;
	dma-names = "rx", "tx";
	power-domains = <&pd_core>;
	status = "disabled";
};

Warning white.png Warning
This device tree part is related to STM32 microprocessors. It must be kept as is, without being modified by the end-user.

    for STM32MP13x lines Warning.png lines, refer to DTS file stm32mp131.dtsi[5]
    for STM32MP15x lines More info.png lines, refer to DTS file stm32mp151.dtsi[6]

3.2 DT configuration (board level)↑

&spi1 {
	pinctrl-names = "default", "sleep";
	pinctrl-0 = <&spi1_pins_a>;
	pinctrl-1 = <&spi1_sleep_pins_a>;
	status = "okay";

        foo@0 {
                compatible = "spi-foo";
                reg = <0>; /* CS #0 */
                spi-max-frequency = <10000000>;
        };
};

There are two levels of configuration:

    Configuration of the SPI bus properties:
        pinctrl-0&1 configuration depends on hardware board configuration and on how the SPI devices are connected to MOSI, MISO and Clk pins.
        More details about pin configuration are available here: Pinctrl device tree configuration
        cs-gpios represents the list of GPIOs used as chip selects. This property is optional. More details about GPIO configuration are available here: GPIO device tree configuration
        dmas: by default, DMAs are specified for all SPI instances. This is up to the user to remove them if they are not needed. /delete-property/ is used to remove DMA usage for SPI. Both /delete-property/dma-names and /delete-property/dma have to be inserted to get rid of DMAs.

    Configuration of the properties of the SPI device connected on the bus:
        compatible represents the name of the SPI device driver.
        reg represents the index of the gpio chip select associated to this SPI device.
        spi-max-frequency represents the maximum SPI clocking speed for the device (in Hz).

For more information about SPI bus and SPI device bindings, please refer to spi-controller.yaml[3]
3.3 DT configuration example↑

Example: of an external TPM device:

&spi1 {
	pinctrl-names = "default", "sleep";
	pinctrl-0 = <&spi1_pins_a>;
	pinctrl-1 = <&spi1_sleep_pins_a>;
	cs-gpios = <&gpioz 3 0>;
	status = "okay";

	st33zp24@0 {
		compatible = "st,st33htpm-spi";
		reg = <0>; /* CS #0 */
		spi-max-frequency = <10000000>;
	};
};

The above example registers a TPM device on spi1 bus, selected by chip select 0 also known as GPIO-Z3. This instance is compatible with the driver registered with the same compatible property (st,st33htpm-spi).


^ RaspberryPi resources for developers

A good introduction to device tree:

Github pull request comments requesting board support for RPi Pico:

A forum post by someone attempting to add a SPI device to a RaspberryPi device tree file, though not RP2040 based board:

Comment in pull request by Yonatan Schachter, RPi Pico Zephyr board support:


^ DMA peripherals in dts

Looking into the dependent DMA peripheral details in Zephyr supported board dts files.

DMA dts excerpt 1 - zephyr/dts/arm/nxp/nxp_lpc55S6x_common.dtsi

169         dma0: dma-controller@82000 {
170                 compatible = "nxp,lpc-dma";
171                 reg = <0x82000 0x1000>;
172                 interrupts = <1 0>;
173                 label = "DMA_0";
174                 status = "disabled";
175                 #dma-cells = <1>;
176         };
177 
178         dma1: dma-controller@a7000 {
179                 compatible = "nxp,lpc-dma";
180                 reg = <0xa7000 0x1000>;
181                 interrupts = <58 0>;
182                 label = "DMA_1";
183                 status = "disabled";
184                 #dma-cells = <1>;
185         };
186 
187         mailbox0:mailbox@8b000 {
188                 compatible = "nxp,lpc-mailbox";
189                 reg = <0x8b000 0xEC>;
190                 interrupts = <31 0>;
191                 label = "MAILBOX_0";
192                 status = "disabled";
193         };


^ Reference

Rocketboards wiki article on how to create a device tree file. Keywords and key phrase: Rocket Boards.

  • a85bb3676d61d1ae202088e0d3fec556056b2c9e . . . this commit hash from `git log`, and then a call to `git config -l` clues us in to repository here being 'hal_nordic'.

An RPi Pico SDK documentation page:

RPi Pico SDK examples code:

An NXP device tree reference document, not specifically SPI but detailed:

SPI frame format defines in Zephyr 3.1.0:

    ./include/zephyr/dt-bindings/spi/spi.h:39:#define SPI_FRAME_FORMAT_MOTOROLA (0U << 15)
    ./include/zephyr/dt-bindings/spi/spi.h:40:#define SPI_FRAME_FORMAT_TI (1U << 15)


- - - top of page - - -