1. Trang chủ
  2. » Công Nghệ Thông Tin

Embedded Software phần 2 docx

79 211 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 79
Dung lượng 1,6 MB

Nội dung

Elsevier US Ch01-H8583 21-7-2007 11:51a.m. Page:58 Trimsize:7.5×9.25in Fonts:Times & Legacy Sans Margins:Top:48pt Gutter:60pt Font Size:11/14 Text Width:34.6pc Depth:37 Lines 58 Chapter 1 Therefore, while the GOTO is not a statement that should be used lightly, it is a statement that will be needed for certain fault recovery programming. The CALL and RETURN are more acceptable to mainstream programming, as they are the means of creating subroutines. When a section of programming is used in multiple places in the program, it is a more efficient use of program memory to build a small separate routine and access it through CALL and RETURN statements. Although the CALL and RETURN statements are useful, their use should be tempered with the knowledge that each CALL will place two or more bytes of data onto a data structure called the STACK. The purpose of the STACK is to store temporary values that don’t have a specific storage location, such as the return address of a CALL. The issue with using the STACK is that: 1. Data memory is often limited with small microcontrollers, and any function that increases data memory usage runs the risk of overwriting an existing variable. 2. The number of locations within the STACK is sometimes limited in small microcontrollers, and unnecessary calls may result in the loss of the oldest return address stored there. 3. Interrupt functions also use the STACK to store return addresses, making it difficult to gauge the exact number of locations in use at any given time. Therefore, limiting the number of subroutines built into a program is only prudent. One of the reasons often given for including a large number of subroutines in a program is the ability of subroutines to compress functionality, making the program more readable to anyone following the designer. If the purpose of a subroutine is to alleviate complexity in the listing, then subroutines can still be used, they just have to include the INLINE statement in front of the CALL. What the INLINE statement does is force the language compiler to disregard the CALL/RETURN statements and compile the routines from the subroutine in line with the routines calling the subroutine. In this way, the readability enhancement of the subroutine is still achieved, while eliminating the impact on the amount of data memory available in the STACK. However, it should be noted that the use of the INLINE instruction is not a common practice. Typically, a macro performs the same function and is a more commonly used construct. So, for compatibility and general form, the INLINE statement should only be used if the designer is comfortable with its use and is aware of any impact its use might have on the resulting code. www.newnespress.com Elsevier US Ch01-H8583 21-7-2007 11:51a.m. Page:59 Trimsize:7.5×9.25in Fonts:Times & Legacy Sans Margins:Top:48pt Gutter:60pt Font Size:11/14 Text Width:34.6pc Depth:37 Lines Basic Embedded Programming Concepts 59 1.7 State Machines Control systems that manage electrical or mechanical systems must often be able to generate, or respond to, sequential events in the system. This ability to use time as part of the driver equation is in fact one of the important abilities of a microcontroller that makes it such a good control for electrical and mechanical systems. However, implementing multiple sequences can become long and involved if a linear coding style is used. A simple construct, called a state machine, simplifies the task of generating a sequence by breaking the sequence into a series of steps and then executing them sequentially. While this sounds like an arbitrary definition of a linear piece of code, the difference is that the individual sections, or steps in the sequence, are encoded within a SWITCH/CASE statement. This breaks the sequence into logical units that can be easily recognized in the software listing and, more importantly, it allows other functions to be performed between the individual steps. It does this by only executing one step each time it is called. Repeatedly calling the state machine results in the execution of each step in the sequence. To retain the state machine’s place in the sequence, a storage variable is defined that determines which step in the sequence is to be executed next. This variable is referred to as the state variable, and it is used in the SWITCH/CASE statement to determine which step, or state, in the state machine is to be executed when the state machine is called. For this system to work, the state variable must be incremented at the completion of each state. However, it is also true that the sequence of states may need to change due to changes in the condition of the system. Given that the state variable determines which state is executed, it follows that to change the sequence of states, one must simply load the state variable with a new value corresponding with the new direction the sequence must go. As we will see in this book, this simple construct is very powerful, and is in fact the basis for multitasking. Therefore, the short definition of a state machine is a collection of steps (states) selected for execution based on the value in a state variable. Further, manipulation of the value in the state variable allows the state machine to emulate all the conditional statements previously presented in this chapter. One of the advantages of the state machine-based design is that it allows the easy generation of a sequence of events. Another advantage of state machine-based design is its ability to recognize a sequence of events. It does this by utilizing the conditional change of the state variable, much as described in the previous paragraph. The only difference is that the state variable does not normally change its value, unless a specific event is www.newnespress.com Elsevier US Ch01-H8583 21-7-2007 11:51a.m. Page:60 Trimsize:7.5×9.25in Fonts:Times & Legacy Sans Margins:Top:48pt Gutter:60pt Font Size:11/14 Text Width:34.6pc Depth:37 Lines 60 Chapter 1 detected. As an analogy, consider a combination lock: to open the lock, the numbers have to be entered in a specific sequence such as 5, 8, 3, 2. If the numbers were entered 2, 3, 5, 8, the lock would not open, so the combination is not only the numbers but their order. If we were to create a state machine to recognize this sequence, it would look something like the following: Code Snippet 1.16 State = 0; SWITCH (State) { CASE 0: IF (in_key()==5) THEN state = 1; Break; CASE 1: IF (in_key()==8) THEN State = 2; Else State = 0; Break; CASE 2: IF (in_key()==3) THEN State = 3; Else State = 0; Break; CASE 3: IF (in_key()==2) THEN UNLOCK(); Else State = 0; Break; } Provided that the values returned by in_key() are in the order of 8, 5, 3, 2, the state variable will step from 0 to 3 and the function UNLOCK() will be called. The state variable is only loaded with the value of the next state when the right value is received in the right state. If any of the values are out of sequence, even though they may be valid for another state, the state variable will reset to 0, and the state machine will start over. In this way, the state machine will step through its sequence only if the values are received in the same sequence as the states in the state machine are designed to accept. Therefore, state machines can be programmed to recognize a sequence of events, and they can be programmed to generate a sequence of events. Both rely on the history of the previous states and the programmable nature of the state-to-state transitions. Implementing a state machine is just a matter of: 1. Creating a state variable. 2. Defining a series of states. www.newnespress.com Elsevier US Ch01-H8583 21-7-2007 11:51a.m. Page:61 Trimsize:7.5×9.25in Fonts:Times & Legacy Sans Margins:Top:48pt Gutter:60pt Font Size:11/14 Text Width:34.6pc Depth:37 Lines Basic Embedded Programming Concepts 61 3. Decoding the state variable to access the states. 4. Tying actions to the states. 5. Defining the sequence of the states, and any conditions that change the sequence. For example, consider a state machine designed to make peanut and jelly sandwiches. The sequence of events is: 1. Get two slices of bread. 2. Open peanut butter jar. 3. Scoop out peanut butter. 4. Smear on first slice of bread. 5. Open jelly jar. 6. Scoop out jelly. 7. Smear on second slice of bread. 8. Invert second slice of bread. 9. Put second slice on first slice of bread. 10. Eat. OK, the first thing to do is create a state variable; let’s call it PBJ. It has a range of values from 1 to 10, and it probably defines as a CHAR. Next, we have to define the sequence of steps in the process, and create a means to decode the state variable. If we take each of these instructions and build them into a CASE statement to handle decoding the state variable, then all it needs is the appropriate updates to the state variable and the state machine is complete. www.newnespress.com Elsevier US Ch01-H8583 21-7-2007 11:51a.m. Page:62 Trimsize:7.5×9.25in Fonts:Times & Legacy Sans Margins:Top:48pt Gutter:60pt Font Size:11/14 Text Width:34.6pc Depth:37 Lines 62 Chapter 1 Algorithm 1.3 SWITCH(PBJ) { case 1: Get two slices. PBJ = 2 break case 2: Open peanut butter jar. PBJ = 3 break case 3: Scoop out peanut butter. PBJ = 4 break case 4: Smear on first slice of bread. PBJ = 5 break case 5: Open jelly jar. PBJ = 6 break case 6: Scoop out jelly. PBJ = 7 break case 7: Smear on second slice of bread. PBJ = 8 break case 8: Invert second slice of bread. PBJ = 9 break case 9: Put second slice on first slice of bread. PBJ = 10 break case 10: Eat break Default: break } www.newnespress.com Elsevier US Ch01-H8583 21-7-2007 11:51a.m. Page:63 Trimsize:7.5×9.25in Fonts:Times & Legacy Sans Margins:Top:48pt Gutter:60pt Font Size:11/14 Text Width:34.6pc Depth:37 Lines Basic Embedded Programming Concepts 63 The calling routine then simply calls the subroutine 10 times and the result is an eaten peanut butter and jelly sandwich. Why go to all this trouble? Wouldn’t it be simpler and easier to just write it as one long function? Well, yes, the routine could be done as one long sequence with the appropriate delays and timing. But this format has a couple of limitations. One, making a PB and J sandwich would be all the microcontroller could do during the process. And, two, making one kind of a PB and J sandwich would be all the routine would be capable of doing. There is an important distinction in those two sentences; the first states that the microcontroller would only be able to perform one task, no multitasking, and the second states that all the program would be capable of would be one specific kind of PB and J sandwich, no variations. Breaking the sequence up into a state machine means we can put other functions between the calls to the state machine. The other calls could cover housekeeping details, such as monitoring a serial port, checking a timer, or polling a keyboard. Breaking the sequence up into a state machine also means we can use the same routine to make a peanut butter only sandwich simply by loading the state variable with state 8, instead of state 5 at the end of state 4. In fact, if we include other steps such as pouring milk and getting a cookie, and include some additional conditional state variable changes, we now have a routine that can make several different varieties of snacks, not just a PB and J sandwich. The power of the state machine construct is not limited to just variations of a sequence. By controlling its own state variable, the state machine can become a form of specialized virtual microcontroller—basically a small, software-based controller with a programmable instruction set. In fact, the power and flexibility of the state machine will be the basis for the multitasking system described later in the book. Before we dive into some of the more advanced concepts, it is important to understand some of the basics of state machine operation. The best place to start is with the three basic types of state machines: execution-indexed, data-indexed, and the hybrid state machine. The execution-indexed state machine is the type of state machine that most people envision when they talk about a state machine, and it is the type of state machine shown in the previous examples. It has a CASE statement structure with routine for each CASE, and a state variable that controls which state is executed when the state machine is called. A good example of an execution-indexed state machine is the PB&J state machine in the previous example. The function performed by the state machine is specified by the value held in the state variable. www.newnespress.com Elsevier US Ch01-H8583 21-7-2007 11:51a.m. Page:64 Trimsize:7.5×9.25in Fonts:Times & Legacy Sans Margins:Top:48pt Gutter:60pt Font Size:11/14 Text Width:34.6pc Depth:37 Lines 64 Chapter 1 The other extreme is the data-indexed state machine. It is probably the least recognized form of a state machine, even though most designers have created several, because it doesn’t use a SWITCH/CASE statement. Rather, it uses an array variable with the state variable providing the index into the array. The concept behind a data-indexed state machine is that the sequence of instructions remains constant, and the data that is acted upon is controlled by the state variable. A hybrid state machine combines aspects of both the data-indexed and the execution- indexed to create a state machine with the ability to vary both its execution and the data it operates on. This hybrid approach allows the varied execution of the execution indexed with the variable data aspect of the data-indexed state machine. We have three different formats, with different advantages and disadvantages. Execution indexed allows designers to vary the actions taken in each state, and/or respond to external sequences of events. Data indexed allows designers to vary the data acted upon in each state, but keep the execution constant. And, finally, the hybrid combines both to create a more efficient state machine that requires both the varied execution of the execution-indexed and the indexed data capability of the data-indexed state machine. Let’s take a closer look at the three types and their capabilities. 1.7.1 Data-Indexed State Machines Consider a system that uses an analog-to-digital converter, or ADC, to monitor multiple sensors. Each sensor has its own channel into the ADC, its own calibration offset/scaling factors, and its own limits. To implement these functions using a data-indexed state machine, we start by assigning a state to each input and creating an array-based storage for all the values that will be required. Starting with the data storage, the system will need storage for the following: 1. Calibration offset and scaling values. 2. Upper and lower limit values. 3. The final, calibrated values. Using a two-dimensional array, we can store the values in the following format. Assume that S_var is the state value associated with a specific ADC channel: www.newnespress.com Elsevier US Ch01-H8583 21-7-2007 11:51a.m. Page:65 Trimsize:7.5×9.25in Fonts:Times & Legacy Sans Margins:Top:48pt Gutter:60pt Font Size:11/14 Text Width:34.6pc Depth:37 Lines Basic Embedded Programming Concepts 65 • ADC_Data[0][S_var] variable in the array holding the calibration offset values • ADC_Data[1][S_var] variable in the array holding the calibration scaling values • ADC_Data[2][S_var] variable in the array holding the upper limit values • ADC_Data[3][S_var] variable in the array holding the lower limit values • ADC_Data[4][S_var] variable in the array holding the ADC channel select command value • ADC_Data[5][S_var] variable in the array holding the calibrated final values The actual code to implement the state machine will look like the following: Code Snippet 1.17 Void ADC(char S_var, boolean alarm) { ADC_Data[4][S_var] = (ADC*ADC_Data[1][S_ var])+ADC_Data[0][S_var]; IF (ADC_Data[4][S_var]>ADC_Data[2][S_var]) THEN Alarm = true; IF (ADC_Data[4][S_var]<ADC_Data[3][S_var]) THEN Alarm = true; S_var++; IF (S_var > max_channel) then S_var = 0; ADC_control = ADC_Data[5][S_var]; ADC_convert_start = true; } In the example, the first line converts the raw data value held in ADC into a calibrated value by multiplying the scaling factor and adding in the offset. The result is stored into the ADC_Data array. Lines 2 and 3 perform limit testing against the upper and lower limits store in the ADC_Data array and set the error variable if there is a problem. Next, the state variable S_var is incremented, tested against the maximum number of channels to be polled, and wrapped around if it has incremented beyond the end. Finally, the configuration data www.newnespress.com Elsevier US Ch01-H8583 21-7-2007 11:51a.m. Page:66 Trimsize:7.5×9.25in Fonts:Times & Legacy Sans Margins:Top:48pt Gutter:60pt Font Size:11/14 Text Width:34.6pc Depth:37 Lines 66 Chapter 1 selecting the next channel is loaded into the ADC control register and the conversion is initiated—a total of seven lines of code to scan as many ADC channels as the system needs, including both individual calibration and range checking. From the example, it seems that data-indexed state machines are fairly simple constructs, so how do they justify the lofty name of state machine? Simple, by exhibiting the ability to change its operation based on internal and external influences. Consider a variation on the previous example. If we add another variable to the data array and place the next state information into that variable, we now have a state machine that can be reprogrammed “on the fly” to change its sequence of conversions based on external input. • ADC_Data[6] [S_var] variable in the array holding the next channel to convert Code Snippet 1.18 Void ADC(char S_var, boolean alarm) { ADC_Data[4][S_var] = (ADC*ADC_Data[1][S_ var])+ADC_Data[0][S_var]; IF (ADC_Data[4][S_var]>ADC_Data[2][S_var]) THEN Alarm = true; IF (ADC_Data[4][S_var]<ADC_Data[3][S_var]) THEN Alarm = true; S_var = ADC_Data[6][S_var]; ADC_control = ADC_Data[5][S_var]; ADC_convert_start = true; } Now the sequence of channels is controlled by the array ADC_Data. If the system does not require data from a specific channel, it just reprograms the array to route the state machine around the unneeded channel. The state machine could also be built with two or more next channels, with the actual next channel determined by whether a fault has occurred, or an external flag is set, or a value reported by one of the channels has been exceeded. Don’t let the simplicity of the state machine deceive you; there is power and flexibility in the data-indexed state machine. All that is required is the imagination to look beyond the simplicity and see the possibilities. www.newnespress.com Elsevier US Ch01-H8583 21-7-2007 11:51a.m. Page:67 Trimsize:7.5×9.25in Fonts:Times & Legacy Sans Margins:Top:48pt Gutter:60pt Font Size:11/14 Text Width:34.6pc Depth:37 Lines Basic Embedded Programming Concepts 67 1.7.2 Execution-Indexed State Machines Execution-indexed state machines, as described previously, are often mistakenly assumed to be little more than a CASE statement with the appropriate routines inserted for the individual states. While the CASE statement, or an equivalent machine language construct, is at the heart of an execution-based state machine, there is a lot more to their design and a lot more to their capabilities. For instance, the capability to control its own state variable lends itself to a wide variety of capabilities that rival normal linear coding. By selectively incrementing or loading the state variable, individual states within the state machine can implement: • Sequential execution. • Computed GOTO instructions. • DO/WHILE instructions. • WHILE/DO instructions. • FOR/NEXT instructions. • And even GOSUB/RETURN instructions. Let’s run through some examples to demonstrate some of the capabilities of the execution-indexed state machine type. First of all, to implement a sequence of state steps, it is simply a matter of assigning the value associated with the next state in the sequence, at the end of each state. For example: Code Snippet 1.19 SWITCH(State_var) { CASE 0: State_var = 1; Break; CASE 1: State_var = 2; Break; CASE 2: State_var = 3; Break; } www.newnespress.com [...]... RS- 422 D-15 Localtalk T1/E1 Line 8, 16, or 32- bit Boot ROM Glue Power PC Core DRAM SIMM 16 or 32- bits SCC2 T1/E1 Transceiver 32- bit RISC Memory Cntrlr TDM-A SCC3 Time SCC4 ISDN-Basic or Primary Slot SMC1 Assigner S/T/U S/T/U TDM-B Transevr IDMA 1 IDMA 2 RS -23 2 Local SMC2 Terminal PCMCIA Serial EEPROM MCM2814 SPI Qspan-860 Peripheral 1 Peripheral 2 Buffers I2C PCI Bus Port A Port B Peripheral Figure 2. 3a:... Figure 2. 7a: Motorola/Freescale MPC860 Interrupt Controllers Source: Copyright of Freescale Semiconductor, Inc 20 04 Used by permission 16 µsec M3 726 7M8 Interrupt Input Pins INT1 INT2 Control Unit 32 µsec RE1 8-bit Binary up Counter RE2 Ports (P4) INT2 INT1 Interrupt Interval Determination Register RE2 Selection Gate: Connected to black colored portion at rest Data Bus Figure 2. 7b: Mitsubishi M3 726 7M8... For example: Code Snippet 1 .26 CASE 3: Counter = 6; State_var = 20 ; Back_var = 4 Break; | | | | CASE 12: Counter = 10; State_var = 20 ; Back_var = 13 Break; | | | | CASE 20 : IF (Counter == 0) THEN State_var = Back_var; Counter = Counter – 1; Break; www.newnespress.com 72 Chapter 1 In the example, states 3 and 12 are calling states and state 20 is the subroutine Both 3 and 12 loaded the delay counter... Source: Copyright of Freescale Semiconductor, Inc 20 04 Used by permission Application Software Layer System Software Layer Ethernet (SCCI) RS -23 2 (SMC2) PCMCIA DMA (IDMA) T1/E1 (TDM) I2C ISDN (TDM) I/O MMU L1 Cache Buses Interrupts Memory Timers Other Hardware Layer Generic (Architecture and Board Specific Driver) Architecture Specific Device Drivers Figure 2. 3b: MPC860 Architecture Specific Device Driver... middleware, and application layers Application Software Layer Application Software Layer Application Software Layer System Software Layer System Software Layer System Software Layer Middleware Layer Operating System Layer Device Driver Layer Device Driver Layer Device Driver Layer Hardware Layer Hardware Layer Hardware Layer Figure 2. 1: Embedded Systems Model and Device Drivers The types of hardware components... driver All embedded systems that require software have, at the very least, device driver software in their system software layer Device drivers are the software libraries that initialize the hardware, and manage access to the hardware by higher layers of software Device drivers are the liaison between the hardware and the operating system, middleware, and application layers Application Software Layer... remaining major components of the board, including board buses (I2C, PCI, PCMCIA, and so on), off-chip memory (controllers, level -2+ cache, Flash, and so on), and off-chip I/O (Ethernet, RS -23 2, display, mouse, and so on) www.newnespress.com Device Drivers 87 Figure 2. 3a shows a hardware block diagram of a MPC860-based board, and Figure 2. 3b shows a systems diagram that includes examples of both MPC860... allowing other software to enable hardware on-the-fly • Hardware Acquire, allowing other software to gain singular (locking) access to hardware • Hardware Release, allowing other software to free (unlock) hardware • Hardware Read, allowing other software to read data from hardware • Hardware Write, allowing other software to write data to hardware • Hardware Install, allowing other software to install... on) both at the board and master CPU level Embedded System Board Controls Usage and Manipulation of Data Master Processor 5 System Components Commonly Connected Via Buses Data from CPU or Input Devices Stored in Memory until a CPU or Output Device Request Brings Data into the Embedded System Memory Input Output Sends Data out of the Embedded System Figure 2. 2: Embedded System Board Organization Source:... www.newnespress.com Basic Embedded Programming Concepts 83 Reset Setup Ports & Variables Put Outputs Get Inputs Task 1 Priority Manager Task 2 Task 3 Yes Timeout No Figure 1 .2: State Machine Multitasking of individual states within the state machine do not affect the overall timing of the system • The system does not require any third-party software to implement, so no license fees or specialized software are required . Elsevier US Ch01-H8583 21 -7 -20 07 11:51a.m. Page: 62 Trimsize:7.5×9 .25 in Fonts:Times & Legacy Sans Margins:Top:48pt Gutter:60pt Font Size:11/14 Text Width:34.6pc Depth:37 Lines 62 Chapter 1 Algorithm. Break; CASE 1: State_var = 2; Break; CASE 2: State_var = 3; Break; } www.newnespress.com Elsevier US Ch01-H8583 21 -7 -20 07 11:51a.m. Page:68 Trimsize:7.5×9 .25 in Fonts:Times & Legacy. example: Code Snippet 1 .26 CASE 3: Counter = 6; State_var = 20 ; Back_var = 4 Break; | | | | CASE 12: Counter = 10; State_var = 20 ; Back_var = 13 Break; | | | | CASE 20 : IF (Counter ==

Ngày đăng: 12/08/2014, 16:21

TỪ KHÓA LIÊN QUAN