index.html 17.8 KB
Newer Older
Alexandre Kaspar's avatar
Alexandre Kaspar committed
1 2 3 4 5 6 7 8 9
<!doctype html>
<html>
<title>Programming Helper | Index</title>

<xmp theme="simplex">

# How To Program Your Micro-Controller

This is about using `avr-dude`, `make` and getting a high-level understanding of what's happening under the hood so that you can tune your micro-controller yourself.
Alexandre Kaspar's avatar
Alexandre Kaspar committed
10
Notably, we'll cover the fuse programming for the ATTiny44 (echo ftdi board).
Alexandre Kaspar's avatar
Alexandre Kaspar committed
11 12 13

In practice, you can just read most of what is linked in the **Embedded Programming** class [there](http://academy.cba.mit.edu/classes/embedded_programming/index.html).
In fact, you should have done that already.
Alexandre Kaspar's avatar
Alexandre Kaspar committed
14
But for those who are overwhelmed, we will try to dissect some of the content
Alexandre Kaspar's avatar
Alexandre Kaspar committed
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29

## References

* [HTMAA's Embedding Programming](http://academy.cba.mit.edu/classes/embedded_programming/index.html)
* [Makefiles](https://makefiletutorial.com/) for executing pre-written commands
* [avrdude](https://www.ladyada.net/learn/avr/avrdude.html) (by Lady Ada) for programming through a programmer
* Existing tutorials for various programmers:
  * [Sparkfun's avr programmer](https://learn.sparkfun.com/tutorials/pocket-avr-programmer-hookup-guide/al)
  * [AdaFruit's USBTinyISP](https://learn.adafruit.com/usbtinyisp/avrdude)
* [List of AVR IC's and their packages](https://en.wikipedia.org/wiki/ATtiny_microcontroller_comparison_chart)
  * [ATtiny10](http://www.digikey.com/product-detail/en/ATTINY10-TS8R/ATTINY10-TS8RCT-ND)
  * [ATtiny45V](http://www.digikey.com/product-detail/en/ATTINY45V-10SU/ATTINY45V-10SU-ND)
  * [ATtiny44A](http://www.digikey.com/product-detail/en/ATTINY44A-SSU/ATTINY44A-SSU-ND)
  * [ATtiny814](http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-42721C-AVR-ATtiny417-814-816-817-Datasheet_Complete.pdf)
  * [ATmega328P](http://www.digikey.com/product-detail/en/ATMEGA328P-AU/ATMEGA328P-AU-ND) (same as [Arduino Uno](https://en.wikipedia.org/wiki/Arduino_Uno)), ([datasheet](http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf))
Alexandre Kaspar's avatar
Alexandre Kaspar committed
30
  * [ATmega16U2](http://www.digikey.com/product-detail/en/ATMEGA16U2-AU/ATMEGA16U2-AU-ND) (with 16**U** for USB support)
Alexandre Kaspar's avatar
Alexandre Kaspar committed
31 32 33 34 35 36
  * [ATxmega16E5](http://www.digikey.com/product-detail/en/ATXMEGA16E5-AUR/ATXMEGA16E5-AURCT-ND)
  * [ATxmega16A4U](http://www.digikey.com/product-detail/en/ATXMEGA16A4U-AUR/ATXMEGA16A4U-AURCT-ND) (USB support)

## What are those files?

For most base projects of HTMAA, you are provided with a set of different files:
Alexandre Kaspar's avatar
Alexandre Kaspar committed
37

Alexandre Kaspar's avatar
Alexandre Kaspar committed
38 39 40 41 42 43 44 45 46 47 48 49 50
* `file.png` are typically images for tracing (trace) or cutting (outline)
* `file.c` is a C file that contains a C program, which runs on a micro-controller
* `file.make` (or anything ending in `.make`, so here typically `file.c.make` too) is to use the program `make` to call commands that allow you to do things

## What does `XXX` do?

First thing first, you should try reading the manual.
On Mac / Linux, you can access the manual of a specific command typically by typing

```bash
man fancycommand
```

Alexandre Kaspar's avatar
Alexandre Kaspar committed
51 52 53 54 55 56 57
For example, we want to learn about `make`, so let's do that:
```bash
man make
```

That should give you an interactive stream that you can go over (down/up arrows) and search through (`/` character, followed by search query).

Alexandre Kaspar's avatar
Alexandre Kaspar committed
58
<img src="images/man_make.png" width="800">
Alexandre Kaspar's avatar
Alexandre Kaspar committed
59 60

To exit that manual, just press `q` (quit).
Alexandre Kaspar's avatar
Alexandre Kaspar committed
61

Alexandre Kaspar's avatar
Alexandre Kaspar committed
62 63
To get some help and figure out how to use the manual functions, press `h` (help).

Alexandre Kaspar's avatar
Alexandre Kaspar committed
64
<img src="images/man_help.png" width="400">
Alexandre Kaspar's avatar
Alexandre Kaspar committed
65

Alexandre Kaspar's avatar
Alexandre Kaspar committed
66 67
Now, we're ready to start looking at those commands.

Alexandre Kaspar's avatar
Alexandre Kaspar committed
68 69 70
## What is [Make](https://www.gnu.org/software/make/manual/html_node/Introduction.html#Introduction)

References:
Alexandre Kaspar's avatar
Alexandre Kaspar committed
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154

* [Online make manual](https://www.gnu.org/software/make/manual/make.html)
* `man make`

Make allows you to automate some commands and simplify what you have to type to program things (though it can be used for programming anything, not just programs).

Typically, you'll be using the following pattern:

```bash
make targetname
```

where `targetname` is a specific target to execute.

Targets are just names, behind which are defined sets of commands to do something.

Let's have a look at the basic FTDI echo files:

* [hello.ftdi.44.echo.c](http://academy.cba.mit.edu/classes/embedded_programming/hello.ftdi.44.echo.c) - the c program file (i.e. the code to compile and run onto the micro-controller)
* [hello.ftdi.44.echo.c.make](http://academy.cba.mit.edu/classes/embedded_programming/hello.ftdi.44.echo.c.make) - the makefile

The `.make` file contains the following (in the terminal: `cat hello.ftdi.44.echo.c.make`):

```bash
PROJECT=hello.ftdi.44.echo
SOURCES=$(PROJECT).c
MMCU=attiny44
F_CPU = 20000000

CFLAGS=-mmcu=$(MMCU) -Wall -Os -DF_CPU=$(F_CPU)

$(PROJECT).hex: $(PROJECT).out
	avr-objcopy -O ihex $(PROJECT).out $(PROJECT).c.hex;\
	avr-size --mcu=$(MMCU) --format=avr $(PROJECT).out
 
$(PROJECT).out: $(SOURCES)
	avr-gcc $(CFLAGS) -I./ -o $(PROJECT).out $(SOURCES)
 
program-bsd: $(PROJECT).hex
	avrdude -p t44 -c bsd -U flash:w:$(PROJECT).c.hex

program-dasa: $(PROJECT).hex
	avrdude -p t44 -P /dev/ttyUSB0 -c dasa -U flash:w:$(PROJECT).c.hex

program-avrisp2: $(PROJECT).hex
	avrdude -p t44 -P usb -c avrisp2 -U flash:w:$(PROJECT).c.hex

program-avrisp2-fuses: $(PROJECT).hex
	avrdude -p t44 -P usb -c avrisp2 -U lfuse:w:0x5E:m

program-usbtiny: $(PROJECT).hex
	avrdude -p t44 -P usb -c usbtiny -U flash:w:$(PROJECT).c.hex

program-usbtiny-fuses: $(PROJECT).hex
	avrdude -p t44 -P usb -c usbtiny -U lfuse:w:0x5E:m

program-dragon: $(PROJECT).hex
	avrdude -p t44 -P usb -c dragon_isp -U flash:w:$(PROJECT).c.hex

program-ice: $(PROJECT).hex
	avrdude -p t44 -P usb -c atmelice_isp -U flash:w:$(PROJECT).c.hex

program-ice-fuses: $(PROJECT).hex
	avrdude -p t44 -P usb -c atmelice_isp -U lfuse:w:0x5E:m

```

The **targets** we mentions are all the blocks starting like `targetname:`.

When calling for example
```bash
make -f hello.ftdi.44.echo.c.make program-usbtiny
```

It ...
Wait a second, what's that command?

Unfortunately, you cannot just use `make targetname` all the time.
It only works when the configuration for make (`.make` file) is actually named `Makefile` and available where you run `make`.

Most examples in the class are not named with that single same name because it would create lots of conflicts and there is nothing that associates that file.
By naming the file `myprogram.c.make`, we know that the makefile is associated with the program `myprogram.c`, but then we have to specify the `makefile` that makes uses.

Here is that argument in the manual:
Alexandre Kaspar's avatar
Alexandre Kaspar committed
155

Alexandre Kaspar's avatar
Alexandre Kaspar committed
156
<img src="images/man_make_f.png" width="600">
Alexandre Kaspar's avatar
Alexandre Kaspar committed
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211


Back to the command, `make -f hello.ftdi.44.echo.c.make program-usbtiny` ends up running the target `program-usbtiny` in the makefile.

```bash
program-usbtiny: $(PROJECT).hex
	avrdude -p t44 -P usb -c usbtiny -U flash:w:$(PROJECT).c.hex
```

* `program-usbtiny` is the target name (for the argument to `make`)
* `$(PROJECT).hex` (on the right of the target, after the `:` separator) is the list of dependencies that needs to be `made` before we can run the actual script below.
* `avrdude -p t44 -P usb -c usbtiny -U flash:w:$(PROJECT).c.hex` is the actual command being run
  * Beware, those lines must start with a tabulation character `\t`, which is not visible but is different from a blank space

If we look at the dependency, it's name is actually using a MACRO definition that is available at the top of the make file:
```bash
PROJECT=hello.ftdi.44.echo
```

The dependency name is either another *target* or a *file*, i.e. `hello.ftdi.44.echo.hex`.
If it's a file and the file is the last version, then it doesn't need to be computed again.

The rules are based on the existence of [the file dependencies and their relative timestamps](https://stackoverflow.com/questions/35588153/where-does-make-store-its-cache).

What about the target name? There is no explicit matching target name, but there is if we compute the MACROS (i.e. `$(PROJECT).hex:`)
And this has another dependency on the `.out` file, which is the object output from compiling the c file.

Fortunately, make outputs all the commands it runs, so you can just follow what's written on the terminal.

<img src="images/make_hex.png" width="600">

```bash
avr-gcc -mmcu=attiny44 -Wall -Os -DF_CPU=20000000 -I./ -o hello.ftdi.44.echo.out hello.ftdi.44.echo.c
avr-objcopy -O ihex hello.ftdi.44.echo.out hello.ftdi.44.echo.c.hex;\
	avr-size --mcu=attiny44 --format=avr hello.ftdi.44.echo.out
```

The first command compiled the C file with `avr-gcc`.

* `-mmcu=attiny44` because assumes an attiny44 as mcu
* `-Wall` enables all **w**arnings
* `-Os` optimizes for **s**ize
* `-DF_CPU=20000000` defines the MACRO F_CPU and sets it to `20000000` (20MHz)
* `-I./` adds the current directory to search for included files (`#include "file"`)
* `-o hello.ftdi.44.echo.out` specifies the output name
* `hello.ftdi.44.echo.c` is the input file

Then the second command creates a `hex` file from the program output.
See [.hex vs .out](https://electronics.stackexchange.com/questions/417648/whats-the-difference-between-a-generated-hex-file-and-a-binary-file-in-embedded) for the difference.

TL;DR hex files are easy to read and used for not only programming but also checking that the programming went well, whereas out files are binary codes to be transferred to the memory for execution.

The last command computes information about the size that the program is going to take.
This is important if you are creating your own program, because you need to make sure it will fit in memory.

Alexandre Kaspar's avatar
Alexandre Kaspar committed
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232
## AVRDUDE!

`avrdude` is a tool that allows us to send programs onto avr chips through a programmer interface such as the usbtiny (e.g., [FabTinyISP](http://fab.cba.mit.edu/classes/863.16/doc/projects/ftsmin/index.html)), or an [Atmel ICE](https://www.microchip.com/DevelopmentTools/ProductDetails/ATATMEL-ICE).

Here, the manual of `avrdude` is quite large, so instead, let's start by reading the help summary, which you can typically get by running the command with the argument `-h` or `--help`:

<img src="images/avrdude_h.png" width="600">

* `-p device` specify the type of device to program (in our case, it's an ATTiny44)
* `-P port` selects the port for programming (typically `usb`)
* `-c programmer` selects the programmer (e.g. `usbtiny`)
* `-U ...` requests a memory update (this is the actual action we're doing with avrdude)

```bash
avrdude -p t44 -P usb -c usbtiny -U flash:w:hello.ftdi.44.echo.c.hex
```

How did we know the device label was `t44`?

Well, the manual tells you that you can just query for the available names / devices with `avrdude -p ?`, which gives you a long list.

Alexandre Kaspar's avatar
Alexandre Kaspar committed
233
<img src="images/avrdude_p.png" height="400">
Alexandre Kaspar's avatar
Alexandre Kaspar committed
234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249

You can do the same to find the list of available programmers (and you'll find `usbtiny`).

Finally, the real deal - the memory programming through `-U`.
There are different actions: `-e` erases memory, likely not what you want, and `-U` updates the memory.

## `avrdude -U ...`

The format of the argument is (according to the help):
```bash
avrdude -U <memtype>:r|w|v:<filename>[:format]
```

The manual is slightly more verbose and tells us what's available for the memory types, formats and operations:

<img src="images/avrdude_u.png" width="600">
Alexandre Kaspar's avatar
Alexandre Kaspar committed
250

Alexandre Kaspar's avatar
To hexa  
Alexandre Kaspar committed
251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297
In our case, `program-usbtiny` uses the following update command:
```bash
-U flash:w:hello.ftdi.44.echo.c.hex
```

which means:

* Updating the `flash` memory
* **W**riting to it (not **r**eading nor **v**erifying)
* Using the hex file `hello.ftdi.44.echo.c.hex` that got generated

Why the `flash` memory?

You should read this [memory part](https://en.wikibooks.org/wiki/Embedded_Systems/Atmel_AVR#Memory) of the Embedded Systems from Wikibooks.
And you will definitely need to read the *datasheet* of your target micro-controller.

As a summary, there are different types of memory available. For the simple AVR systems, there are:

* **data** memory, I/O registers and SRAM - those are dynamic, changing during execution, and vanishing upon shutdown (aka *volatile* memory)
* **flash** program memory - this is where your program goes
* **[EEPFROM](https://en.wikipedia.org/wiki/EEPROM)** aka Electrically Eraseable Programmable Read-Only Memory, which allows you to store data that survives a restart / shutdown
* **fuses** are special types of memory that cannot be modified by the program and must be programmed separately

For interested readers:

* [flash vs eeprom](https://electronics.stackexchange.com/questions/69234/what-is-the-difference-between-flash-memory-and-eeprom/69275)

### avrdude and fuses

Fuses are specific bits of the memory that specify low-level configurations.
Thoses have to be programmed separately from the main program memory.

In our previous example with the ATTiny44, the fuse programming was done with the `program-usbtiny-fuses` target:
```bash
program-usbtiny-fuses: $(PROJECT).hex
	avrdude -p t44 -P usb -c usbtiny -U lfuse:w:0x5E:m
```

Here, the `-U` command targets the **low** bits of the fuse memory for the ATTiny44.
The actual value is specified as a hex number: `0x5E`.

### Hexadecimal Numbers

Hex numbers are numbers in hexadecimal base (16) and are typically prefixed with `0x`.
The symbols are:

| Decimal | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
Alexandre Kaspar's avatar
Alexandre Kaspar committed
298
| ------- | - | - | - | - | - | - | - | - | - | - | -- | -- | -- | -- | -- | -- |
Alexandre Kaspar's avatar
To hexa  
Alexandre Kaspar committed
299 300
| Hexa | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F |
| Bin | 0000 | 0001 | 0010 | 0011 | 0100 | 0101 | 0110 | 0111 | 1000 | 1001 | 1010 | 1011 | 1100 | 1101 | 1110 | 1111 |
Alexandre Kaspar's avatar
Alexandre Kaspar committed
301

Alexandre Kaspar's avatar
To hexa  
Alexandre Kaspar committed
302
Looking at the individual bits (in groups of 4 since `2^4 = 16`) is typically the main reason for hexadecimal.
Alexandre Kaspar's avatar
Alexandre Kaspar committed
303

Alexandre Kaspar's avatar
Alexandre Kaspar committed
304 305 306 307 308 309 310
### Fuse meanings

Fuse bits describe low-level configurations.

There are tools available to figure out what fuses to write, notably Atmel Studio allows you to set those interactively during the programming step with help for each individual fuse of each device they support.
There are also [fuse calculators](http://www.engbedded.com/fusecalc) online.

Alexandre Kaspar's avatar
Alexandre Kaspar committed
311
But before you jump and set fuses, you should understand what they do, since they can make your micro-controller stay silent forever by disabling programming capabilities or changing the basic clock frequency while expecting a specific clock (that may not exist, and then you may need to change the hardware to make it work again).
Alexandre Kaspar's avatar
Alexandre Kaspar committed
312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332

Long story short - these are bits you should write carefully because some options are not reversible (or hard to reverse).

The first part is reading the datasheet about your micro-controller and its section related to fuses (e.g. page 192 of the att44 [datasheet](http://fab.cba.mit.edu/classes/863.09/people/ryan/week5/ATtiny44%20Data%20Sheet.pdf#page=159)).
In our ATTiny44 case, it mentions three different fuse bytes:

* **Fuse Extended Byte** (extra for self-programming)
* **Fuse High Byte**
* **Fuse Low Byte**

Let's have a look at the tables:

<img src="images/att44_feb.png" width="400">
<img src="images/att44_fhb.png" width="400">
<img src="images/att44_flb.png" width="400">

In our setup, we're just modifying the low byte and choosing value `0x5E`.
Let's deconstruct that:

`0x5E` is, in binary `01011110`, and the bits start (0-indexed) from the right (least significant bit).

Alexandre Kaspar's avatar
Alexandre Kaspar committed
333
Or in a table:
Alexandre Kaspar's avatar
Alexandre Kaspar committed
334

Alexandre Kaspar's avatar
Alexandre Kaspar committed
335 336 337 338 339 340 341 342 343 344 345 346 347 348
| `CKDIV8` | 0 |
| -------- | - |
| `CKOUT`  | 1 |
| `SUT1`   | 0 |
| `SUT0`   | 1 |
| `CKSEL3` | 1 |
| `CKSEL2` | 1 |
| `CKSEL1` | 1 |
| `CKSEL0` | 0 |


The last four bits are about the clock selection, and their default value `0010` stands for the 8MHz internal RC oscillator as source of the clock.

In our program above, we're using `1110`, which we can understand by looking at the section on the clock (chapter 6, notably [page 24](http://fab.cba.mit.edu/classes/863.09/people/ryan/week5/ATtiny44%20Data%20Sheet.pdf#page=24), or just *search* for the fuse names):
Alexandre Kaspar's avatar
Alexandre Kaspar committed
349 350 351

<img src="images/att44_cksel.png" width="400">

Alexandre Kaspar's avatar
Alexandre Kaspar committed
352
We're in the last row case (`CKSEL3..0` is within `1000`-`1111` cases, for external crystal or resonator), which means we need to go look farther (at page 27):
Alexandre Kaspar's avatar
Alexandre Kaspar committed
353 354 355

<img src="images/att44_cksel2.png" width="500">

Alexandre Kaspar's avatar
Alexandre Kaspar committed
356
And there we find that we're assuming an external crystal/resonator, with frequency from 8MHz and above (`CKSEL3..1` is `111`).
Alexandre Kaspar's avatar
Alexandre Kaspar committed
357 358 359 360 361
The last bit `CKSEL0` requires looking a bit further:

<img src="images/att44_cksel3.png" width="400">

Since we have `CKSEL0=0`, it means we assume a ceramic resonator.
Alexandre Kaspar's avatar
Alexandre Kaspar committed
362
Given the additional `SUT1..0` as `01` (3rd and 4th bits from the left in `0101_1110`, we know that we have BOD (**B**rown-**o**ut **D**etector) enabled.
Alexandre Kaspar's avatar
Alexandre Kaspar committed
363 364 365 366
You can read about that [there](https://microchipdeveloper.com/8avr:bod).

The `CKSEL` fuses are the fuses you are the most likely to every change, whereas the other ones are typically very specific.

Alexandre Kaspar's avatar
Alexandre Kaspar committed
367 368 369 370 371 372 373 374
Finally, if we look at bits 7 (`CKDIV8` set as `0`) and 6 (`CKOUT` as `1`), we can see that it is such that:

* `CKDIV8=0` (programmed) so that the the initial prescaler is set to 1/8. Reading about the prescaler on [page 30](http://fab.cba.mit.edu/classes/863.09/people/ryan/week5/ATtiny44%20Data%20Sheet.pdf#page=30), we see that this just sets the initial prescaler value, but that is available in the program space, which can then be changed at runtime.
* `CKOUT=1` (unprogrammed) does not enable clock output. Had we set it to `0`, the same section near the prescaler on [page 29](http://fab.cba.mit.edu/classes/863.09/people/ryan/week5/ATtiny44%20Data%20Sheet.pdf#page=29) tells that pin `CKOUT` (`PB2`) would be outputting the clock signal.

This output can be useful if you need to debug your clock while using an external clock.
In this way, you can check whether your clock parameters (e.g. capacitors) are doing a good job and your frequency is what you expect.

Alexandre Kaspar's avatar
Alexandre Kaspar committed
375 376 377 378 379 380 381
### Take-aways

1. Read the manuals
2. Read the datasheet (when you need it, no need to memorize)
3. Choose your fuses carefully, notably beware of
  * `RSTDISBL` in the *Fuse High Byte*, since this prevent further programming (needed in FabTinyISP), or similar disable / enable options
  * Choose the clock carefully and especially the meaning hidden behind each bit's value (e.g. ceramic vs crystal, frequency range ...)
Alexandre Kaspar's avatar
Alexandre Kaspar committed
382
  * For debugging, consider outputting the clock signal
Alexandre Kaspar's avatar
Alexandre Kaspar committed
383 384


Alexandre Kaspar's avatar
Alexandre Kaspar committed
385

Alexandre Kaspar's avatar
Alexandre Kaspar committed
386 387 388
</xmp>
<script src="sd/strapdown.js"></script>
</html>