360 likes | 892 Views
. discuss various architectures for embedded software The most important factor that determines which architecture will be the most appropriate for any given system is how much control you need to have over system response. four architectures: round-robin, round-robin with interrupts, function-que
E N D
1. 5 Survey of Software Architectures
2. discuss various architectures for embedded software
The most important factor that determines which architecture will be the most appropriate for any given system is how much control you need to have over system response.
four architectures: round-robin, round-robin with interrupts, function-queue-scheduling, and real-time operating system.
3. 5.1 Round-Robin The code in Figure 5.1 is the prototype for round-robin, the simplest imaginable architecture.
There are no interrupts. The main loop simply checks each of the I/O devices in turn and services any that need service.
no interrupts, no shared data, no latency concerns
4. Figure 5.1 Round-Robin Architecture void main (void)
{
while (TRUE)
{
if (!! I/O Device A needs service)
{
!! Take care of I/O Device A
!! Handle data to or from I/O Device A
}
if (!! I/O Device B needs service)
{
!! Take care of I/O Device B
!! Handle data to or from I/O Device B
}
etc.
etc.
if (!! I/O Device Z needs service)
{
!! Take care of I/O Device Z
!! Handle data to or from I/O Device Z
}
}
}
5. a digital multimeter A digital multimeter measures electrical resistance, current, and potential in units of ohms, amps, and volts, each in several different ranges.
A typical multimeter has two probes that the user touches to two points on the circuit to be measured, a digital display, and a big rotary switch that selects which measurement to make and in what range.
The system makes continuous measurements and changes the display to reflect the most recent measurement.
Each time around its loop, it checks the position of the rotary switch and then branches to code to make the appropriate measurement, to format its results, and to write the results to the display.
7. Figure 5.3 Code for Digital Multimeter void vDigitalMultiMeterMain (void)
{
enum {OHMS_1, OHMS_10,
VOLTS_100) eSwitchPosition;
while (TRUE)
{
eSwitchPosition = !! Read the position of the switch;
switch (eSwitchPosition) {
case OHMS_1:
!! Read hardware to measure ohms
!! Format result
break;
8. Figure 5.3 Code for Digital Multimeter case OHMS_10:
!! Read hardware to measure ohms
!! Format result
break;
case VOLTS_100:
!! Read hardware to measure volts
!! Format result
break;
}
!! Write result to display
}
}
9. Unfortunately, the round-robin architecture has only one advantage over other architecturessimplicitywhereas it has a number of problems that make it inadequate for many systems:
- If any one device needs response in limited time, the system may don't work.
- Respond slowly like dont work
- This architecture is fragile to change
Because of these shortcomings, a round-robin architecture is probably suitable only for very simple devices
10. 5.2 Round-Robin with Interrupts interrupt routines deal with the very urgent needs of the hardware and then set flags; the main loop polls the flags and does any follow-up processing required by the interrupts.
The interrupt routines can get good response, because the hardware interrupt signal causes the microprocessor to stop whatever it is doing in the main function and execute the interrupt routine instead.
11. Figure 5.4 Round-Robin with Interrupts Architecture BOOL fDeviceA = FALSE;
BOOL fDeviceB = FALSE;
BOOL fDeviceZ = FALSE;
void interrupt vHandleDeviceA (void)
{
!! Take care of I/O Device A
fDeviceA = TRUE;
}
void interrupt vHandleDeviceB (void)
{
!! Take care of I/O Device B
fDeviceB = TRUE;
}
12. Figure 5.4 Round-Robin with Interrupts Architecture void interrupt vHandleDeviceZ (void)
{
!! Take care of I/O Device 1
fDeviceZ = TRUE;
}
void main (void)
{
while (TRUE) {
if (fDeviceA)
{
fDeviceA = FALSE;
!! Handle data to or from I/O Device A
}
13. Figure 5.4 Round-Robin with Interrupts Architecture if (fDeviceB)
{
fDeviceB = FALSE;
!! Handle data to or from I/O Device B
}
if (fDeviceZ)
{
fDeviceZ = FALSE;
!! Handle data to or from I/O Device Z
}
}
}
14. The disadvantage is that fDeviceA, fDeviceB, fDeviceZ, and who knows what other data are shared between the interrupt routines and the task code in main
15. Round-Robin-with-Interrupts Example: A Simple Bridge The round-robin-with-interrupts architecture is suitable for many systems, ranging from the fairly simple to the surprisingly complex.
communications bridge, a device with two ports on it that forwards data traffic received on the first port to the second and vice versa.
Assume the data on one of the ports is encrypted and that it is the job of the bridge to encrypt and decrypt the data as it passes it through.
16. assumptions about the bridge: Whenever a character is received on one end, it causes an interrupt, and that interrupt must be serviced reasonably quickly to read the character out of the I/O hardware before the next character arrives.
After the I/O transmitter hardware sends the character; then it will interrupt to indicate for the next character. microprocessor must write the next character to the I/O hardware.
routines that will read characters from and write characters to queues and test whether a queue is empty or not.
The encryption routine can encrypt characters one at a time, and the decryption routine can decrypt characters one at a time.
17. Figure 5.7 Code for a Simple Bridge executes the interrupt routines vGotCharacterOnLinkA and vGotCharacterOnLinkB whenever the hardware receives a character.
The interrupt routines read the characters from the hardware and put them into the queues qData From LinkA and qDataFromLinkB.
vEncrypt and vDecrypt, which read these queues, encrypt and decrypt the data, and write the data to qDataToLinkA and qDataToLinkB.
main routine polls these queues to see whether there is any data to be sent out.
18. The two variables fLinkAReadyToSend and fLinkBReadyToSend keep track of whether the I/O hardware is ready to send characters on the two communications links.
when the task code writes to the hardware or to these variables, it must disable interrupts to avoid the shared-data problem.
The interrupt routines receive characters and write them to the queues; therefore, that processing will take priority over the process of moving characters among the queues, encrypting and decrypting them, and sending them out.
19. Figure 5.7 Code for a Simple Bridge typedef struct
{
char chQueue[QUEUE_SIZE];
int iHead; /* Place to add next item */
int iTail; /* Place to read next item */
} QUEUE;
static QUEUE qDataFromLinkA;
static QUEUE qDataFromLinkB;
static QUEUE qDataToLinkA;
static QUEUE qDataToLinkB;
static BOOL fLinkAReadyToSend = TRUE;
static BOOL fLinkBReadyToSend = TRUE;
20. Figure 5.7 Code for a Simple Bridge void interrupt vGotCharacterOnLinkA (void) {
char ch;
ch = !! Read character from Communications Link A;
vQueueAdd (&qDataFromLinkA, ch);
}
void interrupt vGotCharacterOnLinkB (void) {
char ch;
ch = !! Read character from Communications Link B;
vQueueAdd (&qDataFromLinkB, ch);
}
void interrupt vSentCharacterOnLinkA (void) {
fLinkAReadyToSend = TRUE;
}
void interrupt vSentCharacterOnLinkB (void) {
fLinkBReadyToSend = TRUE;
}
21. Figure 5.7 Code for a Simple Bridge void main (void)
{
char ch;
/* Initialize the queues */
vQueuelnitialize (&qDataFromLinkA);
vQueuelnitialize (&qDataFromLinkB);
vQueuelnitialize (&qDataToLinkA);
vQueuelnitialize (&qDataToLinkB);
/* Enable the interrupts. */
enable ();
while (TRUE) {
vEncrypt ();
vDecrypt ();
22. Figure 5.7 Code for a Simple Bridge if (fLinkAReadyToSend && fQueueHasData (&qDataToLinkA))
{
ch = chQueueGetData (&qDataToLinkA);
disable ();
!!Send ch to Link A
fLinkAReadyToSend = FALSE;
enable ();
}
if (fLinkBReadyToSend && fQueueHasData (&qDataToLinkB))
{
ch = chQueueGetData (&qDataToLinkB);
disable ();
!!Send ch to Link B
fLinkBReadyToSend = FALSE;
enable ();
}} }
23. Figure 5.7 Code for a Simple Bridge void vEncrypt (void)
{
char chClear;
char chCryptic;
/* While there are characters from port A . . .*/
while (fQueueHasData (&qDataFromLinkA))
{
/* . . . Encrypt them and put them on queue for port B */
chClear = chQueueGetData (&qDataFromLinkA);
chCryptic = !! Do encryption (this code is a deep secret)
vQueueAdd (&qDataToLinkB, chCryptic);
}
}
24. Figure 5.7 Code for a Simple Bridge void vDecrypt (void)
{
char chClear;
char chCryptic;
/* While there are characters from port B . . .*/
while (fQueueHasData (&qDataFromLinkB))
{
/*
Decrypt them and put them on queue for port A */
chCryptic = chQueueGetData (&qDataFromLinkB);
chClear = !! Do decryption (no one understands this code)
vQueueAdd (&qDataToLinkA, chClear);
}
}
25. Round-Robin-with-Interrupts Example: The Cordless Bar-Code Scanner the bar-code scanner is essentially a device that gets the data from the laser that reads the bar codes and sends that data out on the radio.
In this system, as in the bridge, the only real response requirements are to service the hardware quickly enough.
The task code processing will get done quickly enough in a round-robin loop.
26. Characteristics of the Round-Robin-with-Interrupts Architecture round-robin-with-interrupts architecture does not work well include the following ones:
A laser printer. calculating the locations where the black dots go is very time-consuming. a laser printer may have many other processing requirements, it becomes impossible to make sure that the low-priority interrupts are serviced quickly enough.
The underground tank-monitoring system. the code that calculates how much gasoline is in the tanks. To avoid putting all the rest of the code into interrupt routines, a more sophisticated architecture is required for this system as well.
27. 5.3 Function-Queue-Scheduling Architecture In this architecture, the interrupt routines add function pointers to a queue of function pointers for the main function to call.
The main routine just reads pointers from the queue and calls the functions.
It can call them based on any priority scheme that suits your purposes. Any task code functions that need quicker response can be executed earlier.
28. Figure 5.8 Function-Queue-Scheduling Architecture !! Queue of function pointers;
void interrupt vHandleDeviceA (void)
{
!! Take care of I/O Device A
!! Put fundion_A on queue of function pointers
}
void interrupt vHandleDeviceB (void)
{
!! Take care of I/O Device B
!! Put function_B on queue of function pointers
}
29. Figure 5.8 Function-Queue-Scheduling Architecture void main (void) {
while (TRUE)
{
while (!!Queue of function pointers is empty)
!! Call first function on queue
}
}
void function_A (void) {
!! Handle actions required by device A
}
void function_B (void) {
!! Handle actions required by device B
}
30. In this architecture the worst wait for the highest-priority task code function is the length of the longest of the task code functions
This worst case happens if the longest task code function has just started when the interrupt for the highest-priority device occurs.
the response for lower-priority task code functions may get worse
if one of the lower-priority task code functions is quite long, it will affect the response for the higher-priority functions.
31. 5.4 Real-Time Operating System Architecture the interrupt routines take care of the most urgent operations
They then "signal" that there is work for the task code to do.
systems using the real-time-operating-system architecture can control task code response as well as interrupt routine response
the worst-case wait for the highest-priority task code is zero
32. Figure 5.9 Real-Time-Operating-System Architecture void interrupt vHandleDeviceA (void)
{
!! Take care of I/O Device A
!! Set signal X
}
void interrupt vHandleDeviceB (void)
{
!! Take care of I/O Device B
!! Set signal Y
}
33. Figure 5.9 Real-Time-Operating-System Architecture void Task1 (void)
{
while (TRUE)
{
!! Wait for Signal X
!! Handle data to or from I/O Device A
}
}
void Task2 (void)
{
while (TRUE)
{
!! Wait for Signal Y
!! Handle data to or from I/O Device B
}
}
34. The differences between this architecture and the previous ones are that: The necessary signaling between the interrupt routines and the task code is handled by the real-time operating system. not use shared variables for this purpose.
No loop in our code decides what needs to be done next. Code inside the real-time operating system (also not shown in Figure 5.9) decides which of the task code functions should run.
The real-time operating system can suspend one task code subroutine in the middle of its processing in order to run another.
36. In the real-time-operating-system architecture, changes to lower-priority functions do not generally affect the response of higher-priority functions.
The primary disadvantage of the real-time-operating-system architecture is that the real-time operating system itself uses a certain amount of processing time.
37. 5.5 Selecting an Architecture Select the simplest architecture that will meet your response requirements.
If your system has response requirements that might necessitate using a real-time operating system, you should lean toward using a real-time operating system.
If it makes sense for your system, you can create hybrids of the architectures discussed in this chapter.