Overview

Inside the microcontroller

The library follows the internal organisation of the micontroller (or MCU for MicroController Unit, or simply the microcontroller), so let's look at that first.

There are 4 main components inside the microcontroller :

  • the CPU is the processing unit : it executes your program and makes computations
  • the Flash is a non-volatile memory unit (meaning that it keeps its content even when the microcontroller is turned off) where the program is stored
  • the RAM is a volatile memory unit (so this one is erased every time the microcontroller is reset) used as a working memory, to store the current program execution state (such as variable values)
  • the peripherals are a collection of hardware controllers, each one of them dedicated to a single task, e.g. generating clock signals, controlling pins or managing communication ports

These two other components are also useful to make your life easier :

  • the JTAG/SWD controller allows you to take complete control over the microcontroller for debugging purposes (more detail about that in the JTAG/SWD vs Bootloader tutorial)
  • the DMA (Direct Memory Access) controller is a nice feature which allows peripherals to access the RAM without CPU intervention (look at the DMA module for more details)

With the exception of the RAM and the JTAG/SWD controller, every one of these hardware components is matched by a dedicated module in the library. The CPU is grouped with some other central features inside the Core module.

See ยง2.1 Block Diagram in the datasheet for a more detailed diagram of the inside of the microcontroller.

Library organisation

The library itself is only a folder. Its only dependencies are a working toolchain (as explained in the Getting Started tutorial), GNU make, and optionally OpenOCD. You will usually want to copy it inside your project folder (yes, there will be a copy for every project, but don't worry : it's very small and this will allow you to customize the library).

The two main parts of the library are the modules' code (inside sam4l/) as explained above, and the Makefile.

Makefile

A Makefile is some sort of script that is read and executed by the GNU make tool. It allows you to define settings and rules that can be used to compile your code or do about anything you want. All the operations defined by the library (such as compiling your program, flashing it into the microcontroller, …) are implemented with these rules. When compiling code, a Makefile is also smart : it will only compile the files that have been modified to save time.

This may sound complicated, but it is actualy really easy. For example, in order to compile your code, just go to your project directory with a terminal and type make. That's it!

In order to execute a rule, type make rule. Omiting the argument will execute the default rule which is, you guessed it, compiling the program. Here is the complete list of available rules :

  • make clean : clear every compiled files, to make sure the next make will re-compile everything from scratch (if you have modified the Makefile, make sure to do this to avoid weird behaviour)
  • make openocd : start a pre-configured OpenOCD session and connect to your JTAG/SWD adapter (you will usually do that in another terminal in background)
  • make flash : flash your program into the microcontroller using OpenOCD
  • make autoflash : flash your program into the microcontroller by automatically launching a temporary OpenOCD session
  • make erase : erase the microcontroller's Flash memory (i.e. the current program inside the microcontroller)
  • make pause : pause the microcontroller execution
  • make reset : reset the microcontroller
  • make debug : start a debug session with GDB
  • make flash-debug : shortcut to flash and immediately start a debug session
  • make bootloader : compile the bootloader
  • make flash-bootloader : flash the bootloader into the microcontroller using an existing OpenOCD session
  • make autoflash-bootloader : flash the bootloader into the microcontroller by automatically starting a temporary OpenOCD session
  • make debug-bootloader : start a debug session aimed at the bootloader
  • make flash-debug-bootloader : shortcut to flash the bootloader into the microcontroller and immediately start a debug session
  • make codeuploader : compile the codeuploader
  • make upload : flash your program using the bootloader using USB by default
  • make upload-usb : flash your program using the bootloader using USB
  • make upload-serial : flash your program using the bootloader using a Serial port

You probably won't have to modify the main library Makefile. As explained in the Getting Started tutorial, all you need to do is to create a Makefile in your project directory, set up a few settings, and include the main Makefile.

Module files

All the modules are built around the same structure : a namespace shared between a .cpp file containing the code and a .h header describing the module interface. In order to call a function inside a module namespace, use the following notation : Module::function(), for example Core::init(). Feel free to look inside the modules code if you are curious about how something works!

What are all those const uint32_t OFFSET_... inside the header files?

At the lowest level, the program interacts with the microcontroller using registers. A register is a small memory space (usually 32-bit (4-byte) long), that have a defined address and a documented content. You can access it exactly like if it was in RAM, even though it is actually located inside a peripheral. Reading and writing registers is the most common way to control peripheral components. For example, there are write-only registers that allow you to issue commands, read-only registers that give you details about the controller status, and read-write registers with configuration settings.

All these OFFSET_... are register addresses. They are used internally by the module in order to operate, but you usually won't need to mess with them.

If you want more information about the registers, the datasheet is the place to go. You can also find more information in the Hacking section in the documentation of each module.

Color code

libtungsten can be used for projects ranging from very simple to very complex, and for this reason, some functions are aimed at more advanced users. Throughout the documentation, modules and functions follow a simple color code so that you know quickly if this is the feature you are looking for :

A green border marks basic functions that can (or even should) be used by everyone
An orange border marks more advanced functions that you might not use everyday, but are useful in some contexts
A red border marks expert function that should be used in specific situations when you know what you are doing; reading the code of these functions before using them is recommended
A gray border marks internal functions that are used by the library itself and that you should probably not use unless you know what you are doing