As most of the Arduino players, I started from Arduino Uno. And soon I collected a lot of shields. To drive those shields I used various libraries, which ate up all the memory space.
So I moved to Arduino Mega and had a lot of fun, until I started working on a little bit more complex projects, like playing with display and sound.
Recently, I upgrade my weapon again to Arduino Due which has completely different architecture (ARM Cortex-M) with my previous boards (AVR). A 32-bit core with "huge" memory space and much higher clock speed, without doubt, is a powerful weapon. However, to fully utilize the power, using a simple "loop" function may not be enough. That's the issue Arduino RT-Thread library project want to address.
RT-ThreadRT-Thread is a free and open source (Apache License 2.0) RTOS. Some unique features, like tiny shell (named FinSH), dynamic loading module and lots of device drivers, make it very interesting. Even though the most important feature is it has a very active community.
Let's StartThe library is hosted on Github and can be installed through "Library Manager".
Currently, there are two examples available which are also listing in "CODE" section. (More examples will be available later.)
The first example "Blink" shows how to create and start a thread named "Blink". The task of "Blink" thread is to blink the builtin LED with 1 second interval.
The second example "FinSH" shows how to add user defined variable and command to the tiny shell. There are two user variables led_id
, led_state
and one user command led()
implemented.
FinSH, the tiny shell accepts C-style input (e.g. hello()
), supports auto-completion (e.g. type lis[Tab]
) and history (after issued several commands try type ↑
and ↓
).
It provides the following predefined commands.
hello()
: print "Hello RT-Thread!"
version()
: print version information
list()
: print available command list
list_mem()
: print memory information
list_thread()
: print thread information
list_sem()
: print semaphore information
list_mutex()
: print mutex information
list_event()
: print event information
list_mb()
: print mailbox information
list_mq()
: print message queue information
list_memp()
: print memory pool information
list_timer()
: print timer information
You may add your own command by two steps.
- Firstly, define a function of cause. The return value can be "
void
" or any type. The recommendation is to return a value with "char
", "byte
", "short
", "unsigned short
", "int
" or "unsigned int
" type, because of these types can be interpreted well by FinSH. There is no limitation on parameters. (However, there do have limit of FinSH command length, which is 80 characters by default.) So any number and any type are fine.
- Secondly insert a line with
ADD_SHELL_CMD(
command_name, command description, function_name, return_type, parameter list
)
macro into "shell_cmd.h
".
Following is a example of adding user command.
- Define the function
led()
.
unsigned int led(unsigned int id, byte state) {
// use "rt_kprintf()" to print a message
rt_kprintf("led%d=%d\n", id, state);
if (id != 0) {
return 1;
}
if (state) {
digitalWrite(LED_BUILTIN, HIGH);
} else {
digitalWrite(LED_BUILTIN, LOW);
}
return 0;
}
- Add a line to "
shell_cmd.h
".
ADD_SHELL_CMD(led, Turn on/off builtin LED, led, unsigned int, unsigned int id, rt_int32_t val)
In the example above the command name and the function name are the same. However, they can be different. Then the command name becomes the alias of the function name. When issue command to FinSH, the command name should be used.
You may also add your own variable by the similar steps.
- Firstly, define a variable. The available types are "
char
", "byte
", "char*
", "short
", "unsigned short
", "short*
", "int
", "unsigned int
", "int*
" and "void*
".
- Secondly, add a line with
ADD_SHELL_VAR(variable_alias, variable description, variable_name, variable_type)
macro into "shell_var.h
". The corresponding variable types here are "finsh_type_char
", "finsh_type_uchar
", "finsh_type_charp
", "finsh_type_short
", "finsh_type_ushort
", "finsh_type_shortp
", "finsh_type_int
", "finsh_type_uint
", "finsh_type_intp
" and "finsh_type_voidp
".
Following is a example of adding user variables.
- Define the variables.
unsigned int led_id = 0;
byte led_state = 1;
- Add two lines to "
shell_var.h
".
ADD_SHELL_VAR(id, LED ID, led_id, finsh_type_uint)
ADD_SHELL_VAR(state, LED state, led_state, finsh_type_uchar)
After uploaded the example sketch "FinSH", open the "Serial Monitor" and you will see the tiny shell.
\ | /
- RT - Thread Operating System
/ | \ 4.0.1 build Mar 8 2019
2006 - 2019 Copyright by rt-thread team
finsh >
Try some predefined commands.
finsh >hello()
Hello RT-Thread!
0, 0x00000000
finsh >list()
--Function List:
hello -- say hello world
version -- show RT-Thread version information
list -- list available commands
list_mem -- list memory usage information
list_thread -- list thread
list_sem -- list semaphore in system
list_mutex -- list mutex in system
list_event -- list event in system
list_mb -- list mail box in system
list_mq -- list message queue in system
list_memp -- list memory pool in system
list_timer -- list timer in system
led -- Turn on/off builtin LED
--Variable List:
dummy -- dummy variable for finsh
id -- LED ID
state -- LED state
0, 0x00000000
You may notice that after executed each command, the tiny shell prints a line with two values, "0, 0x00000000
". These two values are actually the return value of the underlying function, in decimal and hexadecimal formats. "hello()
" and "list()
" return "void
". Trying to issue "led(1, 0)
", you will get a different value (which is an error code).
Now try the user defined command and variables. Having fun!
finsh >id
0, 0x00000000
finsh >state
1, 0x00000001
finsh >led(id, state)
led0=1
0, 0x00000000
finsh >state=0
536870912, 0x20000000
finsh >led(id, state)
led0=0
0, 0x00000000
finsh >led(1, 1)
led1=1
1, 0x00000001
finsh >led(0, 1)
led0=1
0, 0x00000000
Next StepsI have not done the examples of showing how to use kernel utilities like semaphore, mutex, mailbox, memory pool and etc., although all these features are currently ready in the library. I will update the library and this article later. In the meantime, you may check the examples from the original RT-Thread project.
I also plan to bring back some optional components (which I removed when porting) and develop some complex examples to show the potential of RT-Thread.
Thanks for reading!
- RT-Thread Primer (coming soon)
- Mar 15, 2019: The library is already available in "Library Manager".
- Apr 17, 2019: FAT file system and SD card driver are available with v0.4.4.
- May 6, 2019: From v0.5.1 onward, please use ADD_FINSH_CMD instead of ADD_SHELL_CMD.
Comments
Please log in or sign up to comment.