Top Banner
When delivery times are more criti- cal than the budget limitations and extra engineering resources are avail- able, the additional development effort may be justified. The simulator may help to get to the final product faster, but at a higher cost. You should also think about whether or not it’s possible to cleanly separate the appli- cation from the hardware access layer. Remember that when exact timings are a main design concern, the real-time aspects of the target are hard to simu- late, so the simulator will not help. Moreover, the embedded application’s complexity is relatively minor compared to the hardware drivers, so the simulator may not be justified. However, when the application is complex and sitting on top of fairly simple hardware, the simulator can be extremely useful. You should also keep in mind that when it’s likely that the software appli- cation will be completed before the hardware delivery date, there is a strong case for simulation. (If only to keep soft- ware engineers from getting bored and, more seriously, to familiarize them with the hardware before it arrives.) In the majority of cases, simula- tion on the host does not mean that target debugging and testing are com- pletely eliminated. Inevitably, the behavior of the target differs from even the most complete simulator. Some amount of target debugging and testing is required, but it may be significantly reduced by simulation. 58 Issue 164 March 2004 CIRCUIT CELLAR ® www.circuitcellar.com In this article, I will describe tech- niques for the software-only simulation of embedded hardware in the Windows/PC environment. Software-only simulation implies an arrangement with which the embedded application, or parts of it, can be compiled and run on the Windows platform (host) talking to the software simulator as opposed to the real hardware. This arrangement doesn’t require any hardware or tools other than a native Windows development toolset such as Microsoft Developer Studio/Visual C++. Importantly, the same source code is compiled and linked for both the host and the target. It’s possible and often neces- sary to simulate more complex aspects of the embedded target such as interrupts and the RTOS layer. However, I will illus- trate the basics of simulating hardware in the Windows environment with an exam- ple of an extremely simple hypothetical target system (see Figure 1). Assuming that the source code of the embedded application is basically the same whether it runs in Windows or the embedded target, the simulation offers several advantages. You have the ability to develop and debug device drivers and the application before the hardware is ready. An extremely powerful test harness can be creat- ed on the host platform, where all code changes and additions can be verified prior to running on the actual target. The harness can be used as a part of software valida- tion. Furthermore, you have the Software-Only Hardware Simulation Simulating embedded hardware in a Windows environment can significantly reduce devel- opment time. In this article, Michael provides techniques for the software-only simulation of embedded hardware. He presents a simple example of an RTOS-less embedded system that uses memory-mapped I/O to access a UART-like peripheral to serially poll a slave device. The simulator is capable of detecting bugs and troublesome design flaws. ability to test conditions that may not be easy to test using the real hardware. In the vast majority of cases, debug- ging tools available on the host are far superior to those offered by cross- development tool vendors. You have access to runtime checkers to detect memory leaks, especially for embed- ded software developed in C++. Lastly, note that where the final system com- prises a number of CPUs/boards, sim- ulation has the additional advantage of simulating each target CPU via a single process on a multitasking host. FIRST THINGS FIRST Before you decide to invest in simu- lation infrastructure, there are a few things to consider. For instance, when the target hardware is complex, the software simulator becomes a fairly major development task. Also, consider the adequacy of the target development tools. This especially applies to debug- gers. The absence, or insufficient capa- bility, of the debugger on the target presents a strong case for simulation. FEATURE ARTICLE by Michael Melkonian Figure 1—There is a parallel between the embedded target and host environment. Equivalent entities are shown on the same level. Application and device drivers Target hardware access layer Hardware Application and device drivers Simulated hardware access layer Simulator Embedded target environment Host environment Copyright Circuit Cellar Inc. Reproduction of this publication in whole or in part without written consent from Circuit Cellar, Inc. is prohibited.
10

Software-Only Hardware Simulationcircuitcellar.com/wp-content/uploads/2015/09/CC164... · Software-Only Hardware Simulation Simulating embedded hardware in a Windows environment can

Aug 07, 2020

Download

Documents

dariahiddleston
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Software-Only Hardware Simulationcircuitcellar.com/wp-content/uploads/2015/09/CC164... · Software-Only Hardware Simulation Simulating embedded hardware in a Windows environment can

When delivery times are more criti-cal than the budget limitations andextra engineering resources are avail-able, the additional developmenteffort may be justified. The simulatormay help to get to the final productfaster, but at a higher cost. You shouldalso think about whether or not it’spossible to cleanly separate the appli-cation from the hardware access layer.

Remember that when exact timingsare a main design concern, the real-timeaspects of the target are hard to simu-late, so the simulator will not help.Moreover, the embedded application’scomplexity is relatively minor comparedto the hardware drivers, so the simulatormay not be justified. However, when theapplication is complex and sitting on topof fairly simple hardware, the simulatorcan be extremely useful.

You should also keep in mind thatwhen it’s likely that the software appli-cation will be completed before thehardware delivery date, there is a strongcase for simulation. (If only to keep soft-ware engineers from getting bored and,

more seriously, to familiarize themwith the hardware before it arrives.)

In the majority of cases, simula-tion on the host does not mean thattarget debugging and testing are com-pletely eliminated. Inevitably, thebehavior of the target differs fromeven the most complete simulator.Some amount of target debuggingand testing is required, but it may besignificantly reduced by simulation.

58 Issue 164 March 2004 CIRCUIT CELLAR® www.circuitcellar.com

In this article, I will describe tech-niques for the software-only simulation ofembedded hardware in the Windows/PCenvironment. Software-only simulationimplies an arrangement with which theembedded application, or parts of it, canbe compiled and run on the Windowsplatform (host) talking to the softwaresimulator as opposed to the real hardware.This arrangement doesn’t require anyhardware or tools other than a nativeWindows development toolset such asMicrosoft Developer Studio/Visual C++.Importantly, the same source code iscompiled and linked for both the host andthe target. It’s possible and often neces-sary to simulate more complex aspects ofthe embedded target such as interruptsand the RTOS layer. However, I will illus-trate the basics of simulating hardware inthe Windows environment with an exam-ple of an extremely simple hypotheticaltarget system (see Figure 1).

Assuming that the source code of theembedded application is basically thesame whether it runs in Windows or theembedded target, the simulation offersseveral advantages. You have theability to develop and debug devicedrivers and the application beforethe hardware is ready. An extremelypowerful test harness can be creat-ed on the host platform, where allcode changes and additions can beverified prior to running on theactual target. The harness can beused as a part of software valida-tion. Furthermore, you have the

Software-Only Hardware SimulationSimulating embedded hardware in a Windows environment can significantly reduce devel-opment time. In this article, Michael provides techniques for the software-only simulation ofembedded hardware. He presents a simple example of an RTOS-less embedded systemthat uses memory-mapped I/O to access a UART-like peripheral to serially poll a slavedevice. The simulator is capable of detecting bugs and troublesome design flaws.

ability to test conditions that may notbe easy to test using the real hardware.

In the vast majority of cases, debug-ging tools available on the host are farsuperior to those offered by cross-development tool vendors. You haveaccess to runtime checkers to detectmemory leaks, especially for embed-ded software developed in C++. Lastly,note that where the final system com-prises a number of CPUs/boards, sim-ulation has the additional advantageof simulating each target CPU via asingle process on a multitasking host.

FIRST THINGS FIRSTBefore you decide to invest in simu-

lation infrastructure, there are a fewthings to consider. For instance, whenthe target hardware is complex, thesoftware simulator becomes a fairlymajor development task. Also, considerthe adequacy of the target developmenttools. This especially applies to debug-gers. The absence, or insufficient capa-bility, of the debugger on the targetpresents a strong case for simulation.

FEATURE ARTICLE by Michael Melkonian

Figure 1—There is a parallel between the embedded target andhost environment. Equivalent entities are shown on the same level.

Application and device drivers

Target hardware accesslayer

Hardware

Application and device drivers

Simulated hardwareaccess layer

Simulator

Embedded target environment Host environment

Copyright Circuit Cellar Inc. Reproduction of this publication in whole or in part without written consent from Circuit Cellar, Inc. is prohibited.

Page 2: Software-Only Hardware Simulationcircuitcellar.com/wp-content/uploads/2015/09/CC164... · Software-Only Hardware Simulation Simulating embedded hardware in a Windows environment can

www.circuitcellar.com CIRCUIT CELLAR® Issue 164 March 2004 59

are several reasons for this. Keep inmind that the same tools (GNU) areoften used for both host and cross-com-pilation. In addition, the target and hostbuilds are typically controlled by thesame GNU make-driven build infrastruc-ture, so you can easily determine whichmodules are included in a build. Also,the projects tend to be larger and run ina more formal fashion.

Telecommunications products areoften composed of a number of boards,which, in the final product, are likelyto talk to each other via a TCP/IPstack. This maps well into the simula-tion platform for the entire system onthe host, where each target CPU can besimulated via a standalone UNIX process.Finally, the target RTOS is often UNIX-inspired or even fully POSIX-compliant.As such, it is neatly mapped into a UNIXlightweight thread library running withinthe same process on the host.

After this fairly neat infrastructureis created, it’s completely natural toextend the ability of the host builds torun as much of the target applicationas possible. This can be achieved bydifferent levels of simulation of thehardware present on the target boards.

PC/WINDOWSWhen the Windows/PC platform is

used for embedded software develop-ment, the situation is completely differ-ent. You will most likely use a propri-etary and hopefully well-featuredtoolset for the project’s microcontroller.The set would typically include an IDEwith a cross compiler/assembler/link-er/locator, a symbolic debugger, and anevaluation board with the target CPU

Another important point is that it maynot be feasible at times to simulate theentire target system. Nevertheless, it stillcan be worthwhile to simulate a part ofthe system. In this case, only some of theembedded target software modules wouldbe included in the host builds.

There is a case for which simulation isparticularly advantageous: when the tar-get has multiple CPUs and interactionbetween the microprocessors is beingdeveloped. For instance, you may bedeveloping software for a system com-prised of similar boards communicatingwith each other over the Ethernet. Everychange in software would require a sepa-rate download to each board. Also, shouldthere be an issue with interboard commu-nications, it would be nearly impossibleto set up and simultaneously debug soft-ware in multiple target boards. This is notto mention the cost of multiple ICE anddebuggers. On the host, however, it issimply a matter of starting as many appli-cations as needed, with each applicationsimulating a single target board.

COMMON TERMSI assume you’ll use a C or C++ devel-

opment environment for this project.The computer running Windows/UNIXis the host. The embedded target isthe target. The term “process” is usedin relation to UNIX processes and

Windows applications. Theterm “thread” refers to bothp-threads on UNIX and theWindows API standardthread library. Although thefirst example is effectively aDOS console application, Istill refer to it (correctly ornot) as running in theWindows operating environ-ment. Perhaps it also shouldbe noted that Visual C++does not generate 16-bitcode (not since the secondversion anyway), so it willnot run on pure DOSmachines. However, it will run quitehappily in a DOS box on Windows.

Before moving on to the actual sim-ulator, let’s take a step back and havea look at why the two main cross-development platforms (UNIX andderivatives versus Windows/PC) havesuch different approaches to the soft-ware simulation of the target hardware.

UNIXIt appears that on the UNIX (and

derivative) cross-development platform,especially in the military and telecom-munications industries, the develop-ment teams are much more likely tospend significant effort on the creationof a proper simulation harness. There

Application and device drivers

Application and device drivers

Application and device drivers

Target hardware access layer

Host handwareaccess layer

Host hardwareaccess layer

EmbeddedRTOS thread

UNIXLightweight

thread

Win32 APIthread

Embedded board CPU

UNIX Process Windows process

Target UNIX Windows

Figure 2—There is a parallel among the embedded target and the UNIXand Windows environments. Again, equivalent entities are shown on thesame level.

Listing 1—Take a look at the declaration and implementation of the simulated and real hardware access layer.

*****************************************************************// Header file#ifdef SIM// Simulatorextern BYTE read_hw_byte(volatile BYTE *addr);extern void write_hw_byte(BYTE data, volatile BYTE *addr);#else// Real target#define read_hw_byte(x) (*(volatile BYTE *)x)#define write_hw_byte(d, x) ((*(volatile BYTE *)x) = (d))#endif

*****************************************************************// Simulator implementation BYTE read_hw_byte(volatile BYTE *addr){

intercept_read(addr);return *addr;

}

void write_hw_byte(BYTE data, volatile BYTE *addr){

*addr = data;intercept_write(addr);

}

Copyright Circuit Cellar Inc. Reproduction of this publication in whole or in part without written consent from Circuit Cellar, Inc. is prohibited.

Page 3: Software-Only Hardware Simulationcircuitcellar.com/wp-content/uploads/2015/09/CC164... · Software-Only Hardware Simulation Simulating embedded hardware in a Windows environment can

60 Issue 164 March 2004 CIRCUIT CELLAR® www.circuitcellar.com

memory space and can communicate onlywith each other via the special means ofinterprocess communication, which isnot unlike the target CPUs/boards.

SOFTWARE DESIGN GUIDENow let’s focus on what makes

embedded software adaptable for sim-ulation. It’s hardly surprising that thefollowing guidelines closely resemblethose for writing portable code.

First, you need a centralized accessmechanism to the hardware (read_hwand write_hw macros). Second, theapplication code and device driver codemust be separated. Third, you must usea thin operating level interface. Finally,avoid using the nonstandard add-onsthat some cross-compilers may provide.

HARDWARE INTERFACE LAYERIn this example, I assume that all the

peripherals are interfaced via memory-mapped I/O, although the techniques Idescribed are equally applicable to port-mapped I/O or a combination of the two.(Obviously, the hardware interfacemacros for the two types of I/O will bedifferent.) Also, for the sake of simplicity,

on it. All of this allows you toget up and running quickly.

Often, only critical parts of theapplication are initially developedin the host environment, andthen the module is ported acrossto the target. (The ability to runthe code under the host is oftenlost after porting.) For instance, ifyour target system features text-driven screens, it would be completelylogical to develop and debug a screenmodule on your desktop and then portit across. This is as far as most projectswould go with host development.

Because of the dissimilarity betweenthe target-specific cross compiler andtoolset and native Windows develop-ment tools, the division between thehost and the target software is muchgreater. That’s why developers rarelybuild into their designs the ability torun embedded applications in Windows.

The other equally important reason isthe perceived fundamental dissimilaritybetween Windows and the embeddedRTOSs and also between their applica-tion interfaces (API). However, Windowsprovides support for threads that can pro-vide an adequate simulation platform foran embedded RTOS. As on the UNIXplatform, it is possible to map theembedded environment in the Windowshost environment as shown in Figure 2.

Note that this is a neat parallel becauseWindows threads share the memory spaceof the parent process. As such, they areideal to represent the target RTOS. Theprocesses in Windows have separate

I assume that all accesses to thehardware are byte-wide. Again,it is clear that all other types ofaccesses (16- and 32-bit) are easyto implement via simple exten-sions of the technique discussed.

The code fragment in Listing 1illustrates the real and simulat-ed hardware interface layer. Thecompile-time preprocessor flag

SIM differentiates the host builds fromthe target builds.

For the application and device driv-ers, any accesses to the hardware mustbe performed via these macros (target)or functions (host). It is no longer per-missible to access the memory-mapped I/O hardware directly via con-structs such as the following:

byte data = *(byte *)addr;

and

*(byte *)addr = data;

Use the following instead:

byte data = read_hw_byte(addr);

and

write_hw_byte(data, addr);

Note that there are no conditional compi-lation statements around any of the hard-ware access lines of code. This meanscleaner and maintainable source code.

The overhead on the target is kept to

H E L L O \0

Master transmission

Slave transmission

H E L L O – E C H O \0

Figure 3—In the half-duplex communications protocol between the mas-ter and slave, the slave transmission starts after the master transmissionis completed.

Project: SimPolledUartLocation: C:\Embedded

Visual Studio creates a SimPolledUart directory for you.Next, close the project and copy the following seven files to

the SimPolledUart directory: Hw.h, Sim_Uart.c, Sim_uart.h,Main.c, EmbTypes.h, Uart.c, and Uart.h. Select Build and SetActive Configuration (this should be set to Debug). Then,select Project, Settings, C/C++, and add flag SIM at the end ofthe Preprocessor Definitions box. This will ensure that theSIM preprocessor flag is defined.

After you select Project, Add To Project, and Files—andafter the file dialog is displayed—select and add all sevensource files to the project. Lastly, press the F5 key. Thiswill compile and run the program without leaving the IDE.

A Visual C++ EnvironmentBefore getting started, you need to install Visual Studio

or .Net software on your PC. Using the downloadableVisual Studio project is straightforward. First, copy theSimPolledUart directory to a suitable location. (A new fold-er in DevStudio/MyProjects is a good idea.) Second, openMicrosoft Developer Studio Version 5 or 6. Next, open theSimPolledUart workspace. Finally, press the F5 key tocompile and run the program without leaving the IDE.

Creating a new project from the provided source codeisn’t too difficult either. Start by opening DeveloperStudio Version 5 or 6. Then, select File, New, andWin 32 Console Application.

In the Project Name and Location sections, select aconvenient location for your project. Use the followingexample as a guide:

Copyright Circuit Cellar Inc. Reproduction of this publication in whole or in part without written consent from Circuit Cellar, Inc. is prohibited.

Page 4: Software-Only Hardware Simulationcircuitcellar.com/wp-content/uploads/2015/09/CC164... · Software-Only Hardware Simulation Simulating embedded hardware in a Windows environment can

www.circuitcellar.com CIRCUIT CELLAR® Issue 164 March 2004 61

a minimum because macros are used (nofunction call). The overhead is notimportant on the host, and each hard-ware access will be translated into afunction call. In the C++ environment,read_hw_byte and write_hw_bytecan be inlined if required.

All of the hardware access is chan-neled via two simple macros/functions.Some advantages are immediately obvi-ous. Let’s say all the memory-mappedI/O is addressable at even addressesonly. By simply adding an ASSERT inthe host version of read_hw_byte andwrite_hw_byte, accesses at oddaddresses are caught easily. Similarly,you could verify that addresses used formemory-mapped I/O accesses are inthe valid range and catch all attemptsto write to an illegal address. If such anillegal access is detected on the host,it is simply a matter of backtrackingto the offending piece of code.

RUNNING WITH VISUAL STUDIOThis project was developed using

Microsoft’s Developer Studio/VisualC++ environment, which is today’smost popular development environ-ment for creating Windows applica-tions. Contrary to popular belief, youdon’t need to be an expert in WindowsAPI, MFC, COM, and the plethora ofother mysterious acronyms to use thisenvironment. In fact, you can still cre-ate a console Hello World applicationin Visual C++ by simply writing:

int main(){printf(�Hello world\n\r�);

}

This console application will compileand run in a DOS box. The first simu-lator also happens to be a consoleapplication.

If you already have Visual Studioinstalled, you can download the sourcecode and Visual C++ project files fromthe Circuit Cellar ftp site, and then loadthem into Visual Studio. Refer to thesidebar for instructions on setting upyour Visual C++ environment. You canuse Visual C++ version 5 or 6. I’m prettysure you can use the .NET environment(it’s backward-compatible with VisualStudio), but I haven’t tried it myself.

HYPOTHETICAL APPThe rest of this article is written in a

way that allows you to follow the topiceven if you don’t have a PC in front ofyou. (This is not to suggest that thisarticle is a good bedtime read.)

The example is extremely simple.The target hardware board has a UART.It acts as a master in a simple communi-cations protocol, where it polls a fairlydumb slave using an ASCII text string,receives the response, and verifies thatit is as expected. The master sends a

string (poll) to the slave, which respondswith the original string and the - echostring appended at the end. The mastermakes sure that the received string isindeed the original string plus - echo.The master software must be developedand verified to work correctly with theslave (see Figure 3).

The uselessness of this application iscompletely understood. Actually, it helpsto illustrate the core techniques ratherthan the application-specific aspects.Moreover, you will see that things can

Copyright Circuit Cellar Inc. Reproduction of this publication in whole or in part without written consent from Circuit Cellar, Inc. is prohibited.

Page 5: Software-Only Hardware Simulationcircuitcellar.com/wp-content/uploads/2015/09/CC164... · Software-Only Hardware Simulation Simulating embedded hardware in a Windows environment can

62 Issue 164 March 2004 CIRCUIT CELLAR® www.circuitcellar.com

ferent than the byte that hasbeen just written to it. (Soundsjust like real hardware!)

CODE STRUCTUREThe hw.h file contains defi-

nitions for I/O-mapped hard-ware access included by thereal target and simulator. Itdeclares hardware accesslayer macros (real target) orfunctions (simulator). All

modules include this header file. The sim_uart.c file is the simulated

UART implementation, and it containsthe source code for the simulator. It isonly included in the simulated/hostenvironment. To emphasize the point,it is fully surrounded by the #ifdef SIMpreprocessor flag. This illustrates thepoint much better than showing someobscure make file listings. The SIM pre-processor flag is defined only on thehost and not on the target. The initial-ization function changes the pointersused to access the real memory mappedhardware to point to simulators ownstorage registers.

The simulator uses the sim_dataarray to buffer the received data andreuses this buffer to transmit theresponse. It remembers the number ofbytes transmitted and received. Itassumes that it can start transmittingwithout waiting for the end of thestring from the master.

The intercept_uart_write func-tion expects a write either to thetransmit register or the status register.A write to any other location in mem-ory-mapped I/O is flagged as an error.After zero is written to the status reg-ister, the status register always hasthe TX_EMPTY bit set. (Remember,this is how the obscure UART is ini-tialized.) The intercept_uart_readfunction makes sure that read is eitherfrom the receive register, or the statusregister, before analyzing the data. Thesim_user_interface function allowsyou to change the string used to pollthe slave. To change the poll string,press any key on the keyboard andenter the string. Pressing the Escapekey followed by the Enter key orCtrl+C will exit the application.

The sim_uart.h file is the simulatedUART header file for the simulator.

go wrong, even in this absurd-ly simple system. A simulatorcan catch early bugs.

For simplicity, only onethread exists. The simulatorand the real application runin the same thread, as doesthe simple user interface.Normally, with real-worldexamples, you would need tocreate a separate thread inwhich the simulator runs.The application and simulator thenbecome completely independent and thetwo interact via three memory-mappedI/O registers, as shown in Figure 4.

Figure 5 is in Real Time/StructuredAnalysis and/or Structured Design(RT/SASD) notation. Threads/process-es are shown with oval shapes. Datastores via parallel lines.

The UART-like interface has threeregisters: a receive register, a transmitregister, and a status register. They are allbyte-wide. The receive register is read-only. The transmit register is write-only.The status register is both read and write.

As on normal UARTs, the receive reg-ister contains data from when the statusregister has RX_FULL bit set. When theTX_EMPTY bit is set in the status regis-ter, the transmit register can accept newdata. Also, I’ll add a twist here by sayingthat writing a zero to the status registerinitializes this hypothetical UART.

Let’s take another look at the hard-ware interface layer and discuss theintercept_read and intercept_writesimulator functions used in the simulat-ed environment (shown in sim_uart.c,which can be downloaded from theCircuit Cellar ftp site). These two func-tions are the only hooks between theapplication and the simulator. There isonly one thread. Calls to the interceptfunctions kick the simulator. This is theonly chance it gets to analyze the addressand data written and read, and do someprocessing. In the case of more complex

and realistic simulators, the simulatorwould run in its own execution threadand would perhaps maintain the datausing a state machine of its own.

In a larger and more realistic systemwhere multiple simulated devicescould coexist, write_hw_byte andread_hw_byte would work outwhich simulator to call for a particu-lar address access detected. For somesimple examples of how this mecha-nism could be implemented, read thecomments in the source code postedon the Circuit Cellar ftp site.

The intercept_read function putsdata produced by the simulator in the reg-ister pointed to by addr, possibly modi-fies its contents, and then returns thecontents of the addr. intercept_readanalyzes the address being read and putsdata in the register according to its inter-nal logic. In this case, it puts the nextcharacter required to send to the master.

In the case of a write access, notethat the write_hw_byte functionwrites data to the register first. Onlythen is intercept_write called.This is so that the simulator is awareof what data is written. The inter-cept_write function is allowed tomodify the data in the register afterthe write action (see Listing 2).

For example, think of a register with acouple of reserved bits that will alwaysread zero no matter what is written tothem. This is illustrated by requiringthat the UART is initialized by first

writing a zero to it. When awrite of zero to the statusregister is detected, the sim-ulator sets the transmittedempty bit, which starts offthe transmissions. In otherwords, immediately after awrite to it, the UART statusregister contains a byte dif-

Mainapplication

SimulatorSimulated hardware registers

Figure 5—Both the main application and UART simulator access thememory-mapped UART registers.

Figure 4—As you look at the interaction between the main target software and thesimulator, note that the target microprocessor interfaces to the UART-like devicevia three registers. The arrows show the direction of read/write access.

Targetmicroprocessor

Receiveregister

Transmitregister

Statusregister

UART-like device

Slave delayed echo generator

RX

TX

Target Simulator

Copyright Circuit Cellar Inc. Reproduction of this publication in whole or in part without written consent from Circuit Cellar, Inc. is prohibited.

Page 6: Software-Only Hardware Simulationcircuitcellar.com/wp-content/uploads/2015/09/CC164... · Software-Only Hardware Simulation Simulating embedded hardware in a Windows environment can

Copyright Circuit Cellar Inc. Reproduction of this publication in whole or in part without written consent from Circuit Cellar, Inc. is prohibited.

Page 7: Software-Only Hardware Simulationcircuitcellar.com/wp-content/uploads/2015/09/CC164... · Software-Only Hardware Simulation Simulating embedded hardware in a Windows environment can

64 Issue 164 March 2004 CIRCUIT CELLAR® www.circuitcellar.com

simulated builds, the simulatorchanges these pointers.

The tx_msg is initialized to containa string with a single character (H). Theprocess_response simply comparesthe reply string with what’s expectedand prints an OK or Error message.

The serial_comms function is builtaround a simple state machine that canbe in one of three states. In the idlestate, the tx_count is initialized. In thetransmitting state, the data is sent byteby byte to the slave (written to the trans-mit register) until the null-terminatorcharacter is sent. When null character issent, the state machine switches to thereceiving state and reads the data fromthe receive register. The driver looks forTX_EMPTY_BIT and RX_FULL_BIT inthe status register when required (as on anormal polled UART driver). The headerfiles are self-explanatory.

Uart.h is the embedded header filefor UART definitions (e.g., register lay-outs). It contains various definitions forUART bit layouts, and also declaresexterns required. This is a part of nor-mal embedded software, and the simu-lator uses it too.

BUG FINDINGVisual Studio has two build modes,

Release and Debug. The SIM flag isdefined for Debug mode builds only,so make sure that you are building thedebug version of the executable.

You build and run the applicationby pressing F5 in Visual C++. You’llget the following output (repeatedmany times because polling repeatscontinuously):

Send: H, Received H- echo

You can change the string sent to theslave by inputting the string followedby <CR>.

Now, I’ll demonstrate how the sim-ulator can catch silly bugs. To do so,I’ll intentionally introduce a few bugsto the code.

Naturally, it is not used by the realUART driver code.

Main.c contains the code entrypoint, initializations, and the foreverloop. It includes the start-up code andis used for both simulated and targetbuilds. As such, it has a few lines ofcode surrounded by #ifdef SIM. Thestructure of this file would be similarto a much larger and a more realisticproject’s main.c file.

The main.c file has three sections inthe file. In the first section, all simula-tors should be initialized first. This sec-tion is surrounded by the #ifdef SIM flag.The second main.c section is followed bycalls to device drivers/thread initializa-tions. A forever loop follows. Add a sin-gle, simulator-specific thread calledsim_user_interface that allows youto add a degree of interactivity to thesimulator. Naturally, the simulators areinitialized first to detect any hardwareaccesses performed during real initializa-tion. Also, note that the amount of codesurrounded by the #ifdef SIM preproces-sor directive will not change, and thestructure of the file remains clear.

The embtypes.h file includes com-mon types and definitions. It containsthe usual collection of typedefs (e.g.,INT and WORD). In addition, it definesan EMB_ASSERT macro, which worksjust as ASSERT, but is named differ-ently to avoid confusion withWindows ASSERT.

Uart.c contains the actual polledUART thread/driver. The initializa-tion of pointers is included so that theapplication doesn’t have an uninitial-ized pointer even if the SIM flag hasn’tbeen defined on the host:

volatile BYTE *uart_rx_reg =(volatile BYTE *)&foo; //TODO

Clearly on the target, it has to be setto point to a hardware specific memo-ry-mapped I/O address. Note that on

Listing 2—Here, you see the hardware write function in a simulated environment. A memory-mapped address is filled with data, and then a simulator function is called.

*addr = data; //Register contains whatever the main code has written to it

intercept_write(addr); //Register contents may have changed

Copyright Circuit Cellar Inc. Reproduction of this publication in whole or in part without written consent from Circuit Cellar, Inc. is prohibited.

Page 8: Software-Only Hardware Simulationcircuitcellar.com/wp-content/uploads/2015/09/CC164... · Software-Only Hardware Simulation Simulating embedded hardware in a Windows environment can

www.circuitcellar.com CIRCUIT CELLAR® Issue 164 March 2004 65

The source code has three high-lighted points for your attention.Search for the word “point” in thecode to locate these highlights.

The first point illustrates thatthe simulator will catch theincorrect sequence of increment-ing the array index. The follow-ing portion of uart.c is correct:

rx_msg[rx_count] =read_hw_byte (uart_rx_reg);

if (rx_msg[rx_count++] == 0)

Now let’s introduce a bug incrementingthe receive counter one step too early:

rx_msg[rx_count++] = read_hw_ byte(uart_rx_reg);

if (rx_msg[rx_count] == 0)

If you recompile and run the program,you get the following output:

Send: H, Received HEMB: Response incorrect,expected H � echo

You’ll quickly realize that there is aflaw in the program because the nullcharacter was erroneously detectedtoo early, which tricked the softwareinto assuming that the slave responsewas complete. Return the source codeto the original bug-free state beforemoving on to the second point in theuart.c file.

The second point shows thatshould you forget to initialize theUART by writing zero to the statusregister, the communications wouldnever start. This is becauseTX_EMPTY_BIT is never set and thetransmission from the master nevercommences.

Comment out the following line in

the file main.c:

write_hw_byte (0, uart_status_reg);

Then, recompile and run. Thereis no output in the window. Thecommunications with the slaveare not running.

Put the initialization line backin and let’s go to the last and mostinteresting point. Refer to thesim_uart.c file. This file shows that asimulator can catch a fairly high level,almost a design level problem. In thisexample, the software design of theactual driver assumed that the com-munications are half duplex. In otherwords, the software assumes that thereception from the slave will startonly after the poll message has beenfully transmitted. This is effectivelyhow the state machine is written.

On the other hand, the design of thesimulator assumes (rightfully) that thecommunications can be full duplex,and it makes sense to start sendingthe response string back without wait-

H E L L O \0

Master transmission

Slave transmission

H E L L O – E C H O \0

Figure 6—Notice the difference between the half-duplex and full-duplex(shown here) communications protocol between the master and slave.The slave transmission starts while the master is still transmitting.

Copyright Circuit Cellar Inc. Reproduction of this publication in whole or in part without written consent from Circuit Cellar, Inc. is prohibited.

Page 9: Software-Only Hardware Simulationcircuitcellar.com/wp-content/uploads/2015/09/CC164... · Software-Only Hardware Simulation Simulating embedded hardware in a Windows environment can

Copyright Circuit Cellar Inc. Reproduction of this publication in whole or in part without written consent from Circuit Cellar, Inc. is prohibited.

Page 10: Software-Only Hardware Simulationcircuitcellar.com/wp-content/uploads/2015/09/CC164... · Software-Only Hardware Simulation Simulating embedded hardware in a Windows environment can

www.circuitcellar.com CIRCUIT CELLAR® Issue 164 March 2004 67

Michael Melkonian studiedElectronics Engineering in Moscowand completed his B.S. in 1988. Forthe past 15 years, he has worked as asoftware engineer. Currently, he is asenior software engineer at ChubbElectronic Security, which is based inSydney, Australia. Michael’s technicalinterests include embedded systemsand communications protocols, aswell as RTOS and GUI development.In his spare time, he enjoys makingcomputer-animated 3-D movies (nomajor hits so far) and watching soccergames. You may contact him [email protected].

PROJECT FILESTo download the source code, goto ftp.circuitcellar.com/pub/Circuit_Cellar/2004/164.

SOURCEVisual StudioMicrosoft Corp.www.microsoft.com

ing for the entire string to arrive first.Indeed, full-duplex arrangementwould be almost twice as efficient onthe bandwidth (see Figure 6).

So, how come you did not see anyerrors? Let’s change the poll string soit has more than one character. In thiscrude console application, you canenter a string at any time in the DOSconsole window followed by<ENTER>. Enter <Hello><CR>.“Hello” is now the string that’s sentto the slave. The output now changesand you get the following output:

Send: Hello, Received o - echoEMB: Response incorrect,expected Hello � echo

The reason you didn’t see errorsbefore is that the slave only startssending its response after it receivesthe first two characters (see Listing 3).

If you think about it, the responseo � echo makes sense because thedriver misses all the characters thatthe slave transmits while the masteris transmitting too. I failed to imple-ment the driver in a full-duplex capa-ble way because in the implementa-tion it can either transmit or receive,but not both. The simulator caughtthe design flaw.

A VIABLE OPTIONIn many cases, simulating the

embedded target hardware on theWindows platform is a viable optionthat significantly reduces develop-ment time. This is especially truewhen the software development hascommenced before the target hard-ware is available, and when the com-plexity of the application is significantand the interface to peripheral hard-ware relatively simple. Being able tocompile and run target code for PCsand Windows offers access to a set ofexcellent debugging and runtime-

checking tools that may not be avail-able on the embedded platform.

Simulators can range from simpleconsole-driven applications (as shownin this article) to complete simulatorsmodeling the real-time behavior of thetarget, interrupts, and target RTOS.Embedded RTOS threads can bemapped into Windows threads. In caseof multiprocessor systems, separateWindows processes (applications) canbe used to model interaction betweenthe target processor/boards.

In this article, I presented a simpleexample of an RTOS-less embeddedsystem that uses memory-mapped I/Oto access a UART-like peripheral thatis used to serially poll a slave device.Even such a simple simulator is capa-ble of detecting both trivial bugs andserious design flaws. I

Listing 3—After the first 2 bytes are received by the simulated UART, it starts “transmitting” by putting char-acters in the receive register and setting the Receiver Full bit in the status register.

if (sim_rx_byte_count > 2){

sim_uart_status_reg |= RX_FULL_BIT;sim_uart_rx_reg = sim_data[sim_tx_byte_count++];

}

Copyright Circuit Cellar Inc. Reproduction of this publication in whole or in part without written consent from Circuit Cellar, Inc. is prohibited.