Best practice for spawning a (short) Zephyr thread from main and terminating it?

Hi, I am relatively new to the Nordic platform and Zephyr RTOS. I am using nRF Connect SDK version 2.6.0 (the VS Code extension on Windows 11) with the nRF52840DK. I was wondering what the best strategy would be for spawning threads that do a small task and then terminate. I have gone through the documentation here and managed to come up with a small demo program to test my understanding. In the program below, the main thread just periodically reads a button state and if high, spawns a new thread. This newly spawned thread just prints a message and returns, which according to the documentation will cause the thread to terminate. The main thread in the meantime sleeps for sometime, within which the thread will probably have terminated. I have flashed it to my nRF42840DK it is working.

/* Demo program: spawning and terminating Zephyr threads. */
#include <zephyr/kernel.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/sys/printk.h>

/* Define GPIO pin for collecting button input. */
#define BUTTON_NODE DT_ALIAS(sw0)
static const struct gpio_dt_spec button = GPIO_DT_SPEC_GET(BUTTON_NODE, gpios);

/* Define entry point for thread (target function). */
void button_pressed(void *, void *, void *)
{
    static uint32_t npressed = 0;
    printk("[%02" PRIu32 "] pressed!\n", ++npressed);
    /* Terminate thread: exit from here. */
}

/* Define thread params. */
#define MY_STACK_SIZE 500
#define MY_PRIORITY 5

/* Allocate stack for thread. */
K_THREAD_STACK_DEFINE(my_stack_area, MY_STACK_SIZE);

/* Allocate a Thread Control Block (TCB). */
static struct k_thread my_thread_data;

/* Function to be called from main thread. */
int main(void)
{
    /* Setup GPIO. */
    if (!gpio_is_ready_dt(&button)) {
        return 1;
    }
    gpio_pin_configure_dt(&button, GPIO_INPUT);

    /* Poll for button press every 100 ms and spawn thread if found. */
    for (;;) {
        int val = gpio_pin_get_dt(&button);
        if (val == 1) {
            /* Spawn thread. */
            k_thread_create(
                &my_thread_data, my_stack_area,
                K_THREAD_STACK_SIZEOF(my_stack_area),
                button_pressed, NULL, NULL, NULL,
                MY_PRIORITY, 0, K_NO_WAIT
            );
        }
        k_msleep(100); /* Enough time for the thread spawned above to exit. */
    }
    return 0;
}
 

I have a few questions:

1. is this the correct approach for spawning short-lived threads? Am I forgetting to do some cleanup? and are there better approaches to use cases such as this ?

2. is k_thread_join() needed here? Because the code seems to work fine without it.

I am a relatively inexperienced dev delving into the world of RTOS programming for the first time so suggestions are really appreciated. Thanks!

Related