Showing posts with label embedded software. Show all posts
Showing posts with label embedded software. Show all posts

Saturday, 29 October 2016

Constructing Structures at Compile-time in C

In embedded software, it's common to need to pass board-specific configuration data to a function.

In such cases, it's tempting to declare a set of const's (typically structures) to hold all the configuration values .

The downside of this approach is that memory is precious in embedded; d
efining lots of constants, not all of which may be used, is undesirable.

To give a concrete example


Suppose we're writing a library function to start-up a microprocessor's analog-to-digital converter:


fStartADC( pConfigData );

Here pConfigData is a pointer to a C-Structure containing configuration data for the ADC (for example the pin on the board you want the ADC to connect to).

If there are seven (say) possible ADC configurations, its tempting to declare a set of const. structures CONFIG0 ... CONFIG6, for users of your library function.

Should a user only make use of (say) CONFIG3 however, you risk having six unused structures bloating memory.

Instead, you'd like to provide users of your library a set of predefined structures CONFIG0 ... CONFIG6, but have the compiler only create (instantiate) those that the user actually uses.

C++ offers you such things as constructors to help with this. In C it takes a little more work, but here's one way:

To keep things simple, suppose our ADC CONFIG structure needs to hold a single integer, x (in real life, configuring the ADC need require multiple e.g. pin, port, oscillator... etc. values)

First, we declare a type for our structure and a pointer to it.

typedef struct { int x; } ConfigData_t, *pConfigData_t

Next, we define a function that takes an integer, creates a structure containing the integer, and returns a pointer to it.

pConfigStruc_t fConstructor( int x ) {
static ConfigStruc_t CONFIGn;
CONFIGn.x = x;
return &CONFIGn; }


Finally, we define some macro's

#define CONFIG0 ( fConstructor ( 7) )
#define CONFIG1 ( fConstructor (67) )
..etc.


where 7, 67 are examples of board-specific configuration values.

We can now offer users of our library, a set of predefined configurations CONFIG0,CONFIG1 insulating (abstracting) them from any messy details of our board hardware. The user is free to write a line of code like:

fStartADC( CONFIG0 );


At compile-time, in accordance with our #define, the compiler will dutifully replace CONFIG0 with fConstructor(7)

fConstructor (7) will then do its job, returning a pointer to a structure containing '7'.

Notice however, that since our user never wrote CONFIG1, a structure holding 67 was never created!

We've met our goal of providing users with a set of predefined CONIG's  but at the same time made sure that only those they use will be compiled into memory. Neat huh!

To see a 'real world' example of this technique, check-out my gitHub code here

Wednesday, 12 October 2016

Embedded Basics No.1 - Registers

A core concept in embedded-electronics is the register.

For embedded newbies, put simply,

a register is a ‘box’ that stores a number

‘Stores’ means a register is a memory device. Place (embedded programmers say ‘poke’) a number into the ‘box’ (register), and it’s held there until you decide to change it or you power-off the IC.

Other parts of an electronic system may be able to read a number you’ve poked into a register, and adjust their behavior based on its value. Figure 1 shows the general idea. Here a 3-bit register controls 3 LED's. Poking the value '101' turns two LED's on, and poking '010', one LED.



Modern IC’s may contain hundreds of registers, each controlling a different feature of the device. Manufacturers therefore need to give you a way to single-out an individual register. They do this by giving each register a unique name or number termed its “address”. You use the address to send the IC instructions along the lines:

Hi Mr. IC, poke the value 17 to the register with address 82”

Hi Mr. IC, poke 23 to the register TXCTRL”

“Hi Mr. IC, what's the value in register RXBUFF?”

Here “TXCTRL” and “RXBUIFF” are  example register names (its traditional to use uppercase lettering for registers). 

The first two instructions are write-instructions. The third is a read-instruction. Not all registers allow both reads and writes. For example, a manufacturer might include a read-only register in an IC to store a serial number, giving you the ability to read the number, but not over-write it.

Some registers contain both write’able and read-only regions. For example, a register might store an 8-digit (bit) number, but only allow you to write (change) seven of these bits, the eighth bit being permanently fixed (at ‘1’ say). 

It can also be important to know what value may be present in a register before you write anything to it (the default value present in the register immediately after you’ve powered-up the chip for example). 

All the various properties of an chip's registers are stated in the datasheet in a (fairly) standard format. Figure 2 shows a typical (fictitious) example.



In words, the table can be understood as saying:
  • CFG0 is the name of a register name with address "127" (= 7F in hex)

  • The register stores an 8-bit (binary) value. The individual bits are themselves named (LED0, LED1...CTRL).

  • Bits 0 - 4 can be both written (‘W’) and read (‘R’).  

  • Bit 5 - 6 can be read, but not written (changed).

  • Bit 7 can be written but not read.

  • Bits 1,2,3,5,6 have default value '0' 

  • Bits 0,4 have default value '1' 

  • Bit 7  has an undefined ('U') default value
In addition to the table, the datasheet will describe what each section of the register does. For example the datasheet might describe the function of the 'LED0' bit by saying

  • LED0: Writing '1'('0') turns the on-board LED#1 on (off)


(By the way, precisely how you send register-read/write instructions to a chip depends on the device. For some, you might send instructions via an (e.g. SPI or I2C) interface; A microprocessor might have the instruction written into its software. Written in C (you can skip this bit if you don’t know C, but you should be aware that a large proportion of embedded software uses it), the second example instruction above might look something like

*(TXCTRL) = 23

I should add there's a lot more could be said here about pointers, volatiles etc.  but these are software topics for another time).

Finally, at the hardware level, a register is typically just a row of (one or more) edge-triggered D-type flip flops. Unless you’re heavily into transistor-level integrated-circuit design, it’s rarely necessary to understand the inner workings of flip flops, so I won’t get into details here. Wikipedia is the place to start if you’re hungry for more. It’s enough to know that a ‘1’ (or a ‘0’) put on the ‘D’ input of a flip-flop, will be captured and stored if a rising-edge (a voltage step) is applied the ‘Clk’ input. The stored ‘1’ (or ‘0’) will show up on the flip-flop's ‘Q’ output. A row of D-type flip flops allows you store a set of '0’s and ‘1’s – in other words it forms a register.

The ability to arrange and manipulate registers is so important in digital system design (for example, when creating ASIC's or programming FPGA’s) that dedicated hardware design languages (HDL’s) such as VHDL and Verilog are available to help streamline the task. In a language like VHDL, you routinely see lines of code like

If rising_edge(clock) then A <= “10101010”; 

This translates as an instruction to your FPGA / ASIC design- tools that you want a (clocked) register with an output called “A”, storing the value “10101010”.

I’ll end my brief introduction to registers here.

Do drop me a comment on this, or any of the others topics on this blog.

Sunday, 9 October 2016

Introducing the Tiva Lauchpad

Everyone knows the Arduino (/Genuino), but some may less familiar with the Texas Instruments Tiva LaunchPad.  

I’m planning to use this in some future posts, so today is a quick intro. to this nifty little board. All views here are my own by the way - I'm not paid to give them!


The Launchpad is one of a bunch of low-cost boards built around ARM microcontrollers. Others include the Nucleo and boards by RedBear.

Working with these boards is similar to working with the Genuino. You write code on your PC and download it to the board via USB. 

What the Launchpad (full name Tiva-C TM4C123 Launchpad) gives you compared to the Arduino is much-increased processing power and added features.   

On the hardware side, for less than $20, you get an 80MHz ARM M4 processor; 256K of flash memory; a 12-bit ADC; multiple (USB, I2C, SPI, UART and CAN) interfaces;  43 GPIO’s; and several others features including PWM, Comparator and DMA modules. The board doesn't have wireless or ethernet, but there're still plenty of projects you can do without these. (Other boards in the Tiva series do have wireless connectivity - I'll take about these another time).

On the software side the Launchpad is a great way to grow your embedded skills. At first, you might choose to program it using the quick-and-easy Energia software environment. This makes writing Tiva software look-and-feel like Arduino code.  Or you might download Texas Instruments’ (free) Code Composer Studio environment. This comes with ready-made C-code examples (an API) that help you access the Lauchpad's features.  Ultimately you can move on to advanced embedded software techniques such as RTOS programming and the ARM CMSIS.

All round, the Launchpad is great value and has enough power to deliver serious results. It's something I'll be using frequently in future posts.