• SUSPENDED if the task has been initiated but pre-empted during execution by a task of higher priority.. If, when a task moves to the Waiting state, no lower priority task is SUSPENDED,
Trang 21 Introduction 6
1.1 Purpose of this manual 6
1.2 Scope of this manual 6
1.3 Additional help or information 6
2 Overview 7
2.1 Organisation of the manual 7
2.2 General description of tasks 7
2.3 A first example: 2 LEDs 8
2.4 The multitasking capability 9
2.5 KR-51 specification 9
2.6 Simple example 10
2.7 Files supplied 10
2.8 Program development tools 10
2.9 Available versions 10
3 Task description 12
3.1 Task definition 12
3.2 Task states 12
3.3 Priorities and register banks 13
3.4 Clock frequency groups 13
3.5 Waiting for an event 14
3.5.1 Timeout 14
3.5.2 Signal 14
4 Scheduler 15
4.1 Kernel clock 15
4.1.1 Pooler 15
4.1.2 Initiator 16
4.2 Task execution 16
4.3 Receiver 16
4.4 Direct pooling 16
4.4.1 Principle 16
4.5 Interrupt handling 17
Trang 34.5.1 Implementation 17
4.5.2 Register banks 17
4.5.3 Kernel and parallel interrupt priority 17
4.5.4 Response time 18
4.5.5 Permissible delay 18
4.5.6 Tasks/interrupts interface 18
4.6 Possible actions on IE and IP registers 18
4.7 Task lifetime 19
4.8 Notes and suggestions 19
5 Implementation 20
5.1 KR-51 files and installation 20
5.2 Implementation 20
5.3 Task declaration 20
5.4 Tasks written in another language 21
5.4.1 Significance of the different keywords 21
5.4.2 Kernel settings 22
5.4.3 Questions 22
5.5 Saving stacks and local variables 23
5.5.1 Stack storage 23
5.5.2 External stack capability (external versions) 23
5.6 Set-up utility program 25
5.7 Task editing 26
5.8 Debug versions 26
5.8.1 General 26
5.8.2 Recommendations 26
5.8.3 Quick reference tables to return codes in the DEBUG utility program 26
6 List of services 28
6.1 Types of services 28
6.1.1 System services 28
6.1.2 Information services 28
6.1.3 Utility services 28
6.2 Quick reference to the services 28
6.3 Parameter passing convention 29
6.4 Values returned by services 29
6.5 KR_CREATE (system function) 29
6.6 KR_DELETE (system function) 30
Trang 46.7 KR_DEL_ABS (system function) 30
6.7.1 Possible problems with KR_DEL_ABS 31
6.8 KR_DEL_REL (system function) 33
6.9 KR_SENDSIG (system function) 34
6.10 KR_WAITSIG (system function) 34
6.11 KR_DELSIG (or KR_DELSIG_REL) 34
6.12 KR_DELSIG_ABS 34
6.13 KR_PAUSE (system function) 35
6.14 List of the information services 35
7 Semaphore 36
7.1 Semaphores with time-outs (external versions only) 36
7.2 Normal semaphores 37
7.2.1 Implementation 37
7.2.2 Semaphore services for standard semaphores 37
7.3 Implementation 37
7.4 Notes and suggestions 38
7.5 Semaphores and task groups (external versions) 38
7.6 Semaphores and task synchronisation 39
7.7 Resources used 39
8 Mailbox 40
8.1 Available services 40
8.1.1 MAIL_RESET(0) 40
8.1.2 MAIL_SEND(char box, char message_character) 40
8.1.3 MAIL_READ (char box) 40
8.1.4 MAIL_SIZE (char box) 41
8.1.5 MAIL_FLUSH (char box) 41
8.1.6 MAIL_TEST (char box) 41
8.2 Notes and suggestions 41
8.3 Resources used 41
9 Memory allocator (KRX) 42
9.1 Available services 42
9.1.1 MEM_ALLOC 42
9.1.2 MEMFREE 42
9.1.3 PRECAUTIONAY MEASURES 42
Trang 510 Calendar 43
10.1 Available services 43
10.1.1 SPLIT=>COMPRESSED format : (structure=>long) 43
10.1.2 COMPRESSED -> SPLIT format (long -> structure) 44
10.2 Implementation 45
11 Internal version: KRY 46
11.1 Resources used 46
11.2 Example 47
11.3 Performances 47
12 External versions: KRX / KRH 48
12.1 Resources used 48
12.2 Example 49
12.3 Performance 50
13 APPENDIX 51
13.1 TELEMEAS application (recorder) 51
14 Conformity 74
15 Glossary 75
16 Index 76
17 History 78
Trang 6support for any compatible derivatives of the 8051, except the 83C751 and 83C752.
1.1 Purpose of this manual
This is a reference manual for the KR-51
1.2 Scope of this manual
This manual is applicable to all derivatives of the 8051, except the 83C751 and 83C752
1.3 Additional help or information
Please visit the Raisonance website: http://www.raisonance.com/ and the forum
http://www.raisonance.com/Forum/punbb/ or contact Raisonance.
Address: Raisonance S.A.S
17, Avenue Jean Kuntzmann,
38330 Montbonnot Saint Martin
Trang 7KR-51 2 Overview
2 Overview
The KR-51 consists of two parts:
• The scheduler, which is the task scheduling program
• The services or functions that can be called by tasks to send various requests to the scheduler
2.1 Organisation of the manual
The chapters describe the operation of the Kernel in increasing levels of detail:
• Overview: Corresponds to this chapter
• Tasks: Gives a static description of the tasks
• Scheduler: Describes the dynamic characteristics of the scheduler
• Implementation: Indicates how to use KR-51 and associate it with tasks written in a high level language or assembly language
• List of services: Describes the kernel’s services
• Semaphores: Describes how the flag capability ensures resource sharing between tasks
• Mailbox: Describes the mailbox services Mailboxes represent a powerful task communication module
• Memory allocation: Permits dynamic allocation of the external memory space
• Calendar: Conversion to/from various formats
2.2 General description of tasks
A task is a void function, which has no parameters, returns no value, and implements part of the user’s application
A typical declaration is shown in the example below:
Example: task declaration
void taski (void) task 5;
However, a task can affect its own process or that of related tasks, but always via the scheduler to which the requests have to be sent
Requests can be:
• to run another task
• to move a task to the idle state for a given time or to wait for an event
• for task synchronisation or communication
Note that task lifetime varies It can be:
• "permanent": the task will initiate at the beginning of the application and will never terminate, although it can be suspended for a short duration
• "temporary": the task is initiated for a given action
• "periodic": the task is initiated in a cyclic fashion at regular or irregular time intervals
Trang 82.3 A first example: 2 LEDs
Let’s see the following program:
#include <krdcl.h> // Declarations for the services
void main (void)
{ kr_init();
kr_create(_TSKLED1_); // Creates and runs task 1 kr_create(_TSKLED2_); // Creates and runs task 2
}
void tskled1 (void ) task _TSKLED1_ //Task 1
{ while (1)
{ LED1 = !LED1; // Toggles P1.1 kr_del_abs(7); // Waits for 7 ticks }
}
void tskled2 (void ) task _TSKLED2_ //Task 2
{ while (1)
{ LED2 = !LED2; // Toggles P1.2 kr_del_abs(23); // Waits for 23 ticks }
}This program has to be compiled and linked with LX51 For example:
RC51 2led LX51 2led.obj, KRX.LIBThe two permanent tasks will run forever, and the LEDS will blink:
• at the base frequency divided by (2*7) for the task 1
• at the base frequency divided by (2*23) for the task 2
The base frequency can to be set in Ride7 A typical value would be 1 KHz, which allocates time in 1 millisecond intervals
Trang 9KR-51 2 Overview 2.4 The multitasking capability
Strictly speaking, KR-51 does not support either the parallel operation or time slicing functionality used for multi-user systems
In fact, a parallel organisation requires a multiprocessor physical architecture KR-51 has been
designed to operate on a standalone microcontroller only, on which only one instruction runs at a given time within a single task)
KR-51 uses the time-slicing capabilities applicable to any 1-processor based system with an interrupt handler
• In a multi-user computing system, CPU time is ‘sliced’ between different users at such a rate that each user is unaware of the other users
• To the system, each user is merely a ‘task’
• Although time slicing offers numerous advantages, it is often unsuitable for applications
concerned with process control
• It is difficult to use the 8051 where a great number of different tasks must be performed, each with often a short lifetime
• KR-51 thus provides time-slicing capabilities that have been modified for optimised use of the resources available on the 8051 microcontroller
In particular the concept of task is almost identical to that of an interrupt service routine:
• Each task is specified by a configurable priority level between 0 and 3 As for interrupts, the priority level feature permits context overlay on the stack, as only the initiated highest priority task takes control of the CPU
• A task is given a time-slice only if it is in the waiting state, or if a higher priority task takes control
of the CPU
In principle KRX and KRH, which use external RAM, could support a more dynamic task management scheme where, for example, the task's priority or group can be changed during execution However, the current version does not support these capabilities
2.5 KR-51 specification
The features used have been selected to best suit the 8051 The kernel was coded for the best
possible balance of conflicting requirements Here is a list of some of the requirements:
• execute a great number of tasks without leaving some out
• run the highest priority tasks within the minimum delay (minimum context switch time)
• provide reliable time management: a task that generates a square wave signal must create fixed frequency edges A slight offset caused by the execution of a highest priority task is possible, but offsets should not accumulate
• limit and minimal CPU time assigned to the kernel
• limit the number of resources used by the kernel (restrictions on internal RAM use)
• provide a variety of system functions (task communication via MAILBOXES etc.)
• provide resource sharing (via flags)
• provide interrupt handling and TASK/INTERRUPT interface
• ensure low latency for high priority interrupts
• best suit the resources available in the application (availability of an external RAM (XDATA) or not )
• accept development tools used: compilers, assemblers, and support the usual parameter passing conventions
• offer easy configuration by the user
• ensure easy debugging and provide DEBUG capabilities
Trang 10• send file handshake management.
• local keyboard read
• backup battery control
These tasks are specified by:
• a priority level Some can be delayed for several milliseconds or even several seconds; others must be executed quickly
• a scheduling mode Some tasks (such as perpetual calendar management) occur at regular intervals; while others follow an asynchronous or sequential logic e.g measurement processing follows the measurement and will generate an alarm which will initiate phone dialing
• the rate of occurrence: some tasks are initiated once a day, others every 10 milliseconds
In this example, a compiler for a high level language provides a static structure for data and algorithms, whereas KR-51 determines the dynamic characteristics
2.7 Files supplied
KR-51 is supplied with:
• 12 libraries corresponding to the versions described above in the \LIB directory
• Header files needed for ‘C’, PL/M or assembler in the \INC directory
• TUTORIAL directory contains some applications showing some specific features of the kernel: signals, semaphores
• README.DOC file that contains additional information which are not featured in this manual
2.8 Program development tools
KR-51 requires the LX-51 linker and RC-51 ‘C’ compiler programs from Raisonance, and the Ride7 Integrated Development Environment is recommended to simplify project management
2.9 Available versions
KR-51 is available in several versions with each optimised for specific requirements
The first choice relates to the use of either the IDATA (internal RAM) or XDATA (external RAM)
memory space Access to the internal RAM is more rapid but the space is limited, however access to the external RAM is slower but the available space is large (64 K)
• KRY refers to a kernel, which uses internal RAM and is well suited to applications with a limited number of tasks or no XDATA space KRY can be used for tasks written in the ‘C’ language if the ‘SMALL’ memory model is used during compilation (no external stack)
• KRX and KRH require 256 and 1024 bytes of external memory space respectively, but no internal RAM They offer more capability and support more tasks than KRY but are slightly slower
The second important choice relates to the inclusion of a ‘semaphore’ capability Without semaphores the KR-51 module is more rapid and uses less RAM, as the processes and resources required by this feature are ignored (Semaphores are used to share resources between tasks: e.g to control access to sensitive global variables or peripherals)
Trang 11KR-51 2 Overview
Version xdata requirement Maximum number of tasks Notes
* Note: The KRY.LIB creates automatically a task to manage the tasks of group 1 (even if there is not)
So only 6 tasks are still available
Each collection of libraries includes 4 sub-versions:
• Standard version (for example KRX.LIB)
• DEBUG versions that include Debug capabilities Performance is sometimes reduced to gain reliability Parameter consistency checks are performed at function invocation and, if any abnormality is detected, a trap is executed to try to recover correct operation of the program The libraries that contain DEBUG information are given a ‘D_’ prefix (e.g D_KRX.LIB)
• SEMAPHORE versions include semaphore capabilities and have a ‘S’ suffix (e.g KRXS.LIB)
• Versions which include both the DEBUG and the SEMAPHORE capabilities have a ‘D_’ prefix and an ‘S’ suffix (e.g D_KRXS.LIB)
Note:During development, the DEBUG versions are recommended, but they may later be replaced if
performance is too low
Trang 123 Task description
3.1 Task definition
For the KR-51 scheduler, a task is specified by:
• a reference: This corresponds to an identification number used with kernel function calls
• a descriptor: Indicates the task's priority, current state and events triggers (including
semaphore release) Note - For KR-51, the task's priority is associated with a register bank used during the task execution
• a group: each task is assigned a "GROUP" which corresponds to a time base (or clock
frequency)
• a task code (a function) : specified by the address of the code to be executed.
• a stack size: when a task enters the Waiting state, the stack contents are stored (swapped)
However, the storage size must be previously defined
• an external stack size (KRX and KRH versions) : when a task enters the waiting state, the
automatic variables are stored in the ‘external stack’ However, the storage size must be
previously defined
• an appearance (or creation) time : when a task is initiated, the time when it should be executed
is specified If a delay or "time-out" is required, this time is regarded as the starting point, which helps to avoid clock skews caused by offsets Similarly, if more than one task with equal priority
is in the READY state, the oldest is selected
These values are not all directly accessible by tasks However, they help to understand how the
scheduler operates internally
They are initialised at the beginning of the application, using the task declaration table in CODE space (see Implementation section)
3.2 Task states
The task's state is contained in the descriptor
It can be :
• UNVALIDATED if the task has never been set, or if it has already been executed to completion
• READY if the task is ready to be initiated
• WAITING if the task is waiting for an event : it may have been initiated but suspended for a given duration When the event occurs, the task returns to the READY state
• SUSPENDED if the task has been initiated but pre-empted during execution by a task of higher priority
• RUNNING if the task is currently running
• UNKNOWN if the task is non-existent It may be an illegal reference Context switching occurs via the kernel or by system calls
Each task may be either UNVALIDATED, READY or WAITING state However, for a given priority level, there may be only one (or possibly zero) task in the SUSPENDED state
One task only can be in the RUNNING state
Trang 13KR-51 3 Task description 3.3 Priorities and register banks
The priority of the task is indicated in the descriptor and can be in the range 0 to 3
A task of priority 3 is a highest priority task, and will be initiated using register bank 3 If more than one task is simultaneously in the READY state, the highest priority task in the ‘run’ queue, that is ready to run will be the first executed
Register bank 3 (address : 18h-1Fh) is also used by the kernel itself It corresponds to that of the
highest priority tasks and if a task of priority 3 is currently running, the register bank select bits (RS1 and RS0) are not modified
• One SUSPENDED task only per level is allowed
• Each priority level is associated with a register bank More precisely, priority level i corresponds
to bank Rbi and the four register banks correspond to the four priority levels The association of register banks with a priority level avoids the need to save and restore registers when the context is switched
• An interrupt priority level is usually associated with a register bank (Interrupt handling is
discussed hereafter)
• If a priority level and associated register bank is not used, the bank can be used by a service routine associated with an asynchronous interrupt
3.4 Clock frequency groups
Four clock rates (or two for KRY) hereafter referred as GROUPS are available and each task is
associated with one of the four (or two) groups
The clock rate is reduced by successive divisions : the scheduler pools tasks of group 0, and every n1 clocks, creates the clock corresponding to group 1 which initiates that group's pooling task Similarly, every n2 clocks of group 1, a clock is generated for group 2, and so on
• An advantage of the clock frequency group feature is that the scheduler does not have to pool systematically all tasks
• n1, n2 and n3 dividers are referred to as DIVIDE_1, DIVIDE_2 and DIVIDE_3 They are PUBLIC symbols of NUMBER type to be defined by the user when configuring the system (see
"IMPLEMENTATION" section)
• Dividers can be used for generating clocks, which vary from milli-seconds to minutes
Trang 143.5 Waiting for an event
A trigger can be a TIMEOUT, a SIGNAL or a combination of TIMEOUT and SIGNAL or a flag release See chapter 7 for further information on flag capabilities
3.5.1 Timeout
The task is SUSPENDED for a given number of clocks by calling KR_DEL_ABS or KR_DEL_REL function These functions are fully described in the "List of services" section Note that these functions are frequently used when working with a real time kernel
Systematic suspension of a task by calling this function with a constant parameter causes task initiation
at a regular time rate A typical example is in the construction of a perpetual calendar
Time-outs are expressed as signed 8-bit words A time-out is hence limited to 127 clock cycles (or ticks) of the previous group
Example 1 : In the ‘C’ language the following macro permits simulation of a time-out function with a time parameter in the form of a 16-bit word :
} /* End of macro delay16 */
Note: The '\' character represents the end of a line and allows a macro to appear over several lines
• The KR_WAITSIG function causes a task to enter the ‘Wait for signal’ state
• The KR_SENDSIG function causes sending of a signal to a user-specified task
• The KR_DELSIG function causes a task to move to the ‘Wait for a signal’ OR ‘time-out’ state When one of the events occurs the task is activated
KR_SENDSIG, KR_WAITSIG and KR_DELSIG are described in chapter 6 (list of the services)
Other features :
• Sending a signal to a task that is not waiting for a signal has no effect
• Similarly, sending a series of signals will probably have the same effect as sending a signal
• Signal is an easy-to-use task synchronisation feature
• Signals are reset at initialisation by a call to KR_INIT
Trang 15KR-51 4 Scheduler
4 Scheduler
This chapter describes the dynamic characteristics of the scheduler and a full understanding is
essential to make best use of the services provided by KR-51 KR-51 contains a function library for task services and a scheduler The scheduler consists of the following functional modules:
If a task is ready to be initiated, the INITIATOR causes its correct placement and initiation
Finally, the RECEIVER takes control, when a task terminates or moves to the Waiting state
4.1 Kernel clock
The CLOCK function is initiated at regular intervals via the TIMER 0 interrupt service routine
Each clock (or tick) causes :
• increment of the clock timer (which is used as a time reference for time out management)
• reloading of timer 0 to the user defined value The reloading mode adopted eliminates any cumulative
• and finally, initiation of the POOLER by the CLOCK (except if timer 0 interrupt was itself delayed
by a previous execution of POOLER)
Note: For the versions with external RAM, several CLOCKS are used in cascade (divisions in series), as
if there were several schedulers
However, the secondary clocks are not built into the scheduler module : they consist of tasks that are initiated by the INITIATOR module and are only used to place other tasks in the READY state The
POOLER module will recover them at next pooling cycle
4.1.1 Pooler
The POOLER examines all tasks that are defined in the group, to determine if some tasks in the
Waiting state (waiting for a time-out or a signal flag release) may move to the READY state
During the analysis phase,
• It identifies the READY task with the highest priority
• It then calls the INITIATOR if this task has a higher priority than the currently active task
• If more than one task with equal priority is ready to be initiated, only the "oldest" will be selected
A task's ‘creation time’ corresponds to the time when the task moves to the READY state
• At similar priority levels and ages, the final selection is performed as follows:
generally, the first task in the READY queue will be selected
The POOLER places the READY tasks in the READY queue
The READY queue is then examined to select the task to be initiated
Tasks of GROUP 0 only (for which the clock corresponds to the timer overflow) are moved to the READY state by the POOLER The predefined tasks TASK_CL1, TASK_CL2 and TASK_CL3 cause pooling of tasks of group 1, 2 and 3 respectively
The pre-defined tasks bear the following numbers :
Trang 16Task Task Number for the
Note : All TASK_CLi predefined tasks have priority 3.
When initiated, TASK_CLi can move one task (or more) of the GROUP to which it belongs to the READY state The initiation will be performed only at the next TIMER0 interrupt unless the "DIRECT POOLING" mode has been activated
4.1.2 Initiator
The INITIATOR saves the context (PSW, ACC, B, DPH, DPL and stack level) of the task that was previously running, then initiates the new task using the register bank allocated to its priority level.The task is executed at the last INITIATOR instruction, which is a RETI The task is thus placed
outside of the interrupt service structure to allow a scheduler cycle to be performed at the next clock and also to permit asynchronous interrupts
4.2 Task execution
Once initiated, a task runs until it terminates, waits for an event or a flag release or is deleted by itself
or by another task It can also be interrupted by a higher priority task following the scheduler phase In this case, it remains in the SUSPENDED state, but its context is saved and then to be retrieved when the higher priority task terminates The context contains the return address and also the topmost section of the stack that contains the return addresses of the nested calls, as well as the automatic local variables
4.4 Direct pooling
4.4.1 Principle
Waiting, task pooling and initiation occurs only during the timer 0 interrupt service routine, hence at each timer 0 overflow or ‘clock’ If, when a task moves to the Waiting state, no lower priority task is SUSPENDED, a READY task will be initiated only at the next clock For part of a clock cycle, it may occur that no task is executed, although several tasks are READY To eliminate these dead times, the POOLER is initiated by setting the TF0 bit independently from the CLOCK in the following cases :
• at any task termination (automatically at the end of the RECEIVER execution)
• at signal sending, semaphore release, initiation of a daughter task
This mechanism has no effect on the time management as direct pooling is distinguished from a real timer 0 overflow
Trang 17KR-51 4 Scheduler 4.5 Interrupt handling
4.5.1 Implementation
In addition to TIMER0, KR-51 recognises any other unmasked interrupt source These so called
parallel (// below) or asynchronous interrupts can be handled without difficulty, provided you proceed carefully with :
• the use of register banks
• the delay that KR-51 may cause to interrupt handling
• the delay that may be caused by the interrupt handling
• the priority level hierarchy
Note: the priority level for parallel interrupts must be higher than or equal to that of the scheduler
4.5.2 Register banks
One of the fundamental rules of the KR-51 kernel consists in associating a register bank with a task's priority level Tasks of priority 3 are hence automatically associated with bank 3, those of priority 2 with bank 2 and so on
Usually, a register bank is also associated with a particular interrupt priority level
Consequently, to avoid unnecessary swapping of a task's registers, a register bank should be reserved for parallel interrupts, and tasks with the corresponding priority level should not be declared
Consequently, a register bank must be associated exclusively with :
• a task's priority level
• an interrupt level (for a parallel interrupt)
Moreover, bank 3 for priority level 3, must be allocated only to tasks as it is also used by the
SCHEDULER
The table below gives some examples of how to use register banks
Example A Example B Example C Bank 3(used by KR51) Tasks priority3
+ KR 51 Tasks priority 3+KR 51 Tasks priority3+KR 51
Bank 2 Tasks priority2 Ints // priority1 Ints // priority2
Bank 1 Tasks priority1 Tasks priority1 Ints // priority1
Bank 0 Tasks priority0 Tasks priority0 Task priority0
In example A, the 4 banks are available so that the kernel can process 4 priority levels
In example B, one bank is reserved for the parallel (//) interrupts Three priority levels are available for the kernel
In example C, 2 banks are reserved for the parallel (//) interrupts Two priority levels are still available for tasks In this case, the device is assumed to have 4 priority levels
4.5.3 Kernel and parallel interrupt priority
At initialisation (KR_INIT function), TIMER 0 interrupt, which is associated with the KR51 kernel, is given the default priority level (0) It is recommended not to change this priority level
Parallel interrupts must have a priority level equal to or higher than that of TIMER0 interrupt A parallel interrupt may interrupt the kernel
Trang 184.5.4 Response time
This paragraph is concerned with only to delays caused by the KR51 kernel Delays caused by the other enabled user interrupts should also be considered
An interrupt of a priority identical to that of the scheduler can be delayed for at most the kernel’s
execution time The maximum duration depends on the number of tasks, but also of the task's state
An interrupt of higher priority will run with delays defined by the manufacturer of the microcontroller, unless the interrupts were disabled in the kernel by resetting EA bit Interrupts are disabled under the following conditions :
• To reload TIMER 0 and eliminate the risk of offset, the scheduler blocks interrupts for 14 CPU clock cycles
• In the KR_TST (semaphore "test and set") function call, the flag is manipulated with the
interrupts disabled Flag manipulation may last for up to 12 CPU clock cycles
• In the KR_DEL_ABS, KR_DEL_REL, KR_DELETE function calls, task switching is also
performed with the interrupts disabled, but lasts only 7 CPU clock cycles
• Utility services such as MAILBOXES can also block interrupts for a short time See the
description of these services for further details
4.5.5 Permissible delay
At timer 0 reloading, the scheduler CLOCK includes the time expired since the previous overflow The maximum permissible delay is equal to the clock duration If exceeded, the following clock will then be offset by 65536 CPU clock cycles
Practically, it is recommended to limit the duration of the parallel interrupts If an important interrupt processing session is to be initiated, it should be performed as a task (see following paragraph)
4.5.6 Tasks/interrupts interface
A parallel interrupt can initiate some kernel functions such as :
• Information queries
• Initiate task (KR_CREATE)
• Send signal to task
• Functions related to MAILBOXES
However, parallel interrupts may not terminate a task by calling KR_DELETE Similarly, the use of semaphores is reserved for tasks because an interrupt routine cannot be moved to the Idle state Practically, these prohibited functions can still be called via a task initiation to go from the "parallel interrupt" mode to the more powerful "task" mode
4.6 Possible actions on IE and IP registers
KR_51 does not require exclusive access to interrupt control registers The strategy applied is :
• The user can enable/disable the interrupts and can also give them different priority levels
• KR-51 does not initialise and never changes the register(s) which set(s) interrupt priority (IP or IPO/IP1) The scheduler is hence initialised with the lowest priority level
However, the TIMER0 interrupt and the interrupt associated with the direct pooling initiation (if any) should be maintained at lowest priority level
Trang 19KR-51 4 Scheduler
4.7 Task lifetime
This section describes the dynamic properties of the scheduler by analysing the various phases in the lifetime of task T1 The mechanisms are now detailed from the viewpoint of T1
• At RESET, the scheduler initialisation procedure moves the task to the UNVALIDATED state
• If task T1 is permanent (or repetitive), the application’s initialisation routine must be used If not, the initiation is performed later at the request of another task, or during the parallel interrupt service routine
• The initiation moves the task to the READY state, until it is selected by the POOLER The INITIATOR then moves it to the RUNNING state
• The task may temporarily leave the RUNNING state, if a higher priority task pre-empts it The TASK remains in the SUSPENDED state to allow the higher priority task(s) to be executed When the task that interrupted it terminates (or enters the WAITING state), task T1 moves to the RUNNING state
• If T1 is waiting for an event or calls a shared resource protected by a semaphore, T1 becomes WAITING, allowing another task of equal priority to be activated
• T1 is maintained in the WAITING state until the event occurs At detection of the event by the POOLER, T1 moves to the READY state (as for the first initiation)
• A Task continues, alternating between the "RUNNING", "WAITING", "SUSPENDED" and
"READY" states It can also be "INTERRUPTED" (for short times) by the activation of a parallel interrupt or scheduler (TIMER0 overflow)
• Finally, non-permanent tasks can be terminated (killed by themselves of by another task) and hence return to the UNVALIDATED state
4.8 Notes and suggestions
Variables may be overlaid, when using a real time kernel To eliminate this risk, the following rules should be observed:
• in the parallel interrupt services routine, working registers: PSW, ACC, B, DPL and DPH should
be saved With PL/M-51 and C-51 compilers, these values are automatically stored, when a function is declared with the "INTERRUPT" attribute
• common resources such as variables internal peripherals, tasks and mailboxes should be used only if they are protected by semaphores, or if the "volatile" feature of these resources is
controlled and does not pose any problem
• if tasks are written in assembly language, the scheduler function calls that may suspend the current task (kr_del_abs, kr_tst, etc ) should be used carefully as various registers may be corrupted
Hence, the following lines should not be written :
;example of bad practice
inc R6
mov R7,#3 ;passage of the parameter "delay" in R7
lcall KR_DEL_ABS ;call to the kernel service KR_DEL_ABS
mov A,R6 ;R6 lost! (KR_DEL_ABS uses R6)
Note: Generally, kernel services (as with any RC51 or PL/M-51 function) may modify the values in the
currently working registers : R0 R7, ACC, B, PSW, DPL and DPH As a consequence, storing values in them for later retrieval is bad practice
Trang 205 Implementation
5.1 KR-51 files and installation
KR-51 is installed with RKit-51 software To use KR-51, you need a valid serial number
The supplied files are :
• KR-51 libraries in the \LIB directory,
• INCLUDE files, in the \INC directory, that corresponds to the programming language used:KRDCL.H for the ‘C’ language, and KRDCL.H51 for the MA-51 assembler
The INCLUDE files must be inserted at the beginning of the application files For programmers using RC51, the following control should be placed at the beginning of each file :
#include "KRDCL.H" /* Prototypes of the functions of KR-51 */
#include "REG51.H" /* SFR of the 8051 */
These files contain :
• constant definitions (especially the codes returned by the information services)
• pre-defined types (especially for task declaration)
• kernel service prototypes
• Examples in the \EXAMPLES\RTOS directory
5.2 Implementation
To construct a KR-51 based application, proceed as follows :
1 Ensure the linker is configured to use the Kernel libraries (either KRY,KRx or KRH) via Project |
Options | LX51 | Kernel in Ride7.
2 Define the tick rate and the value of the dividers
3 Write a "main" task initialisation procedure: kernel should be initialised by a call to KR_INIT If you use mailboxes, MAIL_RESET() should also be called
4 Write the tasks specific to the application
5 Compile and link the project
Trang 21KR-51 5 Implementation 5.4 Tasks written in another language
It is possible to write tasks in another language (e.g from the MA-51 Assembler) To allow the linker to take into account this task, you must declare it with the external attribute in a ‘C’ source module If the application comprises of several ‘C’ modules, the task declaration must be carried out only once
code
mov A,NUMBER LABEL1:
mov R7,TEMPO1 lcall kr _del_abs ;task is put to sleep
/* Task declaration in a ‘C’ module */
extern void flcd () task _TLCD_ group 2 priority 0
// This task is written in assembler and will be accepted
// by the linker and the kernel.
// ATTENTION: This external declaration must appear only once!!
The parameters NUM_TASK and NUM_TASKi (number of tasks for each group) are processed by the linker and the Compiler They do not have to be defined by the user
5.4.1 Significance of the different keywords
task Indicates to the linker that the function must be dealt with as
task
Must be followed by a constant value corresponding to the task number
mandatory parameter
group Must be followed by a constant corresponding to group to which
the task belongs optional parameter default value = 0priority indicates the task priority optional parameter
default value = 0istack (1) indicates the memory used to save the stack optional parameter
default value = 16 bytes(8 for KRY)
xstack (1) indicates the memory used to save the stack
Ignore for KRY
optional parameter default value = 16 bytes(1) : refer to the section ‘Implementation - Saving stacks and local variables’
Trang 225.4.2 Kernel settings
The kernel options have the following default values :
Parameter Description Default value Notes
TIMO_INIT Tick rate(= reload value) 1000 i.e 1 ms @ 12MHz
The quickest way to change these parameters is to select Options | Project | LX51 | Kernel from
How do we calculate the number of CPU cycles/tick to be able to get 16 usec per tick?
The clock goes at 16MHz, so one CPU cycle takes 1/16=0.0625µs Therefore we'll have
16/0.0625=256 cycles in 16µs So we should set 256
This is the theoretical value, but it may lead to problems see below
What is a smallest CPU cycles/tick that could be set?
The minimum value allowed is 200 If you enter a smaller value, Ride7 uses 200 (the maximum is 65535)
This limitation exists because the kernel takes about 200 cycles to analyse the tasks list when there is only one group 0 task If you used a smaller value, the CPU would spend all its time managing the system, and the task would never be executed (or some ticks would be skipped)
This is really a theoretical minimum, usable only if you have a few tasks of group 0
When actually using the kernel in an application, the number of tasks grows, mailboxes and
semaphores are created, etc All these things take time to be managed and the CPU time needed for the system itself gets bigger In practice, we advise to use at least a value of 500 if you want to avoid problems
That is why even if you set a value of 256, you may still have trouble It all depends on the complexity
of the application
In fact, when you want to perform such precisely timed operations (let's say, below 100µs between ticks, if you have a 16MHz crystal), the best is to use another timer with a higher interrupt level and a dedicated ISR You can still use the kernel for the slower tasks
Indeed, managing an OS takes time, you can't avoid it
The number of clock by CPU cycles depends on the derivative you are using The standard 51 takes
12 clock cycles per CPU cycle
Trang 23KR-51 5 Implementation 5.5 Saving stacks and local variables
5.5.1 Stack storage
The management of return addresses of interrupted tasks requires information to be placed on top of the stack The "size" corresponds to a space reserved in XDATA (or IDATA for KRY) for data storage The return address need not be included in this size To calculate the stack size :
• if the task code does not invoke any sub-program (except kernel function calls), a size of 0 is sufficient
• data storage occurs at "SUSPEND" calls where a task is moved to the WAITING state programs that do not use this function can be ignored
Sub-• RC51 and PL/M-51 do not stack variables before a function call, (except for reentrant functions) and only the function return addresses should be considered
• Enter the required size after the keyword istack in the task declaration Example :
void ftime task _time_ priority 2 istack 2 xstack 0
{ while (1) {
if(++second==60) { inc_minute(); second = 0;}
kr_del_abs(100); /* assuming 100 Ticks per second */
} }
• Change the value from the kernel dialog box in Ride7
• Change the value either in an Assembler module or in a ‘C’ module using the following syntax :
• Assembler: PUBLIC KR_XLEN
KR_XLEN NUMBERxx // xx is the size
• C: #pragma defj(KR_XLEN = xx) // xx is the size
The number of bytes, N, to reserve should be at least the sum of the declared sizes for stack spaces :
+ (NUM_TASK * 4) where NUM_TASKS is the total number of tasks declared by the user,+ 16 bytes,
+ the bytes used for external stack storage (see next section)
to which the size of the space for the memory allocator (if used) should be added (see section 8)
5.5.2 External stack capability (external versions)
This section explains the concept of dynamic external stack management used by the ‘C’ compiler You can skip the remaining part of the section if your tasks are written in assembly, or in the ‘C’
language and compiled with the SMALL memory model where no external stack is used
Although the "SMALL" model may be used, it is logical to compile tasks in the "LARGE" model, if you use kernel KRX versions in order to benefit from the external stack
The reference manual for the RC-51 compiler gives a description of the external stack feature
Trang 24The maximum size for automatic variable storage should be determined before calling a kernel
SUSPEND function The example below explains how to determine the maximum size (which must be placed after the keyword xstack)
pragma auto
void fcounter() task _counter_ istack 4 xstack 4
/*task counter*/
{ int i; /*int = 2 bytes used for this automatic variable*/ for (i=0;i<=5,i++)
{ printf ("fct=fcompteur : compteur=%2.2",i) fct2 ();
kr_del_abs (5); /*timeout of 5 ticks*/
} return () }
void fct2 ()
{ char c; /*automatic variable char = 1 byte used*/
for (c='0';c<='5',c++)
{ printf ("fct=fcompteur : counter=%c",c) fct3();
kr_del_abs (5); /*timeout of 5 ticks*/
} return();
}
void fct3 (char c2)
printf ("fct=fct3") /*but one parameter passed (c2)*/
/*this parameter will be stored in external stack*/
printf ("%6.6f %c",sin(f1),c2);
}
Trang 25KR-51 5 Implementation
Note: via the putchar function, the printf function may indirectly call a kernel suspend function The
TELEMEAS example supplied (and printed out at the end of the manual) illustrates this case
Sufficient reservation (for internal and external stacks) should then be performed to include the possible kernel suspend function calls from printf
In the example above, the external stack storage requires a minimum of 4 bytes as in the ‘worst case’, the counter task may be suspended within fct3 function
Before calling a suspend function within fct3, the following information should be stored in the external stack :
• i value, in fcounter (int=2 bytes)
• c value, in fct2 (char=1 byte)
• the value of the parameter transmitted between fct2 and fct3 (here a char i.e 1 byte)
The minimum size to be reserved for the external stack is hence the sum of the 3 preceding values, which is 4 bytes
These 4 bytes should be included when determining the size of KR_XTOP and KR_LEN (see previous section)
As for the stack storage, it is advisable to reserve some additional bytes for the external stack storage
in case hand calculations are too small A size of 0 for the external stack is appropriate for the following cases :
• tasks written in assembly language
• tasks written in the ‘C’ language but compiled in the ‘SMALL’ memory model
5.6 Set-up utility program
For a KR-51 based application, the typical start-up process consists of the following initialisation
procedures :
• Primary start-up
• Application variable set-up
• Kernel set-up
• Internal peripheral set-up
• "Permanent" task initiation
• Kernel Activation
• Base loop
The primary start-up procedure consists in initialising the Stack Pointer register (SP) and resetting internal RAM (not essential but recommended) The configuration parameters are often placed in the compiler’s set-up utility programs and hence need be of no great concern to most programmers
For the RC-51 compiler, the application variables set-up can also be performed automatically
Practically, some variables will still need to be set up
Initialisation the kernel is achieved by calling the KR_INIT function In the KR_INIT function call, timer 0
is configured, the interrupts enabled (EA and ETO) and tasks moved to the UNVALIDATED state Finally, in the KRX version, the pre-defined tasks (CLOCK of GROUPS 1, 2 and 3) are initiated Note that timer 0 is not initiated : the first clock will occur only after 65536 CPU clock cycles, unless
anticipated by the user (by entering FFh in the TH0 bit for example)
The internal peripheral set-up procedure applies to the peripherals used by the application : serial port, except for timer 0 and its interrupt
The permanent task initiation procedure (refers to tasks that occur at fixed intervals) is performed by the KR_CREATE function
Finally, the base loop is executed, if no task is running it often consists of a simple loop (sjmp$) A background function may be inserted in the procedure, if the register bank used is not the same as that
of any tasks or interrupts
Trang 265.7 Task editing
The examples of tasks provided should be read, before creating any original programs It is appropriate
to remind the reader of some rules :
• the service prototypes and type definition placed in the INCLUDE files should be used : *.h51 in Assembler, *.h in RC-51
• to identify the tasks, constants should be defined (using #define in the ‘C’ language or equ in assembly language) with meaningful These constants should then be used at function calls
• direct memory addressing of registers should be performed with care since this could lead to inappropriate accesses The RB control in the MA-51 macro assembler, or the ‘using’ keyword
in the RC-51 compiler is recommended
5.8 Debug versions
5.8.1 General
The DEBUG utility program offers the four following features :
• consistency checks are performed for easier debugging The debug libraries are indicated by a
‘D_’ prefix The use of the DEBUG capability modifies the kernel’s performance and increases code size
• an error number is placed in the KR_ERR1 bytes, and a parameter, which is often a task number, in KR_ERR2 These bytes are placed in DATA for the KRY version and in XDATA for the KRX version A summary of the errors is given later
• a KR_TRAP function is initiated, if an abnormality in the scheduler module or a service is detected The "TRAP" function should be written by the programmer and given the PUBLIC attribute An example is provided in the KRX directory
A simple trap exception function may be declared as follows :
void KR_TRAP(void)
{
EA = 0; //disable interrupts while(1);
}
• a trace of the maximum value of the SP register is stored in SP_MAX byte in DATA space SP_MAX is updated in the CLOCK and INITIATOR phases If SP is less than 8, the KR_TRAP function with error code 1 is initiated For microcontrollers with 256 bytes of internal RAM, KRY will generate a trap exception if SP>248
• the return address of the abnormal kernel function is loaded in the DPTR 16-bit register
5.8.2 Recommendations
If you have any problems in implementing an application that uses the kernel, the DEBUG utility
program will be of great help, although it reduces kernel performances If you have the SIMICE-51 simulator (or the PCE5130C emulator) integrated in Ride7, you can open the ‘Kernel’ view while
debugging
5.8.3 Quick reference tables to return codes in the DEBUG utility program
The next quick reference tables apply to both internal (KRY) and external versions (KRX)
Functions are discussed in more detail in chapter 5
Trang 27KR-51 5 Implementation
Stack overflow
Function KR_ERR1 KR_ERR2 Notes
Systems KR_ERR1 KR_ERR2 Notes
KR_GETSTATUS 14h Task ref unknown task
KR_GETPRIORITY 15h Task ref unknown task
KR_GETEVENTS 16h Task ref unknown task
KR_GETTASKCUR
-KR_GETPRIORITYCUR
Semaphores
Function KR_ERR1 KR_ERR2 Notes
Mailboxes
Function KR_ERR1 KR_ERR2 Notes (see ‘mailboxes’ section for
further information )
MAIL_READ 8Fh mailbox N° read from an empty mailbox
MAIL_SEND 8Eh mailbox N° write on a full mailbox
any service related to
mailboxes 81h8Dh mailbox N° mailbox N° unknown mailboxincoherent mailbox
Trang 28Each service description includes :
• their prototype in the ‘C’ language
• an explanation of the effects on system status
6.2 Quick reference to the services
Trang 29KR-51 6 List of services 6.3 Parameter passing convention
The parameter passing convention is compatible with the RC-51 compiler and the MA-51 macro
assembler from RAISONANCE Most of the services have only one parameter of 1 byte, which is passed via register R7
6.4 Values returned by services
The system functions kr_delsig_abs, kr_delsig_rel and kr_tst_tout return a value in R7 The other systems functions return no value (void type in the ‘C’ language)
The KR_TRAP function is initiated in the DEBUG versions, if an abnormality is encountered
Information query services and some utility services return a byte located in both the accumulator (A) and register R7
6.5 KR_CREATE (system function)
Function: Put a task into the READY state
Prototype: void kr_create (unsigned char task_id);
Return value: None
Remarks: The initiation or creation of task_id task causes switching from the UNVALIDATED
to the READY state The task does not run immediately, even if it is of higher priority than the initiated task unless followed by a direct call to the POOLER
In the standard version, the task's current state, which should be UNVALIDATED,
is not checked
In the DEBUG version, an exception (call to KR_TRAP) is set and no action is performed, if the task is UNKNOWN or not in the UNVALIDATED state
Error code (debug): 10H Unknown task KR_ERR2 : reference of the task.
11H non compatible state (non UNVALIDATED)
KR_ERR2 : reference of the task
Suggestions: If a task can be initiated by more than one task, it should be regarded as a "shared resource" and be initiated using a semaphore
Trang 306.6 KR_DELETE (system function)
Function: Deletes a task.
Prototype: void kr_delete (unsigned char task_id);
Return value: None
Remarks: Kr_delete causes abnormal, or forced, termination of a task and its use should be
regarded as exceptional
The deleted task moves immediately to the UNVALIDATED state and if the task is currently active its execution stops If the task was interrupted, it is extracted from the running queue and execution will not resume after completion of the interrupt handler
The scheduler stops kr_delete from being interrupted for a time that may exceed
100 CPU cycles for the KRX version with many tasks in the READY state
Error code (debug): None
Note: KR_DELETE should NOT be called from a hardware interrupt service routine
Suggestions: To abort a task, the kr_delete call is not necessary A simple "return" is by far better
The DEBUG version will generate an exception (code 12H) only if the task is unknown
6.7 KR_DEL_ABS (system function)
Function: Moves a task to the idle state for a given time duration
Prototype: void kr_del_abs (unsigned char time);
or void kr_delay (unsigned char time);
Return value: None
Remarks: Moves the current task into the WAITING state for the number of clocks
specified by the ‘time’ parameter
The TIME duration is derived from the CLOCK module (or task's group for the KRX version) See also section "Task description/Waiting for an event".The time taken as a reference is not the current time, but the time when current task was placed in the READY state Exact timing is hence ensured
KR-51 manages delays resulting from the initiation of higher priority tasks
or an interrupt of lower priority tasks If a current task is initiated with a delay of 4 clocks and kr_del_abs (10) is called, a delay of 6 (10-4) clocks is applied, calculated from actual time Delays should not cumulate
Error code (debug): None
In the following timing diagram, it is assumed that to end the task, KR_DEL_ABS (10) function is
systematically used
Trang 31KR-51 6 List of services
Task creation Task ready
Task initiation Task execution LEGEND
TASK SCHEDULING
10 ticks 10 ticks 10 ticks 10 ticks
KR_DEL_ABS may be used anywhere in a task, as dynamic entry point management is employed After the delay has expired, execution continues with the statement/instruction immediately after the KR_DEL_ABS function call
A typical use of the KR-DEL_ABS function is in the construction of timed tasks without "offsets"
However, it is often necessary to move an instruction to the Wait for a time-out state (starting from current time) In this case, KR_DEL_REL should be used This function is described in next section
6.7.1 Possible problems with KR_DEL_ABS
Normally, you need not know any more about how the kernel handles the KR_DEL_ABS function However, for more complex applications, the concept of a task delay (or advance) based on current time should be more thoroughly understood
A way to visualise the process consists in representing the current time (number of clocks) by the position on the circumference of a circle (in the form of a bold radius line in the diagrams below) Times are counted with "modulo 256" and passes in an anti-clockwise direction
Similarly, a "timer" is associated with each task (represented in the form of a fine radius line in the diagrams) At each clock, a comparison between the current time and the task's timer value is
performed by the scheduler
In the following example, tasks 1 and 2 are both waiting for a time-out and at the next clock the
following occurs :
• the scheduler detects that task 2 (delayed) must be moved to the READY state, which will be effectively performed even if task initiation is delayed
• it detects that task 1 (in advance) must remain in the WAITING state
This representation also permits a better understanding of why the KR_DEL_ABS function has a
signed number (-128 to +127) as a parameter KR_DEL_ABS accepts a negative argument, which can
be useful in some specific cases e.g KR_DEL_ABS (-5)
A "reset" compared with task's creation time is thus performed
Trang 32CPU not available
0 (mod 256) Task 1 counter
current time
0 (mod 256) Task 1counter
current time
0 (mod 256) New value of
to initiate task 1 fig 1 : task 1 in the WAITING state
fig 3 : task 1 in the RUNNING state
fig 2 : task 1 in the READY state
fig 4 : task 1 in the WAITING state task1 counter
Example 1
Let us image that a task (task 1 in example above) is to be initiated every 10 clocks, which can be easily obtained by systematically ending the task using the following sequence :
KR_DEL_ABS (10) /*in the ‘C’ language*/
Let us assume that a task placed in the READY state is not initiated immediately and is delayed for more than 128 + 10 = 138 consecutive clocks because the CPU being occupied by tasks or interrupts
of higher priority Figures 1 and 2 illustrate this case
When the CPU is released so that it may initiate task 1 (figure 3), task 1 moves to the RUNNING state and then terminates by a KR_DEL_ABS(10) function call as always
The new reference value for the timer associated with task 1 is calculated as above explained (=old value + 10) It is represented on figure 4
Trang 33KR-51 6 List of services
At the next kernel clock (see figure 4), task 1 will then be regarded as being in ADVANCE, although in fact it has 128 clocks of "delay" It will consequently not be moved to the READY state, before the absolute counter exceeds task 1 counter value In this case, the equivalent to a "half-turn" (=128
clocks) is "lost", before resuming with normal task scheduling Consequently, the kernel handles any delay, provided it does not exceed 128 clocks
expected result, i.e a regular schedule of task sequence every 2 clocks
Practical conclusion
Both previous examples correspond to rare situations where task splitting is badly optimised Note that
an essential rule is that the higher priority tasks or interrupts should be of the shortest duration
Similarly, the second example represents a case where the CPU is "used up", which should of course
be avoided When a task is to be initiated at regular time intervals, the first condition to observe is that the task's duration does not exceed the time interval between two consecutive initiations
Note: If you must work with tasks of a long duration with respect to the time base and of equal priority
(which is not recommended), the KR_PAUSE function should be used
6.8 KR_DEL_REL (system function)
Function: Puts a task to SLEEP for a given duration
Prototype: void kr_del_rel (unsigned char time);
Return value: None
Remarks: Moves the current task to the WAITING state for the TIME duration The TIME
duration is specified in number of clocks in the CLOCK module (or task's group in the KRX version) See section "Task description/Waiting for an event"
In contrast to the kr_del_abs function, the time taken as a reference is the current time A kr_del_rel function call erases any trace of task delays starting from the last time when it was declared as READY
KR_DEL_REL reloads the value of the timer associated with the task using the following value : current timer (or timer associated with its group) + TIME The task will hence be re-declared "READY" in "TIME" clocks
Error code (debug): None
Trang 346.9 KR_SENDSIG (system function)
Function: Sends a signal to a task.
Prototype: void kr_sendsig (unsigned char task_id);
Return value: None
Remarks: Sends a signal to the task indicated by task_id This signal is ignored, if the
specified task is not waiting for the signal If it is, and if the task is not waiting for another event, it moves to the READY state It can hence be selected during the next pooling session
Error code (debug): Task existence checks are performed
6.10 KR_WAITSIG (system function)
Function: Moves a task to the Wait for a signal state (WAITING).
Prototype: void kr_waitsig (void);
Return value: None
Remarks: A flag in the current task descriptor is set Later another task may call
KR_SENDSIG, which resets the flag and causes the present task to be moved
to the READY state
Error code (debug): Task existence checks are performed.
6.11 KR_DELSIG (or KR_DELSIG_REL)
Function: Moves task to Wait for a signal state (WAITING), but the wait is limited by a
time-out
Prototype: char kr_delsig (unsigned char time);
char kr_delsig_rel (unsigned char time);
Return value: 0 if the time-out has elapsed before a signal was received
!=0 otherwiseThe returned value is placed in R7
Remarks: Identical to KR_WAITSIG, but the ‘time_out’ flag is also set The task will leave
the WAITING state (and move to the READY state) if either of "TIMEOUT" or
"SIGNAL" event occurs The delay is a relative delay See kr_del_abs and kr_del_rel for further details
Error code (debug): Task existence checks are performed.
6.12 KR_DELSIG_ABS
Identical to KR_DELSIG_REL but in this case the delay is an absolute delay, referring to the task’s creation time (see kr_del_abs and kr_del_rel for further details)
Trang 35KR-51 6 List of services 6.13 KR_PAUSE (system function)
Function: Moves a task to the READY state, if another task of equal priority is
also ready (to take control) Equivalent to KR_DEL_REL(0)
Prototype: void kr_pause ();
Return value: 0 if the time-out has elapsed before a signal was received
!=0 The returned value is placed in R7
Remarks: When two tasks of long duration and similar priority must be activated,
the first initiated task takes control of the processor, prohibiting the execution of the next task because of its duration Time slicing is the usual solution to this problem but is not supported by KR-51 The KR_PAUSE function is an economic and efficient alternative: you only need place kr_pause calls in the tasks and the arbitration occurs automatically If, at function call, no task of equal priority is ready, the return to the task is immediate and KR_PAUSE has no effect At the call to KR_PAUSE, the task's creation time is modified and given the current timer value (as if the task were just initiated) This permits
‘refresh’ of the task, which is required by the "oldest first" principle However, this time change feature creates a time offset and prohibits task calls at regular time intervals by KR_DEL_ABS function If these offsets pose a problem, a solution consists of interleaving two tasks : the first task occurs at fixed time and calls the second task, which performs KR_PAUSE calls
Error code (debug): None
6.14 List of the information services
The function prototypes, state designation and other definitions are contained in the INCLUDE files
• kr_getstatus: char kr_getstatus (unsigned char task_id)
Returns the state of task_id task in 1 byte The state can be : UNKNOWN (255), READY (0), WAITING (4), UNVALIDATED (8), SUSPENDED (12) RUNNING (1)
• kr_getpriority: char kr_getpriority (unsigned char task_id)
Returns the priority of task_id task as value between 0 and 3
• kr_getevents: event kr_getevents (unsigned char task_id)
Returns the list of the events waited by task_id task It is 1 byte Bits 4, 5 and 6 respectively indicate whether a signal, a timeout or a flag release is waited for (a timeout and a flag may not
be waited for simultaneously) Type event is declared in file ‘krdcl.h’
• kr_gettaskcur: unsigned char kr_gettaskcur ( )
Returns the number of the current task
• kr_getprioritycur: char kr_getprioritycur ( )
Returns the priority level (0 3) of the current task
Trang 367 Semaphore
The semaphore is an easy sharable resource management tool :
• When task T1 uses resource R1, it reserves it by asserting the semaphore associated with R1 via a call to a kernel service function
• If another task T2 requests the same resource (R1), access to it is refused, until the semaphore associated with it is released by T1
• Task T2 moves into the WAITING state and only enters the READY state, when T1 releases the semaphore that protects R1 (via a kr_free function call)
Semaphores can be applied to the following sharable resources :
• memory areas (variables)
• internal peripherals : CAN, UART,
• MAILBOXES
• tasks (initiating slave tasks)
• functions (for example maths library),
Signal/semaphore difference
A signal is associated with a task A semaphore is associated with a resource and is independent of any task
Types of semaphores
There are 2 types of semaphores :
• Semaphores with time-outs apply to versions of the kernel which use external RAM
4 semaphore flags in internal memory are allocated by the kernel to help manage the timer They are called : SEMA_BIT0, SEMA_BIT1, SEMA_BIT2, SEMA_BIT3
• Normal semaphores without time-out facilities
7.1 Semaphores with time-outs (external versions only)
The associated services allow combination of the wait for semaphore with the TIMER (time-out) :
char kr_tst_tout (char time-out, char sem_num) void kr_free_tout (char sem_num)
The delay must be thought of as a "relative delay", like in the kernel service kr_del_rel
The kernel automatically ALLOCATES 4 bits in the bit segment, starting from the PUBLIC label
Trang 37KR-51 7 Semaphore 7.2 Normal semaphores
7.2.1 Implementation
Although 128 bits are available in bit addressable space, some are used by KR-51
From a practical point of view, over 100 bits are available, which is more than sufficient for most
applications using the 8051 microcontroller
Remark : The 4 bits, SEMA_BITi (i=0 3), are automatically allocated by the kernel If you don’t need these bits as timer controlled semaphores, you can use them for any other purpose including « standard semaphores » In this case, you must impose the allocation of the SEMA_BIT0 segment and subsequently refer to the address of these bits Refer to the example SX in the Appendix for further details
7.2.2 Semaphore services for standard semaphores
The only semaphore services available are semaphore set and release
Semaphores must be directly initialised
Semaphores should be used by tasks only and not by interrupt services, which cannot be moved to the WAITING state
kr_tst : Reservation (Test and Set)
void kr_tst (char sema)
In this function, the bit state of the semaphore with the sema address is examined :
• if the semaphore is free (bit at 0), it sets the semaphore, enters the "busy" state and gives control to the calling task that continues its execution
• if the semaphore is set (bit at 1), the calling task enters the WAITING state and waits for release
The semaphore handler is built into KRYS and KRXS versions of KR51
However, the KR_TST and KR_FREE functions expect the semaphore address to be specified as a parameter, whereas a high-level language compiler such a ‘C’ does not usually assign absolute
addresses
To solve this difficulty, you can do any of the following :
• place semaphores at fixed addresses by declaring them in an assembly program You only need define constants corresponding to these addresses :
;Assembly program used for the allocation of the semaphores
BIT at 10H
SEMA0 : DB 1 SEMA1 : DB 1 /* ‘C’ program referring to the above semaphores*/
#define SEMA0 0x10
#define SEMA1 0x11
• reserve one byte in BDATA to be split into 8 semaphores The semaphore address can hence
be found from the byte address, but the computation will be performed at run-time, which is
Trang 38/* ‘C’ program allocating semaphores*/
char bdata sema8_1;
#define SEMA0 ((((char)&sema8_1)-0x20)*8)
#define SEMA1 ((((char)&sema8_1)-0x20)*8+1)
• use the suggested macro in the SX application in the Appendix
7.4 Notes and suggestions
For correct operation, a semaphore should be reserved only via system calls Any direct semaphore reservation will result in incorrect operation of the scheduler
Moreover, to ensure that semaphore release occurs within the shortest time, do not terminate a task that has set a semaphore If you do it, the semaphore will be set forever and no task can access the protected resource
Semaphores should be initialised (to zero) at the start of the application
7.5 Semaphores and task groups (external versions)
Reminder : in the KRX version, 4 task groups are available and each group is associated with a clock.Each task group is assigned a pooler, which pools each task in the group and moves the "waiting for a semaphore release" tasks to the READY state, when the corresponding semaphores are released.The interleaved pooler functionality permits higher kernel performance For example, if a task in group
3 must be initiated every 3 hours and it is associated with a sub-clock of 1 hour it will be pooled only every hour
This behaviour can pose some difficulties in specific cases : if an infrequent task of a higher order group is waiting for a semaphore release, its move to the READY queue may be delayed by lower order groups' tasks that are waiting for the same semaphore release
The example below provides a solution to solve this difficulty :
Example 1 :
void ftestvers0 () task _tstvers0_ priority 0 group 3 {
kr_tst (sema0) /*risk of important delay if tasks from group 0 or 1 share this ressource*/
/* use of the resource */
kr_free (sema0) }
Example 2 (adaptation of the previous example)
/* task channel*/
void fchannel() task _channel_ priority 0 group 0 /*group 0*/
{ /*test if task _tstvers1_ is in the WAITING state (here, waiting for a
signal).*/
while (kr_getstatus (_tstvers1_)!=WAITING)
{ kr_del_abs (30);
}
Trang 39KR-51 7 Semaphore
/*at this stage tstvers1 is waiting for a signal*/
kr_test (sema0) /* SEMAPHORE_X set*/
kr_sendsig (_tstvers1_) /* sends signal to ftask_ex*/
end of task channel*/
void ftaskvers1 ()task _tstvers1_ priority 0 group 3
/*adaptation of the task ftaskvers0*/
{
kr_create (_channel_) kr_waitsig /*wait for the signal sent by the task channel*/
/*use of the resource*/
kr_free (sema0) /*release of the semaphore set in the task _channel_)*/
}
7.6 Semaphores and task synchronisation
It is not possible to synchronise a task from a time of origin and to call semaphore facilities To solve this problem you must spawn another task, which will receive a signal from the ‘parent task’
7.7 Resources used
Contrary to the utility services such as MAILBOXES, the semaphore management is performed
internally, which means that for KRXS, KRHS and KRYS versions, the semaphore code will always be loaded with the kernel’s core Other semaphore services such as (kr_tst, kr_tst_tout ) are loaded only
if there are used
Semaphores do not require any RAM resource except for the semaphore bits The semaphore
functionality requires approximately 300 additional bytes of code