diff --git a/doc/guides/c_tutorials/create_project.mdx b/doc/guides/c_tutorials/create_project.mdx new file mode 100644 index 0000000000..4657c7bc54 --- /dev/null +++ b/doc/guides/c_tutorials/create_project.mdx @@ -0,0 +1,191 @@ +--- +title: Creating a Project +description: This tutorial will guide you through creating a new project with a simple hello world program. +code_folder: examples/guides/creating_project/ +--- +import Contact from '@components/contact.astro'; +import GitSetup from '@components/gitsetup.mdx'; + +Now that we have played around with the examples and have a basic understanding of how to use RIOT, +let's create a new project from scratch. +We will create a simple hello world program that will print "Hello World!" to the console. + +Lets start with the basic git setup, +if you already have a git repository set up, +you can skip to the next section. + +## Step 1: The Basics of Git and Submodules + + + +## Step 2: Creating our hello world program + +Now that we have added RIOT as a submodule to our project, +we can start writing our hello world program. +To do this, we create a new file called `main.c` in the `hello_world` directory. +You can use any text editor to create this file. +We will use Visual Studio Code in this example. +To open Visual Studio Code in the directory, you can use the following command: + +```bash +code . +``` + +Now that Visual Studio Code is open, +we create a new file called `main.c` and add the following code: + +```c title="hello_world/main.c" +/* + * For many printing related things, such as the puts function here + * we import stdio, depending on your board, platform or form of output + * it then includes the right definitions without the need to + * worry about the specific details. + */ +#include + +/* + * This is the main function of the program. + * It serves as the entry point for the program and gets called once your CPU is + * initialized. + * + * The function returns an integer value, which is the exit status + * of the program. A return value of 0 indicates that the program has finished + * successfully. + */ +int main(void) { + puts("Hello World!"); + + return 0; +} +``` + +![The hello world program in Visual Studio Code](img/create_project/03_main_c.png) + +This program will print "Hello World!" to the console when it is run. +The `#include ` line includes the standard input/output library, +which allows us to use the `puts` function to print to the console. + +## Step 3: Creating the Makefile + +Now that we have created our hello world program, +we need to create a Makefile to build our program. +The Makefile is a build automation tool that allows us to define how our program should be built. +We create a new file called `Makefile` in the `hello_world` directory and add the following code: + +```makefile title="hello_world/Makefile" +# name of your application +APPLICATION = hello-world + +# Change this to your board if you want to build for a different board +BOARD ?= native + +# This has to be the absolute path to the RIOT base directory: +RIOTBASE ?= $(CURDIR)/RIOT + +# Comment this out to disable code in RIOT that does safety checking +# which is not needed in a production environment but helps in the +# development process: +DEVELHELP ?= 1 + +# Change this to 0 show compiler invocation lines by default: +QUIET ?= 1 + +include $(RIOTBASE)/Makefile.include +``` + +![The Makefile in Visual Studio Code](img/create_project/04_makefile.png) + +Congratulations! You have now created a new project with a simple hello world program. +In the next step, we will build and run our program just like we did in the "Getting Started" guide. + +## Step 4: Building and running the program + + + +To build our program, we use the following command: + +```bash +BUILD_IN_DOCKER=1 make all +``` + +:::note +The `BUILD_IN_DOCKER=1` flag tells the build system to use the docker image provided by RIOT +to build our program. +This ensures that we have all the necessary dependencies to build our program. +If you have already built RIOT on your system, +you can omit this flag and the build system will use the toolchain installed on your system. + +Do note that building in Docker will take quite a bit longer on the first run, +as it needs to download a fairly large Docker image. + +Alteratively, you can simply run: + +```bash +make all +``` +::: + +![Building the program](img/create_project/05_make.png) + +After building the program, +we can run it using the following command to start the RIOT shell: + +```bash +make term +``` + +:::note +Depending on your board, the hello world might appear before the RIOT shell starts. + +If you want to see the output of the hello world program, +you can run `make flash term` instead, +which will flash the program to the board and then start the RIOT shell. + +This does not guarantee that the hello world program will run before the RIOT shell starts +but should increase the chances of it appearing before the shell starts. +::: + +If everything went well, +you should see our hello world program printing "Hello World!" to the console after a few seconds. + +![The hello world program running in the RIOT shell](img/create_project/06_output.png) + +Hooraay! You have successfully created a new project with a simple hello world program. + +:::tip +Before you push your project to a git hosting service such as Github, +make sure to add a `.gitignore` file to your project to exclude +unnecessary files from being tracked by git. + +For this project, a `.gitignore` file could look like this: + +```bash title=".gitignore" +# Ignore build artifacts +bin/ +*.bin +*.elf +*.hex +*.map +*.lst +*.o +*.d +*.a +*.out +``` +::: + +## Conclusion + +In this tutorial, we have created a new project with a simple hello world program. +We have added RIOT as a submodule to our project, created a hello world program, +and built and run the program using the RIOT build system. +You can now start building your own applications using RIOT +and explore the vast possibilities that RIOT has to offer. + +:::note +The source code for this tutorial can be found +[HERE](https://github.com/RIOT-OS/RIOT/tree/master/examples/guides/creating_project). + +If your project is not working as expected, +you can compare your code with the code in this repository to see if you missed anything. +::: diff --git a/doc/guides/c_tutorials/gpio.mdx b/doc/guides/c_tutorials/gpio.mdx new file mode 100644 index 0000000000..46b2d0ea9b --- /dev/null +++ b/doc/guides/c_tutorials/gpio.mdx @@ -0,0 +1,312 @@ +--- +title: GPIO & Real Boards +description: This tutorial explains how to use GPIO in RIOT to control LEDs or read button presses. +code_folder: examples/guides/gpio/ +--- + +import Contact from '@components/contact.astro'; +import WorkingVideo from './img/gpio/05_working_video.mp4'; +import ButtonVideo from './img/gpio/08_buttons.mp4'; + +So far we have been running all our code using the `arduino-feather-nrf52840-sense` board. + +In this tutorial, we will learn how to use the GPIO pins on a real board +to control LEDs or read button presses. + +For this tutorial we will be using a the `arduino-feather-nrf52840-sense` board +with the [Teamagochi PCB](https://github.com/smartuni/teamagochi), +but you can use any board that has GPIO pins. + +## Step 1: Configuring our Board + + + +First, we need to inform RIOT about the board we are using. + +To do this we adapt the `BOARD` variable in our `Makefile` to the board we are using. + +```make +BOARD ?= arduino-feather-nrf52840-sense +``` + +:::tip +If you ever want to just quickly test something +on a board without having to change the `Makefile`, +you can also set the `BOARD` variable in the terminal before running `make`. +```bash +BOARD=arduino-feather-nrf52840-sense make all +``` + +![The board variable in Visual Studio Code](img/gpio/01_define_board.png) + +First we want to make sure that we can build the code for the board. +To do this we can simply run `make all` in the terminal, +this will build the code for the board and check if everything is set up correctly. + +If everything is set up correctly, +we should now be able to move on to flashing the board. + +:::tip +It might return something like: + +``` +/bin/sh: line 1: arm-none-eabi-gcc: command not found +Compiler arm-none-eabi-gcc is required but not found in PATH. Aborting. +``` + +This means that you need to install the ARM toolchain, +you can do this by running `sudo apt install gcc-arm-none-eabi` on Ubuntu +or `sudo pacman -S arm-none-eabi-gcc` on Arch Linux. + +If it still doesn't work, +consider running it via the Docker container using `BUILD_IN_DOCKER=1 make flash`. + +Please refer to the [Flashing a RIOT Application](/getting-started/flashing) +guide for more information. +::: + +Try flashing the board with `make flash` and see if it works, +it should still execute the same code as before when running RIOT natively on your +own hardware but now using the actual board. + +![Flash output in Visual Studio Code](img/gpio/02_flash_output.png) + +Now if we type `make term` we should see the output of the board in the terminal. +Make sure that you have the board connected to your computer via USB and +that your user has the necessary permissions to access the serial port. + +:::tip +On Arch Linux, you might need to add your user to the `uucp` group +to access the serial port. + +```bash +sudo usermod -a -G uucp $USER +``` +::: + +## Step 2: Controlling LEDs + +Now that we have the board working, let's try to control the LEDs on the board. + +The exact pins that control the LEDs might vary depending on the board you are using, +but in the case of the `arduino-feather-nrf52840-sense` board, +the LED would be connected on Port 1 Pin 9. + +You can often find these defines either in the board schematics or in the board +configuration headers in RIOT. + +First we need to include the necessary modules in our projects `Makefile`. + +```make +# Add the gpio module to the build +USEMODULE += periph_gpio +USEMODULE += periph_gpio_irq + +# Enable the milliseconds timer. +USEMODULE += ztimer +USEMODULE += ztimer_msec +``` + +![The Makefile with the GPIO modules](img/gpio/03_gpio_modules.png) + +This allows us to both control the GPIO pins and timers. + +Specifically, we need the `periph_gpio` module to control the GPIO pins, +`periph_gpio_irq` to handle GPIO interrupts, +and `ztimer` to use the timer functionality for blinking the LED. +In this case, we also need the `ztimer_msec` module to use the millisecond timer. + +Now we need to actually define the pin that we want to control in our code. +To do this include the following lines **before** the `main` function. +{/**/} +```c +#include "board.h" +#include "periph/gpio.h" +#include "ztimer.h" + +/* Define the LED0 pin and mode */ +gpio_t led0 = GPIO_PIN(1, 9); +gpio_mode_t led0_mode = GPIO_OUT; +``` + +Now we can control the LED. First we initialize the pin +and afterwards we turn the LED off by clearing the pin. + +{/**/} +```c +int main(void) { + /* Initialize the LED0 pin */ + gpio_init(led0, led0_mode); + /* Turn off the LED0 pin */ + gpio_clear(led0); + + /* Loop forever */ + while (1) { + + } +} +``` + +Turning the LED off when the board starts is quite boring, +so let's make it blink by adding a delay and toggling the LED. + +```c + /* Loop forever */ + while (1) { + /* Toggle the LED0 pin every 500 milliseconds */ + gpio_toggle(led0); + ztimer_sleep(ZTIMER_MSEC, 500); + } +``` + +![The Code in Visual Studio Code](img/gpio/04_code.png) + +If we now `make flash` and then `make term` we should see the LED blinking. + + + +## Step 3: Reading Button Presses + +If you remember what we did in the timers tutorial, +we can use quite similar code to read button presses. + +On a constrained device you usually don't want to poll the button state, +which is why we will use an interrupt to detect the button press, +that way we can drastically reduce the power consumption of the device. + + +First we need to define the callback function +that will be called when the button is pressed. + +```c title="Define the button callback function" +/* This callback function will be called when the button state changes */ +void button_callback(void *arg) { + /* the argument is not used */ + (void)arg; + + /* Toggle the LED1 pin based on the button state */ + if (gpio_read(button)) { + gpio_clear(led1); + } else { + gpio_set(led1); + } +} +``` + +Now we need to define the button and led1 pin and mode and initialize it. + +```c {1-6, 27-33} +/* Define the LED1 pin and mode */ +gpio_t led1 = GPIO_PIN(1, 10); +gpio_mode_t led1_mode = GPIO_OUT; + +/* Define the button pin */ +gpio_t button = GPIO_PIN(1, 2); + +/* This callback function will be called when the button state changes */ +void button_callback(void *arg) { + /* the argument is not used */ + (void)arg; + + /* Toggle the LED1 pin based on the button state */ + if (gpio_read(button)) { + gpio_clear(led1); + } else { + gpio_set(led1); + } +} + +int main(void) { + /* Initialize the LED0 pin */ + gpio_init(led0, led0_mode); + /* Turn off the LED0 pin */ + gpio_clear(led0); + + /* Initialize the LED1 pin */ + gpio_init(led1, led1_mode); + /* Turn off the LED1 pin */ + gpio_clear(led1); + + /* Initialize the button pin */ + gpio_init_int(button, GPIO_IN_PU, GPIO_BOTH, button_callback, NULL); + + /* Loop forever */ + while (1) { + /* Toggle the LED0 pin every 500 milliseconds */ + gpio_toggle(led0); + ztimer_sleep(ZTIMER_MSEC, 500); + } +} +``` + +This code will initialize the button pin and call the `button_callback` +function whenever the button is pressed. + +![Full Code in Visual Studio Code](img/gpio/07_full_code.png) + +If we now `make flash` and then `make term` we should see the LED turn on +when the button is pressed. + +:::tip +If you are using the `arduino-feather-nrf52840-sense` board, +the button is on the back of the board. + +Be careful to not press the reset button by mistake 😉 +::: + + + +## Extra: Board specific defines + +Most boards (if they have LEDs or buttons) will have +specific defines for the GPIO pins that are used. +For example, the `arduino-feather-nrf52840-sense` board has the `LED0_TOGGLE` +define that allows you to toggle the LED without having to define the pin yourself. + +In most cases using gpio like we did in this tutorial is the best way to go, +it's more flexible, documented and standardized for all boards. +However, using these defines can often be easier at the start, +esp. when the GPIO pins are not documented well or the board support is not complete yet. + +Using this define, we can simplify our code to the following: + +{/**/} +```c title="Using the LED0_TOGGLE define" +int main(void) { + /* Initialize the LED0 pin */ + gpio_init(led0, led0_mode); + /* Turn off the LED0 pin */ + gpio_clear(led0); + + /* Loop forever */ + while (1) { + /* Toggle the LED0 pin every 500 milliseconds */ + LED0_TOGGLE; + ztimer_sleep(ZTIMER_MSEC, 500); + } +} +``` + +## Conclusion + +In this tutorial we learned how to use the GPIO pins on a real board to +control LEDs and read button presses. + +This is a very basic example, but it should give you a good starting point +to build more complex applications. + + + +:::note +The source code for this tutorial can be found +[HERE](https://github.com/RIOT-OS/RIOT/tree/master/examples/guides/gpio). + +If your project is not working as expected, +you can compare your code with the code in this repository to see if you missed anything. +::: diff --git a/doc/guides/c_tutorials/img/create_project/03_main_c.png b/doc/guides/c_tutorials/img/create_project/03_main_c.png new file mode 100644 index 0000000000..fd885109dd Binary files /dev/null and b/doc/guides/c_tutorials/img/create_project/03_main_c.png differ diff --git a/doc/guides/c_tutorials/img/create_project/04_makefile.png b/doc/guides/c_tutorials/img/create_project/04_makefile.png new file mode 100644 index 0000000000..dbe293248b Binary files /dev/null and b/doc/guides/c_tutorials/img/create_project/04_makefile.png differ diff --git a/doc/guides/c_tutorials/img/create_project/05_make.png b/doc/guides/c_tutorials/img/create_project/05_make.png new file mode 100644 index 0000000000..e0805b5480 Binary files /dev/null and b/doc/guides/c_tutorials/img/create_project/05_make.png differ diff --git a/doc/guides/c_tutorials/img/create_project/06_output.png b/doc/guides/c_tutorials/img/create_project/06_output.png new file mode 100644 index 0000000000..6172393a8d Binary files /dev/null and b/doc/guides/c_tutorials/img/create_project/06_output.png differ diff --git a/doc/guides/c_tutorials/img/gpio/01_define_board.png b/doc/guides/c_tutorials/img/gpio/01_define_board.png new file mode 100644 index 0000000000..e576d00eba Binary files /dev/null and b/doc/guides/c_tutorials/img/gpio/01_define_board.png differ diff --git a/doc/guides/c_tutorials/img/gpio/02_flash_output.png b/doc/guides/c_tutorials/img/gpio/02_flash_output.png new file mode 100644 index 0000000000..7c75df547c Binary files /dev/null and b/doc/guides/c_tutorials/img/gpio/02_flash_output.png differ diff --git a/doc/guides/c_tutorials/img/gpio/03_gpio_modules.png b/doc/guides/c_tutorials/img/gpio/03_gpio_modules.png new file mode 100644 index 0000000000..340517e7a2 Binary files /dev/null and b/doc/guides/c_tutorials/img/gpio/03_gpio_modules.png differ diff --git a/doc/guides/c_tutorials/img/gpio/04_code.png b/doc/guides/c_tutorials/img/gpio/04_code.png new file mode 100644 index 0000000000..9bfc01864a Binary files /dev/null and b/doc/guides/c_tutorials/img/gpio/04_code.png differ diff --git a/doc/guides/c_tutorials/img/gpio/05_working_video.mp4 b/doc/guides/c_tutorials/img/gpio/05_working_video.mp4 new file mode 100644 index 0000000000..b2ef4df13d Binary files /dev/null and b/doc/guides/c_tutorials/img/gpio/05_working_video.mp4 differ diff --git a/doc/guides/c_tutorials/img/gpio/07_full_code.png b/doc/guides/c_tutorials/img/gpio/07_full_code.png new file mode 100644 index 0000000000..6f19ad0726 Binary files /dev/null and b/doc/guides/c_tutorials/img/gpio/07_full_code.png differ diff --git a/doc/guides/c_tutorials/img/gpio/08_buttons.mp4 b/doc/guides/c_tutorials/img/gpio/08_buttons.mp4 new file mode 100644 index 0000000000..83c39fdbe3 Binary files /dev/null and b/doc/guides/c_tutorials/img/gpio/08_buttons.mp4 differ diff --git a/doc/guides/c_tutorials/img/saul/01_makefile.png b/doc/guides/c_tutorials/img/saul/01_makefile.png new file mode 100644 index 0000000000..6bbbd3260d Binary files /dev/null and b/doc/guides/c_tutorials/img/saul/01_makefile.png differ diff --git a/doc/guides/c_tutorials/img/saul/02_main_c.png b/doc/guides/c_tutorials/img/saul/02_main_c.png new file mode 100644 index 0000000000..c1f13632b2 Binary files /dev/null and b/doc/guides/c_tutorials/img/saul/02_main_c.png differ diff --git a/doc/guides/c_tutorials/img/saul/03_register.png b/doc/guides/c_tutorials/img/saul/03_register.png new file mode 100644 index 0000000000..9571884319 Binary files /dev/null and b/doc/guides/c_tutorials/img/saul/03_register.png differ diff --git a/doc/guides/c_tutorials/img/saul/04_read.png b/doc/guides/c_tutorials/img/saul/04_read.png new file mode 100644 index 0000000000..ec3679f431 Binary files /dev/null and b/doc/guides/c_tutorials/img/saul/04_read.png differ diff --git a/doc/guides/c_tutorials/img/shell/01_makefile.png b/doc/guides/c_tutorials/img/shell/01_makefile.png new file mode 100644 index 0000000000..aa0a23271b Binary files /dev/null and b/doc/guides/c_tutorials/img/shell/01_makefile.png differ diff --git a/doc/guides/c_tutorials/img/shell/02_shell.png b/doc/guides/c_tutorials/img/shell/02_shell.png new file mode 100644 index 0000000000..aa0a23271b Binary files /dev/null and b/doc/guides/c_tutorials/img/shell/02_shell.png differ diff --git a/doc/guides/c_tutorials/img/shell/03_echo.png b/doc/guides/c_tutorials/img/shell/03_echo.png new file mode 100644 index 0000000000..d93741c743 Binary files /dev/null and b/doc/guides/c_tutorials/img/shell/03_echo.png differ diff --git a/doc/guides/c_tutorials/img/threads/01_thread_function.png b/doc/guides/c_tutorials/img/threads/01_thread_function.png new file mode 100644 index 0000000000..8a17790252 Binary files /dev/null and b/doc/guides/c_tutorials/img/threads/01_thread_function.png differ diff --git a/doc/guides/c_tutorials/img/threads/02_stack.png b/doc/guides/c_tutorials/img/threads/02_stack.png new file mode 100644 index 0000000000..50daa6da08 Binary files /dev/null and b/doc/guides/c_tutorials/img/threads/02_stack.png differ diff --git a/doc/guides/c_tutorials/img/threads/03_output.png b/doc/guides/c_tutorials/img/threads/03_output.png new file mode 100644 index 0000000000..4e46096e13 Binary files /dev/null and b/doc/guides/c_tutorials/img/threads/03_output.png differ diff --git a/doc/guides/c_tutorials/img/timers/01_output.png b/doc/guides/c_tutorials/img/timers/01_output.png new file mode 100644 index 0000000000..4abd1e99c0 Binary files /dev/null and b/doc/guides/c_tutorials/img/timers/01_output.png differ diff --git a/doc/guides/c_tutorials/saul.md b/doc/guides/c_tutorials/saul.md new file mode 100644 index 0000000000..7aa5bf38c9 --- /dev/null +++ b/doc/guides/c_tutorials/saul.md @@ -0,0 +1,174 @@ +--- +title: Sensors/Actuators using SAUL +description: Learn how to use sensors and actuators with RIOT +code_folder: examples/guides/saul/ +--- + +In the previous chapter we learned how to interact with the GPIOs directly, +but RIOT provides a more abstract way to interact with sensors and actuators. +RIOT calls this the SAUL (Sensors/Actuators Abstraction Layer) system. + +The availability of sensors and actuators can vary greatly between different boards, +so the SAUL system provides a way to interact with them in a uniform way, +regardless of the underlying hardware. +So consulting the [documentation](https://doc.riot-os.org/group__drivers__saul.html) +is always a good idea. + +## The Makefile + +First we need to include the necessary module in the `Makefile`, to do this +add the following line to the `Makefile`: + +```makefile +USEMODULE += saul +USEMODULE += saul_default +``` + +![Makefile in VSCode](img/saul/01_makefile.png) + +## Including the Headers + +Next we need to include the necessary headers in our `main.c` file. +Add the following lines to the top of the file: + +```c +#include + +#include "board.h" +#include "saul_reg.h" +#include "ztimer.h" +``` + +We need: +- `stdio.h` for the `printf` function, +- `board.h` for the board specific configuration, +- `ztimer.h` for the ztimer module so we can sleep for a while, +- and `saul_reg.h` for the SAUL registry and related functions. + + +![main.c in VSCode](img/saul/02_main_c.png) + +## Registering a Sensor + +To create a SAUL registry entry RIOT provides a function called `saul_reg_find_type` +which searches for the first device on our board that matches the description we provide. + +In this example we will register a temperature sensor, as such we need to simply tell it to +search for `SAUL_SENSE_TEMP` devices. + +```c + /* Define our temperature sensor */ + saul_reg_t *temperature_sensor = saul_reg_find_type(SAUL_SENSE_TEMP); +``` + +This doesn't actually guarantee that the sensor is available, which is why we also need to +check if the sensor truly exists. To do this we create a simple if statement that checks +whether the result of the function was `NULL` or not. + +```c + /* Exit if we can't find a temperature sensor */ + if (!temperature_sensor) { + puts("No temperature sensor found"); + return 1; + } else { + /* + * Otherwise print the name of the temperature sensor + * and continue the program + */ + printf("Temperature sensor found: %s\n", temperature_sensor->name); + } +``` + +![Code to register sensor in VSCode](img/saul/03_register.png) + +Congratulations, by this point your program should be able to find +a temperature sensor on your board. + +## Reading the Sensor + +Here is where SAUL really shines, +to read the sensor we simply call the `saul_reg_read` function +which then stores the result in a `phydat_t` struct we provide. + +```c + /* We start an infinite loop to continuously read the temperature */ + while (1) { + /* Define a variable to store the temperature */ + phydat_t temperature; + + /* + * Read the temperature sensor + * and store the result in the temperature variable + * saul_reg_read returns the dimension of the data read (1 in this case) + */ + int dimension = saul_reg_read(temperature_sensor, &temperature); +``` + +Once again, since C doesn't have exceptions, +we need to check if the sensor was read correctly. +In this case we simply need to check if the dimension is greater than 0. + +```c + /* If the read was successful (1+ Dimensions), print the temperature */ + if (dimension <= 0) { + puts("Error reading temperature sensor"); + return 1; + } +``` + +Now all that is left is to print the temperature to the console and go to sleep. + +RIOT provides a simple function to solve this problem, +`phydat_dump` which prints the data in a `phydat_t` struct to the console. + +```c + /* Dump the temperature to the console */ + phydat_dump(&temperature, dimension); + + /* Sleep for 1 seconds */ + ztimer_sleep(ZTIMER_MSEC, 1000); +``` + +![Code to read sensor in VSCode](img/saul/04_read.png) + +## Building and Running the Program + +As always, we need to build and run our program. +To do this we use the following commands: + +```bash +make flash +``` + +and then to see the output: + +```bash +make term +``` + +If everything went well, +you should see the temperature being printed to the console every second like this: + +```log +2024-10-14 15:31:29,610 # Data: 24.50 °C +2024-10-14 15:31:30,134 # Data: 24.50 °C +2024-10-14 15:31:31,134 # Data: 24.50 °C +2024-10-14 15:31:32,134 # Data: 24.50 °C +2024-10-14 15:31:33,135 # Data: 24.50 °C +2024-10-14 15:31:34,135 # Data: 24.50 °C +2024-10-14 15:31:35,136 # Data: 24.50 °C +``` + +## Conclusion + +Congratulations! You have now learned how to use the SAUL system +to interact with sensors and actuators in RIOT +and how to read the temperature from a temperature sensor. 🎉 + +:::note +The source code for this tutorial can be found +[HERE](https://github.com/RIOT-OS/RIOT/tree/master/examples/guides/saul). + +If your project is not working as expected, you can compare your code +with the code in this repository to see if you missed anything. +::: diff --git a/doc/guides/c_tutorials/shell.md b/doc/guides/c_tutorials/shell.md new file mode 100644 index 0000000000..57de59e1d5 --- /dev/null +++ b/doc/guides/c_tutorials/shell.md @@ -0,0 +1,133 @@ +--- +title: Shell Commands +description: This tutorial explains how to use the RIOT shell. +code_folder: examples/guides/shell/ +--- + +The shell is a powerful tool in RIOT that allows you to interact +with your application at runtime. +You can use the shell to inspect the state of your application, +change configuration parameters, and even run tests. + +In this tutorial, we will take a look at how to use the shell in RIOT +and how to create custom shell commands. + +## Step 1: Using the Shell + +We need to include the shell module in our application to use the shell. +As we did in the previous tutorials, we will have to go into the `Makefile` +of our application and add the following line: + +```make +USEMODULE += shell +``` + +This line tells the build system to include the shell module in our application. +Now we can use the shell in our application. + +![The Makefile in Visual Studio Code](img/shell/01_makefile.png) + +Now we can start the shell in our main function by calling the `shell_init` function. +Go into your `main.c` file and include the following code: + +```c title="The include so we can use the shell" +#include "shell.h" +``` + +```c title="The main function" +int main(void) { + /* Buffer to store command line input */ + char buffer[SHELL_DEFAULT_BUFSIZE]; + + /* Start the shell */ + shell_run(NULL, buffer, SHELL_DEFAULT_BUFSIZE); + + /* Return 0 to indicate that the program has finished successfully */ + return 0; +} +``` + +There are two importants things to note here: +First, we have to provide a buffer to the shell, +the shell will then use this buffer to store your input. +For this example, +we use the `SHELL_DEFAULT_BUFSIZE` macro to define the size of the buffer +but you can use any size you want (as long as it is big enough to store your input). + +The second thing to note is that we pass `NULL` as the first argument to the `shell_run` function. +This argument is used to pass a list of shell commands to the shell, +but we will take a look at that in the next step. + +Now we can build and run our program. +Compile the program and flash it to your board using `make flash`. + +If you look into the terminal via `make term` you should see the shell prompt. +You can now type shell commands and interact with your application. +For example, you can type `help` to get a list of available commands +... which is not very exciting at the moment because we don't have any custom commands. + +![The shell prompt](img/shell/02_shell.png) + +## Step 2: Creating Custom Shell Commands + +Creating custom shell commands is quite simple. +You just have to define a function that implements the command and register it with the shell. +RIOT provides a set of macros to make this process easier. + +Let's create a simple shell command that echoes back the input. +Go into your `main.c` file and include the following code: + +```c title="The include so we can print to the console" +#include +``` + +```c title="The function that implements the echo command" +/* Our command we want to register to the shell */ +int echo_command(int argc, char **argv) { + /* We take the arguments passed to the command */ + for (int i = 1; i < argc; i++) { + /* We print each argument followed by a space */ + printf("%s ", argv[i]); + } + /* Finally, we print a newline character to end the line */ + printf("\n"); + + /* Return 0 to indicate success */ + return 0; +} +``` + +This function takes two arguments: +`argc` and `argv`. `argc` is the number of arguments passed to the command +and `argv` is an array of strings containing the arguments. + +Now all that is left is to register the command with the shell. +Go back to your `main.c` file and include the following code _outside_ of the `main` function: + +```c title="Register the command with the shell" +/* This little macro registers the command so we can use it in the shell */ +SHELL_COMMAND(echo, "Echo a message", echo_command); + +``` + +This macro takes three arguments: the name of the command, +a short description of the command, and the function that implements the command. + +And that's it! You have created a custom shell command. +Now you can build and run your program again and type +`echo hello world` in the shell to see the command in action. + +![The echo command in action](img/shell/03_echo.png) + +## Conclusion + +In this tutorial, we have learned how to use the shell in RIOT +and how to create custom shell commands. + +:::note +The source code for this tutorial can be found +[HERE](https://github.com/RIOT-OS/RIOT/tree/master/examples/guides/shell). + +If your project is not working as expected, +you can compare your code with the code in this repository to see if you missed anything. +::: diff --git a/doc/guides/c_tutorials/threads.mdx b/doc/guides/c_tutorials/threads.mdx new file mode 100644 index 0000000000..6679f8cb3f --- /dev/null +++ b/doc/guides/c_tutorials/threads.mdx @@ -0,0 +1,115 @@ +--- +title: Threads +description: This tutorial explains how to use threads in RIOT. +code_folder: examples/guides/threads/ +--- + +import Contact from '@components/contact.astro'; + +Threads allow you to run multiple tasks concurrently in your application. + +## Step 1: Creating a Thread Function + +To create a thread in RIOT, +you need to define a function that implements the thread and then start the thread. +The signature of the thread function should be `void *thread_function_name(void *arg)`. +The argument `arg` is a pointer to any data that you want to pass to the thread. + +Let's create a simple thread that prints a message to the console. +Go into your `main.c` file and add the following code: + +```c +void *my_first_thread(void *arg) { + /* The argument we receive will not be used */ + (void)arg; + + /* We print a simple message from the thread */ + puts("Hello, from the thread!"); + + /* We return NULL to indicate that the thread has finished */ + return NULL; +} +``` + +![The thread function in Visual Studio Code](img/threads/01_thread_function.png) + +This function takes a single argument, +a pointer to any data, and prints "Hello, from the thread!" to the console. +Now all that is left is to start the thread. + +:::caution +You need to specify `void *arg` even if you don't use it, +otherwise the compiler will throw an error. +::: + +## Step 2: Starting the Thread + +To start a thread we need two things: +a stack for the thread and a call to `thread_create`. + +First, we need to define a stack for the thread. +The stack size should be at least `THREAD_STACKSIZE_MAIN` bytes. +You can define the stack as a global variable +or as a local variable in your `main` function. + +The stack size can vary depending on the complexity of your thread. +For example, depending of the amount of local variables you use, +the stack size might need to be larger. + +Lets define the stack as a global variable: + +```c +char my_thread_stack[THREAD_STACKSIZE_MAIN]; +``` + +![The thread stack in Visual Studio Code](img/threads/02_stack.png) + +Lastly, we need to actually start the thread. +Go into your `main` function and include the following code: + +```c +int main(void) { + /* Create a thread with the stack we defined above */ + thread_create(my_thread_stack, sizeof(my_thread_stack), + THREAD_PRIORITY_MAIN - 1, 0, my_first_thread, NULL, + "My first thread"); + + /* The main thread can continue doing its work (e.g., printing a message) */ + puts("Hello, from the main thread!"); +} +``` + +`thread_creates` takes the following arguments: +- `my_thread_stack`: The stack for the thread +- `sizeof(my_thread_stack)`: The size of the stack +- `THREAD_PRIORITY_MAIN - 1`: The priority of the thread +- `0`: The flags for the thread +- `my_first_thread`: The thread function +- `NULL`: The argument for the thread function +- `"My first thread"`: The name of the thread + +## Step 3: Building and Running the Program + +Now that we have created our thread, we can build and run our program. +Compile the program and flash it to your board using `make flash`. + +If we now look into the terminal via `make term` we should see the message +"Hello, from the main thread!" printed to the console followed by +"Hello, from the thread!" printed by the thread. + +![The output](img/threads/03_output.png) + + +## Conclusion + +Congratulations! You have successfully created and started a thread in RIOT. +Threads are a powerful tool but remember that you are on a resource-constrained device, +so don't create too many threads or use too much stack space. + +:::note +The source code for this tutorial can be found +[HERE](https://github.com/RIOT-OS/RIOT/tree/master/examples/guides/threads). + +If your project is not working as expected, +you can compare your code with the code in this repository to see if you missed anything. +::: diff --git a/doc/guides/c_tutorials/timers.md b/doc/guides/c_tutorials/timers.md new file mode 100644 index 0000000000..de61262335 --- /dev/null +++ b/doc/guides/c_tutorials/timers.md @@ -0,0 +1,111 @@ +--- +title: Timers and Callbacks +description: This tutorial explains how to use timers and callbacs in RIOT. +code_folder: examples/guides/timers/ +--- + +Timers and interrupts are essential concepts in embedded systems programming. +In this tutorial, we will take a look at how to use timers and interrupts in RIOT. + +There are two different approaches to timers, +you can either use interrupts or polling. + +Both have their advantages and disadvantages, but in general, +using interrupts is more efficient and allows you to do other things while +waiting for the timer to expire instead of constantly checking if the timer has expired. + +## Step 1: Using Timers + +In the hello world program we created in the previous tutorial, +we used the `ztimer` module to sleep for 3 seconds before printing "Hello World!" to the console. + +But what if we want to do something else while waiting for the timer to expire? +Let's take a closer look at how we can use timers in RIOT. + +### Step 1.1: Creating a Callback + +Timers are a way to schedule tasks to be executed at a later time. +In RIOT, you have to tell the timers two things: +the time when the timer should expire and the function that should be called +when the timer expires. + +Lets start by creating the callback that the timer will call when it expires. +Go into your `main.c` file and add the following code: + +```c +void timer_callback(void *arg) { + /* Cast the received pointer "arg" to a C String type */ + char *message = (char *)arg; + + /* Print the message */ + puts(message); +} +``` + +This function takes a single argument, a pointer to a string, +and prints the string to the console. Congrats, you have created a callback function, +now all that is left is to create the timer and schedule it. +To do that lets restructure our `main` function to use the timer. + +### Step 1.2: Scheduling the Timer + +Go into your `main` function and include the following code: + +```c +int main(void) { + /* Create a timer */ + ztimer_t timer = {.callback = timer_callback, + .arg = "3 seconds have passed!"}; +``` + +This code creates a timer and initializes it with the callback function we +created earlier and a message that will be printed when the timer expires. +Now all that is left is to actually start the timer. To do that, +we need to simply call the `ztimer_set` function with the timer we created as an argument. + +```c + /* Set the timer to fire in 3 seconds */ + ztimer_set(ZTIMER_SEC, &timer, 3); +``` + +This code tells the timer to fire in 3 seconds. +The first argument specifies which type of clock we want to use, +the second argument is the timer we created, and the third argument is the time in seconds. + +### Step 1.3: Running the Program + +Now that we have created the timer and scheduled it, we can run the program. +Compile the program using `make` and flash it to your board using `make flash`. +If you look into the terminal via `make term` you should see the message +"3 seconds have passed!" printed to the console after 3 seconds. + +That's all there is to it! You have successfully used a timer in RIOT. +Now you can do other things while waiting for the timer to expire, +instead of constantly checking if the timer has expired. For example, +lets use our knowledge from before to let the main thread go to sleep for 5 seconds +and then print a message. + +![The output](img/timers/01_output.png) + +```c + /* Sleep for 5 seconds */ + ztimer_sleep(ZTIMER_SEC, 5); + + puts("5 seconds have passed!"); + + return 0; +``` + +## Conclusion + +In this tutorial, we learned how to use timers in RIOT. +We created a callback function that prints a message to the console +and scheduled a timer to call the callback function after 3 seconds. + +:::note +The source code for this tutorial can be found +[HERE](https://github.com/RIOT-OS/RIOT/tree/master/examples/guides/timers). + +If your project is not working as expected, +you can compare your code with the code in this repository to see if you missed anything. +::: diff --git a/doc/guides/getting-started/img/00-Install_Ubuntu-00.png b/doc/guides/getting-started/img/00-Install_Ubuntu-00.png index 78e27ac1b0..6510c6373d 100644 Binary files a/doc/guides/getting-started/img/00-Install_Ubuntu-00.png and b/doc/guides/getting-started/img/00-Install_Ubuntu-00.png differ diff --git a/doc/guides/getting-started/img/00-Install_Ubuntu-01.png b/doc/guides/getting-started/img/00-Install_Ubuntu-01.png index 35f2b19de1..08af2445a4 100644 Binary files a/doc/guides/getting-started/img/00-Install_Ubuntu-01.png and b/doc/guides/getting-started/img/00-Install_Ubuntu-01.png differ diff --git a/doc/guides/getting-started/img/00-Install_Ubuntu-02.png b/doc/guides/getting-started/img/00-Install_Ubuntu-02.png index 56f53fdef3..1684f767fd 100644 Binary files a/doc/guides/getting-started/img/00-Install_Ubuntu-02.png and b/doc/guides/getting-started/img/00-Install_Ubuntu-02.png differ diff --git a/doc/guides/getting-started/img/00-Install_Ubuntu-03.png b/doc/guides/getting-started/img/00-Install_Ubuntu-03.png index 2cbe37d7a4..6097ea17c9 100644 Binary files a/doc/guides/getting-started/img/00-Install_Ubuntu-03.png and b/doc/guides/getting-started/img/00-Install_Ubuntu-03.png differ diff --git a/doc/guides/getting-started/img/00-Install_Ubuntu-04.png b/doc/guides/getting-started/img/00-Install_Ubuntu-04.png index df9c909e45..7b168dc730 100644 Binary files a/doc/guides/getting-started/img/00-Install_Ubuntu-04.png and b/doc/guides/getting-started/img/00-Install_Ubuntu-04.png differ diff --git a/doc/guides/getting-started/img/01-Install_WSL-00.png b/doc/guides/getting-started/img/01-Install_WSL-00.png index e9f8507fa7..32fc3662b8 100644 Binary files a/doc/guides/getting-started/img/01-Install_WSL-00.png and b/doc/guides/getting-started/img/01-Install_WSL-00.png differ diff --git a/doc/guides/getting-started/img/01-Install_WSL-01.png b/doc/guides/getting-started/img/01-Install_WSL-01.png index cc7cde8e20..ee13d3814f 100644 Binary files a/doc/guides/getting-started/img/01-Install_WSL-01.png and b/doc/guides/getting-started/img/01-Install_WSL-01.png differ diff --git a/doc/guides/getting-started/img/01-Install_WSL-02.png b/doc/guides/getting-started/img/01-Install_WSL-02.png index b1cff6edc9..50e08a63ee 100644 Binary files a/doc/guides/getting-started/img/01-Install_WSL-02.png and b/doc/guides/getting-started/img/01-Install_WSL-02.png differ diff --git a/doc/guides/getting-started/img/01-Install_WSL-03.png b/doc/guides/getting-started/img/01-Install_WSL-03.png index 3ba6360dda..9960e33a3e 100644 Binary files a/doc/guides/getting-started/img/01-Install_WSL-03.png and b/doc/guides/getting-started/img/01-Install_WSL-03.png differ diff --git a/doc/guides/getting-started/img/01-Install_WSL-04.png b/doc/guides/getting-started/img/01-Install_WSL-04.png index 413606234c..01b8867c09 100644 Binary files a/doc/guides/getting-started/img/01-Install_WSL-04.png and b/doc/guides/getting-started/img/01-Install_WSL-04.png differ diff --git a/doc/guides/getting-started/img/02-Setup_Ubuntu-00.png b/doc/guides/getting-started/img/02-Setup_Ubuntu-00.png index f18d3ff464..33e0449151 100644 Binary files a/doc/guides/getting-started/img/02-Setup_Ubuntu-00.png and b/doc/guides/getting-started/img/02-Setup_Ubuntu-00.png differ diff --git a/doc/guides/getting-started/img/02-Setup_Ubuntu-01.png b/doc/guides/getting-started/img/02-Setup_Ubuntu-01.png index 918b4cab1a..aae159e625 100644 Binary files a/doc/guides/getting-started/img/02-Setup_Ubuntu-01.png and b/doc/guides/getting-started/img/02-Setup_Ubuntu-01.png differ diff --git a/doc/guides/getting-started/img/02-Setup_Ubuntu-02.png b/doc/guides/getting-started/img/02-Setup_Ubuntu-02.png index ba7bd6996f..4c1c34c9d6 100644 Binary files a/doc/guides/getting-started/img/02-Setup_Ubuntu-02.png and b/doc/guides/getting-started/img/02-Setup_Ubuntu-02.png differ diff --git a/doc/guides/getting-started/img/02-Setup_Ubuntu-03.png b/doc/guides/getting-started/img/02-Setup_Ubuntu-03.png index 34ada15ebb..52c8f47c13 100644 Binary files a/doc/guides/getting-started/img/02-Setup_Ubuntu-03.png and b/doc/guides/getting-started/img/02-Setup_Ubuntu-03.png differ diff --git a/doc/guides/getting-started/img/02-Setup_Ubuntu-04.png b/doc/guides/getting-started/img/02-Setup_Ubuntu-04.png index b7e1c973db..243399bba6 100644 Binary files a/doc/guides/getting-started/img/02-Setup_Ubuntu-04.png and b/doc/guides/getting-started/img/02-Setup_Ubuntu-04.png differ diff --git a/doc/guides/getting-started/img/02-Setup_Ubuntu-05.png b/doc/guides/getting-started/img/02-Setup_Ubuntu-05.png index cd187cc6f2..ff55a9c9bb 100644 Binary files a/doc/guides/getting-started/img/02-Setup_Ubuntu-05.png and b/doc/guides/getting-started/img/02-Setup_Ubuntu-05.png differ diff --git a/doc/guides/getting-started/img/03-Install_Base_Packages-00.png b/doc/guides/getting-started/img/03-Install_Base_Packages-00.png index 80f07d4c48..3aa7d76d66 100644 Binary files a/doc/guides/getting-started/img/03-Install_Base_Packages-00.png and b/doc/guides/getting-started/img/03-Install_Base_Packages-00.png differ diff --git a/doc/guides/getting-started/img/03-Install_Base_Packages-01.png b/doc/guides/getting-started/img/03-Install_Base_Packages-01.png index 5a8b39130f..d7879e63b0 100644 Binary files a/doc/guides/getting-started/img/03-Install_Base_Packages-01.png and b/doc/guides/getting-started/img/03-Install_Base_Packages-01.png differ diff --git a/doc/guides/getting-started/img/03-Install_Base_Packages-02.png b/doc/guides/getting-started/img/03-Install_Base_Packages-02.png index 201e859a98..69ff8b2764 100644 Binary files a/doc/guides/getting-started/img/03-Install_Base_Packages-02.png and b/doc/guides/getting-started/img/03-Install_Base_Packages-02.png differ diff --git a/doc/guides/getting-started/img/04-Install_VS_Code-00.png b/doc/guides/getting-started/img/04-Install_VS_Code-00.png index 697d6c941f..ac6fe7c090 100644 Binary files a/doc/guides/getting-started/img/04-Install_VS_Code-00.png and b/doc/guides/getting-started/img/04-Install_VS_Code-00.png differ diff --git a/doc/guides/getting-started/img/04-Install_VS_Code-01.png b/doc/guides/getting-started/img/04-Install_VS_Code-01.png index dde5dc8a24..3ced260e6e 100644 Binary files a/doc/guides/getting-started/img/04-Install_VS_Code-01.png and b/doc/guides/getting-started/img/04-Install_VS_Code-01.png differ diff --git a/doc/guides/getting-started/img/04-Install_VS_Code-02.png b/doc/guides/getting-started/img/04-Install_VS_Code-02.png index 5f781b04f1..9392f395dd 100644 Binary files a/doc/guides/getting-started/img/04-Install_VS_Code-02.png and b/doc/guides/getting-started/img/04-Install_VS_Code-02.png differ diff --git a/doc/guides/getting-started/img/04-Install_VS_Code-03.png b/doc/guides/getting-started/img/04-Install_VS_Code-03.png index 3e25485d8e..b23297eca5 100644 Binary files a/doc/guides/getting-started/img/04-Install_VS_Code-03.png and b/doc/guides/getting-started/img/04-Install_VS_Code-03.png differ diff --git a/doc/guides/getting-started/img/04-Install_VS_Code-04.png b/doc/guides/getting-started/img/04-Install_VS_Code-04.png index 23901dfeee..4387df4a1f 100644 Binary files a/doc/guides/getting-started/img/04-Install_VS_Code-04.png and b/doc/guides/getting-started/img/04-Install_VS_Code-04.png differ diff --git a/doc/guides/getting-started/img/05-First_Steps-00.png b/doc/guides/getting-started/img/05-First_Steps-00.png index 7e94e69a5a..ef1300b9a7 100644 Binary files a/doc/guides/getting-started/img/05-First_Steps-00.png and b/doc/guides/getting-started/img/05-First_Steps-00.png differ diff --git a/doc/guides/getting-started/img/05-First_Steps-01.png b/doc/guides/getting-started/img/05-First_Steps-01.png index ca6a8bab3d..cbfecd426e 100644 Binary files a/doc/guides/getting-started/img/05-First_Steps-01.png and b/doc/guides/getting-started/img/05-First_Steps-01.png differ diff --git a/doc/guides/getting-started/img/06-Use_VS_Code-00.png b/doc/guides/getting-started/img/06-Use_VS_Code-00.png index 11fa6f91a3..e3229de680 100644 Binary files a/doc/guides/getting-started/img/06-Use_VS_Code-00.png and b/doc/guides/getting-started/img/06-Use_VS_Code-00.png differ diff --git a/doc/guides/getting-started/img/06-Use_VS_Code-01.png b/doc/guides/getting-started/img/06-Use_VS_Code-01.png index 694f630322..52f8a9411b 100644 Binary files a/doc/guides/getting-started/img/06-Use_VS_Code-01.png and b/doc/guides/getting-started/img/06-Use_VS_Code-01.png differ diff --git a/doc/guides/getting-started/img/06-Use_VS_Code-02.png b/doc/guides/getting-started/img/06-Use_VS_Code-02.png index 681f1d2d82..63e9949154 100644 Binary files a/doc/guides/getting-started/img/06-Use_VS_Code-02.png and b/doc/guides/getting-started/img/06-Use_VS_Code-02.png differ diff --git a/doc/guides/getting-started/img/06-Use_VS_Code-03.png b/doc/guides/getting-started/img/06-Use_VS_Code-03.png index 1a0a59c3f5..9e14317707 100644 Binary files a/doc/guides/getting-started/img/06-Use_VS_Code-03.png and b/doc/guides/getting-started/img/06-Use_VS_Code-03.png differ diff --git a/doc/guides/getting-started/img/06-Use_VS_Code-04.png b/doc/guides/getting-started/img/06-Use_VS_Code-04.png index 67e4aa5f99..ff6e811abb 100644 Binary files a/doc/guides/getting-started/img/06-Use_VS_Code-04.png and b/doc/guides/getting-started/img/06-Use_VS_Code-04.png differ diff --git a/doc/guides/getting-started/img/06-Use_VS_Code-05.png b/doc/guides/getting-started/img/06-Use_VS_Code-05.png index f0e300ca41..21b9696991 100644 Binary files a/doc/guides/getting-started/img/06-Use_VS_Code-05.png and b/doc/guides/getting-started/img/06-Use_VS_Code-05.png differ diff --git a/doc/guides/getting-started/img/06-Use_VS_Code-06.png b/doc/guides/getting-started/img/06-Use_VS_Code-06.png index db2602737e..e60adfad14 100644 Binary files a/doc/guides/getting-started/img/06-Use_VS_Code-06.png and b/doc/guides/getting-started/img/06-Use_VS_Code-06.png differ diff --git a/doc/guides/getting-started/img/06-Use_VS_Code-07.png b/doc/guides/getting-started/img/06-Use_VS_Code-07.png index 885ba5f32f..3347c8638a 100644 Binary files a/doc/guides/getting-started/img/06-Use_VS_Code-07.png and b/doc/guides/getting-started/img/06-Use_VS_Code-07.png differ diff --git a/doc/guides/getting-started/img/07-Install_USBIPd-00.png b/doc/guides/getting-started/img/07-Install_USBIPd-00.png index 292e06dc20..246ea8765c 100644 Binary files a/doc/guides/getting-started/img/07-Install_USBIPd-00.png and b/doc/guides/getting-started/img/07-Install_USBIPd-00.png differ diff --git a/doc/guides/getting-started/img/07-Install_USBIPd-01.png b/doc/guides/getting-started/img/07-Install_USBIPd-01.png index afb0a9812b..dfaec85e50 100644 Binary files a/doc/guides/getting-started/img/07-Install_USBIPd-01.png and b/doc/guides/getting-started/img/07-Install_USBIPd-01.png differ diff --git a/doc/guides/getting-started/img/07-Install_USBIPd-02.png b/doc/guides/getting-started/img/07-Install_USBIPd-02.png index 3487f3ce04..7063a8ca68 100644 Binary files a/doc/guides/getting-started/img/07-Install_USBIPd-02.png and b/doc/guides/getting-started/img/07-Install_USBIPd-02.png differ diff --git a/doc/guides/getting-started/img/07-Install_USBIPd-03.png b/doc/guides/getting-started/img/07-Install_USBIPd-03.png index d16ac49666..daa56aecbb 100644 Binary files a/doc/guides/getting-started/img/07-Install_USBIPd-03.png and b/doc/guides/getting-started/img/07-Install_USBIPd-03.png differ diff --git a/doc/guides/getting-started/img/07-Install_USBIPd-04.png b/doc/guides/getting-started/img/07-Install_USBIPd-04.png index d44dfaad92..4ba76b8e58 100644 Binary files a/doc/guides/getting-started/img/07-Install_USBIPd-04.png and b/doc/guides/getting-started/img/07-Install_USBIPd-04.png differ diff --git a/doc/guides/getting-started/img/07-Install_USBIPd-05.png b/doc/guides/getting-started/img/07-Install_USBIPd-05.png index 828c1788f8..2296dc8b91 100644 Binary files a/doc/guides/getting-started/img/07-Install_USBIPd-05.png and b/doc/guides/getting-started/img/07-Install_USBIPd-05.png differ diff --git a/doc/guides/getting-started/img/07-Install_USBIPd-06.png b/doc/guides/getting-started/img/07-Install_USBIPd-06.png index ac06ecbd6c..a50c6afc1f 100644 Binary files a/doc/guides/getting-started/img/07-Install_USBIPd-06.png and b/doc/guides/getting-started/img/07-Install_USBIPd-06.png differ diff --git a/doc/guides/getting-started/img/08-Flash_Real_Hardware-00.png b/doc/guides/getting-started/img/08-Flash_Real_Hardware-00.png index 8c6157e99f..dc2d91e01d 100644 Binary files a/doc/guides/getting-started/img/08-Flash_Real_Hardware-00.png and b/doc/guides/getting-started/img/08-Flash_Real_Hardware-00.png differ diff --git a/doc/guides/getting-started/img/08-Flash_Real_Hardware-01.png b/doc/guides/getting-started/img/08-Flash_Real_Hardware-01.png index cb0cae0381..c92a13ed6a 100644 Binary files a/doc/guides/getting-started/img/08-Flash_Real_Hardware-01.png and b/doc/guides/getting-started/img/08-Flash_Real_Hardware-01.png differ diff --git a/doc/guides/getting-started/img/08-Flash_Real_Hardware-02.png b/doc/guides/getting-started/img/08-Flash_Real_Hardware-02.png index f02bffb68c..4856905858 100644 Binary files a/doc/guides/getting-started/img/08-Flash_Real_Hardware-02.png and b/doc/guides/getting-started/img/08-Flash_Real_Hardware-02.png differ diff --git a/doc/guides/getting-started/img/08-Flash_Real_Hardware-03.png b/doc/guides/getting-started/img/08-Flash_Real_Hardware-03.png index 62f32bcda6..adf5d8f26f 100644 Binary files a/doc/guides/getting-started/img/08-Flash_Real_Hardware-03.png and b/doc/guides/getting-started/img/08-Flash_Real_Hardware-03.png differ diff --git a/doc/guides/getting-started/img/08-Flash_Real_Hardware-04.png b/doc/guides/getting-started/img/08-Flash_Real_Hardware-04.png index 4f9d4f91f4..ca690aa931 100644 Binary files a/doc/guides/getting-started/img/08-Flash_Real_Hardware-04.png and b/doc/guides/getting-started/img/08-Flash_Real_Hardware-04.png differ diff --git a/doc/guides/getting-started/img/08-Flash_Real_Hardware-05.png b/doc/guides/getting-started/img/08-Flash_Real_Hardware-05.png index 937943f341..445c44a788 100644 Binary files a/doc/guides/getting-started/img/08-Flash_Real_Hardware-05.png and b/doc/guides/getting-started/img/08-Flash_Real_Hardware-05.png differ diff --git a/doc/guides/getting-started/img/08-Flash_Real_Hardware-06.png b/doc/guides/getting-started/img/08-Flash_Real_Hardware-06.png index 077d4657ac..6c84d513b8 100644 Binary files a/doc/guides/getting-started/img/08-Flash_Real_Hardware-06.png and b/doc/guides/getting-started/img/08-Flash_Real_Hardware-06.png differ diff --git a/doc/guides/getting-started/img/08-Flash_Real_Hardware-07.png b/doc/guides/getting-started/img/08-Flash_Real_Hardware-07.png index 497a692d6f..2469bb6ecf 100644 Binary files a/doc/guides/getting-started/img/08-Flash_Real_Hardware-07.png and b/doc/guides/getting-started/img/08-Flash_Real_Hardware-07.png differ diff --git a/doc/guides/getting-started/img/08-Flash_Real_Hardware-08.png b/doc/guides/getting-started/img/08-Flash_Real_Hardware-08.png index f6ebab92d1..eb75531e8c 100644 Binary files a/doc/guides/getting-started/img/08-Flash_Real_Hardware-08.png and b/doc/guides/getting-started/img/08-Flash_Real_Hardware-08.png differ diff --git a/doc/guides/getting-started/img/finding_modules/01_api_doc.png b/doc/guides/getting-started/img/finding_modules/01_api_doc.png index 7cf2a57bc9..a3d7ead385 100644 Binary files a/doc/guides/getting-started/img/finding_modules/01_api_doc.png and b/doc/guides/getting-started/img/finding_modules/01_api_doc.png differ diff --git a/doc/guides/getting-started/img/finding_modules/02_examples.png b/doc/guides/getting-started/img/finding_modules/02_examples.png index ebd866ba23..472f783f2e 100644 Binary files a/doc/guides/getting-started/img/finding_modules/02_examples.png and b/doc/guides/getting-started/img/finding_modules/02_examples.png differ diff --git a/doc/guides/getting-started/img/finding_modules/03_source.png b/doc/guides/getting-started/img/finding_modules/03_source.png index 02a6884b8d..c6c79962e7 100644 Binary files a/doc/guides/getting-started/img/finding_modules/03_source.png and b/doc/guides/getting-started/img/finding_modules/03_source.png differ diff --git a/doc/guides/img/riot-logo-large.png b/doc/guides/img/riot-logo-large.png index b0f3e6770f..6e778832fa 100644 Binary files a/doc/guides/img/riot-logo-large.png and b/doc/guides/img/riot-logo-large.png differ diff --git a/doc/guides/misc/how_to_doc.md b/doc/guides/misc/how_to_doc.md index 4ca4fa2606..6f4c17ea87 100644 --- a/doc/guides/misc/how_to_doc.md +++ b/doc/guides/misc/how_to_doc.md @@ -112,6 +112,8 @@ One last manual step is to add the new guide to the navigation. This is done in Compared to the Doxygen output we want to be extremely careful about the navigation and only show the guides that are relevant to the user and in a logical order that does not overwhelm the user with too many options at once. +It is also important to note that the place in each section is directly related to the order in which the guides are listed in the `sidebar` array in the `astro.config.mjs` file. The order of the items in the array determines the order in which they will be displayed in the navigation. So if you want to place your guide at the top of a section, you should add it to the beginning of the `items` array for that section. + Generally, the less information you declare within the config the better, given that ideally your frontmatter information is enough to generate the navigation. You can either add your guide to an existing section or create a new section. In the event that you want to simply append your guide to an existing section, you can simply add the file name to the list of files in the section. The root of the so called `slug` of your file is the guides folder itself, so a guide under `doc/guides/test/hello_world.md` will have the slug `test/hello_world.md`. diff --git a/doc/starlight/astro.config.mjs b/doc/starlight/astro.config.mjs index ffb80294e4..4d141e673c 100644 --- a/doc/starlight/astro.config.mjs +++ b/doc/starlight/astro.config.mjs @@ -61,6 +61,17 @@ export default defineConfig({ "getting-started/finding_modules", ], }, + { + label: "C Basics", + items: [ + "c_tutorials/create_project", + "c_tutorials/timers", + "c_tutorials/shell", + "c_tutorials/threads", + "c_tutorials/gpio", + "c_tutorials/saul", + ], + }, ], }, { diff --git a/doc/starlight/src/components/gitsetup.mdx b/doc/starlight/src/components/gitsetup.mdx index f1d94fa462..da2f69a997 100644 --- a/doc/starlight/src/components/gitsetup.mdx +++ b/doc/starlight/src/components/gitsetup.mdx @@ -3,9 +3,7 @@ This tutorial assumes that you have already set up your development environment as described in the [Getting Started](/getting-started/installing/) guide. ::: -Now that we have played around with the examples and have a basic understanding of how to use RIOT, let's create a new project from scratch. We will create a simple hello world program that will print "Hello World!" to the console. - -#### Step 1: Create a new git repository +#### Create a new git repository We start by creating a new git repository for our project. If you have never worked with git before, you can find a good introduction [here](https://git-scm.com/book/en/v2/Getting-Started-About-Version-Control) or [here](https://docs.github.com/en/get-started/getting-started-with-git/set-up-git). @@ -25,7 +23,7 @@ git init Congratulations! You have now created a new empty git repository. In the next step, we will add RIOT as a submodule to our project. -#### Step 2: Add RIOT as a submodule +#### Add RIOT as a submodule We want to import RIOT as a submodule to our project. This will allow us to easily update to newer versions of RIOT and also allows us to easily share our project with others on GitHub, Gitlab, or any other git hosting service. diff --git a/examples/README.md b/examples/README.md index 89864f175f..2eef2d4ad5 100644 --- a/examples/README.md +++ b/examples/README.md @@ -142,3 +142,16 @@ Here is a quick overview of the examples available in the RIOT: | [twr_aloha](./advanced/twr_aloha/README.md) | This example allows testing different two-way ranging algorithms between two boards supporting a dw1000 device. This makes use of the uwb-core pkg. | | [senml_saul](./advanced/senml_saul/README.md) | This example demonstrates the usage of the SAUL (Sensor Actuator Uber Layer) module with the SenML (Sensor Measurement Lists) format. | | [opendsme](./advanced/opendsme/README.md) | This example demonstrates the usage of the OpenDSME module in RIOT. | + +## Examples from Guides + +[Our guides](https://guide.riot-os.org/) walk you through small tutorials to get started. The following examples are the resulting code from completing their respective guide. + +| Example | Description | +|---------|-------------| +| [creating_project](./guides/creating_project/README.md) | Teaches you the very first steps. How to setup a RIOT project, build and run a Hello World in it. [Create Project](https://guide.riot-os.org/c_tutorials/create_project/) tutorial | +| [shell](./guides/shell/README.md) | Teaches you how to use the interactive RIOT shell for your application. [Shell](https://guide.riot-os.org/c_tutorials/shell/) tutorial | +| [gpio](./guides/gpio/README.md) | Teaches you how to configure and use GPIO pins for external hardware interaction. [GPIO](https://guide.riot-os.org/c_tutorials/gpio/) tutorial | +| [saul](./guides/saul/README.md) | Teaches you how to interact with sensors and actuators through the SAUL interface. [SAUL](https://guide.riot-os.org/c_tutorials/saul/) tutorial | +| [threads](./guides/threads/README.md) | Teaches you how to create and manage multiple execution threads in your RIOT application. [Threads](https://guide.riot-os.org/c_tutorials/threads/) tutorial | +| [timers](./guides/timers/README.md) | Teaches you how to use timers for periodic tasks and time measurement in RIOT. [Timers](https://guide.riot-os.org/c_tutorials/timers/) tutorial | diff --git a/examples/guides/creating_project/Makefile b/examples/guides/creating_project/Makefile new file mode 100644 index 0000000000..9570f05bc7 --- /dev/null +++ b/examples/guides/creating_project/Makefile @@ -0,0 +1,21 @@ +# name of your application +APPLICATION = creating_project_example + +# Change this to your board if you want to build for a different board +BOARD ?= native + +# This has to be the absolute path to the RIOT base directory: +# If you are following the tutorial, your RIOT base directory will +# most likely be something like RIOTBASE ?= $(CURDIR)/RIOT +# instead of this +RIOTBASE ?= $(CURDIR)/../../.. + +# Comment this out to disable code in RIOT that does safety checking +# which is not needed in a production environment but helps in the +# development process: +DEVELHELP ?= 1 + +# Change this to 0 show compiler invocation lines by default: +QUIET ?= 1 + +include $(RIOTBASE)/Makefile.include diff --git a/examples/guides/creating_project/README.md b/examples/guides/creating_project/README.md new file mode 100644 index 0000000000..79ec5b031a --- /dev/null +++ b/examples/guides/creating_project/README.md @@ -0,0 +1,5 @@ +# RIOT Tutorial Replica + +This example is a replica of the output of the RIOT tutorial. The tutorial is available at [RIOT Tutorial](https://guide.riot-os.org). + +The tutorial itself is located within [doc/guides/c_tutorials](/doc/guides/c_tutorials/). Please refer to the original tutorial for more information. diff --git a/examples/guides/creating_project/main.c b/examples/guides/creating_project/main.c new file mode 100644 index 0000000000..811d6a660c --- /dev/null +++ b/examples/guides/creating_project/main.c @@ -0,0 +1,28 @@ +/* + * SPDX-FileCopyrightText: 2025 Tom Hert + * SPDX-FileCopyrightText: 2025 HAW Hamburg + * SPDX-License-Identifier: LGPL-2.1-only + */ + +/* + * For many printing related things, such as the puts function here + * we import stdio, depending on your board, platform or form of output + * it then includes the right definitions without the need to + * worry about the specific details. + */ +#include + +/* + * This is the main function of the program. + * It serves as the entry point for the program and gets called once your CPU is + * initialized. + * + * The function returns an integer value, which is the exit status + * of the program. A return value of 0 indicates that the program has finished + * successfully. + */ +int main(void) { + puts("Hello World!"); + + return 0; +} diff --git a/examples/guides/gpio/Makefile b/examples/guides/gpio/Makefile new file mode 100644 index 0000000000..2d129efd5f --- /dev/null +++ b/examples/guides/gpio/Makefile @@ -0,0 +1,29 @@ +# name of your application +APPLICATION = gpio_example + +# Change this to your board if you want to build for a different board +BOARD ?= arduino-feather-nrf52840-sense + +# This has to be the absolute path to the RIOT base directory: +# If you are following the tutorial, your RIOT base directory will +# most likely be something like RIOTBASE ?= $(CURDIR)/RIOT +# instead of this +RIOTBASE ?= $(CURDIR)/../../.. + +# Comment this out to disable code in RIOT that does safety checking +# which is not needed in a production environment but helps in the +# development process: +DEVELHELP ?= 1 + +# Add the gpio module to the build +USEMODULE += periph_gpio +USEMODULE += periph_gpio_irq + +# Enable the milliseconds timer. +USEMODULE += ztimer +USEMODULE += ztimer_msec + +# Change this to 0 show compiler invocation lines by default: +QUIET ?= 1 + +include $(RIOTBASE)/Makefile.include diff --git a/examples/guides/gpio/Makefile.ci b/examples/guides/gpio/Makefile.ci new file mode 100644 index 0000000000..363d4f3a79 --- /dev/null +++ b/examples/guides/gpio/Makefile.ci @@ -0,0 +1,4 @@ +BOARD_INSUFFICIENT_MEMORY := \ + atmega8 \ + nucleo-l011k4 \ + # diff --git a/examples/guides/gpio/README.md b/examples/guides/gpio/README.md new file mode 120000 index 0000000000..46c307bd29 --- /dev/null +++ b/examples/guides/gpio/README.md @@ -0,0 +1 @@ +../creating_project/README.md \ No newline at end of file diff --git a/examples/guides/gpio/main.c b/examples/guides/gpio/main.c new file mode 100644 index 0000000000..2a5281f165 --- /dev/null +++ b/examples/guides/gpio/main.c @@ -0,0 +1,55 @@ +/* + * SPDX-FileCopyrightText: 2025 Tom Hert + * SPDX-FileCopyrightText: 2025 HAW Hamburg + * SPDX-License-Identifier: LGPL-2.1-only + */ + +#include "board.h" +#include "periph/gpio.h" +#include "ztimer.h" + +/* Define the LED0 pin and mode */ +gpio_t led0 = GPIO_PIN(1, 9); +gpio_mode_t led0_mode = GPIO_OUT; + +/* Define the LED1 pin and mode */ +gpio_t led1 = GPIO_PIN(1, 10); +gpio_mode_t led1_mode = GPIO_OUT; + +/* Define the button pin */ +gpio_t button = GPIO_PIN(1, 2); + +/* This callback function will be called when the button state changes */ +void button_callback(void *arg) { + /* the argument is not used */ + (void)arg; + + /* Toggle the LED1 pin based on the button state */ + if (gpio_read(button)) { + gpio_clear(led1); + } else { + gpio_set(led1); + } +} + +int main(void) { + /* Initialize the LED0 pin */ + gpio_init(led0, led0_mode); + /* Turn off the LED0 pin */ + gpio_clear(led0); + + /* Initialize the LED1 pin */ + gpio_init(led1, led1_mode); + /* Turn off the LED1 pin */ + gpio_clear(led1); + + /* Initialize the button pin */ + gpio_init_int(button, GPIO_IN_PU, GPIO_BOTH, button_callback, NULL); + + /* Loop forever */ + while (1) { + /* Toggle the LED0 pin every 500 milliseconds */ + gpio_toggle(led0); + ztimer_sleep(ZTIMER_MSEC, 500); + } +} diff --git a/examples/guides/saul/Makefile b/examples/guides/saul/Makefile new file mode 100644 index 0000000000..4c380265d9 --- /dev/null +++ b/examples/guides/saul/Makefile @@ -0,0 +1,32 @@ +# name of your application +APPLICATION = saul_example + +# Change this to your board if you want to build for a different board +BOARD ?= arduino-feather-nrf52840-sense + +# This has to be the absolute path to the RIOT base directory: +# If you are following the tutorial, your RIOT base directory will +# most likely be something like RIOTBASE ?= $(CURDIR)/RIOT +# instead of this +RIOTBASE ?= $(CURDIR)/../../.. + +# Comment this out to disable code in RIOT that does safety checking +# which is not needed in a production environment but helps in the +# development process: +DEVELHELP ?= 1 + +# This board requires a start sleep to actually catch the printed output +USEMODULE += shell + +# Add the SAUL module to the application +USEMODULE += saul +USEMODULE += saul_default + +# Enable the milliseconds timer. +USEMODULE += ztimer +USEMODULE += ztimer_msec + +# Change this to 0 show compiler invocation lines by default: +QUIET ?= 1 + +include $(RIOTBASE)/Makefile.include diff --git a/examples/guides/saul/Makefile.ci b/examples/guides/saul/Makefile.ci new file mode 100644 index 0000000000..72db76ccb5 --- /dev/null +++ b/examples/guides/saul/Makefile.ci @@ -0,0 +1,3 @@ +BOARD_INSUFFICIENT_MEMORY := \ + atmega8 \ + # diff --git a/examples/guides/saul/README.md b/examples/guides/saul/README.md new file mode 120000 index 0000000000..46c307bd29 --- /dev/null +++ b/examples/guides/saul/README.md @@ -0,0 +1 @@ +../creating_project/README.md \ No newline at end of file diff --git a/examples/guides/saul/main.c b/examples/guides/saul/main.c new file mode 100644 index 0000000000..bacc0b75bc --- /dev/null +++ b/examples/guides/saul/main.c @@ -0,0 +1,57 @@ +/* + * SPDX-FileCopyrightText: 2025 Tom Hert + * SPDX-FileCopyrightText: 2025 HAW Hamburg + * SPDX-License-Identifier: LGPL-2.1-only + */ + +#include + +#include "board.h" +#include "saul_reg.h" +#include "ztimer.h" + +int main(void) { + /* We sleep for 5 seconds to allow the system to initialize */ + ztimer_sleep(ZTIMER_MSEC, 5000); + puts("Welcome to SAUL magic!"); + + /* Define our temperature sensor */ + saul_reg_t *temperature_sensor = saul_reg_find_type(SAUL_SENSE_TEMP); + + /* Exit if we can't find a temperature sensor */ + if (!temperature_sensor) { + puts("No temperature sensor found"); + return 1; + } else { + /* + * Otherwise print the name of the temperature sensor + * and continue the program + */ + printf("Temperature sensor found: %s\n", temperature_sensor->name); + } + + /* We start an infinite loop to continuously read the temperature */ + while (1) { + /* Define a variable to store the temperature */ + phydat_t temperature; + + /* + * Read the temperature sensor + * and store the result in the temperature variable + * saul_reg_read returns the dimension of the data read (1 in this case) + */ + int dimension = saul_reg_read(temperature_sensor, &temperature); + + /* If the read was successful (1+ Dimensions), print the temperature */ + if (dimension <= 0) { + puts("Error reading temperature sensor"); + return 1; + } + + /* Dump the temperature to the console */ + phydat_dump(&temperature, dimension); + + /* Sleep for 1 seconds */ + ztimer_sleep(ZTIMER_MSEC, 1000); + } +} diff --git a/examples/guides/shell/Makefile b/examples/guides/shell/Makefile new file mode 100644 index 0000000000..2b4ce798c1 --- /dev/null +++ b/examples/guides/shell/Makefile @@ -0,0 +1,24 @@ +# name of your application +APPLICATION = shell_example + +# Change this to your board if you want to build for a different board +BOARD ?= native + +# This has to be the absolute path to the RIOT base directory: +# If you are following the tutorial, your RIOT base directory will +# most likely be something like RIOTBASE ?= $(CURDIR)/RIOT +# instead of this +RIOTBASE ?= $(CURDIR)/../../.. + +# Comment this out to disable code in RIOT that does safety checking +# which is not needed in a production environment but helps in the +# development process: +DEVELHELP ?= 1 + +# This board requires a start sleep to actually catch the printed output +USEMODULE += shell + +# Change this to 0 show compiler invocation lines by default: +QUIET ?= 1 + +include $(RIOTBASE)/Makefile.include diff --git a/examples/guides/shell/README.md b/examples/guides/shell/README.md new file mode 120000 index 0000000000..46c307bd29 --- /dev/null +++ b/examples/guides/shell/README.md @@ -0,0 +1 @@ +../creating_project/README.md \ No newline at end of file diff --git a/examples/guides/shell/main.c b/examples/guides/shell/main.c new file mode 100644 index 0000000000..0764947b31 --- /dev/null +++ b/examples/guides/shell/main.c @@ -0,0 +1,37 @@ +/* + * SPDX-FileCopyrightText: 2025 Tom Hert + * SPDX-FileCopyrightText: 2025 HAW Hamburg + * SPDX-License-Identifier: LGPL-2.1-only + */ + +#include + +#include "shell.h" + +/* Our command we want to register to the shell */ +int echo_command(int argc, char **argv) { + /* We take the arguments passed to the command */ + for (int i = 1; i < argc; i++) { + /* We print each argument followed by a space */ + printf("%s ", argv[i]); + } + /* Finally, we print a newline character to end the line */ + printf("\n"); + + /* Return 0 to indicate success */ + return 0; +} + +/* This little macro registers the command so we can use it in the shell */ +SHELL_COMMAND(echo, "Echo a message", echo_command); + +int main(void) { + /* Buffer to store command line input */ + char buffer[SHELL_DEFAULT_BUFSIZE]; + + /* Start the shell */ + shell_run(NULL, buffer, SHELL_DEFAULT_BUFSIZE); + + /* Return 0 to indicate that the program has finished successfully */ + return 0; +} diff --git a/examples/guides/threads/Makefile b/examples/guides/threads/Makefile new file mode 100644 index 0000000000..bf2deb3df5 --- /dev/null +++ b/examples/guides/threads/Makefile @@ -0,0 +1,21 @@ +# name of your application +APPLICATION = threads_example + +# Change this to your board if you want to build for a different board +BOARD ?= native + +# This has to be the absolute path to the RIOT base directory: +# If you are following the tutorial, your RIOT base directory will +# most likely be something like RIOTBASE ?= $(CURDIR)/RIOT +# instead of this +RIOTBASE ?= $(CURDIR)/../../.. + +# Comment this out to disable code in RIOT that does safety checking +# which is not needed in a production environment but helps in the +# development process: +DEVELHELP ?= 1 + +# Change this to 0 show compiler invocation lines by default: +QUIET ?= 1 + +include $(RIOTBASE)/Makefile.include diff --git a/examples/guides/threads/Makefile.ci b/examples/guides/threads/Makefile.ci new file mode 100644 index 0000000000..b9ff275375 --- /dev/null +++ b/examples/guides/threads/Makefile.ci @@ -0,0 +1,3 @@ +BOARD_INSUFFICIENT_MEMORY := \ + nucleo-l011k4 \ + # diff --git a/examples/guides/threads/README.md b/examples/guides/threads/README.md new file mode 120000 index 0000000000..46c307bd29 --- /dev/null +++ b/examples/guides/threads/README.md @@ -0,0 +1 @@ +../creating_project/README.md \ No newline at end of file diff --git a/examples/guides/threads/main.c b/examples/guides/threads/main.c new file mode 100644 index 0000000000..f5594e0f1f --- /dev/null +++ b/examples/guides/threads/main.c @@ -0,0 +1,36 @@ +/* + * SPDX-FileCopyrightText: 2025 Tom Hert + * SPDX-FileCopyrightText: 2025 HAW Hamburg + * SPDX-License-Identifier: LGPL-2.1-only + */ + +#include + +#include "thread.h" + +/* + * Define a stack for the thread. + * The size of the stack is defined by THREAD_STACKSIZE_MAIN. + */ +char my_thread_stack[THREAD_STACKSIZE_MAIN]; + +void *my_first_thread(void *arg) { + /* The argument we receive will not be used */ + (void)arg; + + /* We print a simple message from the thread */ + puts("Hello, from the thread!"); + + /* We return NULL to indicate that the thread has finished */ + return NULL; +} + +int main(void) { + /* Create a thread with the stack we defined above */ + thread_create(my_thread_stack, sizeof(my_thread_stack), + THREAD_PRIORITY_MAIN - 1, 0, my_first_thread, NULL, + "My first thread"); + + /* The main thread can continue doing its work (e.g., printing a message) */ + puts("Hello, from the main thread!"); +} diff --git a/examples/guides/timers/Makefile b/examples/guides/timers/Makefile new file mode 100644 index 0000000000..2b0c6b7196 --- /dev/null +++ b/examples/guides/timers/Makefile @@ -0,0 +1,24 @@ +# name of your application +APPLICATION = timers_example + +# Change this to your board if you want to build for a different board +BOARD ?= native + +# This has to be the absolute path to the RIOT base directory: +# If you are following the tutorial, your RIOT base directory will +# most likely be something like RIOTBASE ?= $(CURDIR)/RIOT +# instead of this +RIOTBASE ?= $(CURDIR)/../../.. + +# Comment this out to disable code in RIOT that does safety checking +# which is not needed in a production environment but helps in the +# development process: +DEVELHELP ?= 1 + +# Import the ztimer_sec module so we can sleep +USEMODULE += ztimer_sec + +# Change this to 0 show compiler invocation lines by default: +QUIET ?= 1 + +include $(RIOTBASE)/Makefile.include diff --git a/examples/guides/timers/Makefile.ci b/examples/guides/timers/Makefile.ci new file mode 100644 index 0000000000..72db76ccb5 --- /dev/null +++ b/examples/guides/timers/Makefile.ci @@ -0,0 +1,3 @@ +BOARD_INSUFFICIENT_MEMORY := \ + atmega8 \ + # diff --git a/examples/guides/timers/README.md b/examples/guides/timers/README.md new file mode 120000 index 0000000000..46c307bd29 --- /dev/null +++ b/examples/guides/timers/README.md @@ -0,0 +1 @@ +../creating_project/README.md \ No newline at end of file diff --git a/examples/guides/timers/main.c b/examples/guides/timers/main.c new file mode 100644 index 0000000000..af2385bc3e --- /dev/null +++ b/examples/guides/timers/main.c @@ -0,0 +1,33 @@ +/* + * SPDX-FileCopyrightText: 2025 Tom Hert + * SPDX-FileCopyrightText: 2025 HAW Hamburg + * SPDX-License-Identifier: LGPL-2.1-only + */ + +#include + +#include "ztimer.h" + +void timer_callback(void *arg) { + /* Cast the received pointer "arg" to a C String type */ + char *message = (char *)arg; + + /* Print the message */ + puts(message); +} + +int main(void) { + /* Create a timer */ + ztimer_t timer = {.callback = timer_callback, + .arg = "3 seconds have passed!"}; + + /* Set the timer to fire in 3 seconds */ + ztimer_set(ZTIMER_SEC, &timer, 3); + + /* Sleep for 5 seconds */ + ztimer_sleep(ZTIMER_SEC, 5); + + puts("5 seconds have passed!"); + + return 0; +}