When dealing with a microcontroller (or more generally with any electronic component) the most important document by far is the datasheet. This document will provide every information you need about the component, such as a general presentation, electrical characteristics, pinouts, packages description, registers documentation, application examples...
The latest version of the datasheet for the Atmel SAM4L lines of microcontrollers can be found on Atmel's website : http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-42023-ARM-Microcontroller-ATSAM4L-Low-Power-LCD_Datasheet.pdf (take the Complete version). A miror is available here.
As you can see, with more than 1200 pages, this is not a light read. But don't worry, most of the content is not not useful at first, so we will start by browsing through it chapter by chapter to grasp a global view of its organisation. Once you understand how the document is organized, it will be much simpler to dive into specific sections when you need to get more information about something specific.
N.B. : the information on this page is dedicated to the SAM4L datasheet, the datasheets of other microcontrollers might be different. There should be similarities though, so even if you will be using a different microcontroller in the future, having read and understood this datasheet before should help you greatly.
The first few pages offer a succint description of the microcontroller, its peripherals and its features. It doesn't go into too much details and it's always interesting to know what you are dealing with, so it's a good idea to skim it.
Some people like to have a big global diagram of a system to better visualize how everything is connected, so here it is. You do not need to understand every detail at first, but you can already notice :
After this diagram, a few tables describe the differences between the different models in the SAM4L line. For example, Carbide implements an ATSAM4LS8B with 64 pins and without an LCD controller.
Pinouts descriptions are only useful if you want to implement another variation of SAM4L into your project.
Peripheral Muxing tables are already implemented in the library's pin definition files, but if you were wondering where it came from, this is it. You might need these tables if you implement another variation of the SAM4L. More information on this subject can be found in the Pin muxing tutorial.
Signals Description and I/O Line Considerations give more information about the peripheral signal lines and some electrical specifics of some pins.
This chapter describes how Atmel implemented the Cortex M4 core into its SAM4L microcontroller. This core is not designed by Atmel but is a generic design by ARM (the company) that is implemented (with some options) by microcontrollers manufacturers such as Atmel, ST, Freescale or Texas Instruments. For this reason this chapter is relatively short, the most interesting informations are the implementation options and the interrupt map, which you can find implemented in
core.h. The Cortex M4 core has its own datasheet provided by ARM : the ARMv7-M Architecture Reference Manual (miror).
The chapters 5. Power and Startup Considerations, 6. Low Power Techniques, 7. Memories and 8. Debug and Test are more advanced chapters that you don't really need to read unless you want to know more about these specific topics. One interesting bit of information though is the Memories Mapping diagram in section 7.1 which gives an overview of how the memory space is organised.
This is probably a good time to talk about memory space. As you know, the Cortex M4 is a 32-bit microcontroller, which means that memory addresses are coded on 32 bits (4 bytes, also usually called 1 word), so an address might look like this :
0x4003C008. This represents about four billion memory addresses (collectively refered to as "memory space"), and since there is way less than 4GB of RAM and Flash embedded in the microcontroller, this leaves tons of unused addresses which can be used to interface the other peripherals.
The key concept to understand here is that the memory space is somewhat virtual, and a memory address does not necessarily translate into a physical storage byte in Flash or RAM. It is simply a standardised way to read and write data from and to other peripherals. Each peripheral has its own subset of the memory space reserved for its use (a block), and every address used by a peripheral is implicitely an offset relative to its block's base address. If you write to the RAM address block, you will write into physical RAM memory but if you write into a peripheral address block, you might write to a peripheral register (we will talk about registers shortly).
This is precisely the information given by the Memory mapping diagram in chapter 7. As you can see, the memory space starts at
0x00000000 with the internal Flash array, up to
0x00800000 (maximum, it depends on the amount of actual Flash memory available in your version of the microcontroller). This means that reading from the address
0x00001234 will read the address offset
0x1234 from the Flash memory. The RAM extends from
0x20010000 (again, maximum depending on the amount of RAM you have), so all the variable addresses that you can see in GDB will start with
0x2000xxxx. The peripherals address space, where the microcontroller peripherals expose registers to control their behaviour, ranges from
0x60000000, and inside this block, the block reserved for the SPI controller ranges from
0x4000C000. Finally, the block beyond
0xE0000000 is reserved for internal registers of the Cortex M4 core itself, and are described in the ARMv7-M Architecture Reference Manual.
This is the big part. Each of these chapters describes a single peripheral : its purpose, its registers, its requirement and its functionning. Fortunately, all these chapters follow the same layout to facilitate reading :
As you can see in User Interface, each register is defined by its name, access type and offset address. As explained earlier, this offset should be added to the base address of the peripheral given in the Memory mapping diagram in chapter 7. For example, the address
0x4003C008 that we saw at the beginning is in the DACC block (blok address
0x4003C000), register CDR (Conversion Data Register) (offset
0x08). With proper configuration, writing to this address will change the voltage applied to the DAC output pin.
The access type can be Read-Only, Write-Only or Read-Write. Most configuration registers are Read-Write; registers containing temporary data (such as the value of the last byte received on an USART port) will usually by Read-Only, because they are updated by hardware and writing to them wouln't make sense; and registers used to give the hardware an instruction are write-only, because they trigger an operation when written but do not hold any information themselves.
A register can be seen as an independant 4-byte long RAM cell implemented inside the peripheral that can be read and/or written by software (through usual memory access instructions) and by hardware. However, unlike RAM cells, registers are not always passive : the act of reading or writing a register can trigger often other operations. For example, reading the RHR (Receiver Holding Register) of the USART peripheral will not only give you the content of the register (therefore, the value of the last byte received) but also reset the register and mark it free to receive the next byte. Writing the CDR (Conversion Data Register) of the DAC controller will trigger a conversion and updat the output. Writing configuration registers will also usually perform tasks in the background to take the change into account.
Another common application of such triggers is a common scheme that we can call single-bit operations.
Consider this problem : how can we reliably change a single bit in a register? We would usually need to read the register value into a variable, make the change, and write the variable back into the register. However, this requires multiple steps, and if the hardware updated the register in the middle of our operation, this update will be overwritten when the value is written back.
To solve this problem, we need to be able to physically write only the bits that we are interested in, and let the others untouched, without the whole read/change/write back process. This is achieved by adding two new registers with write-only access : one to set bits, and one to reset bits.
This is most commonly used for Interrupt Registers. Most peripherals provide interrupts to let the user know when a specific event happened, and each interrupt source can be individually enabled or disabled. The enabled state of each interrupt is configured in the IMR (Interrupt Mask Register) register of each peripheral, and we need to be able to perform single-bit operations on this register. Therefore, IMR is defined as Read-Only and two more registers are provided as Write-Only : IER (Interrupt Enable Register) and IDR (Interrupt Disable Register). When writing to IER or IDR, only the bit written to 1 will be updated in IMR : if writing to IER the corresponding bits in IMR will be set to 1, if writing to IDR the corresponding bits in IMR will be reset to 0.
This chapter provides all the information you need related to the electrical capabilities of the microcontroller : maximum voltages, power supply caracteristics, clock speeds, ADC and DAC performance specifications... You only need to go through it if you need to know a specific number related to these topics.
This describes packages and references, only useful if you are planning to implement the microcontroller into your own board.
Now that you have a basic understanding of how peripherals and registers work and where you can find the information you need, you can go further and learn how to actually do stuff with this by looking at the library's code. Start by taking a look at the Overview if you haven't already, then choose a peripheral and keep side-by-side the code, its documentation here, and the corresponding chapter in the datasheet. You should quickly start to see the relationship between them and understand how the drivers work. Don't forget to take a look at the Hacking section in the documentation, which gives more information about the internal functionning of the module.