Variable Load: Initial Programming

Now that the board is built, and I can power it up, let’s try programming it!

First is the hardware set-up. I have to power the board and hook up the AVR programmer to it. Below is what it looks like:

Hardware set-up. Shows the board, AVR ICE programmer, and the barrel connector that powers the board with 12 volts.

I’m using Atmel Studio 7 to program the board. Now, in order to see if the programmer recognizes the microcontroller, I open up the Device Programmer and try to read the fuses in the microcontroller.

Fuses, by the way, have nothing to do with the piece of metal that melts when too much current goes through it. Fuses, for AVR microcontrollers, are configuration bits that affect how the microcontroller behaves. Fuses will decide what drives the microcontroller’s clock, whether the watchdog timer is running, etc.

Initial fuse settings

The image above shows the fuses that are being read in the microcontroller. Good news and bad news. The good news is that the microcontroller is responding, and is therefore working. We know this because we can see what the fuses are, and we can get the Device Signature (0x1E9587). The bad news is that the fuses are not setup the way I’d like.

First, this is a 5 V system, so I’d like the Brown Out Detect (BOD) to be closer to 5 volts. So I’ll have to change that to be larger. Secondly, I don’t plan to use the bootloader, so HWBE can be turned off. Adding on to that, since I won’t use a bootloader, I’ll make the boot flash size smaller to make more room for my application code. Third, I’m only planning on using AVR ICE to program the device, which uses a JTAG interface, so I don’t need to program the chip through SPI, so I’ll turn that off. Lastly, the CKDIV8 divides the input clock by 8, which is good for power savings, but not necessary for this application. A higher clock speed allows the microcontroller to work faster, and power is not a concern here, so I’ll turn that off.

Erase chip to allow fuses to be changed

Unfortunately, if you try to change the fuses, you might see that it doesn’t work. This is because of lock bits, which keeps the fuses from changing. If you try to change the lock bits, they can’t be changed either! In order to reset the fuses and the lock bits, you have to erase the chip. You can do that by going to Memories in the Device Programmer window, and click “Erase now” button. Now, you can adjust the fuses as you please.

New fuse settings

The new fuses are shown above. Now, the microcontroller will be put into reset if the 5 volt droops below 4.3 volts, the microcontroller can only be programmed through JTAG, the bootloader size has been made smaller, and the clock-divide-by-8 is disabled. Should be good to go!

One fuse setting I’d like to point out is the last one: SUT_CKSEL. This fuse is, I’d say, the most important one. It controls the Start Up Time (SUT) and what clock the microcontroller will use. The microcontroller can use it’s internal RC oscillator, use an external crystal, or use an external clock; which one you use will affect how fast the microcontroller runs and how much power it uses. If the fuse is set-up incorrectly, then the microcontroller may be waiting for a clock that doesn’t exist, and never run. Make sure it’s what you want! In this case, the fuse is set-up to use an external crystal oscillator that runs above 8 MHz. This is what I want since the crystal oscillator I have runs at 16 MHz. The start-up time is pretty large (65 ms), which is good if you want to make sure the oscillator is good to go when you run the program. If you’re application requires your code to be up and running as soon as possible after power is applied, you’ll want to reduce the start-up time.

Import delay library
Note you must define F_CPU, which tells delay library the oscillator frequency

I want to write a simple code to turn LEDs on and off, the embedded systems equivalent of Hello World. First, I import two libraries: avr/io and util/delay. avr/io is where registers for the ATMEGA32U4 (and other AVR microcontrollers) is defined (for example port, pin and data direction registers), and utill/delay just has delay functions that are useful for testing simple programs. Note that you have to define F_CPU and set it to the crystal oscillation frequency, which is 16 MHz in this case.

Simple code to toggle all four LEDs on and off sequentially

Here’s the application code. In the schematic, I have LEDs hooked up to PE6, PF0, PC6 and PC7. The code above just turns those LEDs on and off, sequentially.

The section outside of the while loop initializes those pins by writing HIGH to them, and then setting them to be outputs by writing to the data direction registers. Since the LEDs are only on when the GPIOs sink current, at this point the LEDs will be off. Inside the while loop, I turn the GPIOs LOW then HIGH one at a time, and this will turn the LEDs on and off, respectively.

Upon programming this code into the microcontroller, the LEDs blinked! So that means the microcontroller is powered and programmable. What’s next?

The code example above is pretty messy. I can understand it because I wrote it a couple of minutes ago, but next week, I may not remember how the code works. Fortunately, the code is simple enough that I can figure it out in a couple of minutes, but as the code gets more complicated, that won’t be feasible. Obviously commenting is helpful, but the real problem is that I have no hardware abstraction.

Hardware abstraction is the concept of “hiding hardware information from the application code.” How this is done is by creating functions that deal with the low level registers, so the application code doesn’t have to worry about it. Below is an example:

Example of what hardware abstraction looks like
This is pseudo code, so there are errors

Ignore the red squiggly lines. Here, you can clearly see what’s happening; you have four LEDs, and you are turning them on and off after setting them up. You don’t have to worry about what registers are involved, or how they’re being manipulated. The application code doesn’t care about that stuff; it only want to turn LEDs on and off. Hardware abstraction allows the application code to not worry about the details and focus on what’s important, keeping the code simple and easy to understand. Another advantage of hardware abstraction is that it improves code maintenance; if you have to change how the registers are being manipulated, then you can do that without touching anything in main() at all!

My point is hardware abstraction is crucial for embedded systems, since they improve code readability and maintenance. For that reason, I’m going to start building a Hardware Abstraction Layer (HAL) that lets you use the microcontroller’s peripherals without having to understand the nitty-gritty details. Of course, I can download one that others have created, or get one directly from Atmel; almost always, chip manufacturers have HALs available on their website (or IDE) so that programmer can start working on application code right away. But since the point of this blog, and this project, is to learn, I’m going to re-invent the wheel. Let’s learn how to program embedded systems!

Leave a comment

Design a site like this with WordPress.com
Get started