Difference between revisions of "Spi device tree source code"
m (→^ Reference: - redirect external link to local page of references.) |
m (→^ Overview: - redirect external link to local list of device bindings references.) |
||
(8 intermediate revisions by the same user not shown) | |||
Line 12: | Line 12: | ||
== [[#top|^]] Overview == | == [[#top|^]] 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. | + | 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 [https://github.com/tedhavelka/rpi-pico-zephyr-exploration/tree/spi-dts-work]. 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 [https://docs.zephyrproject.org/3.1.0/kernel/drivers/index.html 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 [https://github.com/raspberrypi/pico-examples/blob/master/dma/hello_dma/hello_dma.c hello_dma sample app]. | ||
+ | |||
+ | Nordic Semi provides a list of some sixty hardware makers and bindings files to their hardware at their [[External-refs--device-tree-bindings#nordic-semi--device-bindings-index|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: | 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: | ||
Line 291: | Line 297: | ||
<!-- comentario --> | <!-- comentario --> | ||
− | == [[#top|^]] | + | == [[#top|^]] RPi Pico dts in Zephyr 3.1.0 == |
− | From the zephyr/boards/arm/rpi_pico/doc/index.rst file: | + | 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 [https://github.com/zephyrproject-rtos/zephyr/blob/main/boards/arm/rpi_pico/rpi_pico.dts RP2040 dts file] that covers some on chip peripherals. RaspberryPi's restructured text document does not mention SPI support either: |
<pre> | <pre> | ||
− | + | ||
37 Raspberry Pi Pico (Image courtesy of Raspberry Pi) | 37 Raspberry Pi Pico (Image courtesy of Raspberry Pi) | ||
38 | 38 | ||
Line 568: | Line 574: | ||
An NXP device tree reference document, not specifically SPI but detailed: | An NXP device tree reference document, not specifically SPI but detailed: | ||
* [[Device_tree_documentation#AN5125.pdf|AN5125.pdf]] <!-- https://www.nxp.com/docs/en/application-note/AN5125.pdf --> | * [[Device_tree_documentation#AN5125.pdf|AN5125.pdf]] <!-- https://www.nxp.com/docs/en/application-note/AN5125.pdf --> | ||
+ | |||
+ | SPI frame format defines in Zephyr 3.1.0: | ||
+ | <ul> | ||
+ | <span style="font-family: monospace; size=4em;"> | ||
+ | ./include/zephyr/dt-bindings/spi/spi.h:39:#define SPI_FRAME_FORMAT_MOTOROLA (0U << 15)<br /> | ||
+ | ./include/zephyr/dt-bindings/spi/spi.h:40:#define SPI_FRAME_FORMAT_TI (1U << 15)<br /> | ||
+ | </span> | ||
+ | </ul> | ||
Latest revision as of 18:08, 19 August 2022
Device_tree_from_scratch :: Spi_device_tree_source_code :: Pico-sdk_studies
2022-08-11 Thursday
Keywords: YAML conditional logic :: YAML schemas
Contents
- 1 ^ Overview
- 2 ^ TO DO
- 3 ^ SPI dts examples from Zephyr boards
- 4 ^ edit point dts excerpt 2
- 5 ^ edit point dts excerpt 3
- 6 ^ edit point dts excerpt 4
- 7 ^ edit point dts excerpt 5
- 8 ^ RPi Pico dts in Zephyr 3.1.0
- 9 ^ YAML device bindings files
- 10 ^ STMicro device tree SPI documentation
- 11 ^ RaspberryPi resources for developers
- 12 ^ DMA peripherals in dts
- 13 ^ Reference
^ 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 . . .
- [ ] files in Zephyr SDK directories zephyr/soc/arm/rpi_pico and zephyr/soc/arm/rpi_pico/rp2
- [ ] track down &rcc device node in arch/arm/boot/dts/stm32mp131.dtsi
- [ ] learn what necessary to explain dts node attribute for interrupts, which differs from device to device.
- [ ] learn what "native" SPI chip select means, as shown in STMicro SPI dts bindings file.
^ 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:
- ~/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)