Thursday, April 14, 2016

Getting to know the shell in RIOT OS

In a previous article I wrote about writing a simple application for RIOT OS and and running it on native platform. It's time to go beyond that point and explore what's more we can do inside RIOT applications. In this article, I would like to show the things I have explored with shell module in RIOT. When we enable the shell module for a user application, we get a nice shell interface using which we can interact with the application.

Let's go ahead and modify our application program to have a shell interface. It can be done by adding few lines to the existing program. Below code shows the updated main.c program which invokes the shell module.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
#include<stdio.h>
#include "shell_commands.h"

int main(void)
{
    puts("Starting my shell program");

    char line_buff[SHELL_DEFAULT_BUFSIZE];
    shell_run(NULL, line_buff, SHELL_DEFAULT_BUFSIZE);

    return 0;
}

Then we can compile and run this program as usual.

make
./bin/native/helloworld.elf

Now we get the shell prompt of our program. We can type help on the prompt to see the available commands for us in this shell program. However in this shell we don't have any command. We can exit from the running RIOT instance by issuing a Ctrl+C on the prompt.

In order to make different RIOT commands available for the shell, we have to enable different modules at the compile time. We do that by updating the Makefile of our program. Update the right place to enable the two modules shell_commands and ps in our user program. Following excerpt is from the updated region of my Makefile.

1
2
3
4
5
6
7
8
# Modules to include:

USEMODULE += shell
USEMODULE += posix
USEMODULE += xtimer

USEMODULE += shell_commands
USEMODULE += ps

This time when you compile and run the application, you will see that two new commands are available to you. In my shell I got reboot and ps commands. Now we know how we get them by enabling different modules in the Makefile. What if I wanted some new commands in my program with the shell. Is there any way to add my own commands that do different things on the shell? Yes, there is a way to define new commands and make them available to your programs. Let's try that. Following code shows an updated version of our main.c program which has a new command called echo defined by ourself.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include<stdio.h>
#include "shell_commands.h"

int my_echo(int argc, char **argv)
{
    if (argc < 2) {
        printf("usage: %s [string]\n", argv[0]);
        return 1;
    }

    printf("%s\n",argv[1]);
    return 0;
}

static const shell_command_t shell_commands[] = {
    { "echo", "echo back the string given as a parameter", my_echo},
    { NULL, NULL, NULL } 
};

int main(void)
{
    puts("Starting my shell program");
    char line_buf[SHELL_DEFAULT_BUFSIZE];
    shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE);

    return 0;
}

When you compile and run this program you should see that a new command called echo is available to you. I hope this blog post helps to understand how we utilize the shell module in our programs.


2 comments:

  1. Hi thanks for the tutorial.
    I'm trying to use this starting from the gnrc_border_router sample.
    I plugged the openmote device through USB to the Ubuntu machine, but when i try to run the RIOT shell (on the mote) with pyterm, it shows me the "starting my shell program", but i can't enter any command because it doesn't respond.
    If instead i build the project as "native" it works perfectly.

    There is a quick solution?

    thanks a lot and BR,
    Alessandro

    ReplyDelete
  2. Hi Alessandro,

    Since I haven't used openmote, I cannot clearly spot the problem. I think the best place to ask this is RIOT users mailing list. They are very helpful and hopefully solve your problem too.

    ReplyDelete