System Configuration

1. Configuration Wizard
2. Project Compilation
3. System Startup – Runtime Configuration

1. Configuration Wizard

The project contains several files which can be configured. The main configuration folder is localized in the ./config directory. Besides, most drivers and file systems contain their own configuration file. The configuration depends on the driver platform. In the project there is a configuration wizard that helps users to configure the entire project. To start this program, enter the following expression in the command line:

make config
dnx RTOS Configuration tool

dnx RTOS Configuration tool

The configuration wizard is compiled for Linux and Windows systems. The Makefile script automatically detects your system and starts proper program.

2. Project Compilation

To compile the project go to the project’s main directory, open the command line in the project’s root folder and type:

make

If everything is correctly configured, then the building process starts working and finally, you can find compiled binaries that are ready for programming in the build folder.

3. System Startup – Runtime Configuration

The system startup is realized by initd – a program (task) that starts first. The startup program is a part of system configuration that is realized in the runtime. The startup phase is divided into few parts; each part does specific actions, e.g. mount file systems, initialize drivers, performs a network connection, and so on. The system startup depends on the needs of a user and the system application. The initd program code is localized in the ./src/user/initd.c file. After startup, the daemon can be used to check whether all programs are still running, or it can be finished if no more actions are required. By default the initd has specified runtime phases:

  • Boot – realized by the run_level_boot() function. In this phase, basic file systems will be mounted, and first folders will be created.
  • Level 0 – realized by the run_level_0() function. This phase initializes all required drivers (GPIO, PLL, UART, TTY, etc). Drivers cannot be initialized in the boot phase, because driver nodes cannot be created without the mounted file system. It is possible to initialize drivers without the file systems but the user has no possibilities to access the device.
  • Level 1 – realized by the run_level_1() function. In this phase additional actions are performed, e.g. initializing a SD card and mounting its file system. Network interface is also started in this phase.
  • Level 2 – realized by the run_level_2() function. This phase is the latest initialization stage. In this phase the user will start all required applications, e.g. terminal, board specific programs/daemons. The initd can go to the monitoring or sleep mode.
  • Exit – realized by the run_level_exit() function. This phase is executed only when Level 2 was finished. The role of this phase is to safely prepare the system for e.g. power down.

The initd daemon can be easly configured by using the Configuration tool. Generation the code of initd by using Configuration tool is recomended at all, but if system startup is performed in not standard way then the initd may be implemented by user.

The initd configuration by using Configuration tool

The initd configuration by using Configuration tool

Example implementation of the initd:

/* include */
#include <stdio.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/mount.h>
#include <dnx/os.h>
#include <dnx/thread.h>
#include "user/initd.h"


/* prototypes */
static int run_level_boot(void);
static int run_level_0(void);
static int run_level_1(void);
static int run_level_2(void);
static int run_level_exit(void);


/* initd main function */
void initd(void *arg)
{
        (void)arg;

        task_set_priority(INITD_PRIORITY);

        if (run_level_boot() != STD_RET_OK)
                goto start_failure;

        if (run_level_0() != STD_RET_OK)
                goto start_failure;

        if (run_level_1() != STD_RET_OK)
                goto start_failure;

        if (run_level_2() != STD_RET_OK)
                goto start_failure;

start_failure:
        run_level_exit();

        task_exit();
}


/* mounts file systems */
static int run_level_boot(void)
{
        /* root file system */
        mount("lfs", "", "/");
        mkdir("/dev", 0666);
        mkdir("/mnt", 0666);
        mkdir("/proc", 0666);
        mkdir("/tmp", 0666);

        /* additional file systems */
        mount("procfs", "", "/proc");
        mount("devfs", "", "/dev");

        return STD_RET_OK;
}


/* initialize drivers and show welcome message */
static int run_level_0(void)
{
        /*
         * Initialize first most important modules.
         * This drivers are required to show message.
         */
        driver_init("gpio", "/dev/gpio");
        driver_init("pll", "/dev/pll");
        driver_init("uart1", "/dev/ttyS0");
        driver_init("tty0", "/dev/tty0");

        /* enable kernel print in terminal 0 */
        printk_enable("/dev/tty0");

        /* print welcome message in the selected terminal */
        printk(FONT_COLOR_GREEN FONT_BOLD "%s/%s"
               FONT_NORMAL " by " FONT_COLOR_CYAN "%s "
               FONT_COLOR_YELLOW "%s" RESET_ATTRIBUTES "\n\n",
               get_OS_name(),
               get_kernel_name(),
               get_author_name(),
               get_author_email() );

        /* initialize other drivers */
        driver_init("tty1", "/dev/tty1");
        driver_init("tty2", "/dev/tty2");
        driver_init("tty3", "/dev/tty3");
        driver_init("sda", "/dev/sda");    /* enitre SD card */
        driver_init("sda1", "/dev/sda1");  /* parition 1 of SD card */

        return STD_RET_OK;
}


/* detect SD card and mount its contents in the file system */
static int run_level_1(void)
{
        printk("Detecting SD card... ");

        /* open SD card file */
        FILE *sd = fopen("/dev/sda", "r+");
        if (sd) {
                bool status = false;
                ioctl(sd, IOCTL_SDSPI__INITIALIZE_CARD, &status);

                /* check initialization status */
                if (status == true) {
                        printk("initialized\n");

                        /* mount partition 1 in /mnt folder */
                        mount("fatfs", "/dev/sda1", "/mnt");
                } else {
                        printk(FONT_COLOR_RED
                               "fail"
                               RESET_ATTRIBUTES"\n");
                }

                fclose(sd);
        } else {
                printk(FONT_COLOR_RED
                       "Cannot open the file!"
                       RESET_ATTRIBUTES"\n");
        }

        /* change TTY for printk */
        printk_enable("/dev/tty3");

        return STD_RET_OK;
}


/* start user programs */
static int run_level_2(void)
{
        /* open files used as terminal */
        FILE *tty0 = fopen("/dev/tty0", "r+");
        FILE *tty1 = fopen("/dev/tty1", "r+");
        FILE *tty2 = fopen("/dev/tty2", "r+");

        /* error if some of files cannot be opened */
        if (!tty0 || !tty1 || !tty2) {
                return STD_RET_ERROR;
        }

        /* start new programs connected to terminals tty0...tty2 */
        /* single tty file is used as stdin, stdout, and stderr  */
        prog_t *prog1 = program_new("dsh", "/", tty0, tty0, tty0);
        prog_t *prog2 = program_new("prog_x", "/mnt", tty1, tty1, tty1);
        prog_t *prog3 = program_new("prog_y", "/sd", tty2, tty2, tty2);

        /* wait for all programs was closed */
        program_wait_for_close(prog1, MAX_DELAY_MS);
        program_wait_for_close(prog2, MAX_DELAY_MS);
        program_wait_for_close(prog3, MAX_DELAY_MS);

        return STD_RET_OK;
}


/* disable interrupts and wait for power down or reset */
static int run_level_exit(void)
{
        critical_section_begin();
        ISR_disable();

        while (true) {
                sleep(MAX_DELAY_S);
        }

        return STD_RET_OK;
}