Introduction:
This blog mainly describes the process of coding my own RTOS and the problems I encountered, comparing my RTOS with examples and then reflecting on it.
Our RTOS :
After learning about the specific process of RTOS last week, I plan to create my own RTOS.
This RTOS program primarily creates a simple on/off control system. It allows users to control LEDs to turn on and off via serial port input commands or button presses, while simultaneously displaying the current status on an LCD. The program divides different functions into multiple RTOS tasks, allowing the system to handle different tasks concurrently.
First is the input section. The system has two input sources. The first is serial port input, where the user can input `on`, `off`, or `toggle` in the PuTTY. When Enter is pressed, it's considered a command input complete, and the command is then handed over to the kernel task for processing. The second input is the buttons on the board. The program checks the button status every 100ms. If the button changes from open to pressed, a `toggle` event is generated, causing the system to switch states.

Then comes the state machine section. The state machine's role is to determine whether the system should be on or off based on the input events. The system has only two states: `ON` and `OFF`. If an `on` event is received, the state is set to ON; if an `off` event is received, it is set to OFF. `toggle` reverses the current state. If the state changes, a flag `sw_changed` is set to inform the output task that the display needs updating.
Eventually, there's the output section. One RTOS task updates the LCD display, showing "turn on" or "turn off" if the state changes. Another task controls the LED, turning them on when the state is ON and off when the state is OFF. This ensures that the LEDs and LCD continuously reflect the current system state.
And here's the state machine diagram:
As we can see from this diagram, the problem is obvious. The entire process heavily relies on the task chain from input to state machine to output, rather than a single task loop.In particular, the conditions in the process from output1/2 to input2 in the diagram are not rigorous. I should make the program behave more like a loop, rather than a simple input-to-output sequence.
Compared to the example:
About the input part:
The example also includes global variables, the core tasks rely more on the RTOS message queue for information exchange, while my own code depends more on shared variables such as sm_event, sw_state, and sw_changed.
About the output part:
The example's `output1_rtos_task()` primarily does two things:
1. Checks its own message queue for messages.
2. If there are messages, it reads them and prints the serial port debugging information.
In other words, the output task doesn't decide what to do itself; it simply "waits for messages from the state machine."
My own `The_output1_task()` checks `sw_changed`, and updates the LCD if the state changes. This approach also achieves the functionality, but the difference is:
Example: The output task is passive, waiting for notification from the state machine.
My approach: The output task actively checks global state variables.
The example's approach is better because the output doesn't know where the system state comes from; It only knows "I received a message." My output task, however, needs to know `sw_state` and `sw_changed`, indicating that it's more tightly bound to the state machine.
About the state machine part:
The process of `state_machine_rtos_task()` is as follows:
First, check if an input message has been received.
If so, read it using `rtos_msg_read()`.
Based on the current state `state` and the input `state_machine_input`, determine the next step.Execute the corresponding output and switch to the next state:
`STATE_1 + INPUT_1_ON → Send message 1 to output1, go to STATE_2`
`STATE_2 + INPUT_1_ON → Send message 2 to output1, go to STATE_3`
`STATE_3 + INPUT_1_ON → Send message 3 to output2, go to STATE_4`
This is better because it fully embodies the three things a state machine does:
What is the current state?
What input has been received?
What is output, and where does it switch to?
While my own state machine also has this structure, it is much simpler:
`EV_ON → state=1`
`EV_OFF → state=0`
`EV_TOGGLE →` Flip
Therefore, my state machine can perform switch control, but it doesn't have the "multi-state + multi-output path" demonstration effect of the example.
Conclusion
Comparing the examples, we also found that RTOS architectures don't always need to be particularly rigid. For instance, the example lacks a kernel because the RTOS itself handles task scheduling. Input tasks can directly send events to the state machine without needing a kernel as an intermediary, thus simplifying the structure.
This RTOS design wasn't entirely smooth or successful.Comparing it to the examples helps us understand where we can improve. I hope to continue my efforts in future RTOS coding.
Comments
Post a Comment