diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 8a24a14ea6..b7f2386b3a 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -22,7 +22,7 @@ affect a person's ability to participate within them. If you believe someone is violating the code of conduct, we ask that you report it by emailing . For more details please see our [Reporting -Guidelines](https://doc.riot-os.org/coc-reporting-guide.html). +Guidelines][reporting-guidelines]. - **Be friendly and patient.** - **Be welcoming.** We strive to be a community that welcomes and supports @@ -39,7 +39,7 @@ Guidelines](https://doc.riot-os.org/coc-reporting-guide.html). - **Be respectful.** Not all of us will agree all the time, but disagreement is no excuse for poor behavior and poor manners. We might all experience some frustration now and then, but we cannot allow that frustration to turn - into a personal attack. It’s important to remember that a community where + into a personal attack. It's important to remember that a community where people feel uncomfortable or threatened is not a productive one. Members of the RIOT community should be respectful when dealing with other members as well as with people outside the RIOT community. @@ -61,18 +61,23 @@ Guidelines](https://doc.riot-os.org/coc-reporting-guide.html). - **When we disagree, try to understand why.** Disagreements, both social and technical, happen all the time and RIOT is no exception. It is important that we resolve disagreements and differing views constructively. Remember - that we’re different. The strength of RIOT comes from its varied community, + that we're different. The strength of RIOT comes from its varied community, people from a wide range of backgrounds. Different people have different perspectives on issues. Being unable to understand why someone holds a - viewpoint doesn’t mean that they’re wrong. Don’t forget that it is human to - err and blaming each other doesn’t get us anywhere. Instead, focus on + viewpoint doesn't mean that they're wrong. Don't forget that it is human to + err and blaming each other doesn't get us anywhere. Instead, focus on helping to resolve issues and learning from mistakes. Text based on the Code of Conduct of the [Django -community](https://www.djangoproject.com/conduct/). +community][django-community]. Questions? ---------- -If you have questions, please see [the FAQ](https://doc.riot-os.org/coc-faq.html). -If that doesn't answer your questions, feel free to [contact us](mailto:conduct@riot-os.org). +If you have questions, please see [the FAQ][faq]. +If that doesn't answer your questions, feel free to [contact us][contact-us]. + +[reporting-guidelines]: https://guide.riot-os.org/general/code_of_conduct/reporting/ +[django-community]: https://www.djangoproject.com/conduct/ +[faq]: https://guide.riot-os.org/general/code_of_conduct/faq/ +[contact-us]: mailto:conduct@riot-os.org diff --git a/doc/doxygen/riot.doxyfile b/doc/doxygen/riot.doxyfile index 4d10e9740d..8d7a8676e8 100644 --- a/doc/doxygen/riot.doxyfile +++ b/doc/doxygen/riot.doxyfile @@ -2618,7 +2618,7 @@ DOT_PATH = # command). # This tag requires that the tag HAVE_DOT is set to YES. -DOTFILE_DIRS = dot/ +DOTFILE_DIRS = # The MSCFILE_DIRS tag can be used to specify one or more directories that # contain msc files that are included in the documentation (see the \mscfile diff --git a/doc/doxygen/src/advanced-build-system-tricks.md b/doc/doxygen/src/advanced-build-system-tricks.md index 897df4a832..2c52589a82 100644 --- a/doc/doxygen/src/advanced-build-system-tricks.md +++ b/doc/doxygen/src/advanced-build-system-tricks.md @@ -1,4 +1,4 @@ -Advanced build system tricks {#advanced-build-system-tricks} +Advanced build system tricks (Deprecated) {#advanced-build-system-tricks} ============================ @deprecated See [Advanced Build System Tricks](https://guide.riot-os.org/build-system/advanced_build_system_tricks/) diff --git a/doc/doxygen/src/build-in-docker.md b/doc/doxygen/src/build-in-docker.md index 1511672329..e330952212 100644 --- a/doc/doxygen/src/build-in-docker.md +++ b/doc/doxygen/src/build-in-docker.md @@ -1,4 +1,4 @@ -# Build In Docker {#build-in-docker} +# Build In Docker (Deprecated) {#build-in-docker} @deprecated This page is deprecated. See [Build in Docker](https://guide.riot-os.org/build-system/build-in-docker/) diff --git a/doc/doxygen/src/build-system-basics.md b/doc/doxygen/src/build-system-basics.md index 4210fc306e..ad9d57499e 100644 --- a/doc/doxygen/src/build-system-basics.md +++ b/doc/doxygen/src/build-system-basics.md @@ -1,4 +1,4 @@ -# Build System Basics {#build-system-basics} +# Build System Basics (Deprecated) {#build-system-basics} @deprecated See [Build System Basics](https://guide.riot-os.org/build-system/build_system_basics/) on the RIOT Guide Site for the latest information. diff --git a/doc/doxygen/src/coc-faq.md b/doc/doxygen/src/coc-faq.md index 75baa548c2..3bce1a01b3 100644 --- a/doc/doxygen/src/coc-faq.md +++ b/doc/doxygen/src/coc-faq.md @@ -1,75 +1,4 @@ -# FAQ {#coc-faq} +# FAQ (Deprecated) {#coc-faq} -This FAQ attempts to address common questions and concerns around the RIOT -community's [Code of Conduct][CoC]. If you still have questions after -reading it, please feel free to [contact us][CoC-question-mail]. - --------------------------------------------------------------------------------- - -### Why have you adopted a Code of Conduct? - -If you're familiar with the RIOT -community, you'll probably notice that the Code basically matches what we -already do. Think of this as documentation: we're taking implicit expectations -about behavior and making them explicit. - -We're doing this because the RIOT community is growing faster than any of us -could have anticipated. This is on balance a very positive thing, but as we've -grown past the point where it's possible to know the whole community we think -it's very important to be clear about our values. - -We know that the RIOT community is open, friendly, and welcoming. We want to -make sure everyone else knows it too. - -### What does it mean to "adopt" a Code of Conduct? - -For the most part, we don't think it means large changes. We think that the text -does a really good job describing the way the RIOT community already conducts -itself. We expect that most people will simply continue to behave in the awesome -way they have for years. - -However, we do expect that people will abide by the spirit and words of the CoC -when in "official" RIOT spaces. This code has been adopted by the RIOT community -as a whole. That means that it'll apply in all community spaces. - -In practice, this means the [RIOT forum](https://forum.riot-os.org), the Matrix -chats (e.g., [`#riot-os`](https://matrix.to/#/#riot-os:matrix.org) or -[`#riot-os-off-topic`](https://matrix.to/#/#riot-os-off-topic:matrix.org)), -mailing lists (e.g., security@riot-os.org), bug tracking and code review tools, -and "official" RIOT events such as Hack'n'ACKs or RIOT summits. In addition, -violations of this code outside these spaces may affect a person's ability to -participate within them. - -### What happens if someone violates the Code of Conduct? - -Our intent is that anyone in the community can stand up for this code, and -direct people who're unaware to this document. If that doesn't work, or if you -need more help, you can contact . For more details please see -our [Reporting Guidelines](@ref coc-reporting-guide). - -### Why do we need a Code of Conduct? Everyone knows not to be a jerk. - -Sadly, not everyone knows this. - -However, even if everyone was kind, everyone was compassionate, and everyone was -familiar with codes of conduct it would still be incumbent upon our community to -publish our own. Maintaining a code of conduct forces us to consider and -articulate what kind of community we want to be, and serves as a constant -reminder to put our best foot forward. But most importantly, it serves as a -signpost to people looking to join our community that we feel these values are -important. - -### This is censorship! I have the right to say whatever I want! - -You do -- in *your* space. If you'd like to hang out in *our* spaces (as -clarified above), we have some simple guidelines to follow. If you want to, for -example, form a group where RIOT is discussed using language inappropriate for -general channels then nobody's stopping you. We respect your right to establish -whatever codes of conduct you want in the spaces that belong to you. Please -honor this Code of Conduct in our spaces. - -#### References -This FAQ was adapted from the [Django Code of Conduct FAQ](https://www.djangoproject.com/conduct/faq/) - -[CoC-question-mail]: mailto:riot@riot-os.org -[CoC]: @ref coc +@deprecated Guides have moved to the [Guide Site](https://guide.riot-os.org/general/code_of_conduct/faq/). +This page will be removed after release 2026.04. diff --git a/doc/doxygen/src/coc-info.md b/doc/doxygen/src/coc-info.md index 30ce4c1e46..d191a36bfe 100644 --- a/doc/doxygen/src/coc-info.md +++ b/doc/doxygen/src/coc-info.md @@ -1,8 +1,5 @@ -Code of Conduct Information {#coc-info} +Code of Conduct Information (Deprecated) {#coc-info} =========================== -The following documents are describing all matters around our code of conduct: - -- The \subpage coc itself, -- The \subpage coc-reporting-guide, and -- The \subpage coc-faq +@deprecated Guides have moved to the [Guide Site](https://guide.riot-os.org/general/code_of_conduct/). +This page will be removed after release 2026.04. diff --git a/doc/doxygen/src/coc-reporting-guide.md b/doc/doxygen/src/coc-reporting-guide.md index 01ce3ec9b5..a81d93415b 100644 --- a/doc/doxygen/src/coc-reporting-guide.md +++ b/doc/doxygen/src/coc-reporting-guide.md @@ -1,80 +1,4 @@ -# Reporting Guidelines {#coc-reporting-guide} +# Reporting Guidelines (Deprecated) {#coc-reporting-guide} -If you believe someone is violating the [code of conduct][CoC] we ask that you -report it to us by emailing . Currently, the recipients of -this email address are [\@OlegHahm](https://github.com/OlegHahm) (Oleg Hahm) and -[\@miri64](https://github.com/miri64) (Martine Lenders). - -**All reports will be kept confidential.** In some cases we may determine that a -public statement will need to be made. If that's the case, the identities of all -victims and reporters will remain confidential unless those individuals instruct -us otherwise. - -**If you believe anyone is in physical danger, please notify appropriate law -enforcement first.** If you are unsure what law enforcement agency is -appropriate, please include this in your report and we will attempt to notify -them. - -If you are unsure whether the incident is a violation, or whether the space -where it happened is covered by this Code of Conduct, we encourage you to still -report it. We would much rather have a few extra reports where we decide to take -no action, rather than miss a report of an actual violation. We do not look -negatively on you if we find the incident is not a violation. And knowing about -incidents that are not violations, or happen outside our spaces, can also help -us to improve the Code of Conduct or the processes surrounding it. - -In your report please include: - -- Your contact info (so we can get in touch with you if we need to follow up) -- Names (real, nicknames, or pseudonyms) of any individuals involved. If there - were other witnesses besides you, please try to include them as well. -- When and where the incident occurred. Please be as specific as possible. -- Your account of what occurred. If there is a publicly available record (e.g. - forum post, a mailing list archive, or a public Matrix chat link) please include a link. -- Any extra context you believe existed for the incident. -- If you believe this incident is ongoing. -- Any other information you believe we should have. - -### What happens after you file a report? - -You will receive an email from one of the core community members as soon as -possible. We promise to acknowledge receipt within 24 hours (and will aim for -much quicker than that). - -They will review the incident and determine: - -- What happened. -- Whether this event constitutes a code of conduct violation. -- Who the bad actor was. -- Whether this is an ongoing situation, or if there is a threat to anyone's - physical safety. - -If this is determined to be an ongoing incident or a threat to physical safety, -their immediate priority will be to protect everyone involved. -This means we may delay an "official" response until we believe that the -situation has ended and that everyone is physically safe. - -Once the working group has a complete account of the events they will make a -decision as to how to response. Responses may include: - -- Nothing (if we determine no violation occurred). -- A private reprimand from us to the individual(s) involved. -- A public reprimand. -- An imposed vacation (i.e. asking someone to "take a week off" from the forum, the Matrix chats, or a mailing - list). -- A permanent or temporary ban from some or all RIOT spaces (forum, Matrix chats, mailing lists, - etc.) -- A request for a public or private apology. - -We'll respond within one week to the person who filed the report with either a -resolution or an explanation of why the situation is not yet resolved. - -Once we've determined our final action, we'll contact the original reporter to -let them know what action (if any) we'll be taking. We'll take into account -feedback from the reporter on the appropriateness of our response, but we don't -guarantee we'll act on it. - -#### Reference -These reporting guidelines were adapted from the [Django reporting guidelines](https://www.djangoproject.com/conduct/reporting/) - -[CoC]: @ref coc +@deprecated Guides have moved to the [Guide Site](https://guide.riot-os.org/general/code_of_conduct/reporting/). +This page will be removed after release 2026.04. diff --git a/doc/doxygen/src/creating-an-application.md b/doc/doxygen/src/creating-an-application.md index 8a6f0ba46a..eb9f09a321 100644 --- a/doc/doxygen/src/creating-an-application.md +++ b/doc/doxygen/src/creating-an-application.md @@ -1,290 +1,5 @@ -Creating an application {#creating-an-application} +Creating an application (Deprecated) {#creating-an-application} ======================= -[TOC] - -To create your own application you need to create a directory containing one or -multiple C file(s) with your source code and a Makefile. A template Makefile is -available in the `dist` folder of the -[RIOT repository](https://github.com/RIOT-OS/RIOT). - -The main function {#the-main-function} -================= -After the board is initialized, RIOT starts two threads: the idle thread and -the main thread. The idle thread has the lowest priority and will run whenever -no other thread is ready to run. It will automatically use the lowest possible -power mode for the device. The main thread - configured with a default priority -that is right in the middle between the lowest and the highest available -priorities - is the first thread that runs and calls the `main()` function. -This function needs to be defined in the source code of the application -(typically located in `main.c`). - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.c} -#include - -int main(void) -{ - puts("Hello World!"); - return 0; -} -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The application's Makefile {#the-applications-makefile} -========================== -The minimal Makefile {#the-minimal-makefile} --------------------- -At minimum the Makefile of an application (see @ref getting-started) needs to -define the following macros: - * `APPLICATION`: should contain the name of your application - * `RIOTBASE`: specifies the path to your copy of the RIOT repository (note - that you may want to use `$(CURDIR)` here, to give a relative path) - -The `BOARD` macro is also required and recommended to be set to `native` by -default, but is recommended to be overridable with the `?=` operator. -Additionally, it is required to include the `Makefile.include` from the -`RIOTBASE`. - -~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.mk} -# Set the name of your application: -APPLICATION = foobar - -# If no BOARD is found in the environment, use this default: -BOARD ?= native - -# This has to be the absolute path to the RIOT base directory: -RIOTBASE ?= $(CURDIR)/../../RIOT - -include $(RIOTBASE)/Makefile.include -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -How to handle unsupported boards? {#handle-unsupported-boards} ---------------------------------- -Sometimes it is necessary to exclude boards because they don't provide a -required functionality or don't have sufficient memory. RIOT's build system -looks for the macros `BOARD_BLACKLIST`, `BOARD_WHITELIST`, and -`BOARD_INSUFFICIENT_MEMORY`. Any board name that is not included in -`BOARD_WHITELIST` will issue a message that one has to expect errors if they -build the application for the board referred by that name. The list can also be -used by a CI system to not build the application for this board at all. A board -that is included in `BOARD_BLACKLIST` will show the same behavior. The build -system evaluates `BOARD_WHITELIST` first and then `BOARD_BLACKLIST`. The -`BOARD_INSUFFICIENT_MEMORY` macro is similar to `BOARD_BLACKLIST` but will -build in any case. A CI system can use the information provided by the -`BOARD_INSUFFICIENT_MEMORY` macro to skip the linking step in the build -process, since some linkers will issue an error if the code won't fit the -target board's flash memory or RAM. - -Including modules {#including-modules} ------------------ -By default a RIOT application comprises only of the applications' code itself, -the kernel, and platform specific code. In order to use additional modules, -such as a particular [device driver](@ref drivers) or [a system library](@ref sys) -(including [networking capabilities](@ref net)), you have to append the modules' -names to the USEMODULE variable. For example, to build an application using the -SHT11 temperature sensor and UDP/IPv6 functionalities of the GNRC network stack, -your Makefile needs to contain these lines: - -~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.mk} -USEMODULE += sht11 -USEMODULE += gnrc_ipv6_default -USEMODULE += gnrc_udp -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Modules typically pull in all required dependencies. - -## Including source files in subfolders - -By default, all source files in an application's (or any RIOT module's) directory -are automatically compiled as part of the application. In order to organize source -code in a directory structure, two different approaches can be used: - -1. Make each subdirectory a separate RIOT module with a unique name inside its -Makefile, either by adding the directory's path to `DIRS` or with the [out-of-tree -module support](#external-modules). -2. Add the source files within subdirectories to `SRC`, either explicitly or with -Makefile wildcards. - -Both approaches are illustrated and explained in `examples/basic/subfolders`. - -## Setting Board-specific Dependencies - -Required dependencies of applications may change depending on the -target board or architecture. This is especially -relevant for networking applications where multiple hardware implementations -exist and the appropriate implementation has to be chosen for the given board -or architecture. -To achieve this task elegantly, a `Makefile.board.dep` file can be -created in the application folder, which is automatically included and -evaluated by RIOT build system during the dependency resolution phase. -This ensures that all the relevant variables such as `FEATURES_USED` or the -`USEMODULE` list are fully populated. - -~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.mk} -ifneq (,$(filter arch_esp,$(FEATURES_USED))) - USEMODULE += esp_wifi -endif - -ifneq (,$(filter native native32 native64,$(BOARD))) - USEMODULE += netdev_default -endif -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -# Helper tools - -To help you start writing an application within RIOT, the build system provides -the `generate-example` `generate-test` make targets. These targets are wrappers -around the [riotgen](https://pypi.org/project/riotgen/) command line tool and -are helpful when starting to implement an application: all required files are -generated with copyright headers, doxygen groups, etc, so you can concentrate -on the module implementation. -For applications, the `Makefile` is generated with the dependencies (modules, -packages, required features) included. - -**Usage:** - -To generate an example application, e.g in the `examples` directory, from the -RIOT base directory, run: -``` -make generate-example -``` - -To generate a test application, e.g in the `tests` directory, from the -RIOT base directory, run: -``` -make generate-test -``` - -Then answer a few questions about the application: -- Application name: enter a name for your application. It will be used as both - the name of the application directory under `examples` or `tests` and by - the build system module (set in the `APPLICATION` variable). -- Application brief description: Describe in one line what is this application - about. -- Target board: select the default target board. The value is set to `native` - by default. -- Modules: give the list of dependency modules, separated by commas. For - example: ztimer,fmt -- Packages: give the list of dependency packages, separated by commas. -- Features required: give the list of CPU features (`periph_*`, etc) required - by the application, all separated by commas. - -Other global information (author name, email, organization) should be retrieved -automatically from your git configuration. - -Once completed, the application files are either located in -`examples/` or `tests/` depending on the -target used. - -**Testrunner:** when using the `make generate-test`, you can also automatically -add a testrunner Python script. Just answer 'y' when prompted. - -# Creating an out of tree application structure - -Applications written for RIOT do not have to reside in the RIOT tree. Out of -tree applications, modules and boards are supported. - -For a full application with custom board and modules, the following directory -tree can be used: - -``` -├── apps -│   └── my_app -│   └── Makefile -├── boards -│   └── my_board -├── modules -│   └── my_module -│   ├── include -│   │   └── my_module.h -│   ├── Makefile -│   ├── Makefile.include -│   └── my_module.c -└── RIOT -``` - -In this example tree, the `apps` directory contains a collection of applications -for the project. The modules directory could contain extra modules for the -applications. - -The make file inside the application needs at least the following as bare minimum: - -``` -APPLICATION = my_app -PROJECT_BASE ?= $(CURDIR)/../.. -RIOTBASE ?= $(PROJECT_BASE)/RIOT - -# Optionally, provide paths to where external boards and/or modules -# reside, so that they can be included in the app -EXTERNAL_MODULE_DIRS += $(PROJECT_BASE)/modules -EXTERNAL_BOARD_DIRS += $(PROJECT_BASE)/boards - -include $(RIOTBASE)/Makefile.include -``` - -The `RIOTBASE` variable tells the build system where to find the RIOT source -tree and to need to point to the RIOT source tree used for the application for -the application to work. - -The RIOT directory contains the sources of RIOT here. This can be either a -direct checkout of the sources or a git submodule, whichever has your -preference. - -If your project has separate modules or separate boards, these can be contained -inside a modules os boards directory. The RIOT build system has both -`EXTERNAL_MODULE_DIRS` and `EXTERNAL_BOARD_DIRS` variables to specify -directories that contain extra modules and extra boards. - -## External Boards - -External boards can be ported in an identical way as porting a regular board to -RIOT, see @ref porting-boards. - -One approach can be to copy over an existing board and modify it to suit the -needs. Boards in the RIOT tree can be included and used as dependency in the -custom boards. In case you connect additional hardware to an upstream board -(such as e.g. an Arduino shield) or you require a different hardware -configuration (e.g. configuring some of the pins configured as ADC as -additional PWM outputs instead) a copy of the upstream board that is then -customized to the application needs is the best course of action. - -## External Modules {#external-modules} - -Similar to the external boards, external modules can be written in a similar way -as regular in-tree modules. - -One modification is the include directory inside the module directory. For this -include directory to be added to the include path during compilation, the -following snippet is required in the modules `Makefile.include`: - -``` -USEMODULE_INCLUDES_my_module := $(LAST_MAKEFILEDIR)/include -USEMODULE_INCLUDES += $(USEMODULE_INCLUDES_my_module) -``` - -Note that the make variable (here `USEMODULE_INCLUDES_my_module`) must be unique -for every module to make this work. Including the module name here is usually -sufficient. - -## Extra Makefile Scaffolding - -A bit of extra, but optional, Makefile scaffolding can help to keep the project -easy to maintain. An extra `Makefile.include` in the root directory of the -project that sets the necessary variables can help to deduplicate settings. -This includes the `RIOTBASE` variable and the include to the RIOT -`Makefile.include`: - -``` -EXTERNAL_MODULE_DIRS += $(PROJECT_BASE)/modules -EXTERNAL_BOARD_DIRS += $(PROJECT_BASE)/boards -RIOTBASE ?= $(PROJECT_BASE)/RIOT -include $(RIOTBASE)/Makefile.include -``` -Applications then just have to set the `PROJECT_BASE` variable and include this -makefile and don't have to each add the external board and module directories. - -The application makefile would then look like this: -``` -APPLICATION = my_app -PROJECT_BASE ?= $(CURDIR)/../.. -include $(PROJECT_BASE)/Makefile.include -``` +@deprecated Guides have moved to the [Guide Site](https://guide.riot-os.org/advanced_tutorials/creating_application/). +This page will be removed after release 2026.04. diff --git a/doc/doxygen/src/creating-modules.md b/doc/doxygen/src/creating-modules.md index 732a08e57d..42c1ee7664 100644 --- a/doc/doxygen/src/creating-modules.md +++ b/doc/doxygen/src/creating-modules.md @@ -1,194 +1,5 @@ -Creating modules {#creating-modules} +Creating modules (Deprecated) {#creating-modules} ================ -Modules in RIOT are well-defined units of code that provide a set of features -to your application. This includes also drivers and to a certain extent ports -for CPUs and boards (with some exceptions, see the -porting guide for further information). -The general structure {#the-general-structure} -===================== -Like @ref creating-an-application "applications", modules are directories -containing source files and a Makefile. Additionally their API can be defined -in one or more header files, residing in the include path of their -super-module. - -E.g. the @ref sys_shell module is implemented in `sys/shell` and defines its -API in `sys/include/shell.h` and the @ref drivers_isl29020 driver is -implemented in `drivers/isl29020` and defines its API in -`drivers/include/isl29020.h`. - -A module's Makefile just needs to include `Makefile.base` in the RIOT -repository: - -~~~~~~~~~~~~~~~~~~~ {.mk} -include $(RIOTBASE)/Makefile.base -~~~~~~~~~~~~~~~~~~~ - -If your module's name differs from the name of the directory it resides in you -need to set the `MODULE` macro in addition. - -When compiled a module always provides a `MODULE_` macro to the -system. This way, other modules can check if the module is available in the -current configuration or not. - -Modules can be used by adding their name to the `USEMODULE` macro of your -application's Makefile. - -### Pitfalls ### - -The `MODULE` name should be unique or build breaks as modules overwrite the -same output file. This might for example lead to `undefined reference to` errors -in the linker which can be hard to track down. - -This problem happened in the past for: - - * Packages root directory (libfixmath/u8g2) - * boards/cpu/periph and their common boards/cpu/periph - -Note: even if all boards and cpus implement the `board` and `cpu` modules, only - one is used in an application so there is no conflict. - - -Module dependencies -=================== -Your module may depend on other modules to minimize code duplication. These -dependencies are defined in `Makefile.dep` with the following syntax: - -~~~~~~~~~~~~~~~~~~~ {.mk} -ifneq (,$(filter your_module,$(USEMODULE))) # if module in USEMODULE - USEMODULE += dep1 # add dependencies to USEMODULE - USEMODULE += dep2 -endif -~~~~~~~~~~~~~~~~~~~ - -Note, that `Makefile.dep` is processed only once so you have to take care to -add the dependency block for your module *before* your dependencies pull in -their dependencies. - -Modules outside of RIOTBASE {#modules-outside-of-riotbase} -=========================== -Modules can be defined outside `RIOTBASE`. In addition to add it to `USEMODULE` -the user needs to add the directory (or directories) containing external modules -to `EXTERNAL_MODULE_DIRS`. - -External modules can optionally define the following files: -* `Makefile.include` file to set global build configuration like `CFLAGS` or add - API headers include paths to the `USEMODULE_INCLUDES` variable. -* `Makefile.dep` file to set module dependencies - -***NOTE:*** The name of an external module must be unique (both in regard to other - external modules, as well to native RIOT modules). Additionally, the - directory containing the module must match the module name, e.g. - module `foo` must be located in `/foo`. - -An example can be found in -[`tests/build_system/external_module_dirs`](https://github.com/RIOT-OS/RIOT/tree/master/tests/build_system/external_module_dirs) - -Pseudomodules {#pseudomodules} -============= -Pseudomodules are modules that are not static libraries, i.e. do not generate a -`.a` file. - -To create a pseudomodule just add its name to `makefiles/pseudomodules.inc.mk` -with `PSEUDOMODULES += ` in alphabetical order. - -A Pseudomodule may or may not have a source file associated with it. To make the -distinction between them we will refer to those that don't as true-Pseudomodules. - -The main use case for true-Pseudomodules is to provide base information for -dependencies to other modules or information to the code base via the -`MODULE_` macro. - -Pseudomodules with source code exist under a "real" `MODULE` since they will -generate a `.o` file grouped under that `MODULE`s -`.a` file. - -These modules appear in RIOT under two forms: - -1. Conditionally included source files: - - ``` - foo/ - |----foo_bar.c - |----foo.c - |----Makefile - ``` - -In `foo/Makefile` you add the source file to the `SRC` variable, conditioned on -the Pseudomodule inclusion - - ```mk - ifneq (,$(filter foo_bar,$(USEMODULE))) - SRC += foo_bar.c - endif - ``` - -See `sys/net/ble/skald` for an example in code. - -2. Using the `SUBMODULES` mechanism: - - ``` - foo/ - |----spam.c - |----ham.c - |----eggs.c - |----Makefile - ``` - - ```mk - # make all code end up in "foo_bar.a", this can be any name - MODULE := foo_bar - - # ensure that "foo_ham" or "bar_foo_ham" builds "foo_ham.c". - BASE_MODULE := foo - - # list of source files that are not SUBMODULES - SRC := spam.c - - # enable submodules by setting SUBMODULES = 1 - SUBMODULES = 1 - ``` - -When using `SUBMODULES` in a `MODULE` all `SRC` file excluded from `foo/Makefile` -will be considered `SUBMODULES`. In the example above `ham.c` and `eggs.c`. -These source files will be conditionally included depending if the modules have -been added, i.e. `USEMODULE += foo_ham foo_eggs` (it's the same as case 1 but -handled automatically in `Makefile.base`). - -The `SUBMODULES` mechanism is more flexible since `BASE_MODULE` allows matching -the only parts of compounded module names and only match against part of that name. - -See `sys/ztimer/Makefile` for an example in code. - -`SUBMODULES` can also be true-pseudomodules, or become one by conditionally excluding -the source files by adding them to `SUBMODULES_NO_SRC`. - -# Helper tools - -To help you start writing a module, the RIOT build system provides the -`generate-module` make target. It is a wrapper around the -[riotgen](https://pypi.org/project/riotgen/) command line tool that is helpful -when starting to implement a module: all required files are generated with -copyright headers, doxygen groups, etc, so you can concentrate on the module -implementation. -The module source files are created in the `sys` directory. - -**Usage:** - -From the RIOT base directory, run: -``` -make generate-module -``` -Then answer a few questions about the driver: -- Module name: enter a name for your module. It will be used as both the name - of the module directory under sys, where the source files are created, and - the build system module (used with `USEMODULE`). -- Module doxygen name: Enter the name of module, as displayed in the - Doxygen documentation. -- Brief doxygen description: Describe in one line what is this module about. - -Other global information (author name, email, organization) should be retrieved -automatically from your git configuration. - -Once completed, the module files are located in -`sys//.c` and `sys/include/.h`. +@deprecated Guides have moved to the [Guide Site](https://guide.riot-os.org/advanced_tutorials/creating_modules/). +This page will be removed after release 2026.04. diff --git a/doc/doxygen/src/debugging-aids.md b/doc/doxygen/src/debugging-aids.md index 963aa11a4d..902b9ef5eb 100644 --- a/doc/doxygen/src/debugging-aids.md +++ b/doc/doxygen/src/debugging-aids.md @@ -1,48 +1,4 @@ -# Debugging Tools {#debugging-tools} +# Debugging Tools (Deprecated) {#debugging-tools} -## Undefined Behavior Sanitizer (ubsan) {#ubsan} - -RIOT contains makefile convenience support for gcc/clang's undefined -behaviour sanitizer. - -### Overview - -Both gcc and clang allow generation on code that does runtime checks for -undefined behavior (UB). - -E.g., the following code might trigger UB for some parameters: - -```C -void test(int foo) { - return (foo << 24); -} -``` - -In this case, the signed shift would be alright unless: - -- it would "push out" all bits to the left, with undefined runtime result. Here, - that happens on architectures with 16-bit integers. -- `foo` is negative, with implementation defined runtime results. - -Using ubsan, these can be caught at runtime. - -There are three modes for ubsan that define what happens when the sanitizer -observed undefined behaviour: - -1. `trap` -> cause a trap -2. `msg_exit` -> print a message and exit -3. `msg_recover` -> print a message and continue - -`trap` is available on all RIOT platforms, whereas `msg_exit` and `msg_recover` -are currently only available on `native` when building with gcc, as they require runtime support in -the form of `libubsan`. - -The default is `trap`, or `msg_exit` if available (currently, on native:gnu only). - - -### How to use - -1. build with `make all-ubsan`. - -2. build with `UBSAN_MODE=[trap|msg_exit|msg_recover] make all-ubsan` to - override the ubsan mode. +@deprecated Guides have moved to the [Guide Site](https://guide.riot-os.org/build-system/debugging_aids/). +This page will be removed after release 2026.04. diff --git a/doc/doxygen/src/dev-best-practices.md b/doc/doxygen/src/dev-best-practices.md index 5c0485a337..0a7e345cdf 100644 --- a/doc/doxygen/src/dev-best-practices.md +++ b/doc/doxygen/src/dev-best-practices.md @@ -1,118 +1,4 @@ -# Hints for quicker & better RIOT development {#dev-best-practices} +# Hints for quicker & better RIOT development (Deprecated) {#dev-best-practices} -[TOC] - -* Use the [methodology](#methodology) described below. -* Use [`ccache`](https://guide.riot-os.org/build-system/advanced_build_system_tricks/#speed-up-builds-with-ccache) to speedup compilation - -## Coding "Dos" and "Don'ts": {#coding-dos-and-donts} - -### Dos - * Use static memory. See also [Static vs. Dynamic Memory](#static-vs-dynamic). - * Select the priorities carefully. - * Minimize stack usage with `DEVELHELP` and `CREATE_STACKTEST`. - * Use threads to increase flexibility, modularity, and robustness by leveraging IPC. - * Use unsigned or signed integer (`unsigned`, `int`, `size_t` or `ssize_t`) for loop variables wherever possible, but keep in mind that on some platforms an `int` has a width of only 16-bit. In general, you should avoid types like `uint8_t` for loop iterators as they will probably make it more expensive on some platforms. - * Join and factor out parts of the code with existing code in RIOT, where it makes sense. - * Check all `size/length` parameters when passing memory, e.g. using `sizeof(x)` or `strlen(x)` as appropriate. Make sure you don't use the wrong one with a pointer. - * Make sure all code paths can be reached. Make sure there are no always `true/false` conditions. - * Make sure all critical sections (`lock/unlock`, `acquire/release`, ...) are always closed on every code path. - * Make sure return values are consistent with our API documentation. - * Use `assert()` statements to check parameters rather than returning an error code at run-time, to keep the code size down. - * Use the `DEBUG(...)` macro rather than `log_x(...)` - * Declare all internal module variables and functions `static` - * Make sure variables are reduced in scope as much as possible - * Use an appropriate signedness in your variables - * Make sure the variables are big enough to prevent overflow. Be aware that the code may run on platforms with different sizes of variables. For example, `int/unsigned` is only 16-bit on msp430 and avr8. If in doubt, use portable types. - * Reduce the number of function calls as far as possible without duplicating code. - * Use good judgement when using `static inline` functions and macros. If they are used in multiple places, is the increase in performance worth the penalty in code size? - * Use memory judiciously in general. For example: -```c -typedef enum { - A, - B, - ... -} foo_t; - -int bar(foo_t v) -{ - int abc; - ... - - switch(v) { - case A: - abc = 23; - break; - case B: - abc = 42; - break; - ... - } - ... -} - -/* VS */ - -typedef enum { - A = 23, - B = 42, - ... -} foo_t; - -int bar(foo_t v) { - int abc = v; - ... -} -``` - -### Don'ts - * Don't use too many threads. Try not to use more than one thread per module. Don't create threads for one-time tasks. - * Don't use the POSIX wrapper if implementing something from scratch. - * Don't allocate big chunks of memory (for instance the IPC message queue) on the stack, but use rather static memory for that. - * Don't over-provision memory. - * Don't pass stack memory between different contexts unless you can prove conclusively that it won't be a problem. - * Don't use enums for flags, because flags have a width in memory that is in most cases smaller than `sizeof(enum)` (most bitfields are 16 bits max, on most of our newer platforms, `sizeof(enum)` is however 32 bits). This results in every assignment needed to be cast to either `uint8_t` or `uint16_t`. With macros you don't need to cast since they are typeless. Making the enum packed makes its width unpredictable in terms of alignment issues, when used in struct. - * Don't duplicate code from elsewhere in the RIOT code base, unless there is a very good reason to do so. - * Don't duplicate code within your own code, unless there is a very good reason to do so. Use internal functions to this end. - * Don't mix up logical and bitwise operations (`!` vs `~`, or `&&` vs `&`) - -## Methodology: emulator first, target IoT hardware last! {#methodology} - -The below methodology is recommended, using well-known de facto standard tools from the FLOSS community that are compatible with RIOT. Using the below workflow improves time-to-running-code compared to typical IoT software workflows (which can be as retro as "LED-driven" debugging). - -0. For newbies, preliminaries are typically faster with the provisioned virtual environment setup, e.g. with **Vagrant**. -1. To check your code, first use available **static analysis** as much as possible initially, which means (i) enable all compiler warnings and fix all problems found, then (ii) use a supported linter such as **cppcheck** to find bad coding patterns (i.e. code smells) and identify misuse of standard APIs. -2. Next, use available **dynamic analysis** tools to find further defects while running the code on **RIOT native**, which means (i) running unit tests and integration tests on RIOT native emulator, and (ii) using **Valgrind** memcheck, as well as the **GCC stack smashing detection**, to detect and avoid undefined behavior due to invalid memory access. -3. In case of networked applications or protocols, test **several instances of native** communicating via a virtual network mimicking the targeted scenario, which means (i) either using the default virtual full-mesh or other topologies configured via DESvirt, and (ii) using **Wireshark** to capture and analyze virtual network traffic, e.g. to ensure protocol packets are syntactically correct, and to observe network communication patterns. -4. In case of incorrect behavior at this stage, analyze the system state for semantic errors on native using the standard debugger **gdb**, which allows virtually unlimited conditional breakpoints, record and replay, catchpoints, tracepoints and watchpoints. -5. In case of suspected performance bottleneck, use performance profilers **gprof**, or else cachegrind, to identify precisely the bottlenecks. -6. At this stage the implementation has proven bug-free on the native emulator. One can thus finally move on to hardware-in-the-loop, which means (i) flashing the binary on the targeted IoT hardware, typically using standard flasher **OpenOCD** or **edbg**, and (ii) using the **RIOT shell** running on the target IoT device(s) for easier debugging on the target hardware. -7. In case the hardware is not available on-site, one can consider remotely flashing and testing the binary on supported open-access testbeds, e.g. [IoT-LAB](https://www.iot-lab.info) hardware is fully supported by RIOT. -8. In case of failure, after analyzing the failure and attempting to fix the defect, go back to step 1 to make sure the fix did not itself introduce a new defect. - -## Static vs. Dynamic Memory {#static-vs-dynamic} - -In your C program you have to decide where the memory you want to use comes from. -There are two ways to get memory in your C code: - -1. Define static memory. -2. Use dynamic memory (call `malloc()`/`free()` to get memory from the heap). - -Both ways have some drawbacks which are listed here. -If you want to analyze the static memory consumption of your code you can use [otm](https://github.com/LudwigOrtmann/otm) or `make cosy`. - -### Static memory -* Access the memory in one operation O(1) ⇒ real time condition -* Programmer needs to know the amount of memory on compile time - * Leads to over and undersized buffers -* Forces the programmer to think about the amount of need memory at compile time - -### Dynamic memory -* `malloc()` and `free()` are implemented in your `libc` (RIOT on ARM: `newlib`/`picolib`) - * Runtime behavior is not predictable -* Code can request the amount of memory it needs on runtime -* On most platforms: the size of the heap is `sizeof()-sizeof()` - * If you reduce your usage of static memory your heap gets bigger -* On some platforms calling `free()` will not or not always make heap memory available again (see @ref oneway_malloc on MSP430) -* Programmer needs to handle failed memory allocation calls at runtime -* Static code analysis is unable to find errors regarding memory management +@deprecated Guides have moved to the [Guide Site](https://guide.riot-os.org/misc/dev_best_practices/). +This page will be removed after release 2026.04. diff --git a/doc/doxygen/src/driver-guide.md b/doc/doxygen/src/driver-guide.md index d4510c0c13..d0af6892fa 100644 --- a/doc/doxygen/src/driver-guide.md +++ b/doc/doxygen/src/driver-guide.md @@ -1,501 +1,5 @@ -Writing a Device Driver in RIOT {#driver-guide} +Writing a Device Driver in RIOT (Deprecated) {#driver-guide} =============================== -This document describes the requirement, design objectives, and some -non-function details when writing device drivers in/for RIOT. The term device -driver in this context includes all 'CPU-external' devices connected to the CPU -typically via peripherals like SPI, I2C, UART, GPIO, and similar. CPU -peripherals itself are in RIOT not considered to be device drivers, but -peripheral or low-level drivers. Typical devices are network devices like -radios, Ethernet adapters, sensors, and actuators. - -[TOC] - -# General Design Objectives {#driver-guide-design-objectives} - -Device drivers should be as easy to use as possible. This implies an -'initialize->ready' paradigm, meaning, that device drivers should be ready to use -and in operation right after they have been initialized. On top, devices should -work with physical values wherever possible. So e.g. sensors should return -already converted values in some physical unit instead of RAW data, so that -users can work directly with data from different devices directly without having -to care about device specific conversion. - -However, please avoid the use of `float` or `double`. Instead, multiply to the -next SI (or appropriate) unit. E.g. if an ADC would return values like `1.23 V`, -chose to return `1230 mV` instead. - -Additionally, towards ease of use, all device drivers in RIOT should provide a -similar 'look and feel'. They should behave similarly in terms of their state -after initialization, like their used data representation and so on. - -Secondly, all device drivers should be optimized for minimal RAM/ROM usage, as -RIOT targets (very) constrained devices. This implies that instead of exposing -all thinkable functionality, the drivers should focus on exporting and -implementing a device's core functionality, thus covering ~95% of the use cases. - -Third, it should always be possible to handle more than a single device of the -same kind. Drivers and their interfaces are thus designed to keep their state -information in a parameterized location instead of driver defined global -variables. - -Fourth, RIOT defines high-level interfaces for certain groups of devices (i.e. -netdev for network devices, SAUL for sensors and actuators), which enable users -to work with a wide variety of devices without having to know much about the -actual device that is mapped. - -Fifth, during initialization, we make sure that we can communicate with a device. -Other functions should check the dev pointer is not void, and should also handle -error return values from the lower layer peripheral driver implementations, -where there are some. - -Sixth, device drivers SHOULD be implemented independent of any CPU/board code. -To achieve this, the driver implementations should strictly be based on -platform independent interfaces as the peripheral drivers, xtimer, etc. - -# General {#driver-guide-general} - -## Documentation {#driver-guide-doc} - -Document what your driver does! Most devices come with a very large number of -features, while the corresponding device driver only supports a subset of them. -This should be clearly stated in the device driver's documentation so that -anyone wanting to use the driver can find out the supported features without -having to scan through the code. - -## Device descriptor and parameter configuration {#driver-guide-types} - -Each device MUST supply a data structure, holding the devices state and -configuration, using the naming scheme of `DEVNAME_t` (e.g. `dht_t`, or -`at86rf2xx_t`). In the context of RIOT, we call this data structure the device -descriptor. - -This device descriptor MUST contain all the state data of a device. By this, we -are not limited to the number of instances of the driver we can run -concurrently. The descriptor is hereby used for identifying the device we want -to interact with, and SHOULD always be the first parameter for all device driver -related functions. - -Typical things found in these descriptors are e.g. used peripherals (e.g. SPI or -I2C bus used, interfacing GPIO pins), data buffers (e.g. RX/TX buffers where -needed), or state machine information. - -On top of the device descriptor, each device driver MUST also define a data -structure holding the needed configuration data. The naming scheme for this type -is `DEVNAME_params_t`. In contrary to the device descriptor, this data structure -should only contain static information, that is needed for the device -initialization as it is preferably allocated in ROM. - -A simple I2C temperature sensors' device descriptor could look like this: - -@code{.c} -typedef struct { - tmpabc_params_t p; /**< device configuration parameter like I2C bus and bus addr */ - int scale; /**< some custom scaling factor for converting the results */ -} tmpabc_t; - -/* with params being */ -typedef struct { - i2c_t bus; /**< I2C bus the device is connected to */ - uint8_t addr; /**< the device's address on the bus */ -} tmpabc_params_t; -@endcode - -**NOTE:** In many cases it makes sense, to copy the `xxx_params` data into the -device descriptor during initialization. In some cases, it is, however, better -to just link the `params` data via pointer and only copy selected data. This way, -configuration data that is only used once can be read directly from ROM, while -often used fields (e.g. used peripherals) are stored directly in the device -descriptor and one saves hereby one de-referencing step when accessing them. - -## Default device configuration {#driver-guide-config} - -Each device driver in RIOT MUST supply a default configuration file, named -`DEVNAME_params.h`. This file should be located in the `RIOT/drivers/...`. The -idea is that this file can be overridden by an application or a board, by -simply putting a file with the same name in the application's or the board's -include folders, while RIOT's build system takes care of preferring those files -instead of the default params file. - -A default parameter header file for the example temperature sensor above would -look like this (`tmpabc_params.h`): - -@code{.c} -/* ... */ - -#include "board.h" /* THIS INCLUDE IS MANDATORY */ -#include "tmpabc.h" - -/* ... */ - -/** - * @brief Default configuration parameters for TMPABC sensors - * @{ - */ -#ifndef TMPABC_PARAM_I2C -#define TMPABC_PARAM_I2C (I2C_DEV(0)) -#endif -#ifndef TMPABC_PARAM_ADDR -#define TMPABC_PARAM_ADDR (0xab) -#endif - -#ifndef TMPABC_PARAMS -#define TMPABC_PARAMS { .i2c = TMPABC_PARAM_I2C \ - .addr = TMPABC_PARAM_ADDR } -#endif -/** @} */ - -/** - * @brief Allocation of TMPABC configuration - */ -static const tmpabc_params_t tmpabc_params[] = { - TMPABC_PARAMS -} -/* ... */ -@endcode - -Now to influence the default configuration parameters, we have these options: - -First, we can override one or more of the parameter from the makesystem, e.g. - -@code{.sh} -CFLAGS="-DTMPABC_PARAM_ADDR=0x23" make all -@endcode - -Second, we can override selected parameters from the board configuration -(`board.h`): - -@code -/* ... */ -/** - * @brief TMPABC sensor configuration - * @{ - */ -#define TMPABC_PARAM_I2C (I2C_DEV(1)) -#define TMPABC_PARAM_ADDR (0x17) -/** @} */ -/* ... */ -@endcode - -Third, we can define more than a single device in the board configuration -(`board.h`): - -@code{.c} -/* ... */ -/** - * @brief Configure the on-board temperature sensors - * @{ - */ -#define TMPABC_PARAMS { \ - .i2c = I2C_DEV(1), \ - .addr = 0x31 \ - }, \ - { \ - .i2c = I2C_DEV(1), \ - .addr = 0x21 \ - } -/** @} */ -/* ... */ -@endcode - -And finally, we can simply override the `tmpabc_params.h` file as described -above. - -## Compile-time configuration documentation {#driver-guide-doxygen} - -The macros that configure the driver during compilation is added to the listing -for [Compile time configurations](@ref config). Refer to the following example -that exposes -[TMP00x sensor](https://github.com/RIOT-OS/RIOT/blob/master/drivers/include/tmp00x.h#L96-L157) -to [sensors group](@ref config_drivers_sensors). - -@code -/** - * @defgroup drivers_tmp00x_config TMP006/TMP007 Infrared Thermopile - * Sensor driver compile configuration - * @ingroup config_drivers_sensors - * @{ - */ -/** - * @brief Default Address - * .... - */ -#ifndef TMP00X_I2C_ADDRESS -#define TMP00X_I2C_ADDRESS (0x40) -#endif -.... -/** @} */ -@endcode - -Sub-groups defined for different types of drivers can be found in -[drivers/doc.txt](https://github.com/RIOT-OS/RIOT/blob/master/drivers/doc.txt) - -## Initialization {#driver-guide-initialization} - -In general, the initialization functions should do the following: - -- initialize the device descriptor -- initialize non-shared peripherals they use, e.g. GPIO pins -- test for device connectivity, e.g. does an SPI/I2C slave react -- reset the device to a well-defined state, e.g. use external reset lines or do - a software rest -- do the actual device initialization - -For testing a device's connectivity, it is recommended to read certain -configuration data with a defined value from the device. Some devices offer -`WHO_AM_I` or `DEVICE_ID` registers for this purpose. Writing and reading back -some data to the device is another valid option for testing its responsiveness. - -For more detailed information on how the signature of the init functions should -look like, please refer below to the specific requirements for network devices -and sensors. - -## Return Values {#driver-guide-return-values} - -As stated above, we check communication of a device during initialization and -handle error return values from the lower layers, where they exist. To prevent -subsequent misuse by passing NULL pointers and similar to the subsequent -functions, the recommended way is to check the parameter using `assert`, e.g.: - -@code{.c} -int16_t tmpabc_read(const tmpabc_t *dev) -{ - assert(dev); - /* ... */ - return value; -} -@endcode - -Whenever you implement status/error return values in your driver, magic numbers -MUST ***NOT*** be used. Instead, use negative `errno` codes (such as `-EIO` for -an input/output error) and *document* every single error code that can be -return for each function using the `reval` Doxygen command. E.g. like this: - -@code -/** - * @brief Initialize the foo device and its descriptor - * @param[out] dev Device descriptor to initialized - * @param[in] params Device initialization parameters - * - * @retval 0 Success - * @retval -ENXIO No foo device connected to the I2C bus - * @retval -ENODEV Device using the foo I2C address is not a foo device - * etc. - */ -int foo_init(foo_t *dev, const foo_params_t *params); -@endcode - -You can multiplex this information whenever this is reasonable, as long as a -negative return value indicates an error without exceptions. E.g. like this: - -@code -/** - * @brief Perform a relative humidity measurement - * @param[in] dev Humidity sensor to perform the measurement on - * - * @return The relative humidity in percent - * @retval -EIO Communication with the sensor failed - */ -int foo_humidity(const foo_t *dev); -@endcode - -### Documenting Return Values {#driver-guide-return-values-doc} - -With the exception of functions returning `void`, all return values have to be -documented. Use the `return` Doxygen command to describe what is returned. In -order to document special return value (such as error codes), use the `retval` -command. The `retval` command expects the specific value to document as first -argument (no spaces in the value allowed!), and a description (spaces allowed -here) as second. It is safe to use both `return` and `retval` commands, or just -one of them - whatever makes most sense for a given function. - -## General Device Driver Checklist {#driver-guide-general-checklist} - -- *MUST*: the supported feature set and any custom behavior is clearly - documented -- *MUST*: device descriptor is defined: `devab_t` -- *MUST*: device parameter `struct` is defined: `devab_params_t` -- *MUST*: a default parameter configuration file is present, e.g. - `RIOT/drivers/devab/include/devab_params.h` -- *MUST*: all error and status return codes are named, e.g. - `DEVAB_OK, DEVAB_NOSPI, DEVAB_OVERFLOW, ...` -- *MUST*: use `const devab_t *dev` when the device descriptor can be access - read-only - -## Build system integration - -### Internal include files - -If the driver contains internal include files, a `Makefile.include` must be -added in the driver implementation directory, with the following content -(adapted to the name of the driver module): - -``` -USEMODULE_INCLUDES_ := $(LAST_MAKEFILEDIR)/include -USEMODULE_INCLUDES += $(USEMODULE_INCLUDES_) -``` - -### External dependencies - -If the driver has other module or CPU features dependencies (like `xtimer` or -`periph_i2c`), they must be added in the `$(RIOTBASE)/drivers/Makefile.dep` -file in a block like below (this is an example, you'll have to adapt to the -driver requirements): - -``` -ifneq (,$(filter ,$(USEMODULE))) - FEATURES_REQUIRED += periph_i2c - USEMODULE += xtimer -endif -``` - -**Warning:** Please be careful with alphabetical order when modifying this file. - -## Helper tools - -To help you start writing a device driver, the RIOT build system provides the -`generate-driver` make target. It is a wrapper around the -[riotgen](https://pypi.org/project/riotgen/) command line tool that is helpful -when starting to implement a driver: all minimum files are generated with -copyright headers, doxygen groups, etc, so you can concentrate on the driver -implementation. - -**Usage:** - -From the RIOT base directory, run: -``` -make generate-driver -``` -Then answer a few questions about the driver: -- Driver name: enter a name for your driver. It will be used as both the name - of the driver directory where the source files are created and the build - system module. -- Driver doxygen group name: Enter the name of the driver, as displayed in the - Doxygen documentation. -- Brief doxygen description: Describe in one line what is this driver about. -- Parent driver Doxygen group: Enter the Doxygen group the driver belongs to. - It can be `actuators`, `display`, `misc`, `netdev`, `sensors`, `storage`. - -Other global information (author name, email, organization) should be retrieved -automatically from your git configuration. - -# Sensors {#driver-guide-sensors} - -## SAUL {#driver-guide-saul} - -All sensor drivers SHOULD implement the SAUL interface. It is however -recommended, that the drivers are written in a way, that the drivers do not -solely export the SAUL interface, but map the SAUL interface upon a driver -specific one. - -For example, a temperature driver provides the following function (`tmpabc.c`): - -@code{.c} -int16_t tmpabc_read(tmpabc_t *dev); -@endcode - -which then can easily be mapped to SAUL (`tmpabc_saul.c`): - -@code{.c} -int saul_read(saul_t *dev, phydat_t *data) -{ - memset(data, 0, sizeof(phydat_t)); - data->x = tmpabc_read((tmpabc_t *)dev); - data->unit = UNIT_TEMP_C; - data->scale = -2; - return 1; -} -@endcode - -This ensures the versatility of the device driver, having in mind that one might -want to use the driver without SAUL or maybe in a context without RIOT. - -## Initialization {#driver-guide-sensor-initialization} - -Sensor device drivers are expected to implement a single initialization -function, `DEVNAME_init`, taking the device descriptor and the device's -parameter struct as argument: - -@code{.c} -int tmpabc_init(tmpabc_t *dev, const tmpabc_params_t *params); -@endcode - -After this function is called, the device MUST be running and usable. - -## Value handling {#driver-guide-sensor-value-handling} - -### Value semantics {#driver-guide-sensor-value-semantics} - -All sensors in RIOT MUST return their reading results as real physical values. -When working with sensor data, these are the values of interest, and the -overhead of the conversion is normally neglectable. - -### Typing {#driver-guide-sensor-types} - -All values SHOULD be returned using integer types, with `int16_t` being the -preferred type where applicable. - -In many situations, the physical values cannot be mapped directly to integer -values. For example, we do not want to map temperature values to integers -directly while using their fraction. The recommended way to solve this is by -scaling the result value using decimal fixed point arithmetic, in other words, -just return centi-degree instead of degree (e.g. 2372c°C instead of 23.72°C). - -## Additional Sensor Driver Checklist {#driver-guide-sensor-checklist} - -- *MUST*: mandatory device parameters are configurable through this file, e.g. - sampling rate, resolution, sensitivity -- *MUST*: an init function in the style of - `int devab_init(devab_t *dev, const devab_params_t *params);` exists -- *MUST*: after initialization, the device must be operational -- *MUST*: all error and return values are named, e.g. - `DEVAB_OK, DEVAB_NODEV, ...` -- *MUST*: all 'read' functions return values in their physical representation, - e.g. `centi-degree, Pa, lux, mili-G` -- *MUST*: all 'read' functions return integer values, preferably `int16_t` -- *SHOULD*: if multiple dimensions are read, they SHOULD be combined into a - data structure -- *SHOULD*: the driver implements the SAUL interface -- *SHOULD*: the driver exports functions for putting it to sleep and waking up - the device - -# Network devices {#driver-guide-netdev} - -## Initialization {#driver-guide-netdev-init} - -The initialization process MUST be split into 2 steps: first, initialize the -device descriptor and if applicable the used peripherals, and secondly do the -actual device initialization. The reason for this is, that before a device is -actually activated and can start to process data, the network stack for the -device needs to be initialized. By supplying a second init function, that does -the actual initialization, we can hand the control over when this is done to the -actual network stacks. - -The initialization functions SHOULD follow this naming scheme: - -@code{.c} -void netabc_setup(netabc_t *dev, const netabc_params_t *params); -int netabs_init(netabc_t *dev); -@endcode - -## netdev {#driver-guide-netdev-interface} - -Device driver for network device SHOULD implement the `netdev` interface. It is -up to the implementer, if the device driver also offers a device specific -interface which is then mapped to the `netdev` interface, or if the device -driver can be purely interfaced using `netdev`. While the second option is -recommended for efficiency reasons, this is not mandatory. - -## Additional Network Device Driver Checklist {#driver-guide-netdev-checklist} - -- *MUST*: a setup function in the style of - `int devab_setup(devab_t *dev, const devab_params_t *params);` exists -- *MUST*: an init function in the style of `int devnet_init(devnet_t *dev)` - exists -- *SHOULD*: the driver implements 'netdev' [if applicable] - -# TODO {#driver-guide-todo} - -Add some information about how to handle multiple threads, when to use mutexes, -and how to deal with interrupts? And especially patterns for being nice from -other threads and power consumption point of view... +@deprecated Guides have moved to the [Guide Site](https://guide.riot-os.org/advanced_tutorials/device_drivers/). +This page will be removed after release 2026.04. diff --git a/doc/doxygen/src/emulators.md b/doc/doxygen/src/emulators.md index 734cc610c0..85445effc3 100644 --- a/doc/doxygen/src/emulators.md +++ b/doc/doxygen/src/emulators.md @@ -1,151 +1,5 @@ -Emulators {#emulators} +Emulators (Deprecated) {#emulators} ========= -RIOT supports the [Qemu](https://www.qemu.org/) and [Renode](https://renode.io/) -emulation tools. The emulation offers a hardware-free development environment -for quickly testing applications. - -From the build system point of view, the emulation support in RIOT is -transparent compared to the usual workflow: simply add `EMULATE=1` to the -command line and the emulator supported by the board will be called instead of -the board flashing/debugging tool. -Targets compatible with `EMULATE=1` are `term`, `cleanterm`, `debug`, -`debugserver` and `test`. - -If a board supports multiple emulators, the emulator backend can be selected -with the `RIOT_EMULATOR` variable. Possible values are `qemu` and `renode`. -If no emulator is specified by the board configuration (e.g. in its -`Makefile.include`), the default emulator is `renode`. - -The boards with emulator supported can be listed using the -`info-emulated-boards` target: - -``` -$ make info-emulated-boards -``` - -## Features - -Be aware that not all hardware features provided by a board - and described as -such in the build system by `FEATURES_PROVIDED` - are implemented in emulators. -For example, the `hifive1b` provides the RTC peripheral feature but this is not -implemented by the renode driver. -So you may expect some failures when running advanced applications on the -emulator. - -## Usage - -All emulators can be used the same way. Just add `EMULATE=1` to the command -line. - -To start an emulator and connect to the serial port of the emulated board, run: - -``` -$ EMULATE=1 make BOARD= -C all term -``` - -To start an emulator with a GDB server and connect a GDB client to it, run: - -``` -$ EMULATE=1 make BOARD= -C all debug -``` - -To start an automatic test script with the emulated board, run: - -``` -$ EMULATE=1 make BOARD= -C all test -``` - -The `EMULATOR_SERIAL_PORT` variable can be used to specify a custom serial port -on the host running the emulator. -The default value is built based on a random temporary directory: -`$(EMULATOR_TMP_DIR)/uart`. -The randomness of this variable allows several emulated sessions of the same -application with the same board to run in parallel. - -# Qemu - -## Overview - -[Qemu](https://www.qemu.org/) is a machine emulator and virtualizer. It can -be used to emulate regular computer architectures but also some microcontroller -based boards such as the @ref boards_microbit. - -## Installation - -Qemu is usually available via the package manager of common Linux distributions. -Depending on your local system, the installation procedure is described on the -[qemu website](https://www.qemu.org/download/). - -## Boards supported - -So far, in RIOT, only the @ref boards_microbit board is supported with qemu. - -## Configuration - -The QEMU emulated serial port is exposed on a local Unix socket, redirected to a -local PTY file (using [socat](http://www.dest-unreach.org/socat/)). This makes -it possible to open the PTY file in a regular serial port. - -# Renode - -## Overview - -[Renode](http://renode.io) is a virtual development tool for multinode embedded -networks (both wired and wireless) enabling a scalable workflow for building -effective, tested and secure IoT systems, created by -Antmicro](http://antmicro.com/blog/2017/08/renode-press-release/). -It can easily be used to run applications on a broad range of embedded platforms -without any changes in the code itself, as if you were running on real -hardware - but with more possibilities. - -## Installation - -### From package - -Packages for macOS, deb-based and rpm-based systems, for Windows and for Arch -Linux are available on [GitHub](https://github.com/renode/renode/releases/latest). - -### From source - -Follow the installation instructions on Renode's -[GitHub](https://github.com/renode/renode#installation) page. - -If you choose to build renode from source, after the compilation is successful, -ensure that `renode` is available on your `PATH`. -One way to do so, is via symlink: - -``` -sudo ln -s path/to/renode/repository/renode /usr/local/bin/renode -``` - -### Testing - -After installation, verify that Renode is working using `renode --help`. You -should be presented with a help screen. - -## Documentation - -Documentation for Renode can be found on [Read The Docs](https://renode.readthedocs.io). - -## Usage - -From within RIOT-OS, add `EMULATE=1` to start the emulation. The emulation -expects a board definition file in `boards//dist/board.resc`. - -The board definition file will tell Renode how to setup an emulation session. -The application binary file (`*.elf`) is available using the variable -`$image_file`. - -For an example, refer to `boards/cc2538dk/dist/board.resc`. - -The renode logging level can be configured from the command line using the -following variables: -- `RENODE_SHOW_LOG`: set it to 1 to show the logs in the standard output -- `RENODE_LOG_LEVEL`: set it to the desired log level, default is 2 (warning) - -The renode monitor and serial console GUI windows are hidden by default but -they can be displayed by setting `RENODE_SHOW_GUI` to 1 in the command line. - -If uart0 is not the default serial port used for stdio, use `RENODE_SYSBUS_UART` -to specify a custom one in the board `Makefile.include`. +@deprecated Guides have moved to the [Guide Site](https://guide.riot-os.org/misc/emulators/). +This page will be removed after release 2026.04. diff --git a/doc/doxygen/src/flashing.md b/doc/doxygen/src/flashing.md index 32a402c2a5..84a4a3782d 100644 --- a/doc/doxygen/src/flashing.md +++ b/doc/doxygen/src/flashing.md @@ -1,523 +1,5 @@ -Flashing via RIOT's Build System {#flashing} +Flashing via RIOT's Build System (Deprecated) {#flashing} ================================ -[TOC] - -General Approach {#flashing-general} -================ - -In general, flashing a board from RIOT is as straight forward as typing in a -shell (with the application directory as current working directory): - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -make BOARD= flash -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -This will **rebuild** ***AND*** **flash** the application in the current working -directory for board ``, using its default programming tool. If -you want to use an alternative programming tool, say `stm32flash`, use: - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -make BOARD= PROGRAMMER=stm32flash flash -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -To flash without rebuilding use `flash-only` as target instead of `flash`. - - -Supported Tools {#flashing-supported-tools} -=============== - -RIOT supports plenty of flashing tools, that are below grouped into general -flashing tools that support multiple MCU families, and specialized tools that -only support one platform. - -Note that some programmers require additional configuration on a per board -level or rely on features only available on some boards. Hence, a given board -may not be supported by a programmer listed as supported for the platform of -the board due to a missing board feature, bootloader, or similar. - -To ease use the programmers are given by the value to pass via -`PROGRAMMER=`, rather than the official spelling of the programmer. - -Compatibility Matrix of Generic Tools {#flashing-supported-tools-generic} --------------------- - - - - -MCU Family | `bmp` | `dfu-util` | `jlink` | `openocd` | `pyocd` | `uf2conv` ----------------|--------|------------|---------|-----------|---------|---------- -ATmega | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ -ATXmega | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ -CC13xx / C26xx | ✗ | ✗ | ✓ | ✓ (1) | ✗ | ✗ -CC2538 | ✗ | ✗ | ✓ | ✗ | ✗ | ✗ -EFM32 | ✗ | ✗ | ✓ | ✓ | ✗ | ✗ -ESP8266 | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ -ESP32 (Xtensa) | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ -ESP32 (RISC-V) | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ -FE310 | ✗ | ✗ | ✓ | ✓ | ✗ | ✗ -GD32V | ✗ | ✗ | ✗ | ✓ (1) | ✗ | ✗ -Kinetis | ✗ | ✗ | ✓ | ✓ | ✗ | ✗ -LPC1768 | ✗ | ✗ | ✓ | ✓ | ✗ | ✗ -LPC23xx | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ -MIPS32r2 | ✗ | ✗ | ✓ | ✗ | ✗ | ✗ -MSP430 | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ -nRF51 | ✗ | ✗ | ✓ | ✓ | ✓ | ✗ -nRF52 | ✓ | ✗ | ✓ | ✓ | ✓ | ✓ -RP2040 | ✗ | ✗ | ✓ | ✓ | ✗ | ✗ -SAM | ✗ | ✗ | ✓ | ✓ | ✗ | ✗ -Stellaris | ✗ | ✗ | ✓ | ✓ | ✗ | ✗ -STM32 | ✓ | ✓ | ✓ | ✓ | ✗ | ✗ - -Remarks: - -1. Requires a patched version of the programmer tool - -Specialized Flashing Tools Per Platform {#flashing-supported-tools-special} ---------------------------------------- - -The following list only contains single-platform flashing tools. Tools that -support multiple platforms are given in section -\ref flashing-supported-tools-generic above. - -### AVR - -- `avrdude` - -### CC13xx / CC26xx - -- `uniflash` - -### CC2538 - -- `cc2538-bsl` - -### ESP8266 / ESP32 (Xtensa) / ESP32 (RISC-V) - -- `esptool` - -### LPC23xx - -- `lpc2k_pgm` - -### MSP430 - -- `mspdebug` -- `goodfet` - -### nRF52 - -- `adafruit-nrfutil`, `uf2conv` (requires Adafruit bootloader), see @ref boards_common_adafruit-nrf52-bootloader -- `nrfutil` (required nRF bootloader) -- `nrfjprog` (requires a separate J-Link debugger) - -### RP2040 - -- `picotool` - -### SAM - -- `bossa` -- `edbg` - -### STM32 - -- `stm32flash` -- `stm32loader` -- `cpy2remed` (requires integrated ST-Link programmer, e.g. Nucleo boards) -- `robotis-loader` (requires robotis bootloader, only one board supported) - - -Programmer Configuration {#flashing-configuration} -======================== - -This section will list additional configuration options to control the behavior -of a programming tool, such as selecting the hardware adapter used for -programming. - -OpenOCD Configuration {#flashing-configuration-openocd} ---------------------- - -### OPENOCD_DEBUG_ADAPTER - -`OPENOCD_DEBUG_ADAPTER` can be set via command line or as environment variable -to use non-default flashing hardware. - -### OPENOCD_RESET_USE_CONNECT_ASSERT_SRST - -`OPENOCD_RESET_USE_CONNECT_ASSERT_SRST` can be set via command line or as -environment variable to `0` to disable resetting the board via the `SRST` line. -This is useful when the `SRST` signal is not connected to the debug adapter or -when using cheap ST-Link V2 clones with broken `SRST` output. Note that it may -not be possible to attach the debugger while the MCU is in deep sleeping mode. -If this is set to `0` by the user, the user may need a carefully timed reset -button press to be able to flash the board. - -### OPENOCD_PRE_FLASH_CMDS - -`OPENOCD_PRE_FLASH_CMDS` can be set as environment variable to pass additional -commands to OpenOCD prior to flashing, e.g. to disable flash write protection. - -### OPENOCD_PRE_VERIFY_CMDS - -`OPENOCD_PRE_VERIFY_CMDS` can be set as environment variable to pass additional -flags to OpenOCD prior to verifying the flashed firmware. E.g. this is used -in the `pba-d-01-kw2x` to disable the watchdog to prevent it from disrupting -the verification process. - -### OPENOCD_PRE_FLASH_CHECK_SCRIPT - -`OPENOCD_PRE_FLASH_CHECK_SCRIPT` can be set via command line or as -environment variable to execute a script before OpenOCD starts flashing. It is -used for Kinetis boards to prevent bricking a board by locking the flash via -magic value in the flash configuration field protection bits. - -The script is expected to exit with code `0` if flashing should resume, or with -exit code `1` if flashing should be aborted. - -### OPENOCD_CONFIG - -`OPENOCD_DEBUG_ADAPTER` can be set via command line or as environment variable -to use non-default OpenOCD configuration file. - -### OPENOCD_TRANSPORT - -`OPENOCD_TRANSPORT` can be set via command line or as environment variable to -select a non-default transport protocol. E.g. to use JTAG rather than SWD for a -board that defaults to SWD use: - -``` -make PROGRAMMER=openocd OPENOCD_TRANSPORT=jtag -``` - -Note that OpenOCD configuration file of a given board may only support SWD or -JTAG. Also JTAG requires more signal lines to be connected compared to SWD and -some internal programmers only have the SWD signal lines connected, so that -JTAG will not be possible. - -stm32flash Configuration {#flashing-configuration-stm32flash} ------------------------- - -It is possible to automatically boot the STM32 board into the in-ROM bootloader -that `stm32flash` communicates with for flashing by connecting the RST pin to -DTR and the BOOT pin (or BOOT0 for STM32 MCU families with BOOT0 and BOOT1 pins) -to RTS of the TTL adapter. In addition, set `STM32FLASH_RESET` to `1` via -environment or command line to actually issue a reset with BOOT (or BOOT0) -pulled high prior flashing to enter the bootloader, and a second reset with BOOT -(or BOOT0) pulled low to reboot into the application. `STM32FLASH_RESET` -defaults to `0` as of know, as with `PROGRAMMER=stm32flash STM32FLASH_RESET=1` -additional terminal flags are set, so that `make term` doesn't accidentally -keeps the reset signal pulled low or boot the board into the bootloader. - -The TTL adapter this was tested with had inverted RTS and DTR signal. By setting -`STM32FLASH_RESET_INVERT` to `1` RIOT will assume RTS and DTR signals to be -inverted, by setting it to `0` non-inverted signals will be generated. As of -now, `STM32FLASH_RESET_INVERT` is by default `1`. This may change if it -becomes evident that non-inverted TTL adapters are in fact more common than -inverted adapters. - -MSPDEBUG Configuration {#flashing-configuration-mspdebug} ----------------------- - -All options can be passed as environment variables or as make arguments. -All options except for `DEBUGSERVER_PORT` apply to both debugging and flashing -alike. - -`MSPDEBUG_PROGRAMMER` is used to set the hardware programmer/debugger to use -for programming and debugging. See `mspdebug --help` or `man mspdebug` for a -list of programmers. - -`MSPDEBUG_PROTOCOL` is used to specify the debugger protocol. It is typically -set by the board used. Only JTAG and Spi-Bi-Wire are supported. - -`MSPDEBUG_TTY` is used to connect via TTY interface instead of directly via -USB to the debugger. Usually, this is not required. - -`DEBUG_ADAPTER_ID` is used to select the debugger/programmer by its serial. If -not set, `mspdebug` will select the first device with matching vendor and -product ID. Unless multiple debuggers of the same type are connected, this -options is typically not needed. - -`DEBUGSERVER_PORT` is used to specify the TCP port to listen for GDB to -connect to. It defaults to 2000. - -Handling Multiple Boards With UDEV-Rules {#multiple-boards-udev} -======================================== - -When developing and working with multiple boards the default `PORT` -configuration for a particular board might not apply anymore so `PORT` will need -to be specified whenever calling `make term/test`. This can also happen if -multiple `DEBUGGERS/PROGRAMMERS` are present so `DEBUG_ADAPTER_ID` will also -need to be passed. Keeping track of this will become annoying. - -One way of handling this is to use `udev` rules to define `SYMLINKS` between the -boards serial port (`riot/tty-`) and the actual serial port -(dev/ttyACM* or other). With this we can query the rest of the boards serial -`dev` information (`DEBUG_ADAPTER_ID`, `PORT`, etc.) to always flash and open a -terminal on the correct port. - -Procedure: - -- use `udevadm info /dev/ttyACM0` to query the udev database for information on - device on port `/dev/ttyACM0`. - - or use `udevadm info --attribute-walk --name /dev/ttyACM0` for more detailed - output when the first level of information isn't enough - -- create a udev rule with information of the device and one parent to create a - matching rule in `/etc/udev/rules.d/70-riotboards.rules`. - -~~~~~~~~~~~~~~~~~~~ - # samr21-xpro - SUBSYSTEM=="tty", SUBSYSTEMS=="usb", ATTRS{idVendor}=="03eb", \ - ATTRS{idProduct}=="2111", ATTRS{manufacturer}=="Atmel Corp.", \ - ATTRS{serial}=="ATML2127031800004957", SYMLINK+="riot/tty-samr21-xpro" -~~~~~~~~~~~~~~~~~~~ - -- reload rules: `udevadm control --reload-rules` - -- Boards `PORT` are symlinked to /dev/riot/tty-`board-name`. - -- Create a `makefile.pre` that will query the real `PORT` and the - `DEBUG_ADAPTER_ID` from the `SYMLINK` info - -~~~~~~~~~~~~~~~~~~~ - PORT = /dev/riot/tty-$(BOARD) - DEBUG_ADAPTER_ID = $(\ - shell udevadm info -q property $(PORT) |\ - sed -n ’/ID_SERIAL_SHORT/ {s/ID_SERIAL_SHORT=//p}’) -~~~~~~~~~~~~~~~~~~~ - -- You can now add `makefile.pre` to `RIOT_MAKEFILES_GLOBAL_PRE` as an environment - variable or on each `make` call: - -~~~~~~~~~~~~~~~~~~~ - $ RIOT_MAKEFILES_GLOBAL_PRE=/path/to/makefile.pre make -C examples/basic/hello-world flash term -~~~~~~~~~~~~~~~~~~~ - -@note if set as an environment variable it would be a good idea to add a - variable to enable/disable it, e.g: - -~~~~~~~~~~~~~~~~~~~ -ifeq (1,$(ENABLE_LOCAL_BOARDS)) - PORT = /dev/riot/tty-$(BOARD) - DEBUG_ADAPTER_ID = $(\ - shell udevadm info -q property $(PORT) |\ - sed -n ’/ID_SERIAL_SHORT/ {s/ID_SERIAL_SHORT=//p}’) -endif -~~~~~~~~~~~~~~~~~~~ - -Handling Multiple Versions of the Same BOARD --------------------------------------------- - -The above procedure works fine when handling different boards, but not -multiple times the same board, e.g: multiple `samr21-xpro`. - -An option for this would be to add an identifier of that board to the mapped -`riot/tty-*`, there are multiple ways of handling this but in the end it means -having a way to identify every copy. - -Another way would be to map the `DEBUG_ADAPTER_ID` in the name: - -~~~~~~~~~~~~~~~~~~~ -SYMLINK+="riot/node-$attr{serial} -~~~~~~~~~~~~~~~~~~~ - -But it will require to know in advance the serial number of each board you want -to use. Another option would be to add some kind of numbering and defining -multiple symlinks for each board. e.g. for `samr21-xpro` number `n`: - -~~~~~~~~~~~~~~~~~~~ - # samr21-xpro - SUBSYSTEM=="tty", SUBSYSTEMS=="usb", ATTRS{idVendor}=="03eb", \ - ATTRS{idProduct}=="2111", ATTRS{manufacturer}=="Atmel Corp.", \ - ATTRS{serial}=="ATML2127031800004957", SYMLINK+="riot/tty-samr21-xpro", \ - SYMLINK+="riot/tty-samr21-xpro-n" -~~~~~~~~~~~~~~~~~~~ - -Then, when flashing, the number can be specified and the parsing adapted: - -~~~~~~~~~~~~~~~~~~~ - ifneq(,$(BOARD_NUM)) - PORT = /dev/riot/tty-$(BOARD)-$(BOARD_NUM) - else - PORT = /dev/riot/tty-$(BOARD) - endif - DEBUG_ADAPTER_ID = $(\ - shell udevadm info -q property $(PORT) |\ - sed -n ’/ID_SERIAL_SHORT/ {s/ID_SERIAL_SHORT=//p}’) -~~~~~~~~~~~~~~~~~~~ - -~~~~~~~~~~~~~~~~~~~ - BOARD=samr21-xpro BOARD_NUM=n make flash term -~~~~~~~~~~~~~~~~~~~ - -In the end, this would be the same as using the serial, but a simple number might -be easier to handle. - -Notes ------ -Udev only parses SUBSYSTEM and one parent. For others, we will rely on ENV -variables defined by 60-serial.rules - -So the current filename should be higher than 60-serial.rules - -If for some reason re-writing the serial is needed there is a windows tool: - https://remoteqth.com/wiki/index.php?page=How+to+set+usb+device+SerialNumber - - -Documentation: --------------- -* The whole documentation - http://reactivated.net/writing_udev_rules.html#udevinfo -* Udev manpage - http://manpages.ubuntu.com/manpages/eoan/en/man7/udev.7.html - -Handling Multiple Boards Without UDEV-Rules {#multiple-boards-no-udev} -=========================================== - -This is a simpler approach to the above mentioned issue. The solution here only -uses a makefile script for selecting the debugger and serial port. No -administrative privileges (e.g. to configure Udev) are required. - -One of the limitations of the solution described here is that it currently -doesn't work with multiple boards of the same type. This limitation is a -limitation of the script and not of the mechanism used, it is possible to adapt -the script to support multiple boards of the same type. This modification is -left as an exercise to the reader. - -The following Make snippet is used: - -~~~~~~~~~~~~~~~~~~~ - LOCAL_BOARD_MAP ?= 1 - - # Adapt this list to your board collection - SERIAL_nucleo-f103rb ?= 066BFF343633464257254156 - SERIAL_same54-xpro ?= ATML2748051800005053 - SERIAL_samr21-xpro ?= ATML2127031800008360 - SERIAL_nrf52dk ?= 000682223007 - - ifeq (1,$(LOCAL_BOARD_MAP)) - - # Retrieve the serial of the selected board - BOARD_SERIAL = $(SERIAL_$(BOARD)) - - # Check if there is a serial for the board - ifneq (,$(BOARD_SERIAL)) - - # Set the variables used by various debug tools to the selected serial - SERIAL ?= $(BOARD_SERIAL) - DEBUG_ADAPTER_ID ?= $(BOARD_SERIAL) - JLINK_SERIAL ?= $(BOARD_SERIAL) - - # Use the existing script to grab the matching /dev/ttyACM* device - PORT ?= $(shell $(RIOTTOOLS)/usb-serial/ttys.py --most-recent --format path --serial $(SERIAL)) - endif - endif -~~~~~~~~~~~~~~~~~~~ - -The array of board serial numbers has to be edited to match your local boards. -The serial numbers used here is the USB device serial number as reported by -the debugger hardware. With the `make list-ttys` it is reported as the 'serial': - -~~~~~~~~~~~~~~~~~~~ -$ make list-ttys -path | driver | vendor | model | model_db | serial | ctime --------------|---------|--------------------------|--------------------------------------|-----------------------|--------------------------|--------- -/dev/ttyUSB0 | cp210x | Silicon Labs | CP2102 USB to UART Bridge Controller | CP210x UART Bridge | 0001 | 15:58:13 -/dev/ttyACM1 | cdc_acm | STMicroelectronics | STM32 STLink | ST-LINK/V2.1 | 0671FF535155878281151932 | 15:58:04 -/dev/ttyACM3 | cdc_acm | Arduino (www.arduino.cc) | EOS High Power | Mega ADK R3 (CDC ACM) | 75230313733351110120 | 15:59:57 -/dev/ttyACM2 | cdc_acm | SEGGER | J-Link | J-Link | 000683475134 | 12:41:36 -~~~~~~~~~~~~~~~~~~~ - -When the above make snippet is included as `RIOT_MAKEFILES_GLOBAL_PRE`, the -serial number of the USB device is automatically set if the used board is -included in the script. This will then ensure that the board debugger is used -for flashing and the board serial device is used when starting the serial -console. - -It supports command line parameters to filter by vendor name, model name, serial -number, or driver. In addition, the `--most-recent` argument will only print the -most recently added interface (out of those matching the filtering by vendor, -model, etc.). The `--format path` argument will result in only the device path -being printed for convenient use in scripts. - -Handling Multiple Boards: Simplest Approach {#multiple-boards-simple} -=========================================== - -Passing `MOST_RECENT_PORT=1` as environment variable or as parameter to -make will result in the most recently connected board being preferred over the -default PORT for the selected board. - -For some boards `TTY_BOARD_FILTER` is provided, which filters TTYs e.g. by -vendor or model to only considered TTYs that actually may belong to the selected -board. E.g. for Nucleo boards this is `--model 'STM32 STLink'`, as they all use -an integrated STLink as programmer. As long as only one TTY is provided from an -STLink, this will reliably select the correct TTY for an Nucleo regardless of -which TTY was most recently connected. Some boards even provide info that -allows to always reliably identify them correctly (e.g. the firmware on the -ATmega16U2 used as USB to UART converted on Arduino Mega2560 will provide -identification data unique to that board). - -Adding Board Filters --------------------- - -After connecting as many variants of the board you target (and maybe some others -to test that the filter actually filters out non-matching boards). Then first -run `./dist/tools/usb-serial/ttys.py` without arguments and study the output. -When a genuine Arduino Mega 2560, a genuine Arduino Mega ADK (a variant of the -Mega 2560),a cheap Arduino Mega 2560 clone, a BBC micro:bit v2, and a -Nucleo F767-ZI are connected, the following output is shown: - -path | driver | vendor | model | model_db | serial | ctime | iface_num --------------|---------|--------------------------|--------------------------------------|------------------------------------------------------|--------------------------------------------------|----------|---------- -/dev/ttyACM0 | cdc_acm | Arduino (www.arduino.cc) | 0042 | Mega 2560 R3 (CDC ACM) | 857353134333519002C1 | 12:13:55 | 0 -/dev/ttyACM1 | cdc_acm | Arduino (www.arduino.cc) | EOS High Power | Mega ADK R3 (CDC ACM) | 75230313733351110120 | 15:59:57 | 0 -/dev/ttyACM2 | cdc_acm | STMicroelectronics | STM32 STLink | ST-LINK/V2.1 | 0670FF535155878281123912 | 10:00:39 | 2 -/dev/ttyACM3 | cdc_acm | Arm | BBC micro:bit CMSIS-DAP | ARM mbed | 99053602000528334c41b84da1f2f09d000000006e052820 | 12:21:03 | 1 -/dev/ttyUSB0 | cp210x | Silicon Labs | CP2102 USB to UART Bridge Controller | CP2102/CP2109 UART Bridge Controller [CP210x family] | 0001 | 16:57:27 | 0 - -Now we add arguments to the invocation of `ttys.py` to filter the list e.g. -by model, vendor etc. (note: as regex!) ideally until only the target boards -are listed. Some boards do not provide enough information to e.g. tell them -apart from other boards using the same USB to UART bridge or the same debugger. -In that case we have to live with some "bycatch". - -In the case of the Arduino Mega 2560 the parameters -`--vendor 'Arduino' --model-db 'Mega 2560|Mega ADK'` will narrow down the -list to only show the genuine Arduino Mega versions. Se we add to the -`Makefile.include` in `boards/arduino-mega2560`: - -```Makefile -TTY_BOARD_FILTER := --vendor 'Arduino' --model-db 'Mega 2560|Mega ADK' -``` - -Note that also matching the `R3` in `Mega 2560 R3` would prevent matching older -or newer revisions than R3, so we don't add that to the regex. - -Advances Board Filters ----------------------- - -In most cases, just adding a simple `TTY_BOARD_FILTER` is sufficient. If we -however have wildly different flavors of the same board (e.g. genuine Arduino -Mega 2560 with an ATmega16U2 and clones with a cheap USB to UART bridge) that we -all want to support, we have to instead provide a `TTY_SELECT_CMD` that prints -the path to and the serial of the TTY (separated by a space) and exists with -`0` if a TTY was found, or that exists with `1` and prints nothing when no TTY -was found. We can still use the `ttys.py` script to detect all Arduino Mega -2560 versions: We first try to detect a genuine Arduino Mega and fall back to -selecting cheap USB UART bridges when that fails using the `||` shell operator: - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - TTY_SELECT_CMD := $(RIOTTOOLS)/usb-serial/ttys.py \ - --most-recent \ - --format path serial \ - --vendor 'Arduino' \ - --model-db 'Mega 2560|Mega ADK' || \ - $(RIOTTOOLS)/usb-serial/ttys.py \ - --most-recent \ - --format path serial \ - --driver 'cp210x' -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +@deprecated Guides have moved to the [Guide Site](https://guide.riot-os.org/build-system/flashing/). +This page will be removed after release 2026.04. diff --git a/doc/doxygen/src/getting-started.md b/doc/doxygen/src/getting-started.md index eb1172e069..8af93f66fa 100644 --- a/doc/doxygen/src/getting-started.md +++ b/doc/doxygen/src/getting-started.md @@ -25,7 +25,8 @@ subset of modules). For instructions on how to configure via `CFLAGS` check the @ref config "identified compile-time configurations". To learn how to use -Kconfig in RIOT, please refer to the @ref kconfig-users-guide. +Kconfig in RIOT, please refer to the +[User's guide to configure with Kconfig](https://guide.riot-os.org/build-system/kconfig/#configure-using-menuconfig). Default configurations {#default-configurations} ---------------------- diff --git a/doc/doxygen/src/io-mapping-and-shields.md b/doc/doxygen/src/io-mapping-and-shields.md index f221fcb92c..28b1f88a23 100644 --- a/doc/doxygen/src/io-mapping-and-shields.md +++ b/doc/doxygen/src/io-mapping-and-shields.md @@ -1,166 +1,5 @@ -IO-Mapping and Shields {#iomaps} +IO-Mapping and Shields (Deprecated) {#iomaps} ====================== -[TOC] - -Introduction {#iomaps-intro} -============ - -Arduino has popularized the concept of adding an abstraction layer over the -MCU GPIOs and ADC multiplexer as "Digital Pins" and "Analog Pins". For historic -reasons as well as to express appreciation for the introduction of concept, we -prefix features and macros that map board pins to MCU pins with `ARDUINO`. - -@note This means, we also explicitly use the Arduino feature for boards that - are neither official Arduino products nor compatible. - -I/O Mappings {#iomaps-mapping} -============ - -All I/O mappings are provided by the `arduino_iomap.h` header file. This is -provided either by the board directly (e.g. in -`/board//include/arduino_iomap.h`) or by the board -family (e.g. in `board/common//include/arduino_iomap.h`). - -To add support to new boards, start by copy-pasting the `arduino_iomap.h` from -an existing board and adapt/extend the macros as needed. Finally, add the -features to the `Makefile.features` and `KConfig` files of the board that -indicate the presence of the added mappings. - -Digital Pins {#iomaps-mapping-gpio} ------------- - -The feature `arduino_pins` is provided by boards that do have a mapping to -digital pins. The GPIO for e.g. `D3` is provided as `ARDUINO_PIN_3`. The -number of the highest digital pin is provided as `ARDUINO_PIN_LAST`. E.g. if -`ARDUINO_PIN_LAST` is 42, digital pins `D0` to `D42` are typically provided. - -@warning Some boards do have "gaps" in the pin mapping. It could be that - e.g. `ARDUINO_PIN_5` is defined, but `ARDUINO_PIN_4` is not. - -@note Often aliases are provided for analog pins in digital mode. E.g. - to use the pin `A3` as digital pin, `ARDUINO_PIN_A3` can be used - to avoid looking up what digital number that pin has. - -Analog Pins {#iomaps-mapping-adc} ------------ - -The feature `arduino_analog` is provided by boards that do have a mapping of -ADC lines to analog pins. E.g. the ADC line corresponding to pin `A5` would -be `ARDUINO_A5`. The number of the highest analog pin is provided as -`ARDUINO_ANALOG_PIN_LAST`. The macro `ARDUINO_ANALOG_PIN_LAST` is defined if -and only if a mapping is provided (so it can be used to test for this feature). - -@warning Some boards do have "gaps" in the analog pin mapping. It could be - that e.g. `ARDUINO_A3` is defined, but `ARDUINO_A2` is not. - -DAC Pins {#iomaps-mapping-dac} --------- - -The feature `arduino_dac` is provided by boards that do have a mapping of -DAC pins to DAC lines. E.g. the DAC line for the pin DAC1 would be -`ARDUINO_DAC1`. The number of the highest DAC pin is provided as -`ARDUINO_DAC_PIN_LAST`. The macro `ARDUINO_DAC_PIN_LAST` is defined if -and only if a mapping is provided (so it can be used to test for this feature). - -@warning Some boards do have "gaps" in the analog pin mapping. It could be - that e.g. `ARDUINO_DAC4` is defined, but `ARDUINO_DAC3` is not. - -PWM Pins {#iomaps-mapping-pwm} --------- - -The feature `arduino_pwm` is provided by boards that do have a mapping of -digital pins to PWM settings. E.g. the PWM device connected to the digital pin -`D11` would be `ARDUINO_PIN_11_PWM_DEV` and the channel would be -`ARDUINO_PIN_11_PWM_CHAN`. A PWM frequency for all PWM pins is defined as -`ARDUINO_PWM_FREQU`. - -@warning Typically only few digital pins support PWM. For pins without PWM - output no `ARDUINO_PIN__PWM_DEV` macro and no - `ARDUINO_PIN__PWM_DEV` is defined. - -UART Device {#iomaps-mapping-uart} ------------ - -The feature `arduino_uart` is provided by boards that do provide an UART device -mapping. For the official Arduino boards and compatible boards, the -`ARDUINO_UART_D0D1` macro refers to the UART device that uses the digital pins -`D0` and `D1`. - -Please extend the table below to keep naming among boards of the same form -factor consistent: - -| Form Factor | Macro Name | Description | -|:---------------- |:--------------------- |:--------------------------------- | -| Arduino Nano | `ARDUINO_UART_D0D1` | UART on D0 (RXD) and D1 (TXD) | -| Arduino Uno | `ARDUINO_UART_D0D1` | UART on D0 (RXD) and D1 (TXD) | -| Arduino Mega | `ARDUINO_UART_D0D1` | UART on D0 (RXD) and D1 (TXD) | -| Seeedstudio XIAO | `ARDUINO_UART_DEV` | UART on D7 (RXD) and D6 (TXD) | - -I²C Buses {#iomaps-mapping-i2c} ---------- - -The feature `arduino_i2c` is provided by boards that do provide an I²C bus -mapping. - -| Form Factor | Macro Name | Description | -|:---------------- |:--------------------- |:--------------------------------- | -| Arduino Nano | `ARDUINO_I2C_NANO` | D18 (SDA) / D19 (SCL) | -| Arduino Uno | `ARDUINO_I2C_UNO` | D18 (SDA) / D19 (SCL) | -| Arduino Mega | `ARDUINO_I2C_UNO` | D20 (SDA) / D21 (SCL) | -| Arduino Zero | `ARDUINO_I2C_UNO` | D20 (SDA) / D21 (SCL) | -| Arduino Due | `ARDUINO_I2C_UNO` | D70 (SDA) / D71 (SCL) | -| Seeedstudio XIAO | `ARDUINO_I2C_DEV` | D4 (SDA) / D5 (SCL) | - -The `ARDUINO_I2C_UNO` refers to the I²C bus next to the AREF pin (the topmost -pins on header on the top right) of an Arduino Uno compatible board, e.g. -such as the Arduino Mega2560. Even though the Arduino UNO, the Arduino MEGA2560, -the Arduino Zero and the Arduino Zero all having the I²C bus at the exact same -mechanical positions, the digital pin number of the I²C bus next to the AREF -differs between the versions. - -SPI Buses {#iomaps-mapping-spi} ---------- - -The feature `arduino_spi` is provided by boards that do provide an SPI bus -mapping. - -| Form Factor | Macro Name | Description | -|:---------------- |:------------------------- |:------------------------------------- | -| Arduino Nano | `ARDUINO_SPI_ISP` | The SPI on the ISP header | -| Arduino Nano | `ARDUINO_SPI_D11D12D13` | D11 (MOSI) / D12 (MISO) / D13 (SCK) | -| Arduino Uno | `ARDUINO_SPI_ISP` | The SPI on the ISP header | -| Arduino Uno | `ARDUINO_SPI_D11D12D13` | D11 (MOSI) / D12 (MISO) / D13 (SCK) | -| Arduino Mega | `ARDUINO_SPI_ISP` | The SPI on the ISP header | -| Arduino Mega | `ARDUINO_SPI_D11D12D13` | D11 (MOSI) / D12 (MISO) / D13 (SCK) | -| Seeedstudio XIAO | `ARDUINO_SPI_DEV` | D10 (MOSI) / D9 (MISO) / D8 (SCK) | - -@note The original AVR based Arduinos only have a single hard SPI bus which - is only provided via the ISP header. Many modern Arduino compatible - boards do not provide the ISP header and only have SPI on D11/D12/D13 - provided. - -Mechanical and Electrical Compatibility {#iomaps-shields} -======================================= - -Modules implementing drivers for extension boards, a.k.a. shields, can express -their mechanical and electrical requirements by depending on `arduino_shield_...` -features. The following list of features currently exists: - -| Feature Name | Compatibility Claim | -|:--------------------- |:------------------------------------------------------------- | -| `arduino_shield_nano` | Board has side headers compatible with the Arduino Nano | -| `arduino_shield_uno` | Board has side headers compatible with the Arduino UNO | -| `arduino_shield_mega` | Board has side headers compatible with the Arduino MEGA | -| `feather_shield` | Board has headers compatible with the Adafruit Feather boards | -| `xiao_shield` | Board has headers compatible with the Seeedstudio XIAO boards | - -@note A board providing `arduino_shield_mega` **MUST** also provide - `arduino_shield_uno`, as Arduino MEGA boards are backward compatible to - shields for the Arduino UNO. - -E.g. a module that implements the W5100 based Ethernet shield would depend on -both `arduino_shield_uno` and `arduino_shield_isp` for electrical compatibility -as well as on `arduino_spi` for SPI bus mapping and `arduino_pins` for the CS -pin mapping. This module could reuse the existing `w5100` driver and just -supply the correct `w5100_params_t` using the I/O mappings. +@deprecated Guides have moved to the [Guide Site](https://guide.riot-os.org/misc/io_mapping_and_shields/). +This page will be removed after release 2026.04. diff --git a/doc/doxygen/src/kconfig/kconfig.md b/doc/doxygen/src/kconfig/kconfig.md index 010f82aa8d..1461f5fbd4 100644 --- a/doc/doxygen/src/kconfig/kconfig.md +++ b/doc/doxygen/src/kconfig/kconfig.md @@ -1,567 +1,4 @@ -# Kconfig in RIOT {#kconfig-in-riot} +# Kconfig in RIOT (Deprecated) {#kconfig-in-riot} -[TOC] - -The objective of using Kconfig in RIOT is to configure software modules at -compile-time. This means having a standard way of: -- Exposing configurable parameters -- Assigning application and user-specific configurations -- Verifying these parameters - - Check possible values - - Check valid configuration considering inter-dependencies -- Applying the selected configuration - -# Overview {#kconfig-overview} - -## Exposure -Modules in RIOT expose their configurable parameters via -Kconfig files (for more information on Kconfig syntax check -[the specification](https://www.kernel.org/doc/html/latest/kbuild/kconfig-language.html)). -In these files documentation, restrictions, default values and dependencies can -be expressed. - -Kconfig files are structured through the file system mirroring the current -module distribution. In time, all modules will have Kconfig files to make -themselves configurable through this system. - -## Assignment -The user can assign values to the exposed parameters, either by manually writing -'.config' files or using an interface such as Menuconfig. Parameters with no -assigned values will take the default ones. For a detailed distinction between -Kconfig and '.config' files see [Appendix B](#kconfig-appendix-b). - -## Verification and application -Using '.config' and Kconfig files the build system takes care of doing the -necessary checks on the values according to the parameter definition. After -that, the `autoconf.h` header file is generated, it contains all the -configurations in the form of (`CONFIG_` prefixed) macros. - ---- -# User's guide to configure with Kconfig {#kconfig-users-guide} - -## Configure using menuconfig {#configure-using-menuconfig} -In order to use the graphical interface menuconfig to configure the -application, run `make menuconfig` in the application's folder. All available -configurations (based on the used modules) for the particular platform will be -presented. By default, the configuration of a module via Kconfig is not enabled. -In order to activate the configuration via Kconfig the corresponding option -should be selected. That will enable the configuration of all inner options, if -available. - -Once the desired configuration is achieved save the configuration to the -default proposed path and exit. The saved configuration will be applied when -the code is compiled (`make all`). - -If the current configuration will be used in the future it can be saved in the -application's folder as `user.config`, using the 'Save' option in menuconfig. -This way it will be persistent after cleaning the application directory -(`make clean`). - -## Configure using '.config' files {#configure-using-files} -The second way to configure the application is by directly writing '.config' -files. Two files will be sources of configuration during the generation of the -final header file: `app.config` and `user.config`, which should be placed -inside the application's folder. `app.config` sets default configuration -values for the particular application, the user can override them by setting -them in `user.config`. Additionally, further `.config` files can be added to -the variable `KCONFIG_ADD_CONFIG`, which will be applied _after_ default CPU and -board configurations, `app.config` and `user.config`. This means that they will -have priority. - -Let's say that the `SOCK_UTIL_SCHEME_MAXLEN` symbol in `sock_util` module needs -to be configured. The `user.config` file could look like: - -```Makefile -# activate configuration of sock_util using Kconfig -CONFIG_KCONFIG_MODULE_SOCK_UTIL=y -# change scheme part length -CONFIG_SOCK_UTIL_SCHEME_MAXLEN=24 -``` - -In this case, there is no need for using menuconfig. It's enough just to call -`make all` in the application folder, as this configuration will be read and -applied. Note that if any dependency issue occurs, warnings will be generated -(e.g. not enabling the configuration of a module via Kconfig). - -## Application configuration with Kconfig {#app-config-kconfig} -To expose application-specific configuration options a `Kconfig` file can -be placed in the application's folder. For an example of this you can check -the [tests/build_system/kconfig](https://github.com/RIOT-OS/RIOT/tree/master/tests/build_system/kconfig) -application. - -## Configuration via environment variables {#env-config-kconfig} -For easy debugging of configuration or testing new modules by compiling them -into existing applications, one can also use environment variables prefixed by -`RIOT_CONFIG_`. To achieve the same configuration exemplified in -@ref configure-using-files, e.g., you could also use - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.sh} -RIOT_CONFIG_KCONFIG_MODULE_SOCK_UTIL=1 \ -RIOT_CONFIG_SOCK_UTIL_SCHEME_MAXLEN=24 \ - make -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -All the checks that apply for `.config` files also are done with this approach. - -Mind that this is only meant to be used during development. In production, -please set the configuration via `.config` files. - -## A note on the usage of CFLAGS -When a certain module is being configured via Kconfig the configuration macro -will no longer be overridable by means of CFLAGS (e.g. set on the -compilation command or on a Makefile). Consider this if you are getting a -'redefined warning'. - ---- -# Integration into the build system {#kconfig-integration-into-build-system} - -The integration of Kconfig into the build system is mainly done in -`makefiles/kconfig.mk`. - -## Steps during the build process {#kconfig-steps-build-process} - -![Output of every step of the build process](kconfig_integration.svg) - -### 0. Module dependency resolution -The resolution of module dependencies is performed by the build -system where all the used modules and packages end up listed in the `USEMODULE` -or `USEPKG` make variables. - - -#### Input -- Makefiles. - -#### Output -- `USEMODULE` and `USEPKG` variables. - -### 1. Module listing -The list of modules needed for the particular build is dumped into the -`$ (GENERATED_DIR)/Kconfig.dep` file, where each module is translated into a -Kconfig symbol as documented in [Appendix A](#kconfig-appendix-a). - -#### Input -- `USEMODULE` and `USEPKG` variables - -#### Output -- `$ (GENERATED_DIR)/Kconfig.dep` file - -### 2. Merging all configuration sources {#kconfig-steps-merge-configs} -In this step configuration values are taken from multiple sources and merged -into a single `out.config` configuration file. This file is temporary and is -removed on clean. If the user needs to save a particular configuration -set, a backup has to be saved (this can be done using the menuconfig interface) -so it can be loaded later in this step. - -To accomplish merging of multiple input files, the `genconfig` script is -used. Note that **the order matters**: existing configuration values are -merged in the order expressed in the input section, where the last value -assigned to a parameter has the highest priority. If no configuration files are -available all default values will be applied. - -`out.config` is the only configuration input for the `autoconf.h` in the -[generation step](#kconfig-steps-header-gen). - -Additionally this step generates a file `out.config.d` which holds the -information of all the used Kconfig files in Makefile format. This file is -included by the build system and allows to re-trigger the generation of -`out.conf` whenever a Kconfig file is modified. - -#### Input -- Optional: - - `$ (APPDIR)/app.config`: Application specific default configurations. - - `$ (APPDIR)/user.config`: Configurations saved by user. - -#### Output -- `$ (GENERATED_DIR)/out.config` file. - -### 3. Menuconfig execution (optional) -Menuconfig is a graphical interface for software configuration. It is used for -the configuration of the Linux kernel. This section explains the process -that occurs when RIOT is being configured using the menuconfig interface. - -The main `Kconfig` file is used in this step to show the configurable -parameters of the system. Kconfig will filter inapplicable parameters (i.e. -parameters exposed by modules that are not being used) based on the file -`$ (GENERATED_DIR)/Kconfig.dep` generated in step 1. - -Note that if Kconfig is not used to configure a module, the corresponding -header files default values will be used. - -`out.config` is one of the inputs for menuconfig. This means that any -configuration that the application defines in the `app.config` or a backup -configuration from the user in `user.config` are taken into account on the -first run (see [Appendix C](#kconfig-appendix-c)). - -In this step the user chooses configuration values (or selects the minimal -configuration) and saves it to the `out.config` file. Here the user can -choose to save a backup configuration file for later at a different location -(e.g. a `user.config` file in the application folder). - -If any changes occur to `out.config`, the -[generation of autoconf.h](#kconfig-steps-header-gen) is executed automatically. - -#### Input -- `/Kconfig` file. -- Optional: - - `$ (APPDIR)/app.config` - - `$ (APPDIR)/user.config` - - `$ (GENERATED_DIR)/out.config` - -#### Output -- Updated `$ (GENERATED_DIR)/out.config` file. -- `$ (GENERATED_DIR)/out.config.old` backup file. - -### 4. Generation of the autoconf.h header {#kconfig-steps-header-gen} -With the addition of Kconfig a dependency has been added to the build -process: the `$ (GENERATED_DIR)/autoconf.h` header file. This header file is -the main output from the Kconfig configuration system. It holds all the macros -that should be used to configure modules in RIOT: -`CONFIG__`. - -In order to generate the `autoconf.h` file the `genconfig` script is used. -Inputs for this script are the main `Kconfig` file and `out.config` -configuration file, which holds the selected values for the exposed parameters. - -#### Input: -- `$ (GENERATED_DIR)/out.config` file. -- Main `Kconfig` file exposing configuration of modules. - -#### Output: -- `$ (GENERATED_DIR)/autoconf.h` configuration header file. -- Optional: - - `$ (GENERATED_DIR)/deps/*/*.h` header files that allow incremental builds - - -### Summary of files -These files are defined in `kconfig.mk`. - -| File | Description | -| ---------------| ----------- | -| `Kconfig` | Defines configuration options of modules. | -| `Kconfig.dep` | Holds a list of the modules that are being compiled. | -| `app.config` | Holds default application configuration values. | -| `user.config` | Holds configuration values applied by the user. | -| `out.config` | Configuration file containing all the symbols defined in `autoconf.h`. | -| `out.config.d` | Dependency file of `out.config` containing the list of Kconfig files used to generate it. | -| `autoconf.h` | Header file containing the macros that applied the selected configuration. | - -## Kconfig symbols in Makefiles -As '.config' files have Makefile syntax they can be included when building, -which allows to access the applied configuration from the build system. - -During migration this is also useful, as it gives the ability to check if a -parameter is being configured via Kconfig or a default value via `CFLAGS` could -be injected. For example: - -```Makefile -ifndef CONFIG_USB_VID - CFLAGS += -DCONFIG_USB_VID=0x1209 -endif -``` - -Symbols will have the same name as the configuration macros (thus will always -have the `CONFIG_` prefix). As the configuration file is loaded in -`Makefile.include` care should be taken when performing checks in the -application's Makefile. The symbols will not be defined until after including -`Makefile.include`. - ---- -# Transition phase {#kconfig-transition-phase} -## Making configuration via Kconfig optional {#kconfig-configuration-optional} -During transition to the usage of Kconfig as the main configuration tool for -RIOT, the default behavior will be the traditional one: expose configuration -options in header files and use CFLAGS as inputs. To allow optional -configuration via Kconfig, a convention will be used when writing Kconfig files. - -Modules should be contained in their own `menu` entries, this way the user -can choose to enable the configuration via Kconfig for an specific module. -These entries should define a dependency on the module they configure (see -[Appendix A](#kconfig-appendix-a) to see how to check if a module is being -used). - -The module configuration must be enabled either via make dependency modelling. - -## Modelling CPUs and boards {#kconfig-cpu-boards-fekconfig-cpu-boards} -CPUs and boards are being modelled in Kconfig. The following is a guide on how to -organize and name the symbols. - -### CPUs -The proposed hierarchy for the classification of CPUs is as follows: - -``` - +------------+ -More Specific | CPU_MODEL | - + +------------+ - | - | - | +------------+ - | | CPU_FAM | - | +------------+ - | - | - | +------------+ - | | CPU_CORE | - | +------------+ - | - | - v +------------+ -Less Specific | CPU_ARCH | - +------------+ -``` - -Where each hierarchy is defined as: -- `CPU_MODEL`: The specific identifier of the used CPU, used for some CPU - implementations to differentiate between different memory - layouts. -- `CPU_FAM`: An intermediate identifier between CPU and CPU_MODEL that - represents a sub-group of a Manufacturers CPU's. -- `CPU_CORE`: The specific identifier of the core present in the CPU. -- `CPU_ARCH`: The specific identifier of the architecture of the core defined - in `CPU_CORE`. - -In order to model the hierarchies, a hidden boolean symbol must be declared for -each. The name of the symbol must begin with the correspondent prefix and must -be followed by the specific value. For instance, the 'samd21' family symbol is -named `CPU_FAM_SAMD21`. - -In addition, a default value to the correspondent common symbol must be defined. -The default value must be guarded by the boolean symbol correspondent to the -hierarchy. - -Features may be provided by any hierarchy symbol. Usually symbols are selected -from more specific to less specific. This means that a `CPU_MODEL_` -symbol usually would select the correspondent `CPU_FAM_` symbol, -which would in turn select the `CPU_CORE_`. This may change in some cases -where `CPU_COMMON_` symbols are defined to avoid repetition. For convenience and -if it makes sense within a CPU vendor family, it's also allowed to use -intermediate grouping levels, like `CPU_LINE_` used for STM32. - -In addition to the symbols of the hierarchy described above, a default value -to the `CPU` symbol should be assigned, which will match the value of the `CPU` -Makefile variable in the build system. - -The declaration of the symbols should be placed in a `Kconfig` file in the -folder that corresponds to the hierarchy. When the symbols are scattered into -multiple files, it is responsibility of file containing the most specific -symbols to `source` the less specific. Keep in mind that only the file located -in `/cpu//Kconfig` will be included by the root `/Kconfig` file. - -#### Example - -```Kconfig -# This is the most specific symbol (selected by the board) -# The CPU model selects the family it belongs to -config CPU_MODEL_SAMR21G18A - bool - select CPU_FAM_SAMD21 - -# In this case the family selects a common 'sam0' symbol (which provides some -# features), and the core it has (cortex-m0+) -config CPU_FAM_SAMD21 - bool - select CPU_COMMON_SAM0 - select CPU_CORE_CORTEX_M0PLUS - -# The value of the common value depends on the selected model -config CPU_MODEL - default "samd21e18a" if CPU_MODEL_SAMD21E18A - default "samd21g18a" if CPU_MODEL_SAMD21G18A - default "samd21j18a" if CPU_MODEL_SAMD21J18A - default "samr21e18a" if CPU_MODEL_SAMR21E18A - default "samr21g18a" if CPU_MODEL_SAMR21G18A - -config CPU_FAM - default "samd21" if CPU_FAM_SAMD21 - -``` - -### Boards -Boards must be modelled as hidden boolean symbols with the prefix `BOARD_` which -default to `y` and are placed in `/boards//Kconfig`. This file will be -`source`d from the main `/Kconfig` file. The board symbol must select the -`CPU_MODEL_` symbol that corresponds to the CPU model present on the -board. The board symbol must also select the symbols that correspond to the -features it provides. - -In the same `Kconfig` file a default value must be assigned to the -common `BOARD` symbol. It must be guarded by the board's symbol, so it only -applies in that case. - -There are cases when grouping common code for multiple boards helps to avoid -unnecessary repetition. In the case features are provided in a common board -folder (e.g. `/boards/common/arduino-atmega`) a symbol should be declared to -model this in Kconfig. Symbols for common boards must have the `BOARD_COMMON_` -prefix, and must select the common provided features. - -#### Example -The samr21-xpro has a `samr21g18a` CPU and provides multiple features. Its -symbol is modelled as following: - -```Kconfig -# /boards/samr21-xpro/Kconfig - -config BOARD - default "samr21-xpro" if BOARD_SAMR21_XPRO - -config BOARD_SAMR21_XPRO - bool - default y - select CPU_MODEL_SAMR21G18A -``` - -### Default configurations - -Boards, common board directories, CPUs and common CPU directories may need to -override default configuration values. Visible configuration symbols are -configurable by the user and show on the menuconfig interface. `.config` files -are used to set their values. To allow multiple sources of `.config` files, -there are two Makefile variables developers should use: `KCONFIG_CPU_CONFIG` for -sources added by the CPU or common CPU directories, and `KCONFIG_BOARD_CONFIG` -for sources added by the board or common board directories. This ensures the -correct priority of the configurations. - -The `Makefile.features` infrastructure is used to populate the -configuration sources. As the order in which `.config` files are merged matters, -configuration sources should be ordered from more generic to more specific. -Because board's `Makefile.features` is included before CPU's `Makefile.features` -it is important to utilize two different lists of configuration sources. For -instance, if `cpu/cortexm_common` adds its configuration, `cpu/stm32` should add -its configuration after it, and `boards/stm32f769i-disco` after it. - -```Makefile -include $(RIOTCPU)/cortexm_common/Makefile.features - -# Add stm32 configs after including cortexm_common so stm32 takes precedence -KCONFIG_CPU_CONFIG += $(RIOTCPU)/stm32/stm32.config -``` - -## Summary of reserved Kconfig prefixes -The following symbol prefixes have been assigned particular semantics and are -reserved for the cases described below: - - -| Prefix | Description | -| :----- | :---------- | -| `BOARD_` | Models a board | -| `BOARD_COMMON_` | Used for common symbols used by multiple boards | -| `CPU_ARCH_` | Models a CPU architecture | -| `CPU_COMMON_` | Used for common symbols used by multiple CPUs | -| `CPU_CORE_` | Models a CPU core | -| `CPU_FAM_` | Models a family of CPUs | -| `CPU_MODEL_` | Models a particular model of CPU | -| `USEMODULE_` | Models a [RIOT module](creating-modules.html#creating-modules). Generated from `USEMODULE` variable | -| `USEPKG_` | Models an [external package](group__pkg.html). Generated from `USEPKG` variable | - ---- -# Appendixes {#kconfig-appendixes} - -## Appendix A: Check if a module or package is used {#kconfig-appendix-a} -In order to show only the relevant configuration parameters to the user with -respect to a given application and board selection, Kconfig needs knowledge -about all modules and packages to be used for a compilation. The dependency -handling among modules is performed by the build system (via -`Makefile.dep` files). The interface defined to declared the used modules and -packages is the `$ (GENERATED_DIR)/Kconfig.dep` file. - -There will be a symbol for every used module (i.e. every module in -`USEMODULE` make variable) and package. The names in the symbols will be -uppercase and separated by `_`. Based on these symbols configurability is -decided. - -The following is an example of how to use these symbols in Kconfig files to -configure compile-time configurations with `USEMODULE` dependencies: - -```Kconfig -menu "Configure Sock Utilities" - depends on USEMODULE_SOCK_UTIL - -config SOCK_UTIL_SCHEME_MAXLEN - int "Maximum length of the scheme part for sock_urlsplit" - default 16 - -... - -endmenu # Configure Sock Utilities -``` - - -## Appendix B: Difference between 'Kconfig' and '.config' files {#kconfig-appendix-b} -Kconfig files describe a configuration database, which is a collection of -configuration options organized in a tree structure. Configuration options may -have dependencies (among other attributes), which are used to determine their -visibility. - -Kconfig files are written in -[Kconfig language](https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt) -defined in the Linux kernel. Configuration options have attributes such as -types, prompts and default values. - -#### Kconfig file - -```Kconfig -menu "Buffer Sizes" - -config GCOAP_PDU_BUF_SIZE - int "Request or response buffer size" - default 128 - -endmenu -``` - -On the other hand configuration files contain assignment of values to -configuration options and use Makefile syntax. They can also be used to save a -set of configuration values as backup. - -#### '.config' file - -```makefile -# enable Kconfig configuration for gcoap -CONFIG_KCONFIG_MODULE_GCOAP=y -# set the value -CONFIG_GCOAP_PDU_BUF_SIZE=12345 -``` - -In other words: Kconfig files describe configuration options and '.config' files -assign their values. - -## Appendix C: Pitfall when using different configuration interfaces {#kconfig-appendix-c} -In the current configuration flow the user can choose to configure RIOT using -the menuconfig graphical interface or writing '.config' files by hand. - -As explained in the -['Configuration sources merging step'](#kconfig-steps-merge-configs) -of the configuration process, configuration from multiple sources are loaded to -create a single `out.config` file, and the order of merging matters: last -file has priority. - -While editing values directly via '.config' files `out.config` will be -re-built. The user can also use menuconfig interface to modify the configuration -file (this is the recommended way, as it gives access to much more information -regarding dependencies and default values of the symbols). Menuconfig will -change `out.config` directly (a backup file `out.config.old` will be kept). - -**It is recommended to save backups of the configurations, as any change on the -configuration sources would re-trigger the merging process and overwrite -`out.config`.** - -## Appendix D: A few key aspects while exposing a macro to Kconfig {#kconfig-appendix-d} -A macro that holds a 0 or 1 is modelled in Kconfig as a `bool` symbol. References to this macro -can then make use of IS_ACTIVE macro from kernel_defines.h with C conditionals -for conditional compilation. -[FXOS8700 driver exposure to Kconfig](https://github.com/RIOT-OS/RIOT/pull/13914) -can be considered as an example. If the macro is defined as `TRUE` by default, -a new symbol gets introduced to invert the semantics. The recommended -practice is to add a new symbol and expose it to Kconfig while the old one is -tagged to be deprecated. The process is documented in this -[commit](https://github.com/RIOT-OS/RIOT/pull/13129/commits/c7b6dc587cf20f3177abe0417a408b6ab90d0ff8) - -There may be cases where a macro is expected to hold only specific values, e.g. -'GNRC_IPV6_MSG_QUEUE_SIZE' expressed as the power of two. These may be modelled -in such a way that a new macro is introduced to hold the restricted figures -while operators are added to arrive at the desired value. The process is -documented in this [pull request.](https://github.com/RIOT-OS/RIOT/pull/14086) - -# Useful references {#kconfig-useful-references} -- [Kconfig language specification](https://www.kernel.org/doc/html/latest/kbuild/kconfig-language.html) -- [Kconfig macro language specification](https://www.kernel.org/doc/html/latest/kbuild/kconfig-macro-language.html) -- [Kconfig - Tips and Best Practices](https://docs.zephyrproject.org/latest/guides/kconfig/tips.html) +@deprecated Guides have moved to the [Guide Site](https://guide.riot-os.org/build-system/kconfig/). +This page will be removed after release 2026.04. diff --git a/doc/doxygen/src/kconfig/kconfig_integration.svg b/doc/doxygen/src/kconfig/kconfig_integration.svg deleted file mode 100644 index 060064b99b..0000000000 --- a/doc/doxygen/src/kconfig/kconfig_integration.svg +++ /dev/null @@ -1,3 +0,0 @@ - - -
$(USEMODULE)
$(USEPKG)
$(USEMODULE)...
Kconfig.dep
Kconfig.dep
out.config
out.config
menuconfig
menuconfig
autoconf.h
autoconf.h
0
0
1
1
2
2
3
3
4
4
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/doc/doxygen/src/porting-boards.md b/doc/doxygen/src/porting-boards.md index 0f49bfa956..cfaa70ad25 100644 --- a/doc/doxygen/src/porting-boards.md +++ b/doc/doxygen/src/porting-boards.md @@ -1,466 +1,5 @@ -Porting boards {#porting-boards} +Porting boards (Deprecated) {#porting-boards} ================ -At some point you might need to port a new `BOARD` to `RIOT`, either because -that specific development board is not yet supported or because you have a -custom `BOARD` for your project. - -If you want to port a `BOARD` to `RIOT` you have two choices: doing it -inside of `RIOTBASE` or outside. In either case the file structure -is basically the same and moving from one to another is easy. - -This guide details the generic structure you need to add a new `BOARD` -to `RIOT`, the different files as well as their functionality. - -@note We assume here that your `CPU` and `CPU_MODEL` is already supported -in `RIOT` so no peripheral or cpu implementation is needed. - -# Porting flowchart {#porting-flowchart} -@dotfile porting-boards.dot - -# General structure {#general-structure} - -Like @ref creating-an-application "applications" or @ref creating-modules -"modules", boards consist on a directory containing source files and -makefiles. Usually a `BOARD` directory has the following structure - -``` - board-foo/ - |----dist/ - |----scripts - |----board.c - |----doc.md - |----include/ - |----periph_conf.h - |----board.h - |----gpio_params.h - |----Makefile - |----Makefile.dep - |----Makefile.features - |----Makefile.include -``` - -## Source files {#board-source-files} - -Header files in `board-foo/include` define physical mappings or -configurations. e.g: - -- `periph_conf.h`: defines configurations and mappings for peripherals as well - as clock configurations. -- `board.h`: holds board specific definitions or mappings, for example LEDs, - buttons. It might as well override default drivers parameters (e.g.: assigning - specific pin connections to a LCD screen, radio, etc.). Some boards might also - define optimized `XTIMER_%` values (e.g. @ref XTIMER_BACKOFF). -- `gpio_params.h`: if the board supports @ref drivers_saul "SAUL" then its - @ref saul_gpio_params_t is defined here. (Analogously, a `adc_params.h` can - contain a @ref saul_adc_params_t, and `pwm_params.h` a @ref - saul_pwm_rgb_params_t and a @ref saul_pwm_dimmer_params_t). -- other: other specific headers needed by one `BOARD` - -@note Header files do not need to be defined in `include/`, but if defined -somewhere else then they must be added to the include path. In -`Makefile.include`: `INCLUDES += -I//` - -Board initialization functions are defined in `board.c`. -This file can define a `board_init()` function that is called at startup. -It is run before the scheduler is started, so it must not block (e.g. by -performing I2C operations). - -```c -void board_init(void) -{ - /* initialize GPIO or others... */ - ... -} -``` - -## Makefiles - -### Makefile {#Makefile} - -A board's Makefile just needs to include `Makefile.base` in the RIOT -repository and define the `MODULE` as `board` (see @ref creating-modules -"modules" for more details) - -```mk -MODULE = board - -include $(RIOTBASE)/Makefile.base -``` - -### Makefile.dep {#makefile-dep} - -Dependencies on other `MODULES` or `FEATURES` can be defined here. This might -specify `MODULES` or dependencies that need to be pulled under specific -configurations. e.g.: if your board has a sx1276 lora chip: - -```mk -ifneq (,$(filter netdev_default,$(USEMODULE))) - USEMODULE += sx1276 -endif -``` - -@note `Makefile.dep` is processed only once so you have to take care of adding -the dependency block for your board *before* its dependencies pull in their own -dependencies. - -#### Default configurations -As explained in @ref default-configurations "Default Configurations", there are -two pseudomodules that are used to indicate that certain drivers of devices -present in the platform should be enabled. Each board (or CPU) has knowledge as -to which drivers should be enabled in each case. - -The previous code snippet shows how a board which has a @ref drivers_sx127x -device, pulls in its driver when the default network interfaces are required. - -When the pseudomodule `saul_default` is enabled, the board should pull in all -the drivers of the devices it has which provide a @ref drivers_saul interface. This is -usually done as following: - -```mk -ifneq (,$(filter saul_default,$(USEMODULE))) - USEMODULE += saul_gpio - USEMODULE += apds9960 - USEMODULE += bmp280_i2c - USEMODULE += lis3mdl - USEMODULE += sht3x -endif -``` - -### Makefile.features {#makefile-features} - -This file defines all the features provided by the BOARD. These features -might also need to be supported by the `CPU`. Here, define the `CPU` and -`CPU_MODEL` (see @ref build-system-basics "build system basics" for more details - on these variables). - -e.g.: - -```mk -CPU = foo -CPU_MODEL = foobar - -# Put defined MCU peripherals here (in alphabetical order) -FEATURES_PROVIDED += periph_i2c -FEATURES_PROVIDED += periph_spi -FEATURES_PROVIDED += periph_uart -``` - -### Makefile.include {#makefile-include} - -This file contains BSP or toolchain configurations for the `BOARD`. It -should at least define the configuration needed for flashing (i.e. specify a -default programmer) as well as the serial configuration (if one is available). -The default serial port configuration is provided by -`makefiles/tools/serial.inc.mk` and define the following values for the serial -port (depends on the host OS): - -``` -PORT_LINUX ?= /dev/ttyACM0 -PORT_DARWIN ?= $(firstword $(sort $(wildcard /dev/tty.usbmodem*))) -``` - -So if the board is also using this, there's no need to redefine these variables -in the board configuration. - -For example a board that is using a custom serial port (via an USB to serial -adapter) and that is flashed using openocd by default would have the following -content in its `Makefile.include`: - -```mk -# Define the default port depending on the host OS -PORT_LINUX ?= /dev/ttyUSB0 -PORT_DARWIN ?= $(firstword $(sort $(wildcard /dev/tty.usbserial*))) - -# this board uses openocd -PROGRAMMER ?= openocd -``` - -## Timer Configurations {#board-timer-configurations} - -When using the high level timer `ztimer` there is an overhead in calling -the @ref ztimer_sleep and @ref ztimer_set functions. This offset can be -compensated for. It can be measured by running `tests/sys/ztimer_overhead` -on your board, i.e: - -```shell -$ BOARD=my-new-board make -C tests/sys/ztimer_overhead flash term -main(): This is RIOT! -ZTIMER_USEC auto_adjust params: - ZTIMER_USEC->adjust_set = xx - ZTIMER_USEC->adjust_sleep = xx -ZTIMER_USEC auto_adjust params cleared -zitmer_overhead_set... -min=6 max=7 avg_diff=6 -zitmer_overhead_sleep... -min=21 max=21 avg_diff=21 -ZTIMER_USEC adjust params for my-new-board: - CONFIG_ZTIMER_USEC_ADJUST_SET 6 - CONFIG_ZTIMER_USEC_ADJUST_SLEEP 21 -``` - -The last two lines can be added as defines to the new board `board.h`: - -```c -/** - * @name ztimer configuration values - * @{ - */ -#define CONFIG_ZTIMER_USEC_ADJUST_SET 6 -#define CONFIG_ZTIMER_USEC_ADJUST_SLEEP 21 -/** @} */ -``` - -Alternatively, the pseudomodule @ref pseudomodule_ztimer_auto_adjust can be used -in an application to enable automatic timer offset compensation at board startup. -This however incurs overhead both in the text segment and at bootup time. - -## doc.md {#board-doc} - -Although not explicitly needed, if upstreamed and as a general good -practice, this file holds all `BOARD` documentation. This can include -datasheet reference, documentation on how to flash, etc. - -The documentation must be under the proper doxygen group, you can compile the -documentation by calling `make doc` and then open the generated html file on -any browser. - -```md -@defgroup boards_foo FooBoard -@ingroup boards -@brief Support for the foo board -@author FooName BarName - -### User Interface - - ... - -### Using UART - - ... - -### Flashing the device - - ... -``` - -Previously documentation was contained in `doc.txt` files with C-style comment -blocks. This style has been deprecated in favor of using `doc.md` files in -Markdown format, which eliminates formatting and interpretation issues. -Old style files will continually be replaced by the new format. - -Up to version `0.9.2` the [riotgen](https://pypi.org/project/riotgen/) tool -will generate `doc.txt` files instead of `doc.md` files. You can upgrade it to -the latest version with -```sh -pip install --upgrade riotgen -``` - -# Helper tools - -To help you start porting a board, the RIOT build system provides the -`generate-board` make target. It is a wrapper around the -[riotgen](https://pypi.org/project/riotgen/) command line tool that is helpful -when starting to port a board: all required files are generated with -copyright headers, doxygen groups, etc, so you can concentrate on the port. -The board source files are created in the `boards/` directory. - -**Usage:** - -From the RIOT base directory, run: -``` -make generate-board -``` -Then answer a few questions about the driver: -- Board name: Enter a name for your board. It will be used as the name - of the board directory under `boards`. -- Board displayed name: Enter the name of the board, as displayed in the - Doxygen documentation. -- CPU name: Enter the name of the CPU embedded on the board. -- CPU model name: Enter the precise model name of the CPU. -- Features provided: CPU features provided (and configured) for this board. - -Other global information (author name, email, organization) should be retrieved -automatically from your git configuration. - -# Using Common code {#common-board-code} - -To avoid code duplication, common code across boards has been grouped in -`boards/common`. e.g. `BOARD`s based on the same cpu (`boards/common/nrf52`) or -`BOARD`s having the same layout `boards/common/nucleo64`. - -In the case of source files this means some functions like `board_init` can be -already defined in the common code. Unless having specific configurations or -initialization you might not need a `board.c` or `board.h`. Another common use -case is common peripheral configurations, for example in the `cfg_timer_tim5.h`: - -```c -/** - * @name Timer configuration - * @{ - */ -static const timer_conf_t timer_config[] = { - { - .dev = TIM5, - .max = 0xffffffff, - .rcc_mask = RCC_APB1ENR_TIM5EN, - .bus = APB1, - .irqn = TIM5_IRQn - } -}; - -#define TIMER_0_ISR isr_tim5 - -#define TIMER_NUMOF ARRAY_SIZE(timer_config) -/** @} */ -``` - -## New Style Common Code {#new-style-common-code} - -The common board definitions of RIOT are currently being reworked to make the -usage of common code easier and less error prone. For example, if you want -to use the common code for the Adafruit nRF52 Bootloader that is used -by many of the nRF52 based boards from Adafruit, you simply have to add the -following line to the `Makefile.dep` of your board. Everything else -will be automatically included by the build system. - -```mk -USEMODULE += boards_common_adafruit-nrf52-bootloader -``` - -Not all common code is migrated to the new style yet, so if you are unsure -whether it is or not, you can check if the `boards/Makefile` already -includes a reference to the common code you want to use. If you are still -unsure, you can still use the @ref old-style-common-code or ask the -community. - -## Old Style Common Code {#old-style-common-code} - -If you want to use common makefiles, include them at the end of the specific -`Makefile`, e.g. for a `Makefile.features`: - -```mk -CPU = foo -CPU_MODEL = foobar - -# Put defined MCU peripherals here (in alphabetical order) -FEATURES_PROVIDED += periph_i2c -FEATURES_PROVIDED += periph_spi -FEATURES_PROVIDED += periph_uart - -include $(RIOTBOARD)/common/foo_common/Makefile.features -``` - -If the common code includes source files, it might be necessary -to explicitly include the directory in your `Makefile` so the Make system -finds all the necessary files: - -```mk -MODULE = board - -DIRS += $(RIOTBOARD)/common/myCommonFolder - -include $(RIOTBASE)/Makefile.base -``` - -If possible, you should use the @ref new-style-common-code though. - -# Boards outside of RIOTBASE {#boards-outside-of-riotbase} - -All `BOARD`s in RIOT reside in `RIOTBOARD` (`RIOTBOARD` being a make variable -set to `$(RIOTBOARD)/boards`). - -If one wants to use a `BOARD` outside of `RIOTBOARD`, the way to go is setting -the `EXTERNAL_BOARD_DIRS` variable to the path to the directory containing your -external boards, e.g.: `EXTERNAL_BOARD_DIRS=/home/external-boards/` (this would -commonly be done in your application `Makefile` or your environment). You can -specify multiple directories separated by spaces. - -``` -/home/ -|----RIOT/ - |---- ... -|----external-boards/ - |----board-foo/ - |----dist/ - |----scripts - |----board.c - |----doc.md - |----include/ - |----periph_conf.h - |----board.h - |----gpio_params.h - |----Makefile - |----Makefile.dep - |----Makefile.features - |----Makefile.include -``` - -If the external `BOARD` is very similar to a `BOARD` already present in -`RIOTBOARD`, the external `BOARD` (`board-foo`) can inherit from that -parent `BOARD` (e.g: `foo-parent`). - -In this case some special considerations must be taken with the makefiles: - -- `Makefile` - - `MODULE` cannot be `board`: `foo-parent` will already define - `MODULE = board`, so use any other name, lets say `MODULE = board-foo`. - - Include the location of the parent `BOARD` to inherit from (if there is - one): - -```mk - DIRS += $(RIOTBOARD)/foo-parent -``` - -- `Makefile.include` - - duplicate the include done by `$(RIOTBASE)/Makefile.include` to also - include the parent board header. e.g: if inheriting from `foo-parent` - ``INCLUDES += $(addprefix -I,$(wildcard $(RIOTBOARD)/foo-parent/include))` - -- `Makefile.dep`: `board` is added by default to `USEMODULE` but since - `board-foo` is used for this `BOARD`, it must be explicitly included by adding - `USEMODULE += board-foo`. - -- Then simply include in each `Makefile.*` the corresponding parent `BOARD` - `Makefile.*`, just as it is done for common `BOARD` code (as explained in - @ref common-board-code). e.g: - `include $(RIOTBOARD)/foo-parent/Makefile.*include*` - -An example can be found in -[`tests/build_system/external_board_native`](https://github.com/RIOT-OS/RIOT/tree/master/tests/build_system/external_board_native). - -# Board names and aliases {#boards-alias} - -New boards should be named according to -[RDM0003](https://github.com/RIOT-OS/RIOT/blob/master/doc/memos/rdm0003.md). -Historically, some board names have not followed this structure. -For backwards compatibility, RIOT supports board aliases that can be used -in place of the actual board name in the environment or Make variable `BOARD`. - -A list of all existing board aliases can be found in -[`makefiles/board_alias.inc.mk](https://github.com/RIOT-OS/RIOT/blob/master/makefiles/board_alias.inc.mk). -[`BOARD=native`](@ref boards_common_native) is a special alias in that it -resolves to either [`native32`](@ref boards_native32) or [`native64`](@ref boards_native64) -depending on the host architecture. - -# Tools {#boards-tools} - -Some scripts and tools available to ease `BOARD` porting and testing: - - - Run `dist/tools/insufficient_memory/add_insufficient_memory_board.sh ` - if your board has little memory. This updates the `Makefile.ci` lists to - exclude the `BOARD` from automated compile-tests of applications that do - not fit on the `BOARD`s `CPU`. - - - Run `dist/tools/compile_and_test_for_board/compile_and_test_for_board.py . --with-test-only` - to run all automated tests on the new board. - -# Further reference {#further-reference} - -- [In her blog][martines-blog], Martine Lenders documented her approach of - porting the @ref boards_adafruit-feather-nrf52840-express in February 2020. -- [Over at HackMD][hackmd-slstk3400a], Akshai M documented his approach of - porting the @ref boards_slstk3400a in July 2020. - -[martines-blog]: https://blog.martine-lenders.eu/riot-board-en.html -[hackmd-slstk3400a]: https://hackmd.io/njFHwQ33SNS3sQKAkLkNtQ +@deprecated Guides have moved to the [Guide Site](https://guide.riot-os.org/advanced_tutorials/porting_boards/). +This page will be removed after release 2026.04. diff --git a/doc/doxygen/src/release-cycle.md b/doc/doxygen/src/release-cycle.md index d72a3b7351..195ff43d69 100644 --- a/doc/doxygen/src/release-cycle.md +++ b/doc/doxygen/src/release-cycle.md @@ -1,4 +1,4 @@ -Release cycle {#release-cycle} +Release cycle (Deprecated) {#release-cycle} ============= @deprecated Guides have moved to the [Guide Site](https://guide.riot-os.org/misc/release_cycle/). diff --git a/doc/doxygen/src/roadmap.md b/doc/doxygen/src/roadmap.md index b88db039b6..bfc3b342ca 100644 --- a/doc/doxygen/src/roadmap.md +++ b/doc/doxygen/src/roadmap.md @@ -1,136 +1,4 @@ -# Roadmap {#roadmap} +# Roadmap (Deprecated) {#roadmap} -The aim of the roadmap is to identify priority areas of RIOT development & enhancements. -For each area, some near-future plans and concrete next steps are indicated. -The text and items below are tentative, up for discussion, to be updated by regular pull requests. - - -# Network Stack High layers -(contact/steering: [Martine](https://github.com/miri64)) - -- ICN stack support clean-up -- discuss mid- and long-term plans for network stack maintenance & development (GNRC vs other supported stacks) -- revisit network time synchronization -- Provide a border router into 6LoWPANs (a 6LBR) that works out of the box in common scenarios: - - [x] in IPv6 networks with working Prefix Delegation (PD) - - [ ] in IPv6 networks without working Prefix Delegation (eg. by means of ND Proxying) - - [ ] in legacy networks (eg. by means of tunneling) - - [ ] with configurable on-by-default fallbacks - -# Network Stack Low layers -(contact/steering: [Peter](https://github.com/PeterKietzmann)) - -- Point-to-Point Protocol (PPP): finalize and merge `gnrc_ppp` - - -# Integrations -(contact/steering: [Teufelchen](https://github.com/teufelchen1)) - -- [Home-Assistant](https://www.home-assistant.io/) BTHome integration -- [Home-Assistant](https://www.home-assistant.io/) integration via [MQTT Discovery](https://www.home-assistant.io/integrations/mqtt#mqtt-discovery) - -# Power Modes -(contact/steering: [benpicco](https://github.com/benpicco)) - -- concept to fix shell usage issue while LPM activated -- integrate generic power management functions in device driver APIs (netdev, SAUL, ...) -- more advanced LPM concepts: - - sleeping for short periods (in cases where it is not feasible to switch to the idle thread and back) -> mitigate active waiting - - - -# Peripheral drivers -(contact/steering: [maribu](https://github.com/maribu)) - -## Timers - -(contact/steering: [kaspar030](https://github.com/kaspar030), [benpicco](https://github.com/benpicco), [maribu](https://github.com/maribu)) - -- cleanup and unification of low-level timer interfaces (`timer`, `rtt`, `rtc`) -- implement capture mode - -## SPI - -- introduction of `spi_slave` interface -- transition to `spi_clk_t` being the frequency in Hz, not an `enum` constant, to allow arbitrary frequencies - - most implementations have been ported -- allow a way to detect the actual frequency an SPI bus is running at - - see https://github.com/RIOT-OS/RIOT/pull/16727 for one proposal - -## I2C - -- introduction of `i2c_slave` interface - - see https://github.com/RIOT-OS/RIOT/issues/19560 for a discussion - -## GPIO - -(contact/steering: [gschorcht](https://github.com/gschorcht), [maribu](https://github.com/maribu)) - -- add a port-based, feature-rich, thread-safe GPIO API - - [GPIO LL](https://doc.riot-os.org/group__drivers__periph__gpio__ll.html) seems to fit the bill so for - - many MCUs still need an implementation -- add a high level API that unifies external and internal GPIOs on top - -## ADC - -(contact/steering: [benpicco](https://github.com/benpicco), [kfessel](https://github.com/kfessel), [gschorcht](https://github.com/gschorcht), [maribu](https://github.com/maribu)) - -- extend / replace the ADC API to allow advanced use cases - - selecting reference voltages (think: multimeter app) - - differential inputs - - fast (ideally DMA supported) sampling (think: a digital oscilloscope app) - - unify external and internal ADCs - - see https://github.com/RIOT-OS/RIOT/pull/13247 for one proposal - - - -# Software Updates -(contact/steering: [Emmanuel](https://github.com/emmanuelsearch)) - -- Modularize to provide toolbox supporting other image storing (e.g. support external flash), transport (other than CoAP), crypto (e.g. secure element). -- riotboot support for architectures other than Cortex-M - - - -# Documentation -(contact/steering: [Emmanuel](https://github.com/emmanuelsearch)) - -- Write and publish more RDMs - - - -# Low-level Hardware Support -(contact/steering: [Alex](https://github.com/aabadie)) - -- radio support for TI SensorTag -- radio support for Silab Thunderboard - - - -# Testing -(contact/steering: [Kaspar](https://github.com/kaspar030)) - -- automated network functionality tests (e.g. RPL + UDP/PING tests through border router, multi-hop) in IoTLAB dev sites? - - - -# Security -(contact/steering: [Kaspar](https://github.com/kaspar030)) - -- RNG unified (secure, or basic), seeding -- RIOT default configuration = secure configuration (that's our goal/motto) - - -## 802.15.4 link layer security -(contact/steering: [chrysn](https://github.com/chrysn)) - -Current status: RIOT supports application provided keys, -with no guidance on how to (and no practical ways to) use that securely -(see [CVE-2021-41061](https://nvd.nist.gov/vuln/detail/CVE-2021-41061)). - -Goal: Usably secure defaults. - -- Figure out applicability of [RFC9031](https://www.rfc-editor.org/rfc/rfc9031) ("CoJP") to non-6TiSCH scenarios. -- Implement RFC9031 with any extensions needed for the MACs RIOT has. -- Provide tools to set up a recommended JRC, and to provision keys between it and the device at flash time. - This may entail extensions to the build process, as CoJP requires per-device secrets. +@deprecated Roadmap has moved to the [Guide Site](https://guide.riot-os.org/misc/roadmap/). +This page will be removed after release 2026.04. diff --git a/doc/doxygen/src/terminal-programs.md b/doc/doxygen/src/terminal-programs.md index b2446b8bce..d4e65c2b57 100644 --- a/doc/doxygen/src/terminal-programs.md +++ b/doc/doxygen/src/terminal-programs.md @@ -1,55 +1,5 @@ -Terminal programs configuration {#terminal-programs} +Terminal programs configuration (Deprecated) {#terminal-programs} =========================================================== -[TOC] - -Background {#background} -========== -This page explains how to configure some popular terminal programs for correct -display of newlines when using the serial interface of a RIOT powered device. -When printing something using *stdio* (e.g., `printf("Hello World!\n");`, RIOT -sends a line feed character (`0xA`) as `\n` (newline). - -Some terminals need more, for example, a carriage return and a line feed -character (0xD, 0xA). See https://en.wikipedia.org/wiki/Newline for background. - -This page tries to collect needed settings for common terminal programs that -will make them correctly display newlines. - -gtkterm {#gtkterm} -====== -- Graphical method: - - Open the configuration menu. - - Click on ***CR LF auto***. -- Manual method: - - Edit the file `~/.gtktermrc`. - - Change value of ***crlfauto*** option to `True`. - -minicom {#minicom} -======= -- Interactive method: - - Press ***Ctrl+A u***. -- Manual method: - - Edit the configuration file (`~/.minirc.dfl` per default). - - Add the following line: - pu addcarreturn Yes - -miniterm {#miniterm} -======== -- Generic method: - - Start with `--eol CR`parameter. -- Via RIOT build system: - - `RIOT_TERMINAL=miniterm make term` - -picocom {#picocom} -======= -- Generic method: - - Start with `--imap lfcrlf` parameter. -- Via RIOT build system: - - `RIOT_TERMINAL=picocom make term` - -putty {#putty} -===== -- Graphical method: - - Go to configuration tree and choose `Terminal` branch. - - Enable option `Implicit CR in every LF`. +@deprecated Guides have moved to the [Guide Site](https://guide.riot-os.org/misc/terminal_config/). +This page will be removed after release 2026.04. diff --git a/doc/doxygen/src/using-cpp.md b/doc/doxygen/src/using-cpp.md index 74d84ff020..a045b61533 100644 --- a/doc/doxygen/src/using-cpp.md +++ b/doc/doxygen/src/using-cpp.md @@ -1,4 +1,4 @@ -Using C++ in RIOT {#using-cpp} +Using C++ in RIOT (Deprecated) {#using-cpp} ================== @deprecated Guides have moved to the [Guide Site](https://guide.riot-os.org/c_tutorials/using_cpp/). diff --git a/doc/doxygen/src/using-rust.md b/doc/doxygen/src/using-rust.md index 563932a31d..9ced590952 100644 --- a/doc/doxygen/src/using-rust.md +++ b/doc/doxygen/src/using-rust.md @@ -1,4 +1,4 @@ -Using Rust in RIOT {#using-rust} +Using Rust in RIOT (Deprecated) {#using-rust} ================== @deprecated Guides have moved to the [Guide Site](https://guide.riot-os.org/). diff --git a/doc/doxygen/src/vision.md b/doc/doxygen/src/vision.md index 8872bf5e3b..f39bc6a8ad 100644 --- a/doc/doxygen/src/vision.md +++ b/doc/doxygen/src/vision.md @@ -1,3 +1,3 @@ -# RIOT Vision {#vision} +# RIOT Vision (Deprecated) {#vision} @deprecated See [Vision](https://guide.riot-os.org/general/vision/) on the RIOT Guide Site for the latest information. This page will be removed after release 2025.11. diff --git a/doc/guides/advanced_tutorials/creating_application.md b/doc/guides/advanced_tutorials/creating_application.md new file mode 100644 index 0000000000..776c1bca45 --- /dev/null +++ b/doc/guides/advanced_tutorials/creating_application.md @@ -0,0 +1,293 @@ +--- +title: Creating an application +description: How to create your own application for RIOT-OS +--- + +To create your own application you need to create a directory containing one or +multiple C file(s) with your source code and a Makefile. A template Makefile is +available in the `dist` folder of the +[RIOT repository](https://github.com/RIOT-OS/RIOT). + +## The main() Function + +After the board is initialized, RIOT starts two threads: the idle thread and +the main thread. The idle thread has the lowest priority and will run whenever +no other thread is ready to run. It will automatically use the lowest possible +power mode for the device. The main thread - configured with a default priority +that is right in the middle between the lowest and the highest available +priorities - is the first thread that runs and calls the `main()` function. +This function needs to be defined in the source code of the application +(typically located in `main.c`). + +```c +#include + +int main(void) +{ + puts("Hello World!"); + return 0; +} +``` + +## The Application's Makefile + +### The Minimal Makefile + +At minimum the Makefile of an application (see +[Creating a Project](/c_tutorials/create_project/)) needs to +define the following macros: + * `APPLICATION`: should contain the name of your application + * `RIOTBASE`: specifies the path to your copy of the RIOT repository (note + that you may want to use `$(CURDIR)` here, to give a relative path) + +The `BOARD` macro is also required and recommended to be set to `native` by +default, but is recommended to be overridable with the `?=` operator. +Additionally, it is required to include the `Makefile.include` from the +`RIOTBASE`. + +```makefile +# Set the name of your application: +APPLICATION = foobar + +# If no BOARD is found in the environment, use this default: +BOARD ?= native + +# This has to be the absolute path to the RIOT base directory: +RIOTBASE ?= $(CURDIR)/../../RIOT + +include $(RIOTBASE)/Makefile.include +``` + +### How to handle unsupported boards? + +Sometimes it is necessary to exclude boards because they don't provide a +required functionality or don't have sufficient memory. RIOT's build system +looks for the macros `BOARD_BLACKLIST`, `BOARD_WHITELIST`, and +`BOARD_INSUFFICIENT_MEMORY`. Any board name that is not included in +`BOARD_WHITELIST` will issue a message that one has to expect errors if they +build the application for the board referred by that name. The list can also be +used by a CI system to not build the application for this board at all. A board +that is included in `BOARD_BLACKLIST` will show the same behavior. The build +system evaluates `BOARD_WHITELIST` first and then `BOARD_BLACKLIST`. The +`BOARD_INSUFFICIENT_MEMORY` macro is similar to `BOARD_BLACKLIST` but will +build in any case. A CI system can use the information provided by the +`BOARD_INSUFFICIENT_MEMORY` macro to skip the linking step in the build +process, since some linkers will issue an error if the code won't fit the +target board's flash memory or RAM. + +### Including Modules + +By default a RIOT application comprises only of the applications' code itself, +the kernel, and platform specific code. In order to use additional modules, +such as a particular [device driver](https://doc.riot-os.org/group__drivers.html) +or [a system library](https://doc.riot-os.org/group__sys.html) +(including [networking capabilities](https://doc.riot-os.org/group__net.html)), +you have to append the modules' names to the USEMODULE variable. +For example, to build an application using the +SHT11 temperature sensor and UDP/IPv6 functionalities of the GNRC network stack, +your Makefile needs to contain these lines: + +```makefile +USEMODULE += sht11 +USEMODULE += gnrc_ipv6_default +USEMODULE += gnrc_udp +``` + +Modules typically pull in all required dependencies themselves. + +## Including Source Files in Subfolders + +By default, all source files in an application's (or any RIOT module's) directory +are automatically compiled as part of the application. In order to organize source +code in a directory structure, two different approaches can be used: + +1. Make each subdirectory a separate RIOT module with a unique name inside its +Makefile, either by adding the directory's path to `DIRS` or with the [out-of-tree +module support](#external-modules). +2. Add the source files within subdirectories to `SRC`, either explicitly or with +Makefile wildcards. + +Both approaches are illustrated and explained in `examples/basic/subfolders`. + +## Setting Board-specific Dependencies + +Required dependencies of applications may change depending on the +target board or architecture. This is especially +relevant for networking applications where multiple hardware implementations +exist and the appropriate implementation has to be chosen for the given board +or architecture. +To achieve this task elegantly, a `Makefile.board.dep` file can be +created in the application folder, which is automatically included and +evaluated by RIOT build system during the dependency resolution phase. +This ensures that all the relevant variables such as `FEATURES_USED` or the +`USEMODULE` list are fully populated. + +```makefile +ifneq (,$(filter arch_esp,$(FEATURES_USED))) + USEMODULE += esp_wifi +endif + +ifneq (,$(filter native native32 native64,$(BOARD))) + USEMODULE += netdev_default +endif +``` + +# Helper Tools + +To help you start writing an application within RIOT, the build system provides +the `generate-example` and `generate-test` make targets. These targets are wrappers +around the [riotgen](https://pypi.org/project/riotgen/) command line tool and +are helpful when starting to implement an application: all required files are +generated with copyright headers, doxygen groups, etc, so you can concentrate +on the module implementation. +For applications, the `Makefile` is generated with the dependencies (modules, +packages, required features) included. + +## Usage: + +To generate an example application, e.g in the `examples` directory, from the +RIOT base directory, run: +```sh +make generate-example +``` + +To generate a test application, e.g in the `tests` directory, from the +RIOT base directory, run: +```sh +make generate-test +``` + +Then answer a few questions about the application: +- Application name: enter a name for your application. It will be used as both + the name of the application directory under `examples` or `tests` and by + the build system module (set in the `APPLICATION` variable). +- Application brief description: Describe in one line what is this application + about. +- Target board: select the default target board. The value is set to `native` + by default. +- Modules: give the list of dependency modules, separated by commas. For + example: `ztimer,fmt` +- Packages: give the list of dependency packages, separated by commas. +- Features required: give the list of CPU features (`periph_*`, etc) required + by the application, all separated by commas. + +Other global information (author name, email, organization) should be retrieved +automatically from your git configuration. + +Once completed, the application files are either located in +`examples/` or `tests/` depending on the +target used. + +**Testrunner:** when using the `make generate-test`, you can also automatically +add a testrunner Python script. Just answer 'y' when prompted. + +# Creating an Out of Tree Application Structure + +Applications written for RIOT do not have to reside in the RIOT tree. Out of +tree applications, modules and boards are supported. + +For a full application with custom board and modules, the following directory +tree can be used: + +``` +├── apps +│ └── my_app +│ └── Makefile +├── boards +│ └── my_board +├── modules +│ └── my_module +│ ├── include +│ │ └── my_module.h +│ ├── Makefile +│ ├── Makefile.include +│ └── my_module.c +└── RIOT +``` + +In this example tree, the `apps` directory contains a collection of applications +for the project. The modules directory could contain extra modules for the +applications. + +The Makefile inside the application needs at least the following as bare minimum: + +```makefile +APPLICATION = my_app +PROJECT_BASE ?= $(CURDIR)/../.. +RIOTBASE ?= $(PROJECT_BASE)/RIOT + +# Optionally, provide paths to where external boards and/or modules +# reside, so that they can be included in the app +EXTERNAL_MODULE_DIRS += $(PROJECT_BASE)/modules +EXTERNAL_BOARD_DIRS += $(PROJECT_BASE)/boards + +include $(RIOTBASE)/Makefile.include +``` + +The `RIOTBASE` variable tells the build system where to find the RIOT source +tree and to need to point to the RIOT source tree used for the application for +the application to work. + +The RIOT directory contains the sources of RIOT here. This can be either a +direct checkout of the sources or a git submodule, whichever has your +preference. + +If your project has separate modules or separate boards, these can be contained +inside a modules os boards directory. The RIOT build system has both +`EXTERNAL_MODULE_DIRS` and `EXTERNAL_BOARD_DIRS` variables to specify +directories that contain extra modules and extra boards. + +## External Boards + +External boards can be ported in an identical way as porting a regular board to +RIOT, see [Porting Boards](/advanced_tutorials/porting_boards/). + +One approach can be to copy over an existing board and modify it to suit the +needs. Boards in the RIOT tree can be included and used as dependency in the +custom boards. In case you connect additional hardware to an upstream board +(such as e.g. an Arduino shield) or you require a different hardware +configuration (e.g. configuring some of the pins configured as ADC as +additional PWM outputs instead) a copy of the upstream board that is then +customized to the application needs is the best course of action. + +## External Modules + +Similar to the external boards, external modules can be written in a similar way +as regular in-tree modules. + +One modification is the include directory inside the module directory. For this +include directory to be added to the include path during compilation, the +following snippet is required in the modules `Makefile.include`: + +```makefile +USEMODULE_INCLUDES_my_module := $(LAST_MAKEFILEDIR)/include +USEMODULE_INCLUDES += $(USEMODULE_INCLUDES_my_module) +``` + +Note that the make variable (here `USEMODULE_INCLUDES_my_module`) must be unique +for every module to make this work. Including the module name here is usually +sufficient. + +## Extra Makefile Scaffolding + +A bit of extra, but optional, Makefile scaffolding can help to keep the project +easy to maintain. An extra `Makefile.include` in the root directory of the +project that sets the necessary variables can help to deduplicate settings. +This includes the `RIOTBASE` variable and the include to the RIOT +`Makefile.include`: + +```makefile +EXTERNAL_MODULE_DIRS += $(PROJECT_BASE)/modules +EXTERNAL_BOARD_DIRS += $(PROJECT_BASE)/boards +RIOTBASE ?= $(PROJECT_BASE)/RIOT +include $(RIOTBASE)/Makefile.include +``` +Applications then just have to set the `PROJECT_BASE` variable and include this +makefile and don't have to each add the external board and module directories. + +The application makefile would then look like this: +```makefile +APPLICATION = my_app +PROJECT_BASE ?= $(CURDIR)/../.. +include $(PROJECT_BASE)/Makefile.include +``` diff --git a/doc/guides/advanced_tutorials/creating_modules.md b/doc/guides/advanced_tutorials/creating_modules.md new file mode 100644 index 0000000000..b6cfa7d4cc --- /dev/null +++ b/doc/guides/advanced_tutorials/creating_modules.md @@ -0,0 +1,201 @@ +--- +title: Creating modules +description: Guide on how to create modules in RIOT-OS +--- + +Modules in RIOT are well-defined units of code that provide a set of features +to your application. This includes also drivers and to a certain extent ports +for CPUs and boards (with some exceptions, see the +[porting guide](/advanced_tutorials/porting_boards/) for further information). + +## The General Structure + +Like [applications](/advanced_tutorials/creating_application/), modules are directories +containing source files and a Makefile. Additionally their API can be defined +in one or more header files, residing in the include path of their +super-module. + +E.g. the [Shell](https://doc.riot-os.org/group__sys__shell.html) module +is implemented in `sys/shell` and defines its +API in `sys/include/shell.h` and the +[ISL29020 light sensor](https://doc.riot-os.org/group__drivers__isl29020.html) +driver is implemented in `drivers/isl29020` +and defines its API in `drivers/include/isl29020.h`. + +A module's Makefile just needs to include `Makefile.base` in the RIOT +repository: + +```makefile +include $(RIOTBASE)/Makefile.base +``` + +If your module's name differs from the name of the directory it resides in you +need to set the `MODULE` macro in addition. + +When compiled a module always provides a `MODULE_` macro to the +system. This way, other modules can check if the module is available in the +current configuration or not. + +Modules can be used by adding their name to the `USEMODULE` macro of your +application's Makefile. + +### Pitfalls + +The `MODULE` name should be unique or build breaks as modules overwrite the +same output file. This might for example lead to `undefined reference to` errors +in the linker which can be hard to track down. + +This problem happened in the past for: + + * Packages root directory (libfixmath/u8g2) + * boards/cpu/periph and their common boards/cpu/periph + +Note: even if all boards and cpus implement the `board` and `cpu` modules, only + one is used in an application so there is no conflict. + + +## Module Dependencies + +Your module may depend on other modules to minimize code duplication. These +dependencies are defined in `Makefile.dep` with the following syntax: + +```makefile +ifneq (,$(filter your_module,$(USEMODULE))) # if module in USEMODULE + USEMODULE += dep1 # add dependencies to USEMODULE + USEMODULE += dep2 +endif +``` + +Note, that `Makefile.dep` is processed only once so you have to take care to +add the dependency block for your module *before* your dependencies pull in +their dependencies. + +## Modules Outside of RIOTBASE + +Modules can be defined outside of `RIOTBASE`. In addition to adding it to `USEMODULE` +the user needs to add the directory (or directories) containing external modules +to `EXTERNAL_MODULE_DIRS`. + +External modules can optionally define the following files: +* `Makefile.include` file to set global build configuration like `CFLAGS` or add + API headers include paths to the `USEMODULE_INCLUDES` variable. +* `Makefile.dep` file to set module dependencies + +:::note +The name of an external module must be unique (both in regard to other +external modules, as well to native RIOT modules). Additionally, the +directory containing the module must match the module name, e.g. +module `foo` must be located in `/foo`. +::: + +An example can be found in +[`tests/build_system/external_module_dirs`](https://github.com/RIOT-OS/RIOT/tree/master/tests/build_system/external_module_dirs) + +## Pseudomodules + +Pseudomodules are modules that are not static libraries, i.e. do not generate a +`.a` file. + +To create a pseudomodule just add its name to `makefiles/pseudomodules.inc.mk` +with `PSEUDOMODULES += ` in alphabetical order. + +A Pseudomodule may or may not have a source file associated with it. To make the +distinction between them we will refer to those that don't as true-Pseudomodules. + +The main use case for true-Pseudomodules is to provide base information for +dependencies to other modules or information to the code base via the +`MODULE_` macro. + +Pseudomodules with source code exist under a "real" `MODULE` since they will +generate a `.o` file grouped under that `MODULE`s +`.a` file. + +These modules appear in RIOT under two forms: + +1. Conditionally included source files: + + ``` + foo/ + |----foo_bar.c + |----foo.c + |----Makefile + ``` + +In `foo/Makefile` you add the source file to the `SRC` variable, conditioned on +the Pseudomodule inclusion + + ```makefile + ifneq (,$(filter foo_bar,$(USEMODULE))) + SRC += foo_bar.c + endif + ``` + +See `sys/net/ble/skald` for an example in code. + +2. Using the `SUBMODULES` mechanism: + + ``` + foo/ + |----spam.c + |----ham.c + |----eggs.c + |----Makefile + ``` + + ```makefile + # make all code end up in "foo_bar.a", this can be any name + MODULE := foo_bar + + # ensure that "foo_ham" or "bar_foo_ham" builds "foo_ham.c". + BASE_MODULE := foo + + # list of source files that are not SUBMODULES + SRC := spam.c + + # enable submodules by setting SUBMODULES = 1 + SUBMODULES = 1 + ``` + +When using `SUBMODULES` in a `MODULE` all `SRC` file excluded from `foo/Makefile` +will be considered `SUBMODULES`. In the example above `ham.c` and `eggs.c`. +These source files will be conditionally included depending if the modules have +been added, i.e. `USEMODULE += foo_ham foo_eggs` (it's the same as case 1 but +handled automatically in `Makefile.base`). + +The `SUBMODULES` mechanism is more flexible since `BASE_MODULE` allows matching +the only parts of compounded module names and only match against part of that name. + +See `sys/ztimer/Makefile` for an example in code. + +`SUBMODULES` can also be true-pseudomodules, or become one by conditionally excluding +the source files by adding them to `SUBMODULES_NO_SRC`. + +# Helper Tools + +To help you start writing a module, the RIOT build system provides the +`generate-module` make target. It is a wrapper around the +[riotgen](https://pypi.org/project/riotgen/) command line tool that is helpful +when starting to implement a module: all required files are generated with +copyright headers, doxygen groups, etc, so you can concentrate on the module +implementation. +The module source files are created in the `sys` directory. + +## Usage + +From the RIOT base directory, run: +```sh +make generate-module +``` +Then answer a few questions about the driver: +- Module name: enter a name for your module. It will be used as both the name + of the module directory under sys, where the source files are created, and + the build system module (used with `USEMODULE`). +- Module doxygen name: Enter the name of module, as displayed in the + Doxygen documentation. +- Brief doxygen description: Describe in one line what is this module about. + +Other global information (author name, email, organization) should be retrieved +automatically from your git configuration. + +Once completed, the module files are located in +`sys//.c` and `sys/include/.h`. diff --git a/doc/guides/advanced_tutorials/device_drivers.md b/doc/guides/advanced_tutorials/device_drivers.md new file mode 100644 index 0000000000..1470f2417f --- /dev/null +++ b/doc/guides/advanced_tutorials/device_drivers.md @@ -0,0 +1,501 @@ +--- +title: Writing a Device Driver in RIOT +description: Guidelines and best practices for writing device drivers in RIOT-OS +--- + +This document describes the requirement, design objectives, and some +non-function details when writing device drivers in/for RIOT. The term device +driver in this context includes all 'CPU-external' devices connected to the CPU +typically via peripherals like SPI, I2C, UART, GPIO, and similar. CPU +peripherals itself are in RIOT not considered to be device drivers, but +peripheral or low-level drivers. Typical devices are network devices like +radios, Ethernet adapters, sensors, and actuators. + +# General Design Objectives + +Device drivers should be as easy to use as possible. This implies an +'initialize->ready' paradigm, meaning, that device drivers should be ready to use +and in operation right after they have been initialized. On top, devices should +work with physical values wherever possible. So e.g. sensors should return +already converted values in some physical unit instead of RAW data, so that +users can work directly with data from different devices directly without having +to care about device specific conversion. + +However, please avoid the use of `float` or `double`. Instead, multiply to the +next SI (or appropriate) unit. E.g. if an ADC would return values like `1.23 V`, +choose to return `1230 mV` instead. + +Additionally, towards ease of use, all device drivers in RIOT should provide a +similar 'look and feel'. They should behave similarly in terms of their state +after initialization, like their used data representation and so on. + +Secondly, all device drivers should be optimized for minimal RAM/ROM usage, as +RIOT targets (very) constrained devices. This implies that instead of exposing +all thinkable functionality, the drivers should focus on exporting and +implementing a device's core functionality, thus covering ~95% of the use cases. + +Third, it should always be possible to handle more than a single device of the +same kind. Drivers and their interfaces are thus designed to keep their state +information in a parameterized location instead of driver defined global +variables. + +Fourth, RIOT defines high-level interfaces for certain groups of devices (i.e. +netdev for network devices, SAUL for sensors and actuators), which enable users +to work with a wide variety of devices without having to know much about the +actual device that is mapped. + +Fifth, during initialization, we make sure that we can communicate with a device. +Other functions should check the dev pointer is not void, and should also handle +error return values from the lower layer peripheral driver implementations, +where there are some. + +Sixth, device drivers SHOULD be implemented independent of any CPU/board code. +To achieve this, the driver implementations should strictly be based on +platform independent interfaces as the peripheral drivers, xtimer, etc. + +# General + +## Documentation + +Document what your driver does! Most devices come with a very large number of +features, while the corresponding device driver only supports a subset of them. +This should be clearly stated in the device driver's documentation so that +anyone wanting to use the driver can find out the supported features without +having to scan through the code. + +## Device descriptor and parameter configuration + +Each device MUST supply a data structure, holding the devices state and +configuration, using the naming scheme of `DEVNAME_t` (e.g. `dht_t`, or +`at86rf2xx_t`). In the context of RIOT, we call this data structure the device +descriptor. + +This device descriptor MUST contain all the state data of a device. By this, we +are not limited to the number of instances of the driver we can run +concurrently. The descriptor is hereby used for identifying the device we want +to interact with, and SHOULD always be the first parameter for all device driver +related functions. + +Typical things found in these descriptors are e.g. used peripherals (e.g. SPI or +I2C bus used, interfacing GPIO pins), data buffers (e.g. RX/TX buffers where +needed), or state machine information. + +On top of the device descriptor, each device driver MUST also define a data +structure holding the needed configuration data. The naming scheme for this type +is `DEVNAME_params_t`. In contrary to the device descriptor, this data structure +should only contain static information, that is needed for the device +initialization as it is preferably allocated in ROM. + +A simple I2C temperature sensors' device descriptor could look like this: + +```c +typedef struct { + tmpabc_params_t p; /**< device configuration parameter like I2C bus and bus addr */ + int scale; /**< some custom scaling factor for converting the results */ +} tmpabc_t; + +/* with params being */ +typedef struct { + i2c_t bus; /**< I2C bus the device is connected to */ + uint8_t addr; /**< the device's address on the bus */ +} tmpabc_params_t; +``` + +**NOTE:** In many cases it makes sense, to copy the `xxx_params` data into the +device descriptor during initialization. In some cases, it is, however, better +to just link the `params` data via pointer and only copy selected data. This way, +configuration data that is only used once can be read directly from ROM, while +often used fields (e.g. used peripherals) are stored directly in the device +descriptor and one saves hereby one de-referencing step when accessing them. + +## Default device configuration + +Each device driver in RIOT MUST supply a default configuration file, named +`DEVNAME_params.h`. This file should be located in the `RIOT/drivers/...`. The +idea is that this file can be overridden by an application or a board, by +simply putting a file with the same name in the application's or the board's +include folders, while RIOT's build system takes care of preferring those files +instead of the default params file. + +A default parameter header file for the example temperature sensor above would +look like this (`tmpabc_params.h`): + +```c +/* ... */ + +#include "board.h" /* THIS INCLUDE IS MANDATORY */ +#include "tmpabc.h" + +/* ... */ + +/** + * @brief Default configuration parameters for TMPABC sensors + * @{ + */ +#ifndef TMPABC_PARAM_I2C +#define TMPABC_PARAM_I2C (I2C_DEV(0)) +#endif +#ifndef TMPABC_PARAM_ADDR +#define TMPABC_PARAM_ADDR (0xab) +#endif + +#ifndef TMPABC_PARAMS +#define TMPABC_PARAMS { .i2c = TMPABC_PARAM_I2C \ + .addr = TMPABC_PARAM_ADDR } +#endif +/** @} */ + +/** + * @brief Allocation of TMPABC configuration + */ +static const tmpabc_params_t tmpabc_params[] = { + TMPABC_PARAMS +} +/* ... */ +``` + +Now to influence the default configuration parameters, we have these options: + +First, we can override one or more of the parameter from the makesystem, e.g. + +```sh +CFLAGS="-DTMPABC_PARAM_ADDR=0x23" make all +``` + +Second, we can override selected parameters from the board configuration +(`board.h`): + +```c +/* ... */ +/** + * @brief TMPABC sensor configuration + * @{ + */ +#define TMPABC_PARAM_I2C (I2C_DEV(1)) +#define TMPABC_PARAM_ADDR (0x17) +/** @} */ +/* ... */ +``` + +Third, we can define more than a single device in the board configuration +(`board.h`): + +```c +/* ... */ +/** + * @brief Configure the on-board temperature sensors + * @{ + */ +#define TMPABC_PARAMS { \ + .i2c = I2C_DEV(1), \ + .addr = 0x31 \ + }, \ + { \ + .i2c = I2C_DEV(1), \ + .addr = 0x21 \ + } +/** @} */ +/* ... */ +``` + +And finally, we can simply override the `tmpabc_params.h` file as described +above. + +## Compile-time configuration documentation + +The macros that configure the driver during compilation is added to the listing +for [Compile time configurations](https://doc.riot-os.org/group__config.html). Refer to the following example +that exposes +[TMP00x sensor](https://github.com/RIOT-OS/RIOT/blob/2025.07-branch/drivers/include/tmp00x.h#L96-L157) +to [sensors group](https://doc.riot-os.org/group__config__drivers__sensors.htmls). + +```c +/** + * @defgroup drivers_tmp00x_config TMP006/TMP007 Infrared Thermopile + * Sensor driver compile configuration + * @ingroup config_drivers_sensors + * @{ + */ +/** + * @brief Default Address + * .... + */ +#ifndef TMP00X_I2C_ADDRESS +#define TMP00X_I2C_ADDRESS (0x40) +#endif +.... +/** @} */ +``` + +Sub-groups defined for different types of drivers can be found in +[drivers/doc.txt](https://github.com/RIOT-OS/RIOT/blob/master/drivers/doc.txt) + +## Initialization + +In general, the initialization functions should do the following: + +- initialize the device descriptor +- initialize non-shared peripherals they use, e.g. GPIO pins +- test for device connectivity, e.g. does an SPI/I2C slave react +- reset the device to a well-defined state, e.g. use external reset lines or do + a software rest +- do the actual device initialization + +For testing a device's connectivity, it is recommended to read certain +configuration data with a defined value from the device. Some devices offer +`WHO_AM_I` or `DEVICE_ID` registers for this purpose. Writing and reading back +some data to the device is another valid option for testing its responsiveness. + +For more detailed information on how the signature of the init functions should +look like, please refer below to the specific requirements for network devices +and sensors. + +## Return Values + +As stated above, we check communication of a device during initialization and +handle error return values from the lower layers, where they exist. To prevent +subsequent misuse by passing NULL pointers and similar to the subsequent +functions, the recommended way is to check the parameter using `assert`, e.g.: + +```c +int16_t tmpabc_read(const tmpabc_t *dev) +{ + assert(dev); + /* ... */ + return value; +} +``` + +Whenever you implement status/error return values in your driver, magic numbers +MUST ***NOT*** be used. Instead, use negative `errno` codes (such as `-EIO` for +an input/output error) and *document* every single error code that can be +return for each function using the `reval` Doxygen command. E.g. like this: + +```c +/** + * @brief Initialize the foo device and its descriptor + * @param[out] dev Device descriptor to initialized + * @param[in] params Device initialization parameters + * + * @retval 0 Success + * @retval -ENXIO No foo device connected to the I2C bus + * @retval -ENODEV Device using the foo I2C address is not a foo device + * etc. + */ +int foo_init(foo_t *dev, const foo_params_t *params); +``` + +You can multiplex this information whenever this is reasonable, as long as a +negative return value indicates an error without exceptions. E.g. like this: + +```c +/** + * @brief Perform a relative humidity measurement + * @param[in] dev Humidity sensor to perform the measurement on + * + * @return The relative humidity in percent + * @retval -EIO Communication with the sensor failed + */ +int foo_humidity(const foo_t *dev); +``` + +### Documenting Return Values + +With the exception of functions returning `void`, all return values have to be +documented. Use the `return` Doxygen command to describe what is returned. In +order to document special return value (such as error codes), use the `retval` +command. The `retval` command expects the specific value to document as first +argument (no spaces in the value allowed!), and a description (spaces allowed +here) as second. It is safe to use both `return` and `retval` commands, or just +one of them - whatever makes most sense for a given function. + +## General Device Driver Checklist + +- *MUST*: the supported feature set and any custom behavior is clearly + documented +- *MUST*: device descriptor is defined: `devab_t` +- *MUST*: device parameter `struct` is defined: `devab_params_t` +- *MUST*: a default parameter configuration file is present, e.g. + `RIOT/drivers/devab/include/devab_params.h` +- *MUST*: all error and status return codes are named, e.g. + `DEVAB_OK, DEVAB_NOSPI, DEVAB_OVERFLOW, ...` +- *MUST*: use `const devab_t *dev` when the device descriptor can be access + read-only + +## Build system integration + +### Internal include files + +If the driver contains internal include files, a `Makefile.include` must be +added in the driver implementation directory, with the following content +(adapted to the name of the driver module): + +``` +USEMODULE_INCLUDES_ := $(LAST_MAKEFILEDIR)/include +USEMODULE_INCLUDES += $(USEMODULE_INCLUDES_) +``` + +### External dependencies + +If the driver has other module or CPU features dependencies (like `xtimer` or +`periph_i2c`), they must be added in the `$(RIOTBASE)/drivers/Makefile.dep` +file in a block like below (this is an example, you'll have to adapt to the +driver requirements): + +``` +ifneq (,$(filter ,$(USEMODULE))) + FEATURES_REQUIRED += periph_i2c + USEMODULE += xtimer +endif +``` + +**Warning:** Please be careful with alphabetical order when modifying this file. + +## Helper tools + +To help you start writing a device driver, the RIOT build system provides the +`generate-driver` make target. It is a wrapper around the +[riotgen](https://pypi.org/project/riotgen/) command line tool that is helpful +when starting to implement a driver: all minimum files are generated with +copyright headers, doxygen groups, etc, so you can concentrate on the driver +implementation. + +**Usage:** + +From the RIOT base directory, run: +``` +make generate-driver +``` +Then answer a few questions about the driver: +- Driver name: enter a name for your driver. It will be used as both the name + of the driver directory where the source files are created and the build + system module. +- Driver doxygen group name: Enter the name of the driver, as displayed in the + Doxygen documentation. +- Brief doxygen description: Describe in one line what is this driver about. +- Parent driver Doxygen group: Enter the Doxygen group the driver belongs to. + It can be `actuators`, `display`, `misc`, `netdev`, `sensors`, `storage`. + +Other global information (author name, email, organization) should be retrieved +automatically from your git configuration. + +# Sensors + +## SAUL + +All sensor drivers SHOULD implement the SAUL interface. It is however +recommended, that the drivers are written in a way, that the drivers do not +solely export the SAUL interface, but map the SAUL interface upon a driver +specific one. + +For example, a temperature driver provides the following function (`tmpabc.c`): + +```c +int16_t tmpabc_read(tmpabc_t *dev); +``` + +which then can easily be mapped to SAUL (`tmpabc_saul.c`): + +```c +int saul_read(saul_t *dev, phydat_t *data) +{ + memset(data, 0, sizeof(phydat_t)); + data->x = tmpabc_read((tmpabc_t *)dev); + data->unit = UNIT_TEMP_C; + data->scale = -2; + return 1; +} +``` + +This ensures the versatility of the device driver, having in mind that one might +want to use the driver without SAUL or maybe in a context without RIOT. + +## Initialization + +Sensor device drivers are expected to implement a single initialization +function, `DEVNAME_init`, taking the device descriptor and the device's +parameter struct as argument: + +```c +int tmpabc_init(tmpabc_t *dev, const tmpabc_params_t *params); +``` + +After this function is called, the device MUST be running and usable. + +## Value handling + +### Value semantics + +All sensors in RIOT MUST return their reading results as real physical values. +When working with sensor data, these are the values of interest, and the +overhead of the conversion is normally neglectable. + +### Typing + +All values SHOULD be returned using integer types, with `int16_t` being the +preferred type where applicable. + +In many situations, the physical values cannot be mapped directly to integer +values. For example, we do not want to map temperature values to integers +directly while using their fraction. The recommended way to solve this is by +scaling the result value using decimal fixed point arithmetic, in other words, +just return centi-degree instead of degree (e.g. 2372c°C instead of 23.72°C). + +## Additional Sensor Driver Checklist + +- *MUST*: mandatory device parameters are configurable through this file, e.g. + sampling rate, resolution, sensitivity +- *MUST*: an init function in the style of + `int devab_init(devab_t *dev, const devab_params_t *params);` exists +- *MUST*: after initialization, the device must be operational +- *MUST*: all error and return values are named, e.g. + `DEVAB_OK, DEVAB_NODEV, ...` +- *MUST*: all 'read' functions return values in their physical representation, + e.g. `centi-degree, Pa, lux, mili-G` +- *MUST*: all 'read' functions return integer values, preferably `int16_t` +- *SHOULD*: if multiple dimensions are read, they SHOULD be combined into a + data structure +- *SHOULD*: the driver implements the SAUL interface +- *SHOULD*: the driver exports functions for putting it to sleep and waking up + the device + +# Network devices + +## Initialization + +The initialization process MUST be split into 2 steps: first, initialize the +device descriptor and if applicable the used peripherals, and secondly do the +actual device initialization. The reason for this is, that before a device is +actually activated and can start to process data, the network stack for the +device needs to be initialized. By supplying a second init function, that does +the actual initialization, we can hand the control over when this is done to the +actual network stacks. + +The initialization functions SHOULD follow this naming scheme: + +```c +void netabc_setup(netabc_t *dev, const netabc_params_t *params); +int netabs_init(netabc_t *dev); +``` + +## netdev + +Device driver for network device SHOULD implement the `netdev` interface. It is +up to the implementer, if the device driver also offers a device specific +interface which is then mapped to the `netdev` interface, or if the device +driver can be purely interfaced using `netdev`. While the second option is +recommended for efficiency reasons, this is not mandatory. + +## Additional Network Device Driver Checklist + +- *MUST*: a setup function in the style of + `int devab_setup(devab_t *dev, const devab_params_t *params);` exists +- *MUST*: an init function in the style of `int devnet_init(devnet_t *dev)` + exists +- *SHOULD*: the driver implements 'netdev' [if applicable] + +# TODO + +Add some information about how to handle multiple threads, when to use mutexes, +and how to deal with interrupts? And especially patterns for being nice from +other threads and power consumption point of view... diff --git a/doc/doxygen/dot/porting-boards.dot b/doc/guides/advanced_tutorials/img/porting-boards.dot similarity index 100% rename from doc/doxygen/dot/porting-boards.dot rename to doc/guides/advanced_tutorials/img/porting-boards.dot diff --git a/doc/guides/advanced_tutorials/img/porting-boards.svg b/doc/guides/advanced_tutorials/img/porting-boards.svg new file mode 100644 index 0000000000..f01f4b4e4e --- /dev/null +++ b/doc/guides/advanced_tutorials/img/porting-boards.svg @@ -0,0 +1,199 @@ + + + + + + + + + +Start + +Start + + + +IfCPU + + +CPU/MCU +already ported? + + + + + +Start->IfCPU + + + + + +End + + +Blink the LEDs + + + + + +IfBoard + + +Board definitions +already provided? + + + + + +IfCPU->IfBoard + + +Yes + + + +PortCPU + + +Port +CPU +(TBD: provide guide) + + + + + +IfCPU->PortCPU + + +No + + + +IfDrivers + + +All on-board +devices supported? + + + + + +IfBoard->IfDrivers + + +Yes + + + +PortBoard + + +Provide +board definitions + + + + + +IfBoard->PortBoard + + +No + + + +IfNetdev + + +Network device +supported by +network stack? + + + + + +IfDrivers->IfNetdev + + +Yes + + + +PortDrivers + + +Provide +device drivers + + + + + +IfDrivers->PortDrivers + + +No + + + +IfNetdev->End + + +Yes + + + +PortNetdev + + +Provide +network device support +for network stack + + + + + +IfNetdev->PortNetdev + + +No + + + +PortCPU->IfBoard + + + + + + +PortBoard->IfDrivers + + + + + + +PortDrivers->IfNetdev + + + + + + +PortNetdev->End + + + + + diff --git a/doc/guides/advanced_tutorials/porting_boards.md b/doc/guides/advanced_tutorials/porting_boards.md new file mode 100644 index 0000000000..d40ef8c696 --- /dev/null +++ b/doc/guides/advanced_tutorials/porting_boards.md @@ -0,0 +1,435 @@ +--- +title: Porting Boards +description: Guide on how to port new boards to RIOT-OS +--- + +At some point you might need to port a new `BOARD` to `RIOT`, either because +that specific development board is not yet supported or because you have a +custom `BOARD` for your project. + +If you want to port a `BOARD` to `RIOT` you have two choices: doing it +inside of `RIOTBASE` or outside. In either case the file structure +is basically the same and moving from one to another is easy. + +This guide details the generic structure you need to add a new `BOARD` +to `RIOT`, the different files as well as their functionality. + +:::note +We assume here that your `CPU` and `CPU_MODEL` is already supported +in `RIOT` so no peripheral or cpu implementation is needed. +::: + +# Porting Flowchart +![Porting flowchart](img/porting-boards.svg) + +# General Structure + +Like [applications](/advanced_tutorials/creating_applications/) or +[modules](/advanced_tutorials/creating_modules), +boards consist of a directory containing source files and +Makefiles. Usually a `BOARD` directory has the following structure, +although not all of the subdirectories or Makefiles have to be present for +a board implementation to work. + +``` + board-foo/ + |----dist/ + |----scripts + |----board.c + |----doc.md + |----include/ + |----periph_conf.h + |----board.h + |----gpio_params.h + |----Makefile + |----Makefile.dep + |----Makefile.features + |----Makefile.include +``` + +## Source Files + +Header files in `board-foo/include` define physical mappings or +configurations. e.g: + +- `periph_conf.h`: defines configurations and mappings for peripherals as well + as clock configurations. +- `board.h`: holds board specific definitions or mappings, for example LEDs, + buttons. It might as well override default drivers parameters (e.g.: assigning + specific pin connections to a LCD screen, radio, etc.). +- `gpio_params.h`: if the board supports + [SAUL](https://doc.riot-os.org/group__drivers__saul.html) then its + [saul_gpio_params_t](https://doc.riot-os.org/structsaul__gpio__params__t.html) + is defined here. (Analogously, an `adc_params.h` can + contain a [saul_adc_params_t](https://doc.riot-os.org/structsaul__adc__params__t.html) + and `pwm_params.h` a + [saul_pwm_rgb_params_t](https://doc.riot-os.org/structsaul__pwm__rgb__params__t.html) + and a [saul_pwm_dimmer_params_t](https://doc.riot-os.org/structsaul__pwm__dimmer__params__t.html)). +- other: other specific headers needed by one `BOARD` + +:::note +Header files do not need to be defined in `include/`, but if defined +somewhere else then they must be added to the include path in +`Makefile.include`: `INCLUDES += -I//` +::: + +Board initialization functions are defined in `board.c`. +This file can define a `board_init()` function that is called at startup. +It is run before the scheduler is started, so it must not block (e.g. by +performing I2C operations). + +```c +void board_init(void) +{ + /* initialize GPIO or others... */ + ... +} +``` + +## Makefiles + +### Makefile + +A board's Makefile just needs to include `Makefile.base` in the RIOT +repository and define the `MODULE` as `board` (see +[modules](/advanced_tutorials/creating_modules) for more details) + +```makefile +MODULE = board + +include $(RIOTBASE)/Makefile.base +``` + +### Makefile.dep + +Dependencies on other `MODULES` or `FEATURES` can be defined here. This might +specify `MODULES` or dependencies that need to be pulled under specific +configurations. e.g.: if your board has a sx1276 lora chip: + +```makefile +ifneq (,$(filter netdev_default,$(USEMODULE))) + USEMODULE += sx1276 +endif +``` + +:::note +`Makefile.dep` is processed only once so you have to take care of adding +the dependency block for your board *before* its dependencies pull in their own +dependencies. +::: + +#### Default Configurations +There are two pseudomodules that are used to indicate that certain drivers of devices +present in the platform should be enabled. Each board (or CPU) has knowledge as +to which drivers should be enabled in each case. + +The previous code snippet shows how a board which has a +[Semtech SX1272 and SX1276 radio driver](https://doc.riot-os.org/group__drivers__sx127x.html) +device, pulls in its driver when the default network interfaces are required. + +When the pseudomodule `saul_default` is enabled, the board should pull in all +the drivers of the devices it has which provide a +[[S]ensor [A]ctuator [U]ber [L]ayer](https://doc.riot-os.org/group__drivers__saul.html) +interface. This is usually done as following: + +```makefile +ifneq (,$(filter saul_default,$(USEMODULE))) + USEMODULE += saul_gpio + USEMODULE += apds9960 + USEMODULE += bmp280_i2c + USEMODULE += lis3mdl + USEMODULE += sht3x +endif +``` + +### Makefile.features + +This file defines all the features provided by the BOARD. These features +might also need to be supported by the `CPU`. Here, define the `CPU` and +`CPU_MODEL` (see [build system basics](/build-system/build_system_basics/) +for more details on these variables). + +e.g.: + +```makefile +CPU = foo +CPU_MODEL = foobar + +# Put defined MCU peripherals here (in alphabetical order) +FEATURES_PROVIDED += periph_i2c +FEATURES_PROVIDED += periph_spi +FEATURES_PROVIDED += periph_uart +``` + +### Makefile.include + +This file contains BSP or toolchain configurations for the `BOARD`. It +should at least define the configuration needed for flashing (i.e. specify a +default programmer) as well as the serial configuration (if one is available). +The default serial port configuration is provided by +`makefiles/tools/serial.inc.mk` and defines the following values for the serial +port (depending on the host OS): + +``` +PORT_LINUX ?= /dev/ttyACM0 +PORT_DARWIN ?= $(firstword $(sort $(wildcard /dev/tty.usbmodem*))) +``` + +So if the board is also using this, there's no need to redefine these variables +in the board configuration. + +For example a board that is using a custom serial port (via an USB to serial +adapter) and that is flashed using OpenOCD by default would have the following +content in its `Makefile.include`: + +```makefile +# Define the default port depending on the host OS +PORT_LINUX ?= /dev/ttyUSB0 +PORT_DARWIN ?= $(firstword $(sort $(wildcard /dev/tty.usbserial*))) + +# this board uses OpenOCD +PROGRAMMER ?= openocd +``` + +## Timer Configurations + +When using the high level timer `ztimer` there is an overhead in calling the +[ztimer_sleep](https://doc.riot-os.org/group__sys__ztimer.html#gade98636e198f2d571c8acd861d29d360) +and [ztimer_set](https://doc.riot-os.org/group__sys__ztimer.html#ga8934a79a89e35d58673418a1e4a2e69c) +functions. This offset can be compensated for. +It can be measured by running `tests/sys/ztimer_overhead` on your board, i.e: + +```bash +$ BOARD=my-new-board make -C tests/sys/ztimer_overhead flash term +main(): This is RIOT! +ZTIMER_USEC auto_adjust params: + ZTIMER_USEC->adjust_set = xx + ZTIMER_USEC->adjust_sleep = xx +ZTIMER_USEC auto_adjust params cleared +zitmer_overhead_set... +min=6 max=7 avg_diff=6 +zitmer_overhead_sleep... +min=21 max=21 avg_diff=21 +ZTIMER_USEC adjust params for my-new-board: + CONFIG_ZTIMER_USEC_ADJUST_SET 6 + CONFIG_ZTIMER_USEC_ADJUST_SLEEP 21 +``` + +The last two lines can be added as defines to the new board `board.h`: + +```c +/** + * @name ztimer configuration values + * @{ + */ +#define CONFIG_ZTIMER_USEC_ADJUST_SET 6 +#define CONFIG_ZTIMER_USEC_ADJUST_SLEEP 21 +/** @} */ +``` + +Alternatively, the pseudomodule [ztimer_auto_adjust](https://doc.riot-os.org/group__pseudomodule__ztimer__auto__adjust.html) +can be used in an application to enable automatic timer offset compensation at board startup. +This however incurs overhead both in the text segment and at bootup time. + +## doc.md + +Although not explicitly needed, if upstreamed and as a general good +practice, this file holds all `BOARD` documentation. This can include +datasheet reference, documentation on how to flash, etc. + +The documentation must be under the proper doxygen group, you can compile the +documentation by calling `make doc` and then open the generated html file on +any browser. + +```markdown +@defgroup boards_foo FooBoard +@ingroup boards +@brief Support for the foo board +@author FooName BarName + +### User Interface + + ... + +### Using UART + + ... + +### Flashing the device + + ... +``` + +Previously documentation was contained in `doc.txt` files with C-style comment +blocks. This style has been deprecated in favor of using `doc.md` files in +Markdown format, which eliminates formatting and interpretation issues. +Old style files will continually be replaced by the new format. + +Up to version `0.9.2` the [riotgen](https://pypi.org/project/riotgen/) tool +will generate `doc.txt` files instead of `doc.md` files. You can upgrade it to +the latest version with + +```bash +pip install --upgrade riotgen +``` + +# Helper Tools + +To help you start porting a board, the RIOT build system provides the +`generate-board` make target. It is a wrapper around the +[riotgen](https://pypi.org/project/riotgen/) command line tool that is helpful +when starting to port a board: all required files are generated with +copyright headers, doxygen groups, etc, so you can concentrate on the port. +The board source files are created in the `boards/` directory. + +## Usage: + +From the RIOT base directory, run: + +```bash +make generate-board +``` + +Then answer a few questions about the driver: +- Board name: Enter a name for your board. It will be used as the name + of the board directory under `boards`. +- Board displayed name: Enter the name of the board, as displayed in the + Doxygen documentation. +- CPU name: Enter the name of the CPU embedded on the board. +- CPU model name: Enter the precise model name of the CPU. +- Features provided: CPU features provided (and configured) for this board. + +Other global information (author name, email, organization) should be retrieved +automatically from your git configuration. + +# Using Common Code + +To avoid code duplication, common code across boards has been grouped in +`boards/common`. e.g. `BOARD`s based on the same cpu (`boards/common/nrf52`) or +`BOARD`s having the same layout `boards/common/nucleo64`. + +In the case of source files this means some functions like `board_init` can be +already defined in the common code. Unless having specific configurations or +initialization you might not need a `board.c` or `board.h`. Another common use +case is common peripheral configurations, for example in the `cfg_timer_tim5.h`: + +```c +/** + * @name Timer configuration + * @{ + */ +static const timer_conf_t timer_config[] = { + { + .dev = TIM5, + .max = 0xffffffff, + .rcc_mask = RCC_APB1ENR_TIM5EN, + .bus = APB1, + .irqn = TIM5_IRQn + } +}; + +#define TIMER_0_ISR isr_tim5 + +#define TIMER_NUMOF ARRAY_SIZE(timer_config) +/** @} */ +``` + +# Boards Outside of RIOTBASE + +All `BOARD`s in RIOT reside in `RIOTBOARD` (`RIOTBOARD` being a make variable +set to `$(RIOTBOARD)/boards`). + +If one wants to use a `BOARD` outside of `RIOTBOARD`, the way to go is setting +the `EXTERNAL_BOARD_DIRS` variable to the path to the directory containing your +external boards, e.g.: `EXTERNAL_BOARD_DIRS=/home/external-boards/` (this would +commonly be done in your application `Makefile` or your environment). You can +specify multiple directories separated by spaces. + +``` +/home/ +|----RIOT/ + |---- ... +|----external-boards/ + |----board-foo/ + |----dist/ + |----scripts + |----board.c + |----doc.md + |----include/ + |----periph_conf.h + |----board.h + |----gpio_params.h + |----Makefile + |----Makefile.dep + |----Makefile.features + |----Makefile.include +``` + +If the external `BOARD` is very similar to a `BOARD` already present in +`RIOTBOARD`, the external `BOARD` (`board-foo`) can inherit from that +parent `BOARD` (e.g: `foo-parent`). + +In this case some special considerations must be taken with the makefiles: + +- `Makefile` + - `MODULE` cannot be `board`: `foo-parent` will already define + `MODULE = board`, so use any other name, lets say `MODULE = board-foo`. + - Include the location of the parent `BOARD` to inherit from (if there is + one): + +```makefile + DIRS += $(RIOTBOARD)/foo-parent +``` + +- `Makefile.include` + - duplicate the include done by `$(RIOTBASE)/Makefile.include` to also + include the parent board header. e.g: if inheriting from `foo-parent` + ``INCLUDES += $(addprefix -I,$(wildcard $(RIOTBOARD)/foo-parent/include))` + +- `Makefile.dep`: `board` is added by default to `USEMODULE` but since + `board-foo` is used for this `BOARD`, it must be explicitly included by adding + `USEMODULE += board-foo`. + +- Then simply include in each `Makefile.*` the corresponding parent `BOARD` + `Makefile.*`, just as it is done for common `BOARD` code (as explained in + [Using Common Code](#using-common-code)). e.g: + `include $(RIOTBOARD)/foo-parent/Makefile.*include*` + +An example can be found in +[`tests/build_system/external_board_native`](https://github.com/RIOT-OS/RIOT/tree/master/tests/build_system/external_board_native). + +# Board Names and Aliases + +New boards should be named according to +[RDM0003](https://github.com/RIOT-OS/RIOT/blob/master/doc/memos/rdm0003.md). +Historically, some board names have not followed this structure. +For backwards compatibility, RIOT supports board aliases that can be used +in place of the actual board name in the environment or Make variable `BOARD`. + +A list of all existing board aliases can be found in +[`makefiles/board_alias.inc.mk`](https://github.com/RIOT-OS/RIOT/blob/master/makefiles/board_alias.inc.mk). +[`BOARD=native`](https://doc.riot-os.org/group__boards__common__native.html) +is a special alias in that it +resolves to either [`native32`](https://doc.riot-os.org/group__boards__native32.html) +or [`native64`](https://doc.riot-os.org/group__boards__native64.html) +depending on the host architecture. + +# Tools + +Some scripts and tools available to ease `BOARD` porting and testing: + + - Run `dist/tools/insufficient_memory/add_insufficient_memory_board.sh ` + if your board has little memory. This updates the `Makefile.ci` lists to + exclude the `BOARD` from automated compile-tests of applications that do + not fit on the `BOARD`s `CPU`. + + - Run `dist/tools/compile_and_test_for_board/compile_and_test_for_board.py . --with-test-only` + to run all automated tests on the new board. + +# Further Reference + +- [In her blog](https://blog.martine-lenders.eu/riot-board-en.html), Martine Lenders documented her approach of + porting the [Adafruit Feather nRF52840 Express](https://doc.riot-os.org/group__boards__adafruit-feather-nrf52840-express.html) + in February 2020. +- [Over at HackMD][https://hackmd.io/njFHwQ33SNS3sQKAkLkNtQ], Akshai M documented his approach of + porting the [Silicon Labs SLSTK3400A starter kit](https://doc.riot-os.org/group__boards__slstk3400a.html) in July 2020. diff --git a/doc/guides/build-system/debugging_aids.md b/doc/guides/build-system/debugging_aids.md new file mode 100644 index 0000000000..394a624cf0 --- /dev/null +++ b/doc/guides/build-system/debugging_aids.md @@ -0,0 +1,51 @@ +--- +title: Debugging Tools +description: Overview of debugging tools supported in RIOT-OS +--- + +## Undefined Behavior Sanitizer (ubsan) + +RIOT contains Makefile convenience support for gcc/clang's undefined +behaviour sanitizer. + +### Overview + +Both gcc and clang allow generation of code that does runtime checks for +undefined behavior (UB). + +E.g., the following code might trigger UB for some parameters: + +```c +void test(int foo) { + return (foo << 24); +} +``` + +In this case, the signed shift would be alright unless: + +- it would "push out" all bits to the left, with undefined runtime result. Here, + that happens on architectures with 16-bit integers. +- `foo` is negative, with implementation-specific runtime results. + +Using ubsan, these can be caught at runtime. + +There are three modes for ubsan that define what happens when the sanitizer +observed undefined behaviour: + +1. `trap` -> cause a trap +2. `msg_exit` -> print a message and exit +3. `msg_recover` -> print a message and continue + +`trap` is available on all RIOT platforms, whereas `msg_exit` and `msg_recover` +are currently only available on `native` when building with gcc, as they require runtime support in +the form of `libubsan`. + +The default is `trap`, or `msg_exit` if available (currently, on native:gnu only). + + +### How to Use + +1. build with `make all-ubsan`. + +2. build with `UBSAN_MODE=[trap|msg_exit|msg_recover] make all-ubsan` to + override the ubsan mode. diff --git a/doc/guides/build-system/flashing.md b/doc/guides/build-system/flashing.md new file mode 100644 index 0000000000..304f7d7daf --- /dev/null +++ b/doc/guides/build-system/flashing.md @@ -0,0 +1,506 @@ +--- +title: Flashing via RIOT's Build System +description: Guide on how to flash boards using RIOT's build system +--- + +# General Approach + +In general, flashing a board from RIOT is as straight forward as typing in a +shell (with the application directory as current working directory): + +```sh +make BOARD= flash +``` + +This will **rebuild** ***AND*** **flash** the application in the current working +directory for board ``, using its default programming tool. If +you want to use an alternative programming tool, say `stm32flash`, use: + +```sh +make BOARD= PROGRAMMER=stm32flash flash +``` + +To flash without rebuilding use `flash-only` as target instead of `flash`. + +# Supported Tools + +RIOT supports plenty of flashing tools, that are below grouped into general +flashing tools that support multiple MCU families, and specialized tools that +only support one platform. + +Note that some programmers require additional configuration on a per board +level or rely on features only available on some boards. Hence, a given board +may not be supported by a programmer listed as supported for the platform of +the board due to a missing board feature, bootloader, or similar. + +To ease use the programmers are given by the value to pass via +`PROGRAMMER=`, rather than the official spelling of the programmer. + +## Compatibility Matrix of Generic Tools + + + + +MCU Family | `bmp` | `dfu-util` | `jlink` | `openocd` | `pyocd` | `uf2conv` +---------------|--------|------------|---------|-----------|---------|---------- +ATmega | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ +ATXmega | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ +CC13xx / C26xx | ✗ | ✗ | ✓ | ✓ (1) | ✗ | ✗ +CC2538 | ✗ | ✗ | ✓ | ✗ | ✗ | ✗ +EFM32 | ✗ | ✗ | ✓ | ✓ | ✗ | ✗ +ESP8266 | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ +ESP32 (Xtensa) | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ +ESP32 (RISC-V) | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ +FE310 | ✗ | ✗ | ✓ | ✓ | ✗ | ✗ +GD32V | ✗ | ✗ | ✗ | ✓ (1) | ✗ | ✗ +Kinetis | ✗ | ✗ | ✓ | ✓ | ✗ | ✗ +LPC1768 | ✗ | ✗ | ✓ | ✓ | ✗ | ✗ +LPC23xx | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ +MIPS32r2 | ✗ | ✗ | ✓ | ✗ | ✗ | ✗ +MSP430 | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ +nRF51 | ✗ | ✗ | ✓ | ✓ | ✓ | ✗ +nRF52 | ✓ | ✗ | ✓ | ✓ | ✓ | ✓ +RP2040 | ✗ | ✗ | ✓ | ✓ | ✗ | ✗ +SAM | ✗ | ✗ | ✓ | ✓ | ✗ | ✗ +Stellaris | ✗ | ✗ | ✓ | ✓ | ✗ | ✗ +STM32 | ✓ | ✓ | ✓ | ✓ | ✗ | ✗ + +Remarks: + +1. Requires a patched version of the programmer tool + +## Specialized Flashing Tools Per Platform + +The following list only contains single-platform flashing tools. Tools that +support multiple platforms are given in section above. + +### AVR + +- `avrdude` + +### CC13xx / CC26xx + +- `uniflash` + +### CC2538 + +- `cc2538-bsl` + +### ESP8266 / ESP32 (Xtensa) / ESP32 (RISC-V) + +- `esptool` + +### LPC23xx + +- `lpc2k_pgm` + +### MSP430 + +- `mspdebug` +- `goodfet` + +### nRF52 + +- `adafruit-nrfutil`, `uf2conv` (requires Adafruit bootloader), +see [Adafruit nRF52 Bootloader Common](https://doc.riot-os.org/group__boards__common__adafruit-nrf52-bootloader.html) +- `nrfutil` (required nRF bootloader) +- `nrfjprog` (requires a separate J-Link debugger) + +### RP2040 / RP2350 + +- `picotool` + +### SAM + +- `bossa` +- `edbg` + +### STM32 + +- `stm32flash` +- `stm32loader` +- `cpy2remed` (requires integrated ST-Link programmer, e.g. Nucleo boards) +- `robotis-loader` (requires robotis bootloader, only one board supported) + +# Programmer Configuration + +This section will list additional configuration options to control the behavior +of a programming tool, such as selecting the hardware adapter used for +programming. + +## OpenOCD Configuration + +### OPENOCD_DEBUG_ADAPTER + +`OPENOCD_DEBUG_ADAPTER` can be set via command line or as environment variable +to use non-default flashing hardware. + +### OPENOCD_RESET_USE_CONNECT_ASSERT_SRST + +`OPENOCD_RESET_USE_CONNECT_ASSERT_SRST` can be set via command line or as +environment variable to `0` to disable resetting the board via the `SRST` line. +This is useful when the `SRST` signal is not connected to the debug adapter or +when using cheap ST-Link V2 clones with broken `SRST` output. Note that it may +not be possible to attach the debugger while the MCU is in deep sleeping mode. +If this is set to `0` by the user, the user may need a carefully timed reset +button press to be able to flash the board. + +### OPENOCD_PRE_FLASH_CMDS + +`OPENOCD_PRE_FLASH_CMDS` can be set as environment variable to pass additional +commands to OpenOCD prior to flashing, e.g. to disable flash write protection. + +### OPENOCD_PRE_VERIFY_CMDS + +`OPENOCD_PRE_VERIFY_CMDS` can be set as environment variable to pass additional +flags to OpenOCD prior to verifying the flashed firmware. E.g. this is used +in the `pba-d-01-kw2x` to disable the watchdog to prevent it from disrupting +the verification process. + +### OPENOCD_PRE_FLASH_CHECK_SCRIPT + +`OPENOCD_PRE_FLASH_CHECK_SCRIPT` can be set via command line or as +environment variable to execute a script before OpenOCD starts flashing. It is +used for Kinetis boards to prevent bricking a board by locking the flash via +magic value in the flash configuration field protection bits. + +The script is expected to exit with code `0` if flashing should resume, or with +exit code `1` if flashing should be aborted. + +### OPENOCD_CONFIG + +`OPENOCD_DEBUG_ADAPTER` can be set via command line or as environment variable +to use non-default OpenOCD configuration file. + +### OPENOCD_TRANSPORT + +`OPENOCD_TRANSPORT` can be set via command line or as environment variable to +select a non-default transport protocol. E.g. to use JTAG rather than SWD for a +board that defaults to SWD use: + +```sh +make PROGRAMMER=openocd OPENOCD_TRANSPORT=jtag +``` + +Note that the OpenOCD configuration file of a given board may only support SWD or +JTAG. Also JTAG requires more signal lines to be connected compared to SWD and +some internal programmers only have the SWD signal lines connected, so that +JTAG will not be possible. + +## stm32flash Configuration + +It is possible to automatically boot the STM32 board into the in-ROM bootloader +that `stm32flash` communicates with for flashing by connecting the RST pin to +DTR and the BOOT pin (or BOOT0 for STM32 MCU families with BOOT0 and BOOT1 pins) +to RTS of the TTL adapter. In addition, set `STM32FLASH_RESET` to `1` via +environment or command line to actually issue a reset with BOOT (or BOOT0) +pulled high prior flashing to enter the bootloader, and a second reset with BOOT +(or BOOT0) pulled low to reboot into the application. `STM32FLASH_RESET` +defaults to `0` as of know, as with `PROGRAMMER=stm32flash STM32FLASH_RESET=1` +additional terminal flags are set, so that `make term` doesn't accidentally +keeps the reset signal pulled low or boot the board into the bootloader. + +The TTL adapter this was tested with had inverted RTS and DTR signal. By setting +`STM32FLASH_RESET_INVERT` to `1` RIOT will assume RTS and DTR signals to be +inverted, by setting it to `0` non-inverted signals will be generated. As of +now, `STM32FLASH_RESET_INVERT` is by default `1`. This may change if it +becomes evident that non-inverted TTL adapters are in fact more common than +inverted adapters. + +## MSPDEBUG Configuration + +All options can be passed as environment variables or as make arguments. +All options except for `DEBUGSERVER_PORT` apply to both debugging and flashing +alike. + +`MSPDEBUG_PROGRAMMER` is used to set the hardware programmer/debugger to use +for programming and debugging. See `mspdebug --help` or `man mspdebug` for a +list of programmers. + +`MSPDEBUG_PROTOCOL` is used to specify the debugger protocol. It is typically +set by the board used. Only JTAG and Spi-Bi-Wire are supported. + +`MSPDEBUG_TTY` is used to connect via TTY interface instead of directly via +USB to the debugger. Usually, this is not required. + +`DEBUG_ADAPTER_ID` is used to select the debugger/programmer by its serial. If +not set, `mspdebug` will select the first device with matching vendor and +product ID. Unless multiple debuggers of the same type are connected, this +options is typically not needed. + +`DEBUGSERVER_PORT` is used to specify the TCP port to listen for GDB to +connect to. It defaults to 2000. + +## Handling Multiple Boards with UDEV-Rules + +When developing and working with multiple boards the default `PORT` +configuration for a particular board might not apply anymore, so `PORT` will need +to be specified whenever calling `make term/test`. This can also happen if +multiple `DEBUGGERS/PROGRAMMERS` are present so `DEBUG_ADAPTER_ID` will also +need to be passed. Keeping track of this will become annoying. + +One way of handling this is to use `udev` rules to define `SYMLINKS` between the +boards serial port (`riot/tty-`) and the actual serial port +(dev/ttyACM* or other). With this we can query the rest of the boards serial +`dev` information (`DEBUG_ADAPTER_ID`, `PORT`, etc.) to always flash and open a +terminal on the correct port. + +### Procedure + +- use `udevadm info /dev/ttyACM0` to query the udev database for information on + device on port `/dev/ttyACM0`. + +- or: use `udevadm info --attribute-walk --name /dev/ttyACM0` for more detailed + output when the first level of information isn't enough + +- create a udev rule with information of the device and one parent to create a + matching rule in `/etc/udev/rules.d/70-riotboards.rules`. + +``` + # samr21-xpro + SUBSYSTEM=="tty", SUBSYSTEMS=="usb", ATTRS{idVendor}=="03eb", \ + ATTRS{idProduct}=="2111", ATTRS{manufacturer}=="Atmel Corp.", \ + ATTRS{serial}=="ATML2127031800004957", SYMLINK+="riot/tty-samr21-xpro" +``` + +- reload rules: `udevadm control --reload-rules` + +- Boards `PORT` are symlinked to /dev/riot/tty-`board-name`. + +- Create a `makefile.pre` that will query the real `PORT` and the + `DEBUG_ADAPTER_ID` from the `SYMLINK` info + +```makefile + PORT = /dev/riot/tty-$(BOARD) + DEBUG_ADAPTER_ID = $(\ + shell udevadm info -q property $(PORT) |\ + sed -n '/ID_SERIAL_SHORT/ {s/ID_SERIAL_SHORT=//p}') +``` + +- You can now add `makefile.pre` to `RIOT_MAKEFILES_GLOBAL_PRE` as an environment + variable or on each `make` call: + +```sh + $ RIOT_MAKEFILES_GLOBAL_PRE=/path/to/makefile.pre make -C examples/basic/hello-world flash term +``` + +:::note + If set as an environment variable it would be a good idea to add a + variable to enable/disable it, e.g: + +```makefile +ifeq (1,$(ENABLE_LOCAL_BOARDS)) + PORT = /dev/riot/tty-$(BOARD) + DEBUG_ADAPTER_ID = $(\ + shell udevadm info -q property $(PORT) |\ + sed -n '/ID_SERIAL_SHORT/ {s/ID_SERIAL_SHORT=//p}') +endif +``` +::: + +## Handling Multiple Versions of the same BOARD + +The above procedure works fine when handling different boards, but not +multiple times the same board, e.g: multiple `samr21-xpro`. + +An option for this would be to add an identifier of that board to the mapped +`riot/tty-*`, there are multiple ways of handling this but in the end it means +having a way to identify every copy. + +Another way would be to map the `DEBUG_ADAPTER_ID` in the name: + +```makefile +SYMLINK+="riot/node-$attr{serial} +``` + +But it will require to know in advance the serial number of each board you want +to use. Another option would be to add some kind of numbering and defining +multiple symlinks for each board. e.g. for `samr21-xpro` number `n`: + +``` + # samr21-xpro + SUBSYSTEM=="tty", SUBSYSTEMS=="usb", ATTRS{idVendor}=="03eb", \ + ATTRS{idProduct}=="2111", ATTRS{manufacturer}=="Atmel Corp.", \ + ATTRS{serial}=="ATML2127031800004957", SYMLINK+="riot/tty-samr21-xpro", \ + SYMLINK+="riot/tty-samr21-xpro-n" +``` + +Then, when flashing, the number can be specified and the parsing adapted: + +```makefile + ifneq(,$(BOARD_NUM)) + PORT = /dev/riot/tty-$(BOARD)-$(BOARD_NUM) + else + PORT = /dev/riot/tty-$(BOARD) + endif + DEBUG_ADAPTER_ID = $(\ + shell udevadm info -q property $(PORT) |\ + sed -n '/ID_SERIAL_SHORT/ {s/ID_SERIAL_SHORT=//p}') +``` + +```sh + BOARD=samr21-xpro BOARD_NUM=n make flash term +``` + +In the end, this would be the same as using the serial, but a simple number might +be easier to handle. + +## Notes +Udev only parses SUBSYSTEM and one parent. For others, we will rely on ENV +variables defined by 60-serial.rules + +So the current filename should be higher than 60-serial.rules + +If for some reason re-writing the serial is needed there is a windows tool: + https://remoteqth.com/wiki/index.php?page=How+to+set+usb+device+SerialNumber + +## Documentation: +* The whole documentation + http://reactivated.net/writing_udev_rules.html#udevinfo +* Udev manpage + http://manpages.ubuntu.com/manpages/eoan/en/man7/udev.7.html + +# Handling Multiple Boards without UDEV-Rules + +This is a simpler approach than the above mentioned issue. The solution here only +uses a Makefile for selecting the debugger and serial port. No +administrative privileges (e.g. to configure Udev) are required. + +One of the limitations of the solution described here is that it currently +doesn't work with multiple boards of the same type. This is a +limitation of the script and not of the mechanism used, it is possible to adapt +the script to support multiple boards of the same type. This modification is +left as an exercise to the reader. + +The following Make snippet is used: + +```makefile + LOCAL_BOARD_MAP ?= 1 + + # Adapt this list to your board collection + SERIAL_nucleo-f103rb ?= 066BFF343633464257254156 + SERIAL_same54-xpro ?= ATML2748051800005053 + SERIAL_samr21-xpro ?= ATML2127031800008360 + SERIAL_nrf52dk ?= 000682223007 + + ifeq (1,$(LOCAL_BOARD_MAP)) + + # Retrieve the serial of the selected board + BOARD_SERIAL = $(SERIAL_$(BOARD)) + + # Check if there is a serial for the board + ifneq (,$(BOARD_SERIAL)) + + # Set the variables used by various debug tools to the selected serial + SERIAL ?= $(BOARD_SERIAL) + DEBUG_ADAPTER_ID ?= $(BOARD_SERIAL) + JLINK_SERIAL ?= $(BOARD_SERIAL) + + # Use the existing script to grab the matching /dev/ttyACM* device + PORT ?= $(shell $(RIOTTOOLS)/usb-serial/ttys.py --most-recent --format path --serial $(SERIAL)) + endif + endif +``` + +The array of board serial numbers has to be edited to match your local boards. +The serial numbers used here is the USB device serial number as reported by +the debugger hardware. With the `make list-ttys` it is reported as the 'serial': + +```sh +$ make list-ttys +path | driver | vendor | model | model_db | serial | ctime +-------------|---------|--------------------------|--------------------------------------|-----------------------|--------------------------|--------- +/dev/ttyUSB0 | cp210x | Silicon Labs | CP2102 USB to UART Bridge Controller | CP210x UART Bridge | 0001 | 15:58:13 +/dev/ttyACM1 | cdc_acm | STMicroelectronics | STM32 STLink | ST-LINK/V2.1 | 0671FF535155878281151932 | 15:58:04 +/dev/ttyACM3 | cdc_acm | Arduino (www.arduino.cc) | EOS High Power | Mega ADK R3 (CDC ACM) | 75230313733351110120 | 15:59:57 +/dev/ttyACM2 | cdc_acm | SEGGER | J-Link | J-Link | 000683475134 | 12:41:36 +``` + +When the above make snippet is included as `RIOT_MAKEFILES_GLOBAL_PRE`, the +serial number of the USB device is automatically set if the used board is +included in the script. This will then ensure that the board debugger is used +for flashing and the board serial device is used when starting the serial +console. + +It supports command line parameters to filter by vendor name, model name, serial +number, or driver. In addition, the `--most-recent` argument will only print the +most recently added interface (out of those matching the filtering by vendor, +model, etc.). The `--format path` argument will result in only the device path +being printed for convenient use in scripts. + +# Handling Multiple Boards: Simplest Approach + +Passing `MOST_RECENT_PORT=1` as environment variable or as parameter to +make will result in the most recently connected board being preferred over the +default PORT for the selected board. + +For some boards `TTY_BOARD_FILTER` is provided, which filters TTYs e.g. by +vendor or model to only considered TTYs that actually may belong to the selected +board. E.g. for Nucleo boards this is `--model 'STM32 STLink'`, as they all use +an integrated STLink as programmer. As long as only one TTY is provided from an +STLink, this will reliably select the correct TTY for an Nucleo regardless of +which TTY was most recently connected. Some boards even provide info that +allows to always reliably identify them correctly (e.g. the firmware on the +ATmega16U2 used as USB to UART converter on Arduino Mega2560 will provide +identification data unique to that board). + +## Adding Board Filters + +After connecting as many variants of the board you target (and maybe some others +to test that the filter actually filters out non-matching boards). Then first +run `./dist/tools/usb-serial/ttys.py` without arguments and study the output. +When a genuine Arduino Mega 2560, a genuine Arduino Mega ADK (a variant of the +Mega 2560), a cheap Arduino Mega 2560 clone, a BBC micro:bit v2 and a +Nucleo F767-ZI are connected, the following output is shown: + +path | driver | vendor | model | model_db | serial | ctime | iface_num +-------------|---------|--------------------------|--------------------------------------|------------------------------------------------------|--------------------------------------------------|----------|---------- +/dev/ttyACM0 | cdc_acm | Arduino (www.arduino.cc) | 0042 | Mega 2560 R3 (CDC ACM) | 857353134333519002C1 | 12:13:55 | 0 +/dev/ttyACM1 | cdc_acm | Arduino (www.arduino.cc) | EOS High Power | Mega ADK R3 (CDC ACM) | 75230313733351110120 | 15:59:57 | 0 +/dev/ttyACM2 | cdc_acm | STMicroelectronics | STM32 STLink | ST-LINK/V2.1 | 0670FF535155878281123912 | 10:00:39 | 2 +/dev/ttyACM3 | cdc_acm | Arm | BBC micro:bit CMSIS-DAP | ARM mbed | 99053602000528334c41b84da1f2f09d000000006e052820 | 12:21:03 | 1 +/dev/ttyUSB0 | cp210x | Silicon Labs | CP2102 USB to UART Bridge Controller | CP2102/CP2109 UART Bridge Controller [CP210x family] | 0001 | 16:57:27 | 0 + +Now we add arguments to the invocation of `ttys.py` to filter the list e.g. +by model, vendor etc. (note: as regex!) ideally until only the target boards +are listed. Some boards do not provide enough information to e.g. tell them +apart from other boards using the same USB to UART bridge or the same debugger. +In that case we have to live with some "bycatch". + +In the case of the Arduino Mega 2560 the parameters +`--vendor 'Arduino' --model-db 'Mega 2560|Mega ADK'` will narrow down the +list to only show the genuine Arduino Mega versions. Se we add to the +`Makefile.include` in `boards/arduino-mega2560`: + +```makefile +TTY_BOARD_FILTER := --vendor 'Arduino' --model-db 'Mega 2560|Mega ADK' +``` + +Note that also matching the `R3` in `Mega 2560 R3` would prevent matching older +or newer revisions than R3, so we don't add that to the regex. + +## Advances Board Filters + +In most cases, just adding a simple `TTY_BOARD_FILTER` is sufficient. If we +however have wildly different flavors of the same board (e.g. genuine Arduino +Mega 2560 with an ATmega16U2 and clones with a cheap USB to UART bridge) that we +all want to support, we have to instead provide a `TTY_SELECT_CMD` that prints +the path to and the serial of the TTY (separated by a space) and exists with +`0` if a TTY was found, or that exists with `1` and prints nothing when no TTY +was found. We can still use the `ttys.py` script to detect all Arduino Mega +2560 versions: We first try to detect a genuine Arduino Mega and fall back to +selecting cheap USB UART bridges when that fails using the `||` shell operator: + +```makefile + TTY_SELECT_CMD := $(RIOTTOOLS)/usb-serial/ttys.py \ + --most-recent \ + --format path serial \ + --vendor 'Arduino' \ + --model-db 'Mega 2560|Mega ADK' || \ + $(RIOTTOOLS)/usb-serial/ttys.py \ + --most-recent \ + --format path serial \ + --driver 'cp210x' +``` diff --git a/doc/guides/build-system/img/kconfig_integration.svg b/doc/guides/build-system/img/kconfig_integration.svg new file mode 100644 index 0000000000..59a3ef1768 --- /dev/null +++ b/doc/guides/build-system/img/kconfig_integration.svg @@ -0,0 +1,637 @@ + + + + + + + + + + + + + + + + + $(USEMODULE) +$(USEPKG) + + + + + + + $(USEMODULE)... + + + + + + + + + + + Kconfig.dep + + + + + + Kconfig.dep + + + + + + + + + + + out.config + + + + + + out.config + + + + + + + + + + + menuconfig + + + + + + + menuconfig + + + + + + + + + + + + + + + + + + + + autoconf.h + + + + + + + autoconf.h + + + + + + + + + + + + + + 0 + + + + + + 0 + + + + + + + + + + + 1 + + + + + + 1 + + + + + + + + + + + 2 + + + + + + 2 + + + + + + + + + + + 3 + + + + + + 3 + + + + + + + + + + + 4 + + + + + + 4 + + + + + diff --git a/doc/doxygen/src/kconfig/kconfig_menuconfig.png b/doc/guides/build-system/img/kconfig_menuconfig.png similarity index 100% rename from doc/doxygen/src/kconfig/kconfig_menuconfig.png rename to doc/guides/build-system/img/kconfig_menuconfig.png diff --git a/doc/guides/build-system/kconfig.md b/doc/guides/build-system/kconfig.md new file mode 100644 index 0000000000..bbcbb464bc --- /dev/null +++ b/doc/guides/build-system/kconfig.md @@ -0,0 +1,568 @@ +--- +title: Kconfig in RIOT +description: Using Kconfig to configure RIOT modules at compile-time +--- + +The objective of using Kconfig in RIOT is to configure software modules at +compile-time. This means having a standard way of: +- Exposing configurable parameters +- Assigning application and user-specific configurations +- Verifying these parameters + - Check possible values + - Check valid configuration considering inter-dependencies +- Applying the selected configuration + +# Overview + +## Exposure +Modules in RIOT expose their configurable parameters via +Kconfig files (for more information on Kconfig syntax check +[the specification](https://www.kernel.org/doc/html/latest/kbuild/kconfig-language.html)). +In these files documentation, restrictions, default values and dependencies can +be expressed. + +Kconfig files are structured through the file system mirroring the current +module distribution. In time, all modules will have Kconfig files to make +themselves configurable through this system. + +## Assignment +The user can assign values to the exposed parameters, either by manually writing +'.config' files or using an interface such as Menuconfig. Parameters with no +assigned values will take the default ones. For a detailed distinction between +Kconfig and '.config' files see [Appendix B](#appendix-b-difference-between-kconfig-and-config-files). + +## Verification and Application +Using '.config' and Kconfig files the build system takes care of doing the +necessary checks on the values according to the parameter definition. After +that, the `autoconf.h` header file is generated, it contains all the +configurations in the form of (`CONFIG_` prefixed) macros. + +# User Guide to Configure with Kconfig + +## Configure using menuconfig +In order to use the graphical interface menuconfig to configure the +application, run `make menuconfig` in the application's folder. All available +configurations (based on the used modules) for the particular platform will be +presented. By default, the configuration of a module via Kconfig is not enabled. +In order to activate the configuration via Kconfig, the corresponding option +should be selected. That will enable the configuration of all inner options, if +available. + +Once the desired configuration is achieved, save the configuration to the +default proposed path and exit. The saved configuration will be applied when +the code is compiled (`make all`). + +If the current configuration should be used in the future, it can be saved in the +application's folder as `user.config`, using the 'Save' option in menuconfig. +This way it will be persistent after cleaning the application directory +(`make clean`). + +## Configure using '.config' Files +The second way to configure the application is by directly writing '.config' +files. Two files will be sources of configuration during the generation of the +final header file: `app.config` and `user.config`, which should be placed +inside the application's folder. `app.config` sets default configuration +values for the particular application, the user can override them by setting +them in `user.config`. Additionally, further `.config` files can be added to +the variable `KCONFIG_ADD_CONFIG`, which will be applied _after_ default CPU and +board configurations, `app.config` and `user.config`. This means that they will +have priority. + +Let's say that the `SOCK_UTIL_SCHEME_MAXLEN` symbol in `sock_util` module needs +to be configured. The `user.config` file could look like: + +```makefile +# activate configuration of sock_util using Kconfig +CONFIG_KCONFIG_MODULE_SOCK_UTIL=y +# change scheme part length +CONFIG_SOCK_UTIL_SCHEME_MAXLEN=24 +``` + +In this case, there is no need for using menuconfig. It's enough just to call +`make all` in the application folder, as this configuration will be read and +applied. Note that if any dependency issue occurs, warnings will be generated +(e.g. not enabling the configuration of a module via Kconfig). + +## Application Configuration with Kconfig +To expose application-specific configuration options a `Kconfig` file can +be placed in the application's folder. For an example of this you can check +the [tests/build_system/kconfig](https://github.com/RIOT-OS/RIOT/tree/master/tests/build_system/kconfig) +application. + +## Configuration via Environment Variables +For easy debugging of configurations or testing new modules by compiling them +into existing applications, one can also use environment variables prefixed by +`RIOT_CONFIG_`. To achieve the same configuration exemplified in +[Configure using '.config' files](#configure-using-config-files), e.g., you could also use + +```sh +RIOT_CONFIG_KCONFIG_MODULE_SOCK_UTIL=1 \ +RIOT_CONFIG_SOCK_UTIL_SCHEME_MAXLEN=24 \ + make +``` + +All the checks that apply for `.config` files also are done with this approach. + +Mind that this is only meant to be used during development. In production, +please set the configuration via `.config` files. + +## A Note on the Usage of CFLAGS +When a certain module is being configured via Kconfig, the configuration macro +will no longer be overridable by means of CFLAGS (e.g. set on the +compilation command or on a Makefile). Consider this if you are getting a +'redefined warning'. + +--- +# Integration into the Build System + +The integration of Kconfig into the build system is mainly done in +`makefiles/kconfig.mk`. + +## Steps during the Build Process + +![Output of every step of the build process](img/kconfig_integration.svg) + +### 0. Module Dependency Resolution +The resolution of module dependencies is performed by the build +system where all the used modules and packages end up listed in the `USEMODULE` +or `USEPKG` make variables. + + +#### Input +- Makefiles. + +#### Output +- `USEMODULE` and `USEPKG` variables. + +### 1. Module Listing +The list of modules needed for the particular build is dumped into the +`$ (GENERATED_DIR)/Kconfig.dep` file, where each module is translated into a +Kconfig symbol as documented in [Appendix A](#appendix-a-check-if-a-module-or-package-is-used). + +#### Input +- `USEMODULE` and `USEPKG` variables + +#### Output +- `$ (GENERATED_DIR)/Kconfig.dep` file + +### 2. Merging all Configuration Sources +In this step configuration values are taken from multiple sources and merged +into a single `out.config` configuration file. This file is temporary and is +removed on cleanup. If the user needs to save a particular configuration +set, a backup has to be saved (this can be done using the menuconfig interface) +so it can be loaded later in this step. + +To accomplish merging of multiple input files, the `genconfig` script is +used. Note that **the order matters**: existing configuration values are +merged in the order expressed in the input section, where the last value +assigned to a parameter has the highest priority. If no configuration files are +available, all default values will be applied. + +`out.config` is the only configuration input for the `autoconf.h` in the +[generation step](#4-generation-of-the-autoconfh-header). + +Additionally this step generates a file `out.config.d` which holds the +information of all the used Kconfig files in Makefile format. This file is +included by the build system and allows to re-trigger the generation of +`out.conf` whenever a Kconfig file is modified. + +#### Input +- Optional: + - `$ (APPDIR)/app.config`: Application specific default configurations. + - `$ (APPDIR)/user.config`: Configurations saved by user. + +#### Output +- `$ (GENERATED_DIR)/out.config` file. + +### 3. Menuconfig Execution (optional) +Menuconfig is a graphical interface for software configuration. It is, for example, used for +the configuration of the Linux kernel. This section explains the process +that occurs when RIOT is being configured using the menuconfig interface. + +The main `Kconfig` file is used in this step to show the configurable +parameters of the system. Kconfig will filter inapplicable parameters (i.e. +parameters exposed by modules that are not being used) based on the file +`$ (GENERATED_DIR)/Kconfig.dep` generated in step 1. + +Note that if Kconfig is not used to configure a module, the corresponding +header files default values will be used. + +`out.config` is one of the inputs for menuconfig. This means that any +configuration that the application defines in the `app.config` or a backup +configuration from the user in `user.config` are taken into account on the +first run (see [Appendix C](#appendix-c-pitfall-when-using-different-configuration-interfaces)). + +In this step the user chooses configuration values (or selects the minimal +configuration) and saves it to the `out.config` file. Here the user can +choose to save a backup configuration file for later at a different location +(e.g. a `user.config` file in the application folder). + +If any changes occur to `out.config`, the +[generation of autoconf.h](#4-generation-of-the-autoconfh-header) is executed automatically. + +#### Input +- `/Kconfig` file. +- Optional: + - `$ (APPDIR)/app.config` + - `$ (APPDIR)/user.config` + - `$ (GENERATED_DIR)/out.config` + +#### Output +- Updated `$ (GENERATED_DIR)/out.config` file. +- `$ (GENERATED_DIR)/out.config.old` backup file. + +### 4. Generation of the autoconf.h Header +With the addition of Kconfig, a dependency has been added to the build +process: the `$ (GENERATED_DIR)/autoconf.h` header file. This header file is +the main output from the Kconfig configuration system. It holds all the macros +that should be used to configure modules in RIOT: +`CONFIG__`. + +In order to generate the `autoconf.h` file, the `genconfig` script is used. +Inputs for this script are the main `Kconfig` file and `out.config` +configuration file, which holds the selected values for the exposed parameters. + +#### Input: +- `$ (GENERATED_DIR)/out.config` file. +- Main `Kconfig` file exposing configuration of modules. + +#### Output: +- `$ (GENERATED_DIR)/autoconf.h` configuration header file. +- Optional: + - `$ (GENERATED_DIR)/deps/*/*.h` header files that allow incremental builds + + +### Summary of Files +These files are defined in `kconfig.mk`. + +| File | Description | +| ---------------| ----------- | +| `Kconfig` | Defines configuration options of modules. | +| `Kconfig.dep` | Holds a list of the modules that are being compiled. | +| `app.config` | Holds default application configuration values. | +| `user.config` | Holds configuration values applied by the user. | +| `out.config` | Configuration file containing all the symbols defined in `autoconf.h`. | +| `out.config.d` | Dependency file of `out.config` containing the list of Kconfig files used to generate it. | +| `autoconf.h` | Header file containing the macros that applied the selected configuration. | + +## Kconfig Symbols in Makefiles +As `.config` files have Makefile syntax, they can be included when building, +which allows to access the applied configuration from the build system. + +During migration this is also useful, as it gives the ability to check whether a +parameter is being configured via Kconfig or a default value via `CFLAGS` could +be injected. For example: + +```makefile +ifndef CONFIG_USB_VID + CFLAGS += -DCONFIG_USB_VID=0x1209 +endif +``` + +Symbols will have the same name as the configuration macros (thus will always +have the `CONFIG_` prefix). As the configuration file is loaded in +`Makefile.include`, care should be taken when performing checks in the +application's Makefile. The symbols will not be defined until after including +`Makefile.include`. + +--- +# Transition Phase + +## Making Configuration via Kconfig optional +During transition to the usage of Kconfig as the main configuration tool for +RIOT, the default behavior will be the traditional one: expose configuration +options in header files and use CFLAGS as inputs. To allow optional +configuration via Kconfig, a convention will be used when writing Kconfig files. + +Modules should be contained in their own `menu` entries, this way the user +can choose to enable the configuration via Kconfig for an specific module. +These entries should define a dependency on the module they configure (see +[Appendix A](#appendix-a-check-if-a-module-or-package-is-used) to see how to +check if a module is being used). + +The module configuration must be enabled via make dependency modelling. + +## Modelling CPUs and Boards +CPUs and boards are being modelled in Kconfig. The following part is a guide on how to +organize and name the symbols. + +### CPUs +The proposed hierarchy for the classification of CPUs is as follows: + +``` + +------------+ +More Specific | CPU_MODEL | + + +------------+ + | + | + | +------------+ + | | CPU_FAM | + | +------------+ + | + | + | +------------+ + | | CPU_CORE | + | +------------+ + | + | + v +------------+ +Less Specific | CPU_ARCH | + +------------+ +``` + +Where each hierarchy is defined as: +- `CPU_MODEL`: The specific identifier of the used CPU, used for some CPU + implementations to differentiate between different memory + layouts. +- `CPU_FAM`: An intermediate identifier between CPU and CPU_MODEL that + represents a sub-group of a manufacturers CPUs. +- `CPU_CORE`: The specific identifier of the core present in the CPU. +- `CPU_ARCH`: The specific identifier of the architecture of the core defined + in `CPU_CORE`. + +In order to model the hierarchies, a hidden boolean symbol must be declared for +each. The name of the symbol must begin with the correspondent prefix and must +be followed by the specific value. For instance, the 'samd21' family symbol is +named `CPU_FAM_SAMD21`. + +In addition, a default value to the corresponding common symbol must be defined. +The default value must be guarded by the boolean symbol corresponding to the +hierarchy. + +Features may be provided by any hierarchy symbol. Usually symbols are selected +from more specific to less specific. This means that a `CPU_MODEL_` +symbol usually would select the corresponding `CPU_FAM_` symbol, +which would in turn select the `CPU_CORE_`. This may change in some cases +where `CPU_COMMON_` symbols are defined to avoid repetition. For convenience and +if it makes sense within a CPU vendor family, it's also allowed to use +intermediate grouping levels, like `CPU_LINE_` used for STM32. + +In addition to the symbols of the hierarchy described above, a default value +to the `CPU` symbol should be assigned, which will match the value of the `CPU` +Makefile variable in the build system. + +The declaration of the symbols should be placed in a `Kconfig` file in the +folder that corresponds to the hierarchy. When the symbols are scattered into +multiple files, it is responsibility of file containing the most specific +symbols to `source` the less specific. Keep in mind that only the file located +in `/cpu//Kconfig` will be included by the root `/Kconfig` file. + +#### Example + +``` +# This is the most specific symbol (selected by the board) +# The CPU model selects the family it belongs to +config CPU_MODEL_SAMR21G18A + bool + select CPU_FAM_SAMD21 + +# In this case the family selects a common 'sam0' symbol (which provides some +# features), and the core it has (cortex-m0+) +config CPU_FAM_SAMD21 + bool + select CPU_COMMON_SAM0 + select CPU_CORE_CORTEX_M0PLUS + +# The value of the common value depends on the selected model +config CPU_MODEL + default "samd21e18a" if CPU_MODEL_SAMD21E18A + default "samd21g18a" if CPU_MODEL_SAMD21G18A + default "samd21j18a" if CPU_MODEL_SAMD21J18A + default "samr21e18a" if CPU_MODEL_SAMR21E18A + default "samr21g18a" if CPU_MODEL_SAMR21G18A + +config CPU_FAM + default "samd21" if CPU_FAM_SAMD21 + +``` + +### Boards +Boards must be modelled as hidden boolean symbols with the prefix `BOARD_` which +default to `y` and are placed in `/boards//Kconfig`. This file will be +`source`d from the main `/Kconfig` file. The board symbol must select the +`CPU_MODEL_` symbol that corresponds to the CPU model present on the +board. The board symbol must also select the symbols that correspond to the +features it provides. + +In the same `Kconfig` file a default value must be assigned to the +common `BOARD` symbol. It must be guarded by the board's symbol, so it only +applies in that case. + +There are cases when grouping common code for multiple boards helps to avoid +unnecessary repetition. In the case features are provided in a common board +folder (e.g. `/boards/common/arduino-atmega`) a symbol should be declared to +model this in Kconfig. Symbols for common boards must have the `BOARD_COMMON_` +prefix, and must select the common provided features. + +#### Example +The samr21-xpro has a `samr21g18a` CPU and provides multiple features. Its +symbol is modelled as following: + +``` +# /boards/samr21-xpro/Kconfig + +config BOARD + default "samr21-xpro" if BOARD_SAMR21_XPRO + +config BOARD_SAMR21_XPRO + bool + default y + select CPU_MODEL_SAMR21G18A +``` + +### Default Configurations + +Boards, common board directories, CPUs and common CPU directories may need to +override default configuration values. Visible configuration symbols are +configurable by the user and show on the menuconfig interface. `.config` files +are used to set their values. To allow multiple sources of `.config` files, +there are two Makefile variables developers should use: `KCONFIG_CPU_CONFIG` for +sources added by the CPU or common CPU directories, and `KCONFIG_BOARD_CONFIG` +for sources added by the board or common board directories. This ensures the +correct priority of the configurations. + +The `Makefile.features` infrastructure is used to populate the +configuration sources. As the order in which `.config` files are merged matters, +configuration sources should be ordered from more generic to more specific. +Because the board's `Makefile.features` is included before the CPU's `Makefile.features` +it is important to utilize two different lists of configuration sources. For +instance, if `cpu/cortexm_common` adds its configuration, `cpu/stm32` should add +its configuration after it, and `boards/stm32f769i-disco` after it. + +```makefile +include $(RIOTCPU)/cortexm_common/Makefile.features + +# Add stm32 configs after including cortexm_common so stm32 takes precedence +KCONFIG_CPU_CONFIG += $(RIOTCPU)/stm32/stm32.config +``` + +## Summary of Reserved Kconfig Prefixes +The following symbol prefixes have been assigned particular semantics and are +reserved for the cases described below: + + +| Prefix | Description | +| :----- | :---------- | +| `BOARD_` | Models a board | +| `BOARD_COMMON_` | Used for common symbols used by multiple boards | +| `CPU_ARCH_` | Models a CPU architecture | +| `CPU_COMMON_` | Used for common symbols used by multiple CPUs | +| `CPU_CORE_` | Models a CPU core | +| `CPU_FAM_` | Models a family of CPUs | +| `CPU_MODEL_` | Models a particular model of CPU | +| `USEMODULE_` | Models a [RIOT module](https://doc.riot-os.org/creating-modules.html#creating-modules). Generated from `USEMODULE` variable | +| `USEPKG_` | Models an [external package](https://doc.riot-os.org/group__pkg.html). Generated from `USEPKG` variable | + +--- +# Appendices + +## Appendix A: Check if a Module or Package is used +In order to show only the relevant configuration parameters to the user with +respect to a given application and board selection, Kconfig needs knowledge +about all modules and packages to be used for a compilation. The dependency +handling among modules is performed by the build system (via +`Makefile.dep` files). The interface defined to declare the used modules and +packages is the `$ (GENERATED_DIR)/Kconfig.dep` file. + +There will be a symbol for every used module (i.e. every module in +`USEMODULE` make variable) and package. The names in the symbols will be +uppercase and separated by `_`. Based on these symbols, configurability is +decided. + +The following is an example of how to use these symbols in Kconfig files to +configure compile-time configurations with `USEMODULE` dependencies: + +``` +menu "Configure Sock Utilities" + depends on USEMODULE_SOCK_UTIL + +config SOCK_UTIL_SCHEME_MAXLEN + int "Maximum length of the scheme part for sock_urlsplit" + default 16 + +... + +endmenu # Configure Sock Utilities +``` + + +## Appendix B: Difference between 'Kconfig' and '.config' Files +Kconfig files describe a configuration database, which is a collection of +configuration options organized in a tree structure. Configuration options may +have dependencies (among other attributes), which are used to determine their +visibility. + +Kconfig files are written in +[Kconfig language](https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt) +defined in the Linux kernel. Configuration options have attributes such as +types, prompts and default values. + +#### Kconfig File + +``` +menu "Buffer Sizes" + +config GCOAP_PDU_BUF_SIZE + int "Request or response buffer size" + default 128 + +endmenu +``` + +On the other hand configuration files contain assignment of values to +configuration options and use Makefile syntax. They can also be used to save a +set of configuration values as backup. + +#### '.config' File + +```makefile +# enable Kconfig configuration for gcoap +CONFIG_KCONFIG_MODULE_GCOAP=y +# set the value +CONFIG_GCOAP_PDU_BUF_SIZE=12345 +``` + +In other words: Kconfig files describe configuration options and '.config' files +assign their values. + +## Appendix C: Pitfall when using Different Configuration Interfaces +In the current configuration flow the user can choose to configure RIOT using +the menuconfig graphical interface or writing '.config' files by hand. + +As explained in the +['Configuration sources merging step'](#2-merging-all-configuration-sources) +of the configuration process, configuration from multiple sources are loaded to +create a single `out.config` file, and the order of merging matters: last +file has priority. + +While editing values directly via '.config' files, `out.config` will be +re-built. The user can also use the menuconfig interface to modify the configuration +file (this is the recommended way, as it gives access to much more information +regarding dependencies and default values of the symbols). Menuconfig will +change `out.config` directly (a backup file `out.config.old` will be kept). + +**It is recommended to save backups of the configurations, as any change on the +configuration sources would re-trigger the merging process and overwrite +`out.config`.** + +## Appendix D: A few Key Aspects while Exposing a Macro to Kconfig +A macro that holds a 0 or 1 is modelled in Kconfig as a `bool` symbol. References to this macro +can then make use of IS_ACTIVE macro from kernel_defines.h with C conditionals +for conditional compilation. +[FXOS8700 driver exposure to Kconfig](https://github.com/RIOT-OS/RIOT/pull/13914) +can be considered as an example. If the macro is defined as `TRUE` by default, +a new symbol gets introduced to invert the semantics. The recommended +practice is to add a new symbol and expose it to Kconfig while the old one is +tagged to be deprecated. The process is documented in this +[commit](https://github.com/RIOT-OS/RIOT/pull/13129/commits/c7b6dc587cf20f3177abe0417a408b6ab90d0ff8) + +There may be cases where a macro is expected to hold only specific values, e.g. +'GNRC_IPV6_MSG_QUEUE_SIZE' expressed as the power of two. These may be modelled +in such a way that a new macro is introduced to hold the restricted figures +while operators are added to arrive at the desired value. The process is +documented in this [pull request.](https://github.com/RIOT-OS/RIOT/pull/14086) + +# Useful references +- [Kconfig language specification](https://www.kernel.org/doc/html/latest/kbuild/kconfig-language.html) +- [Kconfig macro language specification](https://www.kernel.org/doc/html/latest/kbuild/kconfig-macro-language.html) +- [Kconfig - Tips and Best Practices](https://docs.zephyrproject.org/latest/guides/kconfig/tips.html) diff --git a/doc/guides/general/code_of_conduct/faq.md b/doc/guides/general/code_of_conduct/faq.md new file mode 100644 index 0000000000..4e550d4d32 --- /dev/null +++ b/doc/guides/general/code_of_conduct/faq.md @@ -0,0 +1,76 @@ +--- +title: FAQ +description: Frequently Asked Questions about the RIOT Code of Conduct +--- + +This FAQ attempts to address common questions and concerns around the RIOT +community's [Code of Conduct](/general/code_of_conduct/). +If you still have questions after reading it, +please feel free to [contact us](mailto:riot@riot-os.org). + +-------------------------------------------------------------------------------- + +### Why have you adopted a Code of Conduct? + +If you're familiar with the RIOT +community, you'll probably notice that the Code basically matches what we +already do. Think of this as documentation: we're taking implicit expectations +about behavior and making them explicit. + +We're doing this because the RIOT community is growing faster than any of us +could have anticipated. This is on balance a very positive thing, but as we've +grown past the point where it's possible to know the whole community we think +it's very important to be clear about our values. + +We know that the RIOT community is open, friendly, and welcoming. We want to +make sure everyone else knows it too. + +### What does it mean to "adopt" a Code of Conduct? + +For the most part, we don't think it means large changes. We think that the text +does a really good job describing the way the RIOT community already conducts +itself. We expect that most people will simply continue to behave in the awesome +way they have for years. + +However, we do expect that people will abide by the spirit and words of the CoC +when in "official" RIOT spaces. This code has been adopted by the RIOT community +as a whole. That means that it'll apply in all community spaces. + +In practice, this means the [RIOT forum](https://forum.riot-os.org), the Matrix +chats (e.g., [`#riot-os`](https://matrix.to/#/#riot-os:matrix.org) or +[`#riot-os-off-topic`](https://matrix.to/#/#riot-os-off-topic:matrix.org)), +mailing lists (e.g., security@riot-os.org), bug tracking and code review tools, +and "official" RIOT events such as Hack'n'ACKs or RIOT summits. In addition, +violations of this code outside these spaces may affect a person's ability to +participate within them. + +### What happens if someone violates the Code of Conduct? + +Our intent is that anyone in the community can stand up for this code, and +direct people who're unaware to this document. If that doesn't work, or if you +need more help, you can contact . For more details please see +our [Reporting Guidelines](/general/code_of_conduct/reporting/). + +### Why do we need a Code of Conduct? Everyone knows not to be a jerk. + +Sadly, not everyone knows this. + +However, even if everyone was kind, everyone was compassionate, and everyone was +familiar with codes of conduct it would still be incumbent upon our community to +publish our own. Maintaining a code of conduct forces us to consider and +articulate what kind of community we want to be, and serves as a constant +reminder to put our best foot forward. But most importantly, it serves as a +signpost to people looking to join our community that we feel these values are +important. + +### This is censorship! I have the right to say whatever I want! + +You do -- in *your* space. If you'd like to hang out in *our* spaces (as +clarified above), we have some simple guidelines to follow. If you want to, for +example, form a group where RIOT is discussed using language inappropriate for +general channels then nobody's stopping you. We respect your right to establish +whatever codes of conduct you want in the spaces that belong to you. Please +honor this Code of Conduct in our spaces. + +#### References +This FAQ was adapted from the [Django Code of Conduct FAQ](https://www.djangoproject.com/conduct/faq/) diff --git a/doc/guides/general/code_of_conduct/reporting.md b/doc/guides/general/code_of_conduct/reporting.md new file mode 100644 index 0000000000..a17d1f5665 --- /dev/null +++ b/doc/guides/general/code_of_conduct/reporting.md @@ -0,0 +1,82 @@ +--- +title: Reporting Guidelines +description: How to report violations of the RIOT Code of Conduct +--- + +If you believe someone is violating the [code of conduct](/general/code_of_conduct/) +we ask that you report it to us by emailing . +Currently, the recipients of +this email address are [\@OlegHahm](https://github.com/OlegHahm) (Oleg Hahm) and +[\@miri64](https://github.com/miri64) (Martine Lenders). + +**All reports will be kept confidential.** In some cases we may determine that a +public statement will need to be made. If that's the case, the identities of all +victims and reporters will remain confidential unless those individuals instruct +us otherwise. + +**If you believe anyone is in physical danger, please notify appropriate law +enforcement first.** If you are unsure what law enforcement agency is +appropriate, please include this in your report and we will attempt to notify +them. + +If you are unsure whether the incident is a violation, or whether the space +where it happened is covered by this Code of Conduct, we encourage you to still +report it. We would much rather have a few extra reports where we decide to take +no action, rather than miss a report of an actual violation. We do not look +negatively on you if we find the incident is not a violation. And knowing about +incidents that are not violations, or happen outside our spaces, can also help +us to improve the Code of Conduct or the processes surrounding it. + +In your report please include: + +- Your contact info (so we can get in touch with you if we need to follow up) +- Names (real, nicknames, or pseudonyms) of any individuals involved. If there + were other witnesses besides you, please try to include them as well. +- When and where the incident occurred. Please be as specific as possible. +- Your account of what occurred. If there is a publicly available record (e.g. + forum post, a mailing list archive, or a public Matrix chat link) please include a link. +- Any extra context you believe existed for the incident. +- If you believe this incident is ongoing. +- Any other information you believe we should have. + +### What happens after you file a report? + +You will receive an email from one of the core community members as soon as +possible. We promise to acknowledge receipt within 24 hours (and will aim for +much quicker than that). + +They will review the incident and determine: + +- What happened. +- Whether this event constitutes a code of conduct violation. +- Who the bad actor was. +- Whether this is an ongoing situation, or if there is a threat to anyone's + physical safety. + +If this is determined to be an ongoing incident or a threat to physical safety, +their immediate priority will be to protect everyone involved. +This means we may delay an "official" response until we believe that the +situation has ended and that everyone is physically safe. + +Once the working group has a complete account of the events they will make a +decision as to how to response. Responses may include: + +- Nothing (if we determine no violation occurred). +- A private reprimand from us to the individual(s) involved. +- A public reprimand. +- An imposed vacation (i.e. asking someone to "take a week off" from the forum, + the Matrix chats, or a mailing list). +- A permanent or temporary ban from some or all RIOT spaces (forum, Matrix chats, mailing lists, + etc.) +- A request for a public or private apology. + +We'll respond within one week to the person who filed the report with either a +resolution or an explanation of why the situation is not yet resolved. + +Once we've determined our final action, we'll contact the original reporter to +let them know what action (if any) we'll be taking. We'll take into account +feedback from the reporter on the appropriateness of our response, but we don't +guarantee we'll act on it. + +#### Reference +These reporting guidelines were adapted from the [Django reporting guidelines](https://www.djangoproject.com/conduct/reporting/) diff --git a/doc/guides/misc/dev_best_practices.md b/doc/guides/misc/dev_best_practices.md new file mode 100644 index 0000000000..29ef151650 --- /dev/null +++ b/doc/guides/misc/dev_best_practices.md @@ -0,0 +1,149 @@ +--- +title: Hints for quicker & better RIOT development +description: Best practices and recommended tools for RIOT development +--- + +* Use the [methodology](#methodology-emulator-first-target-iot-hardware-last) described below. +* Use [`ccache`](/build-system/advanced_build_system_tricks/#speed-up-builds-with-ccache) to speedup compilation + +## Coding "Dos" and "Don'ts" + +### Dos + * Use static memory. See also [Static vs. Dynamic Memory](#static-vs-dynamic-memory). + * Select the priorities carefully. + * Minimize stack usage with `DEVELHELP` and `CREATE_STACKTEST`. + * Use threads to increase flexibility, modularity and robustness by leveraging IPC. + * Use unsigned or signed integer (`unsigned`, `int`, `size_t` or `ssize_t`) for loop variables wherever possible, + but keep in mind that on some platforms an `int` has a width of only 16-bit. In general, you should avoid types + like `uint8_t` for loop iterators as they will probably make it more expensive on some platforms. + * Join and factor out parts of the code with existing code in RIOT, where it makes sense. + * Check all `size/length` parameters when passing memory, e.g. using `sizeof(x)` or `strlen(x)` as appropriate. + Make sure you don't use the wrong one with a pointer. + * Make sure all code paths can be reached. Make sure there are no always `true/false` conditions. + * Make sure all critical sections (`lock/unlock`, `acquire/release`, ...) are always closed on every code path. + * Make sure return values are consistent with our API documentation. + * Use `assert()` statements to check parameters rather than returning an error code at run-time, + to keep the code size down. + * Use the `DEBUG(...)` macro rather than `log_x(...)` + * Declare all internal module variables and functions `static` + * Make sure variables are reduced in scope as much as possible + * Use an appropriate signedness in your variables + * Make sure the variables are big enough to prevent overflow. Be aware that the code may run on platforms with + different sizes of variables. For example, `int/unsigned` is only 16-bit on msp430 and avr8. If in doubt, + use portable types. + * Reduce the number of function calls as far as possible without duplicating code. + * Use good judgement when using `static inline` functions and macros. If they are used in multiple places, + is the increase in performance worth the penalty in code size? + * Use memory judiciously in general. For example: +```c +typedef enum { + A, + B, + ... +} foo_t; + +int bar(foo_t v) +{ + int abc; + ... + + switch(v) { + case A: + abc = 23; + break; + case B: + abc = 42; + break; + ... + } + ... +} + +/* VS */ + +typedef enum { + A = 23, + B = 42, + ... +} foo_t; + +int bar(foo_t v) { + int abc = v; + ... +} +``` + +### Don'ts + * Don't use too many threads. Try not to use more than one thread per module. Don't create threads for one-time tasks. + * Don't use the POSIX wrapper if implementing something from scratch. + * Don't allocate big chunks of memory (for instance the IPC message queue) on the stack, + but use rather static memory for that. + * Don't over-provision memory. + * Don't pass stack memory between different contexts unless you can prove conclusively that it won't be a problem. + * Don't use enums for flags, because flags have a width in memory that is in most cases smaller than `sizeof(enum)` + (most bitfields are 16 bits max, on most of our newer platforms, `sizeof(enum)` is however 32 bits). + This results in every assignment needed to be cast to either `uint8_t` or `uint16_t`. With macros you don't need to + cast since they are typeless. Making the enum packed makes its width unpredictable in terms of alignment issues, + when used in struct. + * Don't duplicate code from elsewhere in the RIOT code base, unless there is a very good reason to do so. + * Don't duplicate code within your own code, unless there is a very good reason to do so. + Use internal functions to this end. + * Don't mix up logical and bitwise operations (`!` vs `~`, or `&&` vs `&`) + +## Methodology: emulator first, target IoT hardware last! + +The below methodology is recommended, using well-known de facto standard tools from the FLOSS community that are +compatible with RIOT. Using the below workflow improves time-to-running-code compared to typical IoT software +workflows (which can be as retro as "LED-driven" debugging). + +0. For newbies, preliminaries are typically faster with the provisioned virtual environment setup, e.g. with **Vagrant**. +1. To check your code, first use available **static analysis** as much as possible initially, which means + (i) enable all compiler warnings and fix all problems found, then (ii) use a supported linter such as **cppcheck** + to find bad coding patterns (i.e. code smells) and identify misuse of standard APIs. +2. Next, use available **dynamic analysis** tools to find further defects while running the code on **RIOT native**, + which means (i) running unit tests and integration tests on RIOT native emulator, and (ii) using **Valgrind** memcheck, + as well as the **GCC stack smashing detection**, to detect and avoid undefined behavior due to invalid memory access. +3. In case of networked applications or protocols, test **several instances of native** communicating via a virtual + network mimicking the targeted scenario, which means (i) either using the default virtual full-mesh or other + topologies configured via DESvirt, and (ii) using **Wireshark** to capture and analyze virtual network traffic, + e.g. to ensure protocol packets are syntactically correct, and to observe network communication patterns. +4. In case of incorrect behavior at this stage, analyze the system state for semantic errors on native using the + standard debugger **gdb**, which allows virtually unlimited conditional breakpoints, record and replay, + catchpoints, tracepoints and watchpoints. +5. In case of suspected performance bottleneck, use performance profilers **gprof**, or else cachegrind, + to identify precisely the bottlenecks. +6. At this stage the implementation has proven bug-free on the native emulator. One can thus finally move on to + hardware-in-the-loop, which means (i) flashing the binary on the targeted IoT hardware, typically using + standard flasher **OpenOCD** or **edbg**, and (ii) using the **RIOT shell** running on the target IoT device(s) + for easier debugging on the target hardware. +7. In case the hardware is not available on-site, one can consider remotely flashing and testing the binary on + supported open-access testbeds, e.g. [IoT-LAB](https://www.iot-lab.info) hardware is fully supported by RIOT. +8. In case of failure, after analyzing the failure and attempting to fix the defect, go back to step 1 to make sure + the fix did not itself introduce a new defect. + +## Static vs. Dynamic Memory + +In your C program you have to decide where the memory you want to use comes from. +There are two ways to get memory in your C code: + +1. Define static memory. +2. Use dynamic memory (call `malloc()`/`free()` to get memory from the heap). + +Both ways have some drawbacks which are listed here. +If you want to analyze the static memory consumption of your code you can use +[otm](https://github.com/LudwigOrtmann/otm) or `make cosy`. + +### Static memory +* Access the memory in one operation O(1) ⇒ real time condition +* Programmer needs to know the amount of memory on compile time + * Leads to over and undersized buffers +* Forces the programmer to think about the amount of need memory at compile time + +### Dynamic memory +* `malloc()` and `free()` are implemented in your `libc` (RIOT on ARM: `newlib`/`picolib`) + * Runtime behavior is not predictable +* Code can request the amount of memory it needs on runtime +* On most platforms: the size of the heap is `sizeof()-sizeof()` + * If you reduce your usage of static memory your heap gets bigger +* Programmer needs to handle failed memory allocation calls at runtime +* Static code analysis is unable to find errors regarding memory management diff --git a/doc/guides/misc/emulators.md b/doc/guides/misc/emulators.md new file mode 100644 index 0000000000..c8928b5f52 --- /dev/null +++ b/doc/guides/misc/emulators.md @@ -0,0 +1,155 @@ +--- +title: Emulators +description: Overview of emulators supported in RIOT-OS +--- + +RIOT supports the [Qemu](https://www.qemu.org/) and [Renode](https://renode.io/) +emulation tools. The emulation offers a hardware-free development environment +for quickly testing applications. + +From the build system point of view, the emulation support in RIOT is +transparent compared to the usual workflow: simply add `EMULATE=1` to the +command line and the emulator supported by the board will be called instead of +the board flashing/debugging tool. +Targets compatible with `EMULATE=1` are `term`, `cleanterm`, `debug`, +`debugserver` and `test`. + +If a board supports multiple emulators, the emulator backend can be selected +with the `RIOT_EMULATOR` variable. Possible values are `qemu` and `renode`. +If no emulator is specified by the board configuration (e.g. in its +`Makefile.include`), the default emulator is `renode`. + +The boards with emulator supported can be listed using the +`info-emulated-boards` target: + +```shell +$ make info-emulated-boards +``` + +## Features + +Be aware that not all hardware features provided by a board - and described as +such in the build system by `FEATURES_PROVIDED` - are implemented in emulators. +For example, the `hifive1b` provides the RTC peripheral feature but this is not +implemented by the renode driver. +So you may expect some failures when running advanced applications on the +emulator. + +## Usage + +All emulators can be used the same way. Just add `EMULATE=1` to the command +line. + +To start an emulator and connect to the serial port of the emulated board, run: + +```shell +$ EMULATE=1 make BOARD= -C all term +``` + +To start an emulator with a GDB server and connect a GDB client to it, run: + +```shell +$ EMULATE=1 make BOARD= -C all debug +``` + +To start an automatic test script with the emulated board, run: + +```shell +$ EMULATE=1 make BOARD= -C all test +``` + +The `EMULATOR_SERIAL_PORT` variable can be used to specify a custom serial port +on the host running the emulator. +The default value is built based on a random temporary directory: +`$(EMULATOR_TMP_DIR)/uart`. +The randomness of this variable allows several emulated sessions of the same +application with the same board to run in parallel. + +# Qemu + +## Overview + +[Qemu](https://www.qemu.org/) is a machine emulator and virtualizer. It can +be used to emulate regular computer architectures but also some microcontroller +based boards such as the [BBC micro:bit](https://doc.riot-os.org/group__boards__microbit.html). + +## Installation + +Qemu is usually available via the package manager of common Linux distributions. +Depending on your local system, the installation procedure is described on the +[qemu website](https://www.qemu.org/download/). + +## Boards supported + +So far, in RIOT, only the +[BBC micro:bit](https://doc.riot-os.org/group__boards__microbit.html) +board is supported with qemu. + +## Configuration + +The QEMU emulated serial port is exposed on a local Unix socket, redirected to a +local PTY file (using [socat](http://www.dest-unreach.org/socat/)). This makes +it possible to open the PTY file in a regular serial port. + +# Renode + +## Overview + +[Renode](http://renode.io) is a virtual development tool for multinode embedded +networks (both wired and wireless) enabling a scalable workflow for building +effective, tested and secure IoT systems, created by +Antmicro](http://antmicro.com/blog/2017/08/renode-press-release/). +It can easily be used to run applications on a broad range of embedded platforms +without any changes in the code itself, as if you were running on real +hardware - but with more possibilities. + +## Installation + +### From package + +Packages for macOS, deb-based and rpm-based systems, for Windows and for Arch +Linux are available on [GitHub](https://github.com/renode/renode/releases/latest). + +### From Source + +Follow the installation instructions on Renode's +[GitHub](https://github.com/renode/renode#installation) page. + +If you choose to build renode from source, after the compilation is successful, +ensure that `renode` is available on your `PATH`. +One way to do so, is via symlink: + +```shell +sudo ln -s path/to/renode/repository/renode /usr/local/bin/renode +``` + +### Testing + +After installation, verify that Renode is working using `renode --help`. You +should be presented with a help screen. + +## Documentation + +Documentation for Renode can be found on [Read The Docs](https://renode.readthedocs.io). + +## Usage + +From within RIOT-OS, add `EMULATE=1` to start the emulation. The emulation +expects a board definition file in `boards//dist/board.resc`. + +The board definition file will tell Renode how to setup an emulation session. +The application binary file (`*.elf`) is available using the variable +`$image_file`. + +For an example, refer to `boards/cc2538dk/dist/board.resc`. + +The renode logging level can be configured from the command line using the +following variables: +- `RENODE_SHOW_LOG`: set it to 1 to show the logs in the standard output +- `RENODE_LOG_LEVEL`: set it to the desired log level, default is 2 (warning) + +The renode monitor and serial console GUI windows are hidden by default but +they can be displayed by setting `RENODE_SHOW_GUI` to 1 in the command line. + +If uart0 is not the default serial port used for stdio, use `RENODE_SYSBUS_UART` +to specify a custom one in the board `Makefile.include`. diff --git a/doc/guides/misc/io_mapping_and_shields.md b/doc/guides/misc/io_mapping_and_shields.md new file mode 100644 index 0000000000..e44d601767 --- /dev/null +++ b/doc/guides/misc/io_mapping_and_shields.md @@ -0,0 +1,172 @@ +--- +title: IO-Mapping and Shields +description: How to use Arduino compatible pin mappings and shields in RIOT-OS +--- + +## Introduction + +Arduino has popularized the concept of adding an abstraction layer over the +MCU GPIOs and ADC multiplexer as "Digital Pins" and "Analog Pins". For historic +reasons as well as to express appreciation for the introduction of concept, we +prefix features and macros that map board pins to MCU pins with `ARDUINO`. + +:::note +This means, we also explicitly use the Arduino feature for boards that +are neither official Arduino products nor compatible. +::: + +## I/O Mappings + +All I/O mappings are provided by the `arduino_iomap.h` header file. This is +provided either by the board directly (e.g. in +`/board//include/arduino_iomap.h`) or by the board +family (e.g. in `board/common//include/arduino_iomap.h`). + +To add support to new boards, start by copy-pasting the `arduino_iomap.h` from +an existing board and adapt/extend the macros as needed. Finally, add the +features to the `Makefile.features` and `KConfig` files of the board that +indicate the presence of the added mappings. + +### Digital Pins + +The feature `arduino_pins` is provided by boards that do have a mapping to +digital pins. The GPIO for e.g. `D3` is provided as `ARDUINO_PIN_3`. The +number of the highest digital pin is provided as `ARDUINO_PIN_LAST`. E.g. if +`ARDUINO_PIN_LAST` is 42, digital pins `D0` to `D42` are typically provided. + +:::warn +Some boards do have "gaps" in the pin mapping. It could be that +e.g. `ARDUINO_PIN_5` is defined, but `ARDUINO_PIN_4` is not. +::: + +:::note +Often aliases are provided for analog pins in digital mode. E.g. +to use the pin `A3` as digital pin, `ARDUINO_PIN_A3` can be used +to avoid looking up what digital number that pin has. +::: + +### Analog Pins + +The feature `arduino_analog` is provided by boards that do have a mapping of +ADC lines to analog pins. E.g. the ADC line corresponding to pin `A5` would +be `ARDUINO_A5`. The number of the highest analog pin is provided as +`ARDUINO_ANALOG_PIN_LAST`. The macro `ARDUINO_ANALOG_PIN_LAST` is defined if +and only if a mapping is provided (so it can be used to test for this feature). + +:::warn +Some boards do have "gaps" in the analog pin mapping. It could be +that e.g. `ARDUINO_A3` is defined, but `ARDUINO_A2` is not. +::: + +### DAC Pins + +The feature `arduino_dac` is provided by boards that do have a mapping of +DAC pins to DAC lines. E.g. the DAC line for the pin DAC1 would be +`ARDUINO_DAC1`. The number of the highest DAC pin is provided as +`ARDUINO_DAC_PIN_LAST`. The macro `ARDUINO_DAC_PIN_LAST` is defined if +and only if a mapping is provided (so it can be used to test for this feature). + +:::warn +Some boards do have "gaps" in the analog pin mapping. It could be +that e.g. `ARDUINO_DAC4` is defined, but `ARDUINO_DAC3` is not. +::: + +### PWM Pins + +The feature `arduino_pwm` is provided by boards that do have a mapping of +digital pins to PWM settings. E.g. the PWM device connected to the digital pin +`D11` would be `ARDUINO_PIN_11_PWM_DEV` and the channel would be +`ARDUINO_PIN_11_PWM_CHAN`. A PWM frequency for all PWM pins is defined as +`ARDUINO_PWM_FREQU`. + +:::warn +Typically only few digital pins support PWM. For pins without PWM +output, no `ARDUINO_PIN__PWM_DEV` macro and no +`ARDUINO_PIN__PWM_DEV` is defined. +::: + +### UART Device + +The feature `arduino_uart` is provided by boards that do provide an UART device +mapping. For the official Arduino boards and compatible boards, the +`ARDUINO_UART_D0D1` macro refers to the UART device that uses the digital pins +`D0` and `D1`. + +Please extend the table below to keep naming among boards of the same form +factor consistent: + +| Form Factor | Macro Name | Description | +|:---------------- |:--------------------- |:--------------------------------- | +| Arduino Nano | `ARDUINO_UART_D0D1` | UART on D0 (RXD) and D1 (TXD) | +| Arduino Uno | `ARDUINO_UART_D0D1` | UART on D0 (RXD) and D1 (TXD) | +| Arduino Mega | `ARDUINO_UART_D0D1` | UART on D0 (RXD) and D1 (TXD) | +| Seeedstudio XIAO | `ARDUINO_UART_DEV` | UART on D7 (RXD) and D6 (TXD) | + +### I²C Buses + +The feature `arduino_i2c` is provided by boards that do provide an I²C bus +mapping. + +| Form Factor | Macro Name | Description | +|:---------------- |:--------------------- |:--------------------------------- | +| Arduino Nano | `ARDUINO_I2C_NANO` | D18 (SDA) / D19 (SCL) | +| Arduino Uno | `ARDUINO_I2C_UNO` | D18 (SDA) / D19 (SCL) | +| Arduino Mega | `ARDUINO_I2C_UNO` | D20 (SDA) / D21 (SCL) | +| Arduino Zero | `ARDUINO_I2C_UNO` | D20 (SDA) / D21 (SCL) | +| Arduino Due | `ARDUINO_I2C_UNO` | D70 (SDA) / D71 (SCL) | +| Seeedstudio XIAO | `ARDUINO_I2C_DEV` | D4 (SDA) / D5 (SCL) | + +The `ARDUINO_I2C_UNO` refers to the I²C bus next to the AREF pin (the topmost +pins on header on the top right) of an Arduino Uno compatible board, e.g. +such as the Arduino Mega2560. Even though the Arduino UNO, the Arduino MEGA2560, +the Arduino Zero and the Arduino Zero all having the I²C bus at the exact same +mechanical positions, the digital pin number of the I²C bus next to the AREF +differs between the versions. + +### SPI Buses + +The feature `arduino_spi` is provided by boards that do provide an SPI bus +mapping. + +| Form Factor | Macro Name | Description | +|:---------------- |:------------------------- |:------------------------------------- | +| Arduino Nano | `ARDUINO_SPI_ISP` | The SPI on the ISP header | +| Arduino Nano | `ARDUINO_SPI_D11D12D13` | D11 (MOSI) / D12 (MISO) / D13 (SCK) | +| Arduino Uno | `ARDUINO_SPI_ISP` | The SPI on the ISP header | +| Arduino Uno | `ARDUINO_SPI_D11D12D13` | D11 (MOSI) / D12 (MISO) / D13 (SCK) | +| Arduino Mega | `ARDUINO_SPI_ISP` | The SPI on the ISP header | +| Arduino Mega | `ARDUINO_SPI_D11D12D13` | D11 (MOSI) / D12 (MISO) / D13 (SCK) | +| Seeedstudio XIAO | `ARDUINO_SPI_DEV` | D10 (MOSI) / D9 (MISO) / D8 (SCK) | + +:::note +The original AVR based Arduinos only have a single hard SPI bus which +is only provided via the ISP header. Many modern Arduino compatible +boards do not provide the ISP header and only have SPI on D11/D12/D13 +provided. +::: + +## Mechanical and Electrical Compatibility + +Modules implementing drivers for extension boards, a.k.a. shields, can express +their mechanical and electrical requirements by depending on `arduino_shield_...` +features. The following list of features currently exists: + +| Feature Name | Compatibility Claim | +|:--------------------- |:------------------------------------------------------------- | +| `arduino_shield_nano` | Board has side headers compatible with the Arduino Nano | +| `arduino_shield_uno` | Board has side headers compatible with the Arduino UNO | +| `arduino_shield_mega` | Board has side headers compatible with the Arduino MEGA | +| `feather_shield` | Board has headers compatible with the Adafruit Feather boards | +| `xiao_shield` | Board has headers compatible with the Seeedstudio XIAO boards | + +:::note +A board providing `arduino_shield_mega` **MUST** also provide +`arduino_shield_uno`, as Arduino MEGA boards are backward compatible to +shields for the Arduino UNO. +::: + +E.g. a module that implements the W5100 based Ethernet shield would depend on +both `arduino_shield_uno` and `arduino_shield_isp` for electrical compatibility +as well as on `arduino_spi` for SPI bus mapping and `arduino_pins` for the CS +pin mapping. This module could reuse the existing `w5100` driver and just +supply the correct `w5100_params_t` using the I/O mappings. diff --git a/doc/guides/misc/roadmap.md b/doc/guides/misc/roadmap.md new file mode 100644 index 0000000000..1707107b1f --- /dev/null +++ b/doc/guides/misc/roadmap.md @@ -0,0 +1,139 @@ +--- +title: Roadmap +description: Overview of priority areas of RIOT development & enhancements +--- + +The aim of the roadmap is to identify priority areas of RIOT development and enhancements. +For each area, some near-future plans and concrete next steps are indicated. +The text and items below are tentative, up for discussion, to be updated by regular pull requests. + + +# Network Stack High Layers +(contact/steering: [Martine](https://github.com/miri64)) + +- ICN stack support clean-up +- discuss mid- and long-term plans for network stack maintenance & development (GNRC vs other supported stacks) +- revisit network time synchronization +- Provide a border router into 6LoWPANs (a 6LBR) that works out of the box in common scenarios: + - [x] in IPv6 networks with working Prefix Delegation (PD) + - [ ] in IPv6 networks without working Prefix Delegation (eg. by means of ND Proxying) + - [ ] in legacy networks (eg. by means of tunneling) + - [ ] with configurable on-by-default fallbacks + +# Network Stack Low Layers +(contact/steering: [Peter](https://github.com/PeterKietzmann)) + +- Point-to-Point Protocol (PPP): finalize and merge `gnrc_ppp` + + +# Integrations +(contact/steering: [Teufelchen](https://github.com/teufelchen1)) + +- [Home-Assistant](https://www.home-assistant.io/) BTHome integration +- [Home-Assistant](https://www.home-assistant.io/) integration via [MQTT Discovery](https://www.home-assistant.io/integrations/mqtt#mqtt-discovery) + +# Power Modes +(contact/steering: [benpicco](https://github.com/benpicco)) + +- concept to fix shell usage issue while LPM activated +- integrate generic power management functions in device driver APIs (netdev, SAUL, ...) +- more advanced LPM concepts: + - sleeping for short periods (in cases where it is not feasible to switch to the idle thread and back) -> mitigate active waiting + + + +# Peripheral Drivers +(contact/steering: [maribu](https://github.com/maribu)) + +## Timers + +(contact/steering: [kaspar030](https://github.com/kaspar030), [benpicco](https://github.com/benpicco), [maribu](https://github.com/maribu)) + +- cleanup and unification of low-level timer interfaces (`timer`, `rtt`, `rtc`) +- implement capture mode + +## SPI + +- introduction of `spi_slave` interface +- transition to `spi_clk_t` being the frequency in Hz, not an `enum` constant, to allow arbitrary frequencies + - most implementations have been ported +- allow a way to detect the actual frequency an SPI bus is running at + - see https://github.com/RIOT-OS/RIOT/pull/16727 for one proposal + +## I2C + +- introduction of `i2c_slave` interface + - see https://github.com/RIOT-OS/RIOT/issues/19560 for a discussion + +## GPIO + +(contact/steering: [gschorcht](https://github.com/gschorcht), [maribu](https://github.com/maribu)) + +- add a port-based, feature-rich, thread-safe GPIO API + - [GPIO LL](https://doc.riot-os.org/group__drivers__periph__gpio__ll.html) seems to fit the bill so for + - many MCUs still need an implementation +- add a high level API that unifies external and internal GPIOs on top + +## ADC + +(contact/steering: [benpicco](https://github.com/benpicco), [kfessel](https://github.com/kfessel), [gschorcht](https://github.com/gschorcht), [maribu](https://github.com/maribu)) + +- extend / replace the ADC API to allow advanced use cases + - selecting reference voltages (think: multimeter app) + - differential inputs + - fast (ideally DMA supported) sampling (think: a digital oscilloscope app) + - unify external and internal ADCs + - see https://github.com/RIOT-OS/RIOT/pull/13247 for one proposal + + + +# Software Updates +(contact/steering: [Emmanuel](https://github.com/emmanuelsearch)) + +- Modularize to provide toolbox supporting other image storing (e.g. support external flash), transport (other than CoAP), crypto (e.g. secure element). +- riotboot support for architectures other than Cortex-M + + + +# Documentation +(contact/steering: [Emmanuel](https://github.com/emmanuelsearch)) + +- Write and publish more RDMs + + + +# Low-Level Hardware Support +(contact/steering: [Alex](https://github.com/aabadie)) + +- radio support for TI SensorTag +- radio support for Silab Thunderboard + + + +# Testing +(contact/steering: [Kaspar](https://github.com/kaspar030)) + +- automated network functionality tests (e.g. RPL + UDP/PING tests through border router, multi-hop) in IoTLAB dev sites? + + + +# Security +(contact/steering: [Kaspar](https://github.com/kaspar030)) + +- RNG unified (secure, or basic), seeding +- RIOT default configuration = secure configuration (that's our goal/motto) + + +## 802.15.4 Link Layer Security +(contact/steering: [chrysn](https://github.com/chrysn)) + +Current status: RIOT supports application provided keys, +with no guidance on how to (and no practical ways to) use that securely +(see [CVE-2021-41061](https://nvd.nist.gov/vuln/detail/CVE-2021-41061)). + +Goal: Usably secure defaults. + +- Figure out applicability of [RFC9031](https://www.rfc-editor.org/rfc/rfc9031) ("CoJP") to non-6TiSCH scenarios. +- Implement RFC9031 with any extensions needed for the MACs RIOT has. +- Provide tools to set up a recommended JRC, and to provision keys between it and the device at flash time. + This may entail extensions to the build process, as CoJP requires per-device secrets. diff --git a/doc/guides/misc/terminal_config.md b/doc/guides/misc/terminal_config.md new file mode 100644 index 0000000000..1ef71f58df --- /dev/null +++ b/doc/guides/misc/terminal_config.md @@ -0,0 +1,55 @@ +--- +title: Terminal programs configuration +description: How to configure popular terminal programs for correct display of newlines +--- + +## Background + +This page explains how to configure some popular terminal programs for correct +display of newlines when using the serial interface of a RIOT powered device. +When printing something using *stdio* (e.g., `printf("Hello World!\n");`, RIOT +sends a line feed character (`0xA`) as `\n` (newline). + +Some terminals need more, for example, a carriage return and a line feed +character (0x0D, 0x0A). See https://en.wikipedia.org/wiki/Newline for background. + +This page tries to collect the necessary settings for common terminal programs +that will make them correctly display newlines. + +## gtkterm + +- Graphical method: + - Open the configuration menu. + - Click on ***CR LF auto***. +- Manual method: + - Edit the file `~/.gtktermrc`. + - Change value of ***crlfauto*** option to `True`. + +## minicom + +- Interactive method: + - Press ***Ctrl+A u***. +- Manual method: + - Edit the configuration file (`~/.minirc.dfl` per default). + - Add the following line: + `pu addcarreturn Yes` + +## miniterm + +- Generic method: + - Start with `--eol CR` parameter. +- Via RIOT build system: + - `RIOT_TERMINAL=miniterm make term` + +## picocom + +- Generic method: + - Start with `--imap lfcrlf` parameter. +- Via RIOT build system: + - `RIOT_TERMINAL=picocom make term` + +## putty + +- Graphical method: + - Go to configuration tree and choose `Terminal` branch. + - Enable option `Implicit CR in every LF`. diff --git a/doc/starlight/astro.config.mjs b/doc/starlight/astro.config.mjs index c87988ce5f..2f529af788 100644 --- a/doc/starlight/astro.config.mjs +++ b/doc/starlight/astro.config.mjs @@ -56,6 +56,15 @@ export default defineConfig({ }, ], }, + { + label: "Code of Conduct", + collapsed: true, + items: [ + "general/code_of_conduct", + "general/code_of_conduct/faq", + "general/code_of_conduct/reporting", + ], + }, { label: "RIOT in a Nutshell", items: [ @@ -63,7 +72,6 @@ export default defineConfig({ "general/structure", "general/vision", "general/governance", - "general/code_of_conduct", ], }, { @@ -98,6 +106,15 @@ export default defineConfig({ "rust_tutorials/create_project", ], }, + { + label: "Advanced", + items: [ + "advanced_tutorials/creating_application", + "advanced_tutorials/creating_modules", + "advanced_tutorials/device_drivers", + "advanced_tutorials/porting_boards", + ], + }, ], }, { @@ -105,13 +122,24 @@ export default defineConfig({ items: [ "build-system/build_system", "build-system/build_system_basics", + "build-system/kconfig", + "build-system/flashing", "build-system/build-in-docker", "build-system/advanced_build_system_tricks", + "build-system/debugging_aids", ], }, { label: "Miscellaneous", - items: ["misc/release_cycle", "misc/how_to_doc"], + items: [ + "misc/dev_best_practices", + "misc/io_mapping_and_shields", + "misc/roadmap", + "misc/release_cycle", + "misc/emulators", + "misc/terminal_config", + "misc/how_to_doc", + ], }, ], customCss: ["./src/styles/custom.css", "./src/fonts/font-face.css"], diff --git a/pkg/doc.txt b/pkg/doc.txt index 0400999566..4fa88d48e1 100644 --- a/pkg/doc.txt +++ b/pkg/doc.txt @@ -79,8 +79,8 @@ * if one is working on new packages that aren't ready to be committed to * upstream or if an application needs its own unique packages. For this, one * can use the `EXTERNAL_PKG_DIRS` make variable. It works similar to the way - * [external modules](@ref modules-outside-of-riotbase) are - * handled. In your application's Makefile, in addition to adding the package + * [external modules](https://guide.riot-os.org/advanced_tutorials/creating_modules/#modules-outside-of-riotbase) + * are handled. In your application's Makefile, in addition to adding the package * name to `USEPKG` as shown above, add the path to a folder that contains your * external packages: * diff --git a/pkg/wolfssl/sock_tls/sock_tls.h b/pkg/wolfssl/sock_tls/sock_tls.h index e1c5b9a5cf..5d8cf9ed3e 100644 --- a/pkg/wolfssl/sock_tls/sock_tls.h +++ b/pkg/wolfssl/sock_tls/sock_tls.h @@ -13,8 +13,8 @@ * * How To Use * ---------- - * First you need to @ref including-modules "include" a module that implements - * this API in your application's Makefile. + * First you need to [include][include-link] + * a module that implements this API in your application's Makefile. * * The `sock_tls` module requires the `wolfssl` package. * @@ -107,8 +107,8 @@ * } * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * - * Above you see a simple DTLS echo server. It is important to at least include - * @ref including-modules "include" the IPv6 module of your networking + * Above you see a simple DTLS echo server. It is important to at least + * [include][include-link] the IPv6 module of your networking * implementation (e.g. `gnrc_ipv6_default` for @ref net_gnrc GNRC) and at least * one network device. * A separate file should define the buffers used as certificate and private key, @@ -218,6 +218,7 @@ * return 0; * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * + * [include-link]: https://guide.riot-os.org/advanced_tutorials/creating_application/#including-modules */ #include diff --git a/sys/arduino/doc.txt b/sys/arduino/doc.txt index 71ed93ef76..501e6e46f7 100644 --- a/sys/arduino/doc.txt +++ b/sys/arduino/doc.txt @@ -93,10 +93,14 @@ * the standard C++ lib (feature `libstdcpp`) is not required. * * As a minimum requirement, the features `arduino_pins` is a hard dependency. - * See @ref iomaps-mapping-gpio what a board needs to provide this. + * See [Digital Pins](https://guide.riot-os.org/misc/io_mapping_and_shields/#digital-pins + * what a board needs to provide this. * - * Additional mappings for analog pins (see @ref iomaps-mapping-adc) and PWM - * pins (see @ref iomaps-mapping-pwm) is required to be able to use + * Additional mappings for analog pins + * (see [Analog Pins](https://guide.riot-os.org/misc/io_mapping_and_shields/#analog-pins)) + * and PWM pins + * (see [PWM Pins](https://guide.riot-os.org/misc/io_mapping_and_shields/#pwm-pins)) + * is required to be able to use * `analogRead()` and `analogWrite()`. * * See also @ref iomaps on how a board can provide more I/O mappings and even diff --git a/sys/include/net/sock/async/event.h b/sys/include/net/sock/async/event.h index cf963efd45..352a6446ea 100644 --- a/sys/include/net/sock/async/event.h +++ b/sys/include/net/sock/async/event.h @@ -19,7 +19,7 @@ * How To Use * ---------- * - * You need to [include](@ref including-modules) at least one module that + * You need to [include][include-link] at least one module that * implements a [`sock` API](@ref net_sock) (e.g. `gnrc_sock_udp` and * `gnrc_sock_async` for the [GNRC](@ref net_gnrc) implementation using UDP) and * the module `sock_async_event` in your application's Makefile. @@ -82,7 +82,7 @@ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * Above you see a simple UDP echo server using @ref sys_event. Don't forget to - * also @ref including-modules "include" the IPv6 module of your networking + * also [include][include-link] the IPv6 module of your networking * implementation (e.g. `gnrc_ipv6_default` for @ref net_gnrc GNRC) and at least * one network device. * @@ -159,6 +159,8 @@ * event_loop(&queue); * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * + * [include-link]: https://guide.riot-os.org/advanced_tutorials/creating_application/#including-modules + * * @{ * * @file diff --git a/sys/include/net/sock/dtls.h b/sys/include/net/sock/dtls.h index 4f4ae91888..4955266709 100644 --- a/sys/include/net/sock/dtls.h +++ b/sys/include/net/sock/dtls.h @@ -55,7 +55,9 @@ * * ## Makefile Includes * - * First, we need to [include](@ref including-modules) a module that implements + * First, we need to + * [include](https://guide.riot-os.org/advanced_tutorials/creating_application/#including-modules) + * a module that implements * this API in our applications Makefile. For example the module that * implements this API for [tinydtls](@ref pkg_tinydtls) is called * `tinydtls_sock_dtls'. diff --git a/sys/include/net/sock/ip.h b/sys/include/net/sock/ip.h index 32646a9901..48a512ce62 100644 --- a/sys/include/net/sock/ip.h +++ b/sys/include/net/sock/ip.h @@ -18,7 +18,7 @@ * * How To Use * ---------- - * First you need to @ref including-modules "include" a module that implements + * First you need to [include][include-link] a module that implements * this API in your application's Makefile. For example the implementation for * @ref net_gnrc "GNRC" is called `gnrc_sock_ip`. * @@ -60,7 +60,8 @@ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * Above you see a simple IPv6 server. Don't forget to also - * @ref including-modules "include" the IPv6 module of your networking + * [include][include-link] + * the IPv6 module of your networking * implementation (e.g. `gnrc_ipv6_default` for @ref net_gnrc "GNRC") and at * least one network device. * @@ -195,7 +196,7 @@ * } * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * - * Again: Don't forget to also @ref including-modules "include" the IPv6 module + * Again: Don't forget to also [include][include-link] the IPv6 module * of your networking implementation (e.g. `gnrc_ipv6_default` for * @ref net_gnrc "GNRC") and at least one network device. * @@ -255,6 +256,8 @@ * Finally, we wait a second before sending out the next "Hello!" with * `xtimer_sleep(1)`. * + * [include-link]: https://guide.riot-os.org/advanced_tutorials/creating_application/#including-modules + * * @{ * * @file diff --git a/sys/include/net/sock/tcp.h b/sys/include/net/sock/tcp.h index 95de4b21c0..a964c7de0e 100644 --- a/sys/include/net/sock/tcp.h +++ b/sys/include/net/sock/tcp.h @@ -18,7 +18,7 @@ * * How To Use * ---------- - * First you need to @ref including-modules "include" a module that implements + * First you need to [include][include-link] a module that implements * this API in your application's Makefile. For example the implementation for * @ref net_gnrc "GNRC" is called `gnrc_sock_tcp`. * @@ -84,7 +84,7 @@ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * Above you see a simple TCP echo server. Don't forget to also - * @ref including-modules "include" the IPv6 module of your networking + * [include][include-link] the IPv6 module of your networking * implementation (e.g. `gnrc_ipv6_default` for @ref net_gnrc GNRC) and at least * one network device. * @@ -233,7 +233,7 @@ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * Above you see a simple TCP echo client. Again: Don't forget to also - * @ref including-modules "include" the IPv6 module of your networking + * [include][include-link] the IPv6 module of your networking * implementation (e.g. `gnrc_ipv6_default` for @ref net_gnrc "GNRC") and at * least one network device. Ad0)ditionally, for the IPv6 address parsing you need * the @ref net_ipv6_addr "IPv6 address module". @@ -286,6 +286,8 @@ * return res; * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * + * [include-link]: https://guide.riot-os.org/advanced_tutorials/creating_application/#including-modules + * * @{ * * @file diff --git a/sys/include/net/sock/udp.h b/sys/include/net/sock/udp.h index 0d7005e3e7..9cc9e12247 100644 --- a/sys/include/net/sock/udp.h +++ b/sys/include/net/sock/udp.h @@ -18,7 +18,7 @@ * * How To Use * ---------- - * First you need to @ref including-modules "include" a module that implements + * First you need to [include][include-link] a module that implements * this API in your application's Makefile. For example the implementation for * @ref net_gnrc "GNRC" is called `gnrc_sock_udp`. * @@ -61,7 +61,7 @@ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * Above you see a simple UDP echo server. Don't forget to also - * @ref including-modules "include" the IPv6 module of your networking + * [include][include-link] the IPv6 module of your networking * implementation (e.g. `gnrc_ipv6_default` for @ref net_gnrc GNRC) and at least * one network device. * @@ -193,7 +193,7 @@ * } * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * - * Again: Don't forget to also @ref including-modules "include" the IPv6 module + * Again: Don't forget to also [include][include-link] the IPv6 module * of your networking implementation (e.g. `gnrc_ipv6_default` for * @ref net_gnrc "GNRC") and at least one network device. * @@ -255,6 +255,8 @@ * Finally, we wait a second before sending out the next "Hello!" with * `xtimer_sleep(1)`. * + * [include-link]: https://guide.riot-os.org/advanced_tutorials/creating_application/#including-modules + * * @{ * * @file