diff --git a/doc/nrf/app_dev/config_and_build/hardware/add_new_driver.rst b/doc/nrf/app_dev/config_and_build/hardware/add_new_driver.rst new file mode 100644 index 000000000000..0803577a40bb --- /dev/null +++ b/doc/nrf/app_dev/config_and_build/hardware/add_new_driver.rst @@ -0,0 +1,90 @@ +.. _add_new_driver: + +Adding new drivers +################## + +.. contents:: + :local: + :depth: 2 + +Adding drivers to your embedded project allows you to add support for additional hardware components and extend functionalities of your application. + +To add a new driver to an application in the |NCS|, complete the following steps: + +.. rst-class:: numbered-step + +Create a devicetree binding +*************************** + +In most of the cases you want to make it possible to configure some properties of your driver instance. +For example, a sensor may need to allow configuring used GPIO pins or communication interface. + +A driver instance can be made configurable through a devicetree node that is compatible with a specific binding. +The devicetree bindings provide structure for the devicetree by declaring requirements for the content of devicetree nodes. +The :ref:`compatible ` property defines compatibility of a devicetree node with a devicetree binding. + +You can create a devicetree binding YAML file for your driver in the :file:`dts/bindings` directory of your project. +If applicable, you can also use one of the existing DTS bindings available in the |NCS| or Zephyr. +For implementation examples, see :file:`nrf/dts/bindings` and :file:`zephyr/dts/bindings` directories. +See also :ref:`zephyr:devicetree` documentation for more information about devicetree. + +For more information about devicetree bindings, read the :ref:`documentation about them in Zephyr `. + +.. rst-class:: numbered-step + +Create the driver files +*********************** + +First, create the files that will implement driver and expose driver APIs. +As a reference, you can check the |NCS| :ref:`drivers`, whose code is located at :file:`nrf/drivers`. + +You will need the following files: + +* :file:`CMakeLists.txt` - This file adds your driver sources to the build as a Zephyr library. + See :ref:`app_build_system` for more information about the build system. +* :file:`Kconfig` - This file will include all custom Kconfig options for your driver, including the Kconfig option to enable and disable the driver. + See Zephyr's :ref:`zephyr:kconfig` for more information. +* Driver's source files - These files will include the code for your driver, such as :ref:`zephyr:device_struct`, device definition through the :c:macro:`DEVICE_DT_DEFINE` macro, and other elements. + If possible, your driver should expose a generic API to simplify integrating the driver in user application. + For example, the driver could expose sensor driver API (:c:struct:`sensor_driver_api`). + See :file:`nrf/drivers/sensor/paw3212/paw3212.c` for an example. + See also Zephyr's :ref:`zephyr:device_model_api` for more information, in particular the "Subsystems and API structures" section. + +.. rst-class:: numbered-step + +Include the driver in your application +************************************** + +To enable the driver in your application's configuration, complete the following steps: + +1. Enable the necessary Kconfig options in the application's :file:`prj.conf` file. + This includes the Kconfig option you defined for enabling and disabling the driver. + See :ref:`configuring_kconfig` for information about how to enable Kconfig options. +#. Create or modify a devicetree overlay file for your board to add the necessary devicetree node for your custom driver. + This step is crucial for connecting the driver to the specific hardware on your board. + For information about how to create or modify devicetree files, see :ref:`configuring_devicetree`. +#. Include the appropriate header file for your custom driver in your application code and use the driver APIs in the application. + If your driver exposes a generic API (for example, :ref:`sensor driver API `), you can use generic headers defined for the API. + +DevAcademy courses +****************** + +`Nordic Developer Academy`_ contains introductory courses to the |NCS| and Zephyr. +See the following course lessons to get started with driver development: + +* `Lesson 6 – Serial communication (I2C)`_ in `nRF Connect SDK Fundamentals course`_ describes how to communicate with a sensor connected over I2C using I2C APIs. +* `Lesson 5 – Serial Peripheral Interface (SPI)`_ in `nRF Connect SDK Intermediate course`_ describes how to communicate with sensors over SPI in Zephyr. +* `Lesson 7 - Device driver model`_ in `nRF Connect SDK Intermediate course`_ describes how to start with adding your own sensor driver in the Exercise 1. + +Related documentation +********************* + +The :ref:`nrf_desktop` application describes how to :ref:`add a new motion sensor to the project `. + +Implementation examples +*********************** + +Check the driver implementation examples at the following paths: + +* |NCS|: :ref:`drivers`, with code located at :file:`nrf/drivers`. +* Zephyr: :zephyr:code-sample-category:`drivers`, with code located at :file:`zephyr/samples/drivers`. diff --git a/doc/nrf/app_dev/config_and_build/hardware/index.rst b/doc/nrf/app_dev/config_and_build/hardware/index.rst index b35c0852c669..1ccc235309bf 100644 --- a/doc/nrf/app_dev/config_and_build/hardware/index.rst +++ b/doc/nrf/app_dev/config_and_build/hardware/index.rst @@ -19,9 +19,14 @@ The following guides provide information about configuring specific aspects of h Read them together with Zephyr's :ref:`zephyr:hardware_support` and :ref:`zephyr:dt-guide` guides, and the official `Devicetree Specification`_. In particular, :ref:`zephyr:set-devicetree-overlays` explains how the base devicetree files are selected. +.. note:: + If you want to go through dedicated training related to some of the topics covered here, enroll in the courses in the `Nordic Developer Academy`_. + For example, `nRF Connect SDK Fundamentals course`_ describes devicetree in `Lesson 2 `_. + .. toctree:: :maxdepth: 1 :caption: Subpages: + add_new_driver pin_control use_gpio_pin_directly diff --git a/doc/nrf/app_dev/config_and_build/hardware/use_gpio_pin_directly.rst b/doc/nrf/app_dev/config_and_build/hardware/use_gpio_pin_directly.rst index 69fea7e5fe32..4e9030bc34fa 100644 --- a/doc/nrf/app_dev/config_and_build/hardware/use_gpio_pin_directly.rst +++ b/doc/nrf/app_dev/config_and_build/hardware/use_gpio_pin_directly.rst @@ -7,21 +7,36 @@ Driving a GPIO pin directly :local: :depth: 2 -This user guide shows how to drive a GPIO pin directly. -In the development phase of an embedded project, it can be used to collect execution timings or as a debugging tool. +This user guide shows how to control a GPIO pin directly using GPIO driver APIs. +In the development phase of an embedded project, you can use this configuration to set the pin state using software, without any intermediary circuitry or additional hardware components. +You can use this solution to collect execution timings, or as a debugging tool. -Declaring the GPIO pin -********************** +You can copy the following configuration snippets manually into the devicetree overlay files. +You can also use the `Devicetree Visual Editor `_ (either in GUI or text mode) in the |nRFVSC| to apply them. -To declare a GPIO pin node, use a DTS node with ``nordic,gpio-pins`` compatible set in the :term:`devicetree `. -If your application does not use the same GPIO instance as used by the node, enable the GPIO port instance required by the GPIO driver. +.. rst-class:: numbered-step -This DTS content can be introduced in the DTS of your board, application, or overlay file. -Pins defined this way can be accessed using devicetree macros. +Define the compatible DTS node +****************************** -The following snippet shows the declaration of a GPIO pin node for **Pin 2** of **GPIO0**. -The node is labeled as ``user-dbg-pin``. -Additionally, the ``gpio0`` instance and ``gpiote0`` are enabled, so the GPIO driver can be built and executed. +You need to define a new GPIO pin devicetree node for the pin. +The devicetree node needs to be compatible with the GPIO devicetree binding. +GPIO APIs use the devicetree node to refer to the specified GPIO pin. + +If you work with a Nordic Semiconductor device, you can use the binding definition in :file:`dts/bindings/gpio`. + +See Zephyr's documentation about :ref:`zephyr:devicetree` and :ref:`zephyr:gpio_api` for more information. + +.. rst-class:: numbered-step + +Configure the GPIO pin through DTS +********************************** + +To declare a GPIO pin node, create a DTS node in the DTS of your board or application's DTS overlay. +Pins defined this way can be accessed using the :ref:`GPIO devicetree APIs`. + +Make sure that GPIO ports used by the GPIO pins are enabled. +The following snippet shows the declaration of a GPIO pin node called ``user_dbg_pin``: .. code-block:: c @@ -41,8 +56,18 @@ Additionally, the ``gpio0`` instance and ``gpiote0`` are enabled, so the GPIO dr status = "okay"; }; -Using the pin in your application -********************************* +In this snippet: + +* The node is labelled as ``user-dbg-pin``. +* ``compatible`` specifies the binding definition to be used (``nordic,gpio-pins`` from :file:`dts/bindings/gpio`). +* ``gpios`` specifies which pin node is being used (**Pin 2** of **GPIO0**). +* ``status`` enables the pin node when it is set to ``"okay"``. +* Additionally, the ``gpio0`` and ``gpiote0`` instances are enabled, so the GPIO driver can be built and executed. + +.. rst-class:: numbered-step + +Include the pin in your application +*********************************** To let your application access the declared pins, use the following devicetree macros: @@ -54,7 +79,7 @@ To let your application access the declared pins, use the following devicetree m static const struct gpio_dt_spec pin_dbg = GPIO_DT_SPEC_GET_OR(DT_NODELABEL(user_dbg_pin), gpios, {0}); -#. Make sure your application initializes the pin: +#. Make sure your application initializes the pin using the :c:func:`gpio_pin_configure_dt` function: .. code-block:: c @@ -62,7 +87,7 @@ To let your application access the declared pins, use the following devicetree m gpio_pin_configure_dt(&pin_dbg, GPIO_OUTPUT_INACTIVE); } -#. To let your application drive the pin, add the following code where needed: +#. Add the following code where needed to let your application drive the pin using the :c:func:`gpio_pin_set_dt` function: .. code-block:: c @@ -83,7 +108,8 @@ This is an easy way to disable this debugging infrastructure. Declaring multiple pins *********************** -Multiple pins can be declared in one GPIO property as well. +You can also declare multiple pins in one GPIO property. +See the following code snippet: .. code-block:: c @@ -96,8 +122,7 @@ Multiple pins can be declared in one GPIO property as well. }; }; -To initialize the defined GPIO pin structures, use the ``GPIO_DT_SPEC_INST_GET_BY_IDX_OR()`` macro. - +To initialize the defined GPIO pin structures, use the :c:macro:`GPIO_DT_SPEC_INST_GET_BY_IDX_OR` macro: .. code-block:: c diff --git a/doc/nrf/links.txt b/doc/nrf/links.txt index 2dc1fdd37c5e..cc32adfcc976 100644 --- a/doc/nrf/links.txt +++ b/doc/nrf/links.txt @@ -908,9 +908,13 @@ .. _`nRF Connect SDK Fundamentals course`: https://academy.nordicsemi.com/courses/nrf-connect-sdk-fundamentals/ .. _`Installing nRF Connect SDK and VS Code`: https://academy.nordicsemi.com/courses/nrf-connect-sdk-fundamentals/lessons/lesson-1-nrf-connect-sdk-introduction/topic/exercise-1-1/ +.. _`Lesson 2 - Reading buttons and controlling LEDs`: https://academy.nordicsemi.com/courses/nrf-connect-sdk-fundamentals/lessons/lesson-2-reading-buttons-and-controlling-leds/ +.. _`Lesson 6 – Serial communication (I2C)`: https://academy.nordicsemi.com/courses/nrf-connect-sdk-fundamentals/lessons/lesson-6-serial-com-i2c/topic/i2c-driver/ .. _`nRF Connect SDK Intermediate course`: https://academy.nordicsemi.com/courses/nrf-connect-sdk-intermediate/ .. _`Lesson 2 - Debugging and troubleshooting`: https://academy.nordicsemi.com/courses/nrf-connect-sdk-intermediate/lessons/lesson-2-debugging/ +.. _`Lesson 5 – Serial Peripheral Interface (SPI)`: https://academy.nordicsemi.com/courses/nrf-connect-sdk-intermediate/lessons/lesson-5-serial-peripheral-interface-spi/ +.. _`Lesson 7 - Device driver model`: https://academy.nordicsemi.com/courses/nrf-connect-sdk-intermediate/lessons/lesson-7-device-driver-model/ .. _`Cellular IoT Fundamentals course`: https://academy.nordicsemi.com/courses/cellular-iot-fundamentals/ .. _`Power saving techniques`: https://academy.nordicsemi.com/courses/cellular-iot-fundamentals/lessons/lesson-1-cellular-fundamentals/topic/lesson-1-power-saving-techniques/ diff --git a/dts/bindings/gpio/nordic,gpio-pins.yaml b/dts/bindings/gpio/nordic,gpio-pins.yaml index 9205f237e7b5..0be9c64d8e86 100644 --- a/dts/bindings/gpio/nordic,gpio-pins.yaml +++ b/dts/bindings/gpio/nordic,gpio-pins.yaml @@ -2,13 +2,13 @@ # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause description: | - This allows to define the pin of the GPIO to be owned by the domain. - It does not provide any specyfic driver. - Its function is to allow us to use two functionalities: + This binding allows to assign a GPIO to the domain. + It does not provide any specific driver. + The binding enables the following functionalities: - 1. Generate the right UICR marking the domain to own the selected pin. - 2. Access to pins by the macros from zephyr/devicetree/gpio.h file - increasing the hardware abstraction this way. + - Add an entry in UICR that marks the domain to own the selected pin. + - Allow access to pins using the macros from the `zephyr/devicetree/gpio.h` file, + which increases the hardware abstraction. compatible: "nordic,gpio-pins"