Asistent

Osnove
mikroprocesorskih
sistemov


Računalniško
načrtovanje vezij II


Mikroprocesorji
v elektroniki
  Laboratorijske vaje
    Programiranje v zbirniku
Zbirniška funkcija
Zapis s plavajočo vejico
Digital watch
Generator vlaka
impulzov

Gonilnik
prikazovalnika LCD

Gonilnik asinhronih
zaporednih vrat

Use of real-time
operating system

Slovenščina

Digital watch realisation using real-time operating system

Practice instructions: Code digital watch in given simple real-time operating system. Display current time (hh:mm:ss) on LCD. Use keys T0 to T3 for time setting. Let key T0 increase hours, T1 increase minutes, T2 stop the time, and T3 set time to zero (00:00:00).

Explanation: Use integrated software development environment (winIDEA), which runs on a PC with Windows operating system. A pre-prepared workspace with all related files can be found here. Source code files are included. Files rtos.c and belonging rtos.h are added beside the files known from previous practice work. Simple real-time operating system source code can be found in those two files.

After the start-up code we find ourselves in an empty function named start_up(). It is located in the startup.c file. Here you first have to initialise the microcontroller. Use init() function. The belonging init.h file has to be included. After initialisation simple real-time operating system is raised by sch_on() function. Further explanation of the function follows below. Detailed description of the simple real-time operating system and its source code can be found in lecture notes.

Digital watch will be realised through tasks. Task is a function called by operating system scheduler at the exact predefined time points. The whole project will be divided into smaller parts (tasks). To achieve our goal the following tasks have to be performed: correct time has to be established, obtained value has to be transformed into an appropriate string and the string has to be displayed on LCD. To enable time setting the keys also have to be taken into account during the first task (getting the time). The project can be accomplished by three tasks:

   - tim() ... time setting and time measuring (counting the time),
- string() ... transform time value into an appropriate string, and
- lcd_driver_1() ... display the prepared string on LCD.

Task tim() sets and measures the correct time. Time is saved in time global variable, which holds number of seconds in a day (e.g.: at 08:14:59 the variable value is time = 8 * 60 * 60 + 14 * 60 + 59 = 29699). Task tim() represents a clock. Any other task or main program can always "look" at the clock to get the time. For clock to be accurate the task tim() must be called in equidistant time intervals, which is assured by operating system. Because tim() task counts seconds it is most suitable to be called once per second. The algorithm of the task tim() is shown in a figure below.

Variable time is incremented at every call (once per second). The position of keys T0 to T3 is also adequately reflected in variable's value. T0 increments hours (increase time for 3600 seconds), T1 increments minutes (increase time for 60 seconds). T2 decrements time, which neutralises an increment at the beginning. Therefore the time value does not change. Clock stands still. T3 sets time = 0. Task tim() also takes care about midnight transition from 23:59:59 (= 86399 seconds) to 00:00:00.

The next task string() reads time variable and transforms its value into a "hh:mm:ss" string. As a matter of fact the task puts together a 32 character string for LCD. Missing characters are filled with spaces. The string is prepared for LCD by setting the global pointer lcd_string to it. Tasks tim() and string() are mutually independent. First takes care about the time value, and the second uses the value. The algorithm of the task string() is simple and is shown in a figure below. Number of hours, minutes and seconds can be obtained from the variable time by integer division and modulus operation (the reminder of integer division).

The last task is lcd_driver_1() function for writing on LCD. We already know the function from the laboratory practice at Computer Aided Circuit Analysis II course. The function is now placed among the tasks. That means that it will not be explicitly called. Operating system will take care about that. The function represents a LCD driver, which at all times shows 32 character string to which the global pointer lcd_string points. Refresh frequency is given by number of lcd_driver_1() calls per second. It is defined by operating system settings. Changing LCD inscription is simply achieved by redirecting the pointer lcd_string to another string or by changing the string itself. Task string() takes care about that.

Since all the work is done by the three tasks, the main program reduces to an indefinite empty loop.

In this simple operating system task is a function which does not receive any arguments and does not return anything. Such a function becomes a task by placing it into a list of tasks sch_tab[], which resides in rtos_tasks.c file. Since source code of the tasks does not reside in the same file as operating system source code, extern declarations are needed for each task. Those are placed in file rtos_tasks.h. For described three tasks tim(), string() and lcd_driver_1() the list of tasks sch_tab[] in rtos_tasks.c file with belonging extern declarations in rtos_tasks.h file would be:

rtos_tasks.h:

 extern void tim();
 extern void string();
 extern void lcd_driver_1();

rtos_tasks.c:

 voidfuncptr sch_tab[] = {tim, string, lcd_driver_1};

Write the source code of the three tasks in file main.c.

Simple operating system is initialised and raised by sch_on() function already mentioned above. Belonging rtos.h file has to be included. Function declaration is:

  void sch_on(unsigned int slice);

Argument slice defines timer0 configuration, which is used by operating system to measure the time. The meaning of the argument is as follows:

   - slice ... timeslice duration in microseconds

After sch_on() call operating system becomes active and starts with task scheduling. Frequency of task calls is defined by timeslice, which is given by slice argument. At the moment we have three tasks in our project and task tim() has to be called exactly once per second. Therefore the timeslice should be 1/3 of the second, which is not an integer number (= 1000000/3us). By adding an empty task void_task() pre-prepared in file main.c into the list of tasks sch_tab the number of tasks is increased to four. Thus the timeslice is 1/4 of the second (= 250000us), which is all right.

Consider what should be done to make colons in string "hh:mm:ss" blink at every half of a second?