ADVANCED INDUSTRIAL LEVEL TRAINING IN LINUX BASED EMBEDDED SYSTEMS

ADVANCED INDUSTRIAL LEVEL TRAINING IN LINUX BASED EMBEDDED SYSTEMS
ADMISSIONS OPEN

Search This Blog

Thursday, 4 July 2013

THE CONCEPT OF PORTS


A port can be thought of as a data channel that comes into or goes out of the uC. There can be parallel ports (all data bits present on their own lines) and serial ports (data bits passed serially along one or more lines). A number of types of serial ports will be discussed in later chapters of this tutorial, but for now we'll just talk about GPIO ports. A GPIO port is a set of GPIO pins which are organized into a single N-bit (8/16/32 bit) word, and are thus written out and read in as operations on a single word. A uC can have one or more GPIO ports, and given port may be a full N-bits wide, or a given port may be fewer than N-bits. A shortened port (fewer than N-bits wide) usually exists because the chip designers simply ran out of pins for the extra GPIO bits. For example, a 28-pin, 8-bit microcontroller may dedicate 5 pins to power and GND, and all other pins are available as GPIO. That means 23 GPIO pins, which could be organized as two 8-bit ports and one 7-bit port.
A shortened port will still appear as a full N-bit value to the CPU, it is just that the bit positions that are not brought out to pins are unused, since they can never transmit or receive valid data. and must be ignored. Depending on the CPU design these unused bits may always read as 0s or they may read as undetermined values. The datasheet will give the details, and in any case, the unused bits should be masked out before using the port data.
You will also see this phenomenon of missing or unused bits in configuration registers. It is very common for a configuration register to have unused bits - sometimes a configuration register will only use a single bit in the register! Again, these unused bits may read as 0s or they may be indeterminate. When writing to a configuration register that has unused bits, the datasheet will tell you what values to write to those bits. Usually you are required to write 0s to the unused bits. One reason for this is that unused bit positions may become used in a future version of the device, and writing a 1 to a configuration bit is more likely to enable some feature - some feature you didn't intend, since the bit and the feature didn't even exist when you wrote the software. Just be safe and write the unused bits of any configuration register according to the datasheet. To sum up, mask out unused bits when reading ports or configuration registers, and set unused bits as per the datasheet when writing to ports or configuration registers.
Each GPIO port will have a number of data and configuration registers associated with it. These registers will access data read as inputs, hold data written as outputs, and will allow configuration settings (often for each individual GPIO pin) such as (depending on the device) data direction (input or output), built-in pullup/pulldowns, input hysteresis, output drive strength, and so on. All GPIO register information will be found in the datasheet.

A NOTE ON THE EXAMPLE PROGRAMS


Each tutorial section will include a number of short example programs. The examples will start with the simplest concepts and add some concepts in each succeeding program. Along the way, some comments will be trimmed to try and help keep the visual clutter down and keep the focus on the newer concepts being presented. As an example, comments to the effect that "this bit/port/address needs to be adjusted for your particular hardware" will eventually disappear, because by then you should know that e.g. if I am discussing an LED output on PORTA bit 0 and on your hardware you are using an LED on PORTB bit 7 then you'll make that change accordingly. Or when I mention in the first programs that after a "ret" instruction that you'd better have set up the stack first, after a while that comment and others like it will disappear.

ONES AND ZEROS,HIGHS AND LOWS


As you should already know, a computer program manipulates data in the form of binary digits, 1s and 0s. This data may represent characters, times, temperatures, button pushes, alarm signals, screen pixels, the list is almost endless. But in the computer it's all 1s and 0s. When any computer, and in particular a microcontroller, interfaces with the real world as it must, there must be a translation between these 1s and 0s and external voltages on the device pins. It is enough now to know that externally a 1 will be represented to and from the uC by a high voltage (we'll talk later about how high is high) and a 0 will be represented by a low voltage (again, details will follow). Like every other rule there can be exceptions, but for now just remember 1=high, 0=low. We will try to use "1" and "0" when talking about logical states (the data in the program) and "high" and "low" when talking about signals external to the uC, but we may fuzz up that dividing line now and then.

HOW DOES AN EMBEDDED PROGRAM RUN ??


Before talking much more about embedded programming, this is a good place to give a brief overview of how an embedded program starts up and runs.  Assuming that you have generated a program file and have loaded it into the μC program memory (all steps that we will talk about later), the good stuff happens when you either turn on the device or you push the RESET button.  When the μC comes out of reset it will always go to a particular memory location, as defined by the manufacturer, to begin executing whatever code is found there.  Sometimes this memory location is defined directly, e.g. “upon coming out of reset, program execution begins at program address 0”.  Other times the fixed memory location is a vector, a location that holds the actual address of the beginning of the program, e.g. “upon coming out of reset, the controller will load its program counter with the value found at program address 0xFFFE”.  In the first instance you will have to make sure that your program has loaded at the specified startup address, while in the second instance you will load your program wherever the program memory has been placed in the controller address space, and you will have to make sure that you then load that startup address into the reset address vector.
When an embedded program starts to run, there is usually a fair amount of initialization and housekeeping that must be done before the “meat” of the program begins.  Most of this initialization is something that the average desktop programmer never sees, since it is handled by the computer boot code and operating system.  But in an embedded system, it is just as likely as not that there is no operating system, and all boot code and other startup code must be explicitly provided.  Some very critical hardware may need to be initialized first e.g. hardware that controls memory access times and address maps, as well as system clock hardware.  Then some software initialization may need to happen, such as setting up a stack pointer and perhaps copying data from nonvolatile memory to volatile memory where it can be accessed and perhaps modified.  After that will usually come another round of hardware initialization, setting up any peripheral devices that the system requires, and setting initial output states.  Finally, yet another round of software initialization may occur.
This initialization is usually broken up into two sections, with the first hardware and software initialization steps often being done in what is known as the startup code, and the later hardware and software steps being done in the user program.  This delineation is more distinct in a C program, where the startup code is invisible to the C program, being the code that happens before main() is run, and ending in a jump or call to main() where the “visible” C program begins.  In an assembler program all the initialization steps may be equally visible in the user code, although even then the first steps may reside in a separate startup source file.

WHICH PROGRAMMING LANGUAGE ??


This is a good time to talk about the various programming languages that one can use to write embedded software.  The two languages I will use in this tutorial are C and assembly language.  The first thing I want to point out is that these are not the only two languages available to embedded programmers, and that in many cases other languages may be a better choice.  That being said, both C and assembly language are useful not only for learning about embedded programming, but also for actually doing productive embedded programming.  They are also ubiquitous in that no matter what microcontroller you choose, it will almost certainly have available both an assembler (for converting assembly language code) and a C compiler (for converting C code).  The same is definitely not the case for other languages.  But I would encourage you to consider other languages if you are so inclined and, big IF, if they are available for your device family.
On the subject of assembly language, even if you don’t plan on using assembly language in your embedded programming, I would strongly suggest that you become at least somewhat familiar with the concepts, and with the instruction set of your uC.  The reason for this is that, even if you don’t end up writing any assembly language, you will find yourself at some point needing to examine the output of your compiler and/or your compiler-supplied startup files written or output in assembly language.
Also note that the term "assembly language" will often be shortened, in this tutorial and elsewhere, to "asm" or "ASM."

WHAT ELSE IS REQUIRED FOR THIS TUTORIAL ??

While you could, I suppose, work through this tutorial using just a microcontroller simulator, I strongly recommend that you have either a microcontroller training/development board, or even just a bare μC chip, assorted components and a powered breadboard.  In addition you will need an assembler for your device, and optionally a C compiler that targets your device.  You should have no trouble finding a free assembler for your chip, and you should also be able to find a free C compiler, even if it is a reduced-functionality version of a commercial compiler.  You will also need a method of downloading your programs into your μC.  The details of this download process will depend intimately on the particular μC.
These are the details of the hardware and tools used for each of the processor families:

8051-

keil microvision 4 IDE
flash magic flasher software

PIC-

mplab IDE
PIC kit2 programmer
Mikro c 

ARM-

keil microvision IDE 3 for ARM
HTAG V6.0
Philips flash utility

WHAT MICROCONTROLLER FAMILIES ARE USED IN THIS TUTORIAL ??


To give a good overview of the different “flavors” of microcontrollers available, this tutorial will be written around 2 8-bit family (the 8051 and PIC ) and one 32-bit family (the ARM7TDMI architecture in the form of the NXP LPC2xxx family).  These families were chosen to give a broad picture of the devices and approaches found in the world of microcontrollers.  Most software examples will be written in embedded C for each of these families, as well as in assembly language.

WHAT IS AN "N-BIT CPU/MICROPROCESSOR/MICROCONTROLLER" ??


There is much discussion about what it means to call a device an N-bit processor, but really it’s pretty obvious in most cases.  If the device can perform most of its data manipulation instructions on data words to a maximum of N bits in size, the device is an N-bit processor.  By way of example, a device may have a full set of instructions that can operate on 8 bit data, along with a few instructions that operate on 16 bit data.  That device should be considered an 8-bit design, even if the marketing department says otherwise and calls it a 16-bit chip.
By volume, 8-bit microcontrollers are the biggest segment of the embedded market.  Many applications simply don’t need any more power, and never will.  16-bit devices are more powerful, but they are squeezed between the 8-bit devices on the low end and the 32-bit devices on the high end.  32-bit devices are at the high end of the embedded spectrum for all but the most complex or high-performance designs, but they are moving ever downward in price.

DIFFERENCE BETWEEN MICROCOMPUTER,MICROPROCESSOR AND MICROCONTROLLER


A microprocessor is usually understood to be a single-chip central processing unit (CPU), with the CPU being the "brains" of a computer.  A microcomputer is any computer built around a microprocessor, along with program and data memory, and I/O devices and other peripherals as needed.  A microcontroller (often shortened to “μC” in this tutorial) is a single chip device which has on board not only a microprocessor but also, on the same chip, nonvolatile program (ROM) and volatile data (RAM) memory, along with useful peripherals such as general-purpose I/O (GPIO), timers and serial communications channels.  Thus it follows that all microcontrollers are microcomputers, but not all microcomputers use microcontrollers.
In smaller embedded systems it is most common to use microcontrollers since they give the most compact design and the lowest hardware cost.  Larger embedded systems, on the other hand, may use one or more microprocessors if a microcontroller of suitable speed and functionality cannot be found.  It is also possible to include both microprocessors and microcontrollers in a complex embedded system.  The only rules are, use whatever device(s) fit the task, given the constraints on budget, availability, time, tools, etc.
It should also be pointed out that with most microcontrollers it is possible to add external memory and peripherals, should the on-board mix not take care of all the system needs. When it makes sense to add such external devices, as opposed to choosing a larger microcontroller with the needed resources on-board, is a choice that needs to be made on an individual design basis.

WHAT IS DIFFERENT ABOUT EMBEDDED PROGRAMMING ??


Embedded programs must work closely with the specialized components and custom circuitry that makes up the hardware.  Unlike programming on top of a full-function operating system, where the hardware details are removed as much as possible from the programmer’s notice and control, most embedded programming acts directly with and on the hardware.  This includes not only the hardware of the CPU, but also the hardware which makes up all the peripherals (both on-chip and off-chip) of the system.  Thus an embedded programmer must have a good knowledge of hardware, at least as it pertains to writing software that correctly interfaces with and manipulates that hardware.  This knowledge will often extend to specifying key components of the hardware (microcontroller, memory devices, I/O devices, etc), and in smaller organizations will often go as far as designing and laying out (as a printed circuit board) the hardware.  An embedded programmer will also need to have a good understanding of debugging equipment such as multimeters, oscilloscopes, logic analysers and the like.
Another difference from more general purpose computers is that most (but not all) embedded systems are quite limited as compared to the former.  The microcomputers used in embedded systems may have program memory sizes of a few thousand to a few hundred thousand bytes rather than the gigabytes in the desktop machine, and will typically have even less data (RAM) memory than program memory.  Further, the processors used will often be smaller 8 and 16 bit devices as opposed to the 32 bit and larger devices found in a desktop (although small 32-bit microcontrollers are now under a dollar in moderate quantities, which is amazingly amazing).

INTRODUCTION TO EMBEDDED PROGRAMMING


Embedded programming is the term for the computer programming that lives in and operates the great many computer-controlled devices that surround us in our homes, cars, workplaces and communities.  For every desktop or notebook computer you have, you may have a dozen or more (perhaps a great deal more) microcontrollers quietly doing their embedded duty, and in these devices most people don’t even realize there’s a computer running a program.  But there is, and it is, and those programs had to be written, and that’s why the world needs embedded programming.  Embedded computers (microcontrollers) add intelligence to countless devices and systems, enabling those devices and systems to operate better, faster, more safely, more efficiently, more conveniently, more usefully, and in many cases allowing the very existence of devices and systems that could not be built otherwise.  Spend some time looking around you and trying to perceive where microcontrollers are working, and you will begin to get a sense of how ubiquitous they have become since their invention some 40 years ago.
On top of all that, many people, myself included, find embedded programming a particularly fascinating and rewarding branch of the programming tree, and we just like to program embedded systems.  In ways very different from desktop or mainframe programming, embedded programs make stuff do stuff, and to an embedded programmer, stuff doing stuff is endlessly cool.  If you’re a relative newcomer to embedded programming and want to learn more about the subject, then please read along.  I hope you’ll find some of the information you seek here.

INTRODUCTION TO EMBEDDED SYSTEMS

 Embedded system is one that uses one or more microcomputers (that is, small to very, very small computers), running custom programs and connected to specialized hardware, to perform a dedicated set of functions.  This can be contrasted with a general-purpose computer such as the familiar desktop or notebook, which are not designed to run only one dedicated program with one specialized set of hardware.  It’s not a perfect definition, but it’s a start. 
Some examples of embedded systems are:
  1. Alarm / security system
  2. Automobile cruise control
  3. Heating / air conditioning thermostat
  4. Microwave oven
  5. Anti-skid braking controller
  6. Traffic light controller
  7. Vending machine
  8. Gas pump
  9. Handheld Sudoku game
  10. Irrigation system controller
  11. Singing wall fish (or this gift season’s equivalent)
  12. Mars Rover

For the most part I have listed example embedded applications on the less-complex end of the spectrum, since this is after all a beginning tutorial.  By the end of this tutorial you should have a good idea how most of these applications would be programmed, and in general terms what kinds of I/O, timing, interrupt and communications hardware and functionality they would require. 
There are a few things worth noticing about the above list.  While many embedded systems use fairly traditional user input-output devices (keypads, displays), many others do not.  Also, many embedded systems interact directly with human beings, but others do not (we’re still waiting to see if the Mars Rover interacts directly with Martians)