Signal in RT-Thread RTOS – RT-Thread Tutorial Part 8

This article is a continuation of the  Series on RT-Thread STM32 Tutorials and carries the discussion on RT-Thread RTOS and implementation with STM32. The aim of this series is to provide easy and practical examples that anyone can understand. In our last post, we have seen Message Queue in the RT-Thread RTOS. In this post, we will see the Signal in RT-Thread RTOS.

You can see the video explanation of Getting started with the RT-Thread RTOS.

Prerequisites

This is the continuation of the below tutorials. If you don’t read it, please read that also before this.

Tools and Components Required

Inter-thread Communication in RT-Thread RTOS

If we are working in a multithreaded environment, we need to send data from one thread to another thread. There are many ways to do that. Normally we use global variables or some memory segment for that purpose. Sometimes it is hard to use global data. Because it is difficult to keep track of the messages. To make our lives easier, RTOSs are will support a few inter-thread communication methods. RT-Thread RTOS supports the below inter-thread communication methods.

Signal in RT-Thread RTOS – RT-Thread Tutorial Part 8

Signal

signal is a software interrupt that is generated when an event has occurred. Essentially, signals notify threads of events that occurred during the execution of other threads or ISRs. When it comes to its principle, a thread receiving a signal is similar to the processor receiving an interrupt request.

The signal is also like Counting semaphores and events. But here signals will have a separate handler to process that. Signals are used for asynchronous communication in RT-Thread. It is like signals in the Linux system.

No operation is needed for a thread to wait for the signal’s arrival. In fact, the thread does not know when the signal will arrive.

Management of Signals

In RT-Thread RTOS, the signal supports the below operations.

Install signal

When the thread wants to process or receive the signal, then that thread has to install the signal using the below function interface.

rt_sighandler_t rt_signal_install(int signo, rt_sighandler_t[] handler);

This function will map the signal value and the action of the thread when that signal value is received.

Input parameters and return values for rt_signal_install()

Parameters Description
signo Signal value (only SIGUSR1 and SIGUSR2 are open to the user, the same applies below)
handler Set the approach to process signal values
Return ——
SIG_ERR Wrong signal
The handler value before the signal is installed Successful

Block Signal

If the thread doesn’t want to process the signal, then that thread can use the below function to block the signal.

void rt_signal_mask(int signo);

Unblock Signal

If the thread wants to unblock the blocked signal, then it can use the below function to do that.

void rt_signal_unmask(int signo);

Send Signal

One thread or ISR can send the signal to another thread using the below function.

int rt_thread_kill(rt_thread_t tid, int sig);

Input parameters and return values for rt_thread_kill()

Parameters Description
tid The thread receiving signal
sig Signal value
Return ——
RT_EOK Sent successfully
-RT_EINVAL Parameter error

Wait for Signal

Wait for the arrival of the set signal. If this signal did not arrive, suspend the thread until the signal arrives or wait until time exceeds the specified timeout. If the signal arrived, the pointer pointing to the signal body is stored in si, as follows is the function to wait for the signal.

int rt_signal_wait(const rt_sigset_t *set,
                        rt_siginfo_t[] *si, rt_int32_t timeout);

Input parameters and return values for rt_signal_wait()

Parameters Description
set Specify the signal to wait
si Pointer pointing to signal information
timeout Waiting time
Return ——
RT_EOK Signal arrives
-RT_ETIMEOUT Timeout
-RT_EINVAL Parameter error

Enable Signal in RT-Thread RTOS

By default, the signals won’t be enabled. So, we need to enable them in the RT-Thread RTOS before using the signals. Please follow the below steps.

  1. Create the project in the RT-Thread studio.
  2. Open the RT-Thread Settings. Refer to this image.
    • Open RT-Thread Settings
  3. Click the Kernel –> Inter-thread communication –> Enable signals. Refer to this image.
    • Enable Signals

That’s it. We can start coding.

Signal in RT-Thread Example

In this example, I have created two threads. Thread 2, installs the SIGUSR1 and SIGUSR2 signals. And thread 1 increments the count. When the count value is odd, it will send the SIGUSR1 signal. When the count value is even, it will send the SIGUSR2 signal.

Source code

You can get this entire project’s source code from GitHub.

#include <rtthread.h>

#define DBG_TAG "main"
#define DBG_LVL DBG_LOG

#include <rtdbg.h>
#include <drv_common.h>
#include <rtdevice.h>

static rt_thread_t threadId1 = RT_NULL;
static rt_thread_t threadId2 = RT_NULL;

/* Signal process function for thread 2 signal handler */
void thread2_signal_handler1(int sig)
{
    rt_kprintf("Thread 2 Handler 1: Received signal %d\n", sig);
}

/* Signal process function for thread 2 signal handler */
void thread2_signal_handler2(int sig)
{
    rt_kprintf("Thread 2 Handler 2: Received signal %d\n", sig);
}


/* Thread 1 */
static void thread1_function(void *parameter)
{
    uint32_t count = 0;
    while (1)
    {
        count++;
        LOG_D("Thread 1: count = %d\n", count);

        if( count & 0x01 )
        {
            /* Send signal SIGUSR1 to thread 2 */
            rt_thread_kill(threadId2, SIGUSR1);
        }
        else
        {
            /* Send signal SIGUSR2 to thread 2 */
            rt_thread_kill(threadId2, SIGUSR2);
        }

        rt_thread_mdelay(1000);
    }
}

/* Thread 2 */
static void thread2_function(void *parameter)
{
    /* Install signal */
    rt_signal_install(SIGUSR1, thread2_signal_handler1);
    rt_signal_install(SIGUSR2, thread2_signal_handler2);

    /* Unblock the signal */
    rt_signal_unmask(SIGUSR1);
    rt_signal_unmask(SIGUSR2);

    while (1)
    {
        /* Do nothing or something */
    }
}

int main(void)
{
    /* Create thread 1 */
    threadId1 = rt_thread_create("thread1_fn",        //Name
                                  thread1_function,   //Function address
                                  RT_NULL,            //Thread function parameter
                                  1024,               //Stack Size
                                  1,                  //Thread priority
                                  2000);              //Time slice in ticks

    /* Create thread 2 */
    threadId2 = rt_thread_create("thread2_fn",        //Name
                                  thread2_function,   //Function address
                                  RT_NULL,            //Thread function parameter
                                  1024,               //Stack Size
                                  1,                  //Thread priority
                                  2000);              //Time slice in ticks

    /* Start both threads */
    rt_thread_startup(threadId1);
    rt_thread_startup(threadId2);

    while(1);

    return RT_EOK;
}

Output

 \ | /
- RT -     Thread Operating System
 / | \     4.1.1 build Mar  8 2023 20:05:40
 2006 - 2022 Copyright by RT-Thread team
←[0m[D/main] Thread 1: count = 1
←[0m
Thread 2 Handler 1: Received signal 30
←[0m[D/main] Thread 1: count = 2
←[0m
Thread 2 Handler 2: Received signal 31
←[0m[D/main] Thread 1: count = 3
←[0m
Thread 2 Handler 1: Received signal 30
←[0m[D/main] Thread 1: count = 4
←[0m
Thread 2 Handler 2: Received signal 31
←[0m[D/main] Thread 1: count = 5
←[0m
Thread 2 Handler 1: Received signal 30
←[0m[D/main] Thread 1: count = 6
←[0m
Thread 2 Handler 2: Received signal 31

In our next tutorial, we will see the demo application which uses a few peripherals in RT-Thread RTOS.

You can also read the below tutorials.

Linux Device Driver Tutorials C Programming Tutorials
FreeRTOS Tutorials NuttX RTOS Tutorials
RTX RTOS Tutorials Interrupts Basics
I2C Protocol – Part 1 (Basics) I2C Protocol – Part 2 (Advanced Topics)
STM32 Tutorials LPC2148 (ARM7) Tutorials
PIC16F877A Tutorials 8051 Tutorials
Unit Testing in C Tutorials ESP32-IDF Tutorials
Raspberry Pi Tutorials Embedded Interview Topics
Reset Sequence in ARM Cortex-M4 BLE Basics
VIC and NVIC in ARM SPI – Serial Peripheral Interface Protocol
STM32F7 Bootloader Tutorials Raspberry PI Pico Tutorials
STM32F103 Bootloader Tutorials RT-Thread RTOS Tutorials
Zephyr RTOS Tutorials – STM32 Zephyr RTOS Tutorials – ESP32
AUTOSAR Tutorials UDS Protocol Tutorials
Product Reviews STM32 MikroC Bootloader Tutorial
VHDL Tutorials

Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Table of Contents