Tutorial 3 : Understanding Morey_os coding style - sudeshmoreyos/Morey_os-demo-1.0 GitHub Wiki

Home <<Prev 3 Next>>

In this tutorial we will learn how to write a program from scratch using Morey_os Embedded Operating System. To write a program we need to compulsorily create three files :

  1. Makefile
  2. config.h
  3. user_code.c

In order to create, write, edit and save above mentioned files, we will need a file editor software. We recommend to use Notepad++ text editor software because of its many useful features. Latest version of Notepad++ may be downloaded from here : Notepad++. However any other text editor software like notepad, wordpad, etc can also be used.

Let us understand the process to write all these files :

1. How to write a Makefile :

  1. In order to compile the program Morey_os make use of make utility. make utility combines all required toolchains and create an executable file from Morey_os compatible source codes. Makefile is an essential file for make utility to find all dependencies and rules to compile a code. Writing a complete Makefile is a complex task in itself. Thankfully most of these complexity is already managed by Morey_os. Only bare minimum basic configurations/commands has to be written by the coder. So to create a Makefile, we need to create a file and name it as "Makefile". Please note this file should not have any extension. The content of a typical Makefile is under:

PROJECT = led-blink

MOREY_OS_PATH = ../../../..

BOARD = ARDUINO_UNO

include $(MOREY_OS_PATH)/Makefile.include

  1. Let us understand each line of makefile as mentioned above.

line-1 : PROJECT is a Macro ( a Compiler Variable ) which should hold the name of user code that has to be compiled. User code here is led-blink. Equal = operator is used to assign the value to Macro PROJECT

line-2 : MOREY_OS_PATH is a Macro which should hold the path to Morey_os root folder. In this case Morey_os root directory is located four level up to the current directory. Hence value assigned to MOREY_OS_PATH Macro is ../../../..

line-3 : BOARD holds the name of board to be programmed. In above case Board used is ARDUINO_UNO. Please note ARDUINO_UNO should be in all capital letters.

line-4 : This is a default line and must be included as the last line of Makefile. User should not make any changes to this line.

Thus in makefile we provide three parameters to make utility, 1) Project file name that has to be compiled 2) Path of root directory of Morey_os 3) Board name. Please note all Macro names are in CAPITAL letters. As a convention, Morey_os defines all pre-defined Macros in Capital letters only.

  1. Morey_os can also be used to write program directly for a controller. In such case makefile typically looks like :

PROJECT = led-blink

MOREY_OS_PATH = ../../../..

ARCH = AVR_MEGA

CONTROLLER = MEGA8

include $(MOREY_OS_PATH)/Makefile.include

So in this case, instead of BOARD Macro, ARCH and CONTROLLER is defined. ARCH Macro holds the name of controller family while CONTROLLER Macro holds the name of target controller. In above example, ARCH is AVR MEGA family, while controller is MEGA8 (Atmega8)

2. How to write config.h file

Another compulsory file in a Morey_os program is config.h file. This file must be named as 'config' with file extension '.h'. Files with '.h' extensions are also known as header files in C programming. Purpose of config.h file is similar to Makefile. Makefile declares Macros which are visible both inside and outside Morey_os sources. While config.h declares Macros which are visible only inside Morey_os sources. A typical config.h looks like as shown below :

#ifndef CONFIG_H

#define CONFIG_H

#define COMPILER AVR_GCC

#endif

Line-1 : #ifndef CONFIG_H , Line-2 : #define CONFIG_H and last line : #endif , are compulsory. Expert C programmers would easily understand the use of these three lines. However, beginner level coders may skip its explanation.

Line-3 : #define COMPILER AVR_GCC , in this line COMPILER Macro is declared as AVR_GCC. This Macro must be defined in config.h file. A controller/board may support multiple compilers.

It is important to note here that, though both Makefile and config.h files declares Macros, but procedure is very different. In makefile we declare marco using equal = operator as follows :

PROJECT = led-blink

while in config.h we declare Macro using #define as follows :

#define COMPILER AVR_GCC

3. How to write user_code.c file

  1. Finally user need to write his .c file to implement program in Morey_os. Files with '.c' extensions are known as source files in C programming. User is free to keep any name of .c file provided it do not include spaces or any special characters other than underscore '_' and dash '-'. Numbers are also allowed except for first character of the file name. So valid file names are 'led-blink.c', 'hello.c','hello123.c' etc. Invalid file names are 'hello world.c' , '[email protected]', '1led.c', etc. After saving user code with .c extension, the name of user code must be assigned to PROJECT Macro in Makefile, as discussed before. Otherwise Morey_os will not know that it has to compile which user code.

  2. To understand the typical content of '.c' file, let us explore an example code led-blink.c that can be found in examples folder (examples\board-examples\arduino-uno\led-blink) of Morey_os. The content of 'led-blink.c' is as follows :


// Declare here all header files used in the code.h , OS related files are included by default

#include "morey_os.h"

#include "Digital.h"

// Declare all initialization functions of controller peripherals in the setup function below

void setup(void) {
Digital.pinmode(pin13,OUTPUT);

Digital.pinmode(pinA0,OUTPUT);

}

// Delcare all processes here

TASK_CREATE(LED1,"LED-1");

TASK_CREATE(LED2,"LED-2");

// Delcare autostart processes here. Atleast one process must be autostarted;

TASK_AUTOSTART(&LED1,&LED2);

TASK_RUN(LED1) {

// Declare all variables here, please read documentation to understand which variables should be declared as static variables

// Process starts here

BEGIN();

while(1) {

Digital.write(pin13,HIGH);

DELAY_SEC_PRECISE(0.1);

Digital.write(pin13,LOW);

DELAY_SEC_PRECISE(0.1);

}

// process ends here

END();

}

TASK_RUN(LED2) {

// Declare all variables here, please read documentation to understand which variables should be declared as static variables

// Process starts here

BEGIN();

while(1) {

Digital.write(pinA0,HIGH);

DELAY_SEC_PRECISE(1);

Digital.write(pinA0,LOW);

DELAY_SEC_PRECISE(1);

}

// process ends here

END();

}


  1. User source code is broadly divided into following sections

A. Header Files

B. setup function

C. Task creation

D. Auto-starting Tasks

E. Task run

A. Header files : user code must include morey_os.h header file. Also we need digital input output functionality to blink LEDs hence we will also add Digital.h header file. Similarly all other essential headers files must be added at the top of the code.

B. setup function : It is similar to setup function of Arduino programming , which runs once when board or controller is powered up. setup function usually includes peripheral initialization functions, like function Digital.pinmode(pin13,OUTPUT); which set pin13 of Arduino Uno in output mode. It is important to note that setup function runs before initialization of OS functionality. Also setup function should not include interrupt dependent functions because global interrupt is enabled only after setup function run.

C. Task creation : Tasks implement parallel processing using Morey_os kernel functionality. Tasks are similar to loop function in arduino programming. Arduino allows only one loop in a code, while Morey_os allows multiple Tasks independently running in parallel. Maximum of 32 tasks are allowed in one project. Tasks can be created using Macro TASK_CREATE(task1,"task1 name").

TASK_CREATE Macro has two inputs, first one is the task name while second one is task string name which is used during code debugging. The first input i.e. task name cannot include spaces or special characters other than underscore '_' or dash '-', However there is no such restriction for second input i.e. task string name. task string must be written in double quotes " ". User can create up to 32 independent tasks. In the example 'led-blink.c' code two tasks LED1 and LED2 are created as :

TASK_CREATE(LED1,"LED-1");

TASK_CREATE(LED2,"LED-2");

D. Autostarting Tasks : Tasks may be autostarted after OS boot or can be manually started inside any task. To auto start tasks after OS boot, we use Macro TASK_AUTOSTART which takes Task pointers as input. In 'led-blink.c' example both LED1 and LED2 are autostarted as :

TASK_AUTOSTART(&LED1,&LED2);

E. Task Run : Last section of the code is Task run. A task run is declared by Macro TASK_RUN Macro, which takes only one input as Task. The content of a typical task is as follows :


TASK_RUN(LED1) {

// Declare all variables here, please read documentation to understand which variables should be declared as static variables

// Process starts here

BEGIN();

while(1) {

Digital.write(pin13,HIGH);

DELAY_SEC_PRECISE(0.1);

Digital.write(pin13,LOW);

DELAY_SEC_PRECISE(0.1);

}

END();

}


In a task run function variables should be declared immediately after {. All variables declared must be static variables. Use of static variables is discussed in detail in later tutorials. Variable declaration is of course optional if no variable are used inside task_run. Like example code 'led-blink.c' do not declare any variables. After this step, task begins with BEGIN(); Macro and ends at END(); Macro.

If any task needs to run infinitely a while loop may be used in between BEGIN(); and END(); Macros. Like in led-blink.c example, while(1) loop is created to infinitely blink LED connected to pin13 of Arduino Uno. To include delay we can use Macros DELAY_SEC() or DELAY_SEC_PRECISE(). Any infinite loop in a Task must contain at least one DELAY_SEC() or DELAY_SEC_PRECISE() Macro. DELAY_SEC() or DELAY_SEC_PRECISE() Macro implements delay in seconds. Minimum supported delay by operating system is 1 milli second or 0.001 second. Difference between DELAY_SEC() or DELAY_SEC_PRECISE() is discussed in detail in subsequent tutorials.

In the task example above, we can see that Digital.write(pin13,HIGH); sets pin13 high while Digital.write(pin13,LOW); sets pin13 low. DELAY_SEC_PRECISE(0.1); implements delay of 0.1 seconds or 100 milli seoconds.

This completes our basic introduction to Morey_os programming style. Next we will briefly discuss how to use Arduino Uno as a Board in Morey_os in Tutorial-4.

Home <<Prev 3 Next>>