Chapter 5: Alarms
5.1 Counters
5
Chapter 5
Alarms
Now that the concept of a task has been defined, the services available within the OSEK/VDX API can be expanded. The first API service discussed is alarms, which also includes the con-cept of counters. Unlike other real-time OSs, OSEK/VDX does not have a timer concon-cept;
instead, an alarm is defined that covers the functions of a timer and the unique need of an embedded control system to take an action based on the occurrence of a series of events. This is accomplished by creating a counter object that is incremented whenever an event occurs.
The alarm is triggered when the corresponding counter reaches a preset value. This counter can be a free-running timer, or it can be another type of input, such as a series of pulses from a sensor.
This chapter introduces the concepts of counters and alarms and defines the API services that manage these objects. The OSEK/VDX standards do not currently define an API for counters. Only the API for alarms is defined. Consequently, the counter API can be different for each vendor-specific implementation of the OSEK/VDX OS.
5.1 Counters
A counter is an OS object that keeps track of the number of ticks that have occurred. Some counter-specific constants are defined in the OIL configuration file. Because a standardized API for managing counters does not exist, I strongly advise that all counter manipulation be kept in a separate file to allow portability between implementations or target processors.
52
Chapter 5: AlarmsIn every OSEK/VDX OS implementation, at least one counter must be based on either a hardware or software timer. This counter is used by alarms as a system timer to accomplish the same function as a timer in other real-time OSs. For example, an alarm based on this counter would be used to schedule a periodically executing task.
In the example application, I use the system counter extensively to generate periodic tasks and delays to implement the card game application. In order to demonstrate the use of counters, I have added a special circuit that allows the user to randomize card shuffling. The circuit is shown in Figure 5.1.
Figure 5.1 Shuffling circuit.
In the circuit, I use an output of the MPC555 to generate a frequency output then feed that back into an input that is sampled periodically to determine when a pulse occurs. I will also create a task that samples the input and updates a counter every time a pulse occurs. Ide-ally, this frequency output would be fed back into an input that can generate an interrupt whenever a pulse occurs (I make this modification when I discuss interrupts later in the book). By depressing the switch, the user can determine how long the deck of cards are shuf-fled and thereby generate a random number to be used by the shuffling routine. The portion of the OIL configuration file that defines both the system counter and the shuffling counter is shown in Listing 5.1.
1K ohm
MDA12
MDA11
Counters
53 Listing 5.1 Counter configuration definitions.
Each counter has three standard attributes.
• MAXALLOWEDVALUE This is the maximum value for the counter. When it is reached, the next counter increment is to 0. For example, a sensor on a wheel that sends a pulse every time the wheel turns one degree would have a maximum allowed value of 359 (zero base) if the counter represents the current angle of the wheel.
• TICKSPERBASE This attribute is vaguely defined by the OSEK/VDX standard as being the number of ticks required to reach a counter-specific unit. The standard indicates that the interpretation of this attribute is specific to the implementation. Consequently, you should refer to your implementation documentation for a description of the use of this attribute.
• MINCYCLE This attribute defines the minimum cyclic number of counter ticks allowed for a cyclic alarm. Cyclic alarms are described in the next section.
For the card game example application, the SHUFFLE_COUNTER shuffling counter is defined with a maximum value of 9 and a minimum cycle of 3. In the next section, I use this counter to generate a random number that is used to sort the cards when the application shuffles the deck.
The standard timer counter in OSEKWorks is called SYSTEM_COUNTER and is set up as a free-running 16-bit counter. The minimum number of counts for a cyclic alarm is 1. The name of this timer varies with each implementation, and in some, multiple standard timers might be
/**************************************************************************/
/* Counters */
/**************************************************************************/
COUNTER SHUFFLE_COUNTER {
/*@****************************************************************/
/* Shuffling Counter */
/*@****************************************************************/
MAXALLOWEDVALUE = 9;
TICKSPERBASE = 1;
MINCYCLE = 3;
};
COUNTER SYSTEM_COUNTER {
MAXALLOWEDVALUE = 65535;
TICKSPERBASE = 1000000;
MINCYCLE = 1;
};
54
Chapter 5: Alarmsavailable. In the OSEKWorks implementation, the TICKSPERBASE attribute is not used by the implementation, but it is available for the application to use as required. The OSTICKDURATION system constant, discussed later, is set to this value for the system counter. The TICKSPERBASE attribute is available to the application as a return from an API service that is discussed in the next section. I have chosen the value of TICKSPERBASE for SYSTEM_COUNTER to be 1000000, which corresponds to 1ms (1,000,000ns).
After a counter is defined, a minimum of two routines must be created: an initialization routine and a handler routine. The initialization and handler routines for the standard system counter that is used as a timer are not only specific to each implementation, but also specific to the individual microcontroller. Refer to the implementation documentation for details on how the standard system counter is initialized and handled. Initialization and processing can be provided by the implementation supplier, or the end user might have to supply these func-tions. The initialization routine for the example program is shown in Listing 5.2; the handler task is shown in Listing 5.3. Many of the services included in Listing 5.3 will be discussed throughout this chapter, so do not worry if the task is confusing at this time. These routines are found in shuffle.c on the accompanying CD.
Listing 5.2 Shuffling counter initialization.
I must add InitShuffleSwitch() to the table of initialization functions that are called fromInitSystem(). In this routine, the shuffling counter is initialized to a set value. In the example case, as will typically be the case for most counters, the counter initializes to 0. The OSEKWorks InitCounter() API service allows counters to be initialized to any valid value.
Although this is typical of most OSEK/VDX implementations, because the counter API is not defined, it is not necessary to support this behavior. After initialization, a flag is set to indicate the last state of the input to be used in the sampling routine. Counter initialization should be performed from StartupHook(), and in the example routine, I check this based on the value of the type parameter that is passed by InitSystem().
To handle the counter, I have created an IOSampleShuffleSwitch task that executes peri-odically and samples the input from the switch. The counter is incremented whenever the input makes the transition from low to high. As mentioned earlier, this will eventually be done by an interrupt service routine. The counter is incremented using the IncrCounter() API service, which is also specific to OSEKWorks. Most OSEK/VDX implementations will have a similar function to increment the counter. In addition, many implementations provide a ser-vice that allows the application to query the current value of the counter. In OSEKWorks, this is GetCounterValue(). The rest of the routine is considered later when I discuss alarms in more detail.
void InitShuffleSwitch(InitType type) {
if(type==INIT_STARTUP) {
InitCounter(SHUFFLE_COUNTER,0);
}
ShuffleState = SHUFFLE_LOW;
}
Counters
55
Now that the system has two basic counters and the routines to handle them, you can cre-ate alarms based on these counters.
Listing 5.3 Shuffling counter handler.
TASK(IOSampleShuffleSwitch) {
static UINT8 timeout;
TickType tick;
switch(ShuffleState){
case SHUFFLE_HIGH:
if(HWGetValue(&SHUFFLESWITCH)==INACTIVE){
ShuffleState = SHUFFLE_LOW;
} break;
case SHUFFLE_LOW:
if(HWGetValue(&SHUFFLESWITCH)==ACTIVE){
timeout = SHUFFLE_SWITCH_OFF;
if(GetAlarm(ShuffleAlarm,(TickRefType)tick) == E_OS_NOFUNC){
SetAbsAlarm(ShuffleAlarm,5,3);
strcpy(displayBuffer,"\fSHUFFLING -");
ActivateTask(OutputDisplay);
}
ShuffleState = SHUFFLE_HIGH;
IncrCounter(SHUFFLE_COUNTER);
} else{
if(timeout!=0){
if(--timeout == 0){
CancelAlarm(ShuffleAlarm);
CancelAlarm(SampleShuffleSwitchAlarm);
ActivateTask(ShufflingComplete);
} } }