SAM-BA Functionality

Following on from our introduction to the SAM-BA® Bootloader, let’s now go over the functionality of the bootloader to better understand how we need to approach this. We’ll start by looking at the code behind it all.

Atmel Example Project

Fortunately, Atmel have already written the SAM-BA bootloader for the SAML21, and it can be viewed in Atmel Studio by selecting File > New > Example Project and searching for “samba”

SAM-BA Example Project

SAM-BA Example Project

Application Check

Let’s look at the start of the bootloader:

Before we initialise the system, we first check what program to execute: do we start the main program or do we stay in the bootloader?

SAM-BA Application Start-Up Check

SAM-BA Application Start-Up Check

This may look like a lot of code but it’s actually very simple:

This gets the address of the program

Note before when I mentioned that application could start at any address, not just at 0x1000 or 0x2000. Here we have defined the start of the application memory to be at 0x6000.

Since app_start_address is a pointer, it will return the value at that address:

The application start address is the location of the reset handler. Therefore, if there’s no reset handler to be found, there’s no application that can be called, so we must remain in the bootloader.

If the bootloader does discover that there is a reset handler to be called, it carries on executing:

This retrieves the state of SW0 (PIN PA02) which can be found on the SAML21 Xplained Pro board.

If the switch is being pressed, we should remain in the bootloader. This means that, even if the SAML21 has an application programmed, if the SW0 switch is held down during power-on it can start the bootloader.

If, however, the switch is not being held down then we continue executing:

Finally, we update the stack pointer to the start of our application, update the vector table and change the program counter to the reset handler of our application at 0x6000.

Or in simple terms, we start executing the program.

Let’s give this a try.

Demo

Once the bootloader has been programmed into the SAML21 Xplained Pro, we can connect to it using the SAM-BA software using a PC.

Connecting

Select the COM Port that the Xplained Pro is connected to and select saml21_xplained_pro from the list of boards. Then click connect.

Once loaded, we can see in the internal memory, and we can either write to or read from the flash.

At the top, under Memory Display, let’s set the start address to 0x6000 and hit Refresh.

The memory display has now changed and shows us the data stored in each memory location. As you can see in the image above, the memory locations starting at 0x000060000 are all set to 0xFFFFFFFF, ie, they’re empty. Remember before:

This is how the bootloader knows if there’s an application in the memory or not.

Writing an Application

Let’s now write an application to go into our memory. Start a new example project in Atmel Studio by selecting File > New > Example Project:

Type saml21 into the search bar and select “Getting-Started Application – SAM L21 Xplained Pro”

Once programmed, the SAML21 Xplained Pro will be begin running our application and the on board LED will start to flash. This only happens at the beginning of the program, but it’s enough for us to know that it’s running

Before I mentioned the application start address. If we were to look at the on-board flash currently, we’d see our “Getting Started” application at 0x00000000, so we need to change so that our application will work when programmed at a different address. Right click on the project name in the Solution Explorer and click Properties:

We then need to select Toolchain on the left, and select ARM/GNU Linker > Miscellaneous.

In the “Linker Flags” field, we need to add

Since:

If we now compile and program that, nothing will happen. But why?

Application Start Address

When Atmel Studio programs the compiled application, it starts programming at memory location 0x00006000, but the SAML21 will begin executing at 0x00000000 – which is blank. Our reset handler is never called and so our program never runs.

If we use the bootloader to program an application that is configured to start at 0x00000000, we run into a different problem. The bootloader will move the program counter to the application start address:

And this will call the reset handler at the beginning of our application. However, the reset handler will try to call the main function which it thinks will be around 0x00001A00. But instead, it’ll wind up executing some of the bootloader code and this will probably cause an error.

To explain this better, I’ll give an example. If we remove

From the linker flags of our “Getting Started” application and click “Start Debugging and Break” in Atmel Studio. Then we select Debug > Windows > Disassembly. The application will stop at the start of main() and the Disassembly window will show the memory location:

The yellow arrow in the Disassembly window shows where we are. In this case we’re at memory location 0x000019D8.

Therefore, if we programmed our application at 0x00006000 using the bootloader, after the reset handler the program counter will move to 0x000019D8 rather than 0x000079D8 which is where the main() function will be.

Programming our Application

Let’s re-compile our Getting Started application with the linker flag included to set the start address to 0x00006000 and we also need to re-program the SAM-BA bootloader back into the SAML21. Then, re-connect the bootloader using the PC software.

Once connected, we need to click the folder icon next to the “Send File” button and select our compiler application:

This can be found in the project folder under Debug. Note that the compiler outputs a .bin, .elf, .hex and many other files. They’re all used for debugging and the disassembly etc, but the .bin file is the raw data that we need to send.

If we click ‘Send’ now we’ll receive an error:

The address to send to the file to is set to 0x00000000, which is where our bootloader is. We need to adjust this to be the application start address:

And we can click send once again. This takes a few seconds to write, and we’re done. Before we carry on, let’s set our Memory Display start address to 0x00006000 and click Refresh:

We now have an application programmed. Let’s look at our .bin file for comparison:

Note that the SAML21 stores data “backwards”. That is for each 32-bit data word, each 8-bit byte of the word is stored sequentially, with the Least Significant Byte stored first. So the bytes 0xA8 0x21 0x00 and 0x20 are stored in each 32-bit memory location as 0x200021A8. Then next 4 bytes, 0xB9 0x77 0x00 and 0x00 are stored as 0x000077B9, and so on. This is what’s known as “Little Endian”.

If we now reset the SAML21 Xplained Pro, the on-board LED will start to flash and we will no longer be able to connect to the bootloader.

Scripts

If we reset the SAML21 Xplained Pro and hold down the switch SW0 as we do, the bootloader will load up and we can re-connect using the PC software. At the bottom of the SAM-BA window is “Scripts”, here we can do quite a few things with the chip using the bootloader:

  • Erase Application Area: this erases our chip, ie from 0x00006000 to the end of flash memory.
  • Invalidate Application: this is a quicker process as it simply erases the location that the bootloader checks. This means that the bootloader thinks the application doesn’t exist, but the majority of the data is still there in memory.
  • Read Device ID: the device ID tell the bootloader what the chip is, but it is not unique to each chip. There is a 64-bit unique ID programmed into every SAM chip, but this isn’t it. The device ID 0x1081010F is the SAML21J18B, which the chip we are using on the Xplained Pro.
  • Read fuses: returns the value of the fuse settings.
  • Read lock fuses: returns the current lock settings.
  • Set Lock Bit xx: sets the lock bit of each region of memory so that it cannot be accidentally overwritten.
  • Set Security Bit: sets the security bit so that the chip’s memory cannot be read.
  • Unlock All: unlocks all locked regions of memory so that they can be written to again.

Security Bit

Just as a little side note before we continue, the security bit on the SAML21 stops the internal flash memory from being read using an external interface. The SAML21 only supports SWD programming and testing so this is what we are referring to here. This means that connecting a debugger and trying to read the memory will be denied. This is standard practice for anyone wishing to stop people from copying their code.

Taken from SAML21 Datasheet

However, the internal memory can still be read by the application running on the chip. If the application could not read from the Flash, then no data could ever be stored after the power was removed. Since the SAM-BA bootloader is an application running on the chip, it can still read the internal memory, regardless of the security bit. Therefore, despite setting the security bit, we can still view the internal memory of the chip using the SAM-BA PC software, and we can also download the internal memory to a file.

Currently the SAM-BA bootloader does not check the security bit whilst reading memory to send back to the PC, and this is something that I am also going to address when adapting my bootloader.

If we click Erase Application Area and reset the SAML21 Xplained Pro, we’ll see that the bootloader will be loaded and we are back to a blank chip with just the bootloader running.

Methodology

Now that we can see how the SAM-BA software works, let’s look at how the bootloader software allows all of this to happen. Returning back to the bootloader software in Atmel Studio, the only file we will be focussing on from now on is sam_ba_monitor.c. The other parts of the software relate to the USART and USB interface with the connected PC.

SAM-BA Monitor

The SAM-BA monitor is the application that runs to allow the PC to manipulate the internal flash of the SAML21 and only runs if there is no application loaded. In main.c, the function sam_ba_monitor_run() is called continuously if either, a) a usb cdc interface has been initialised or b) if a # has been received via USART to indicate the start of a new connection with the SAM-BA PC software.

The bottom of this function shows how data is collected as it arrives:

Data is sent from the SAM-BA software as ascii and so this needs to be interpreted as it arrives. Ie the number 2000008C is actually sent as 0x32 0x30 0x30 0x30 0x30 0x30 0x38 0x43. Since the code above is nested inside a loop that goes through the received data one byte at a time (where ptr is a pointer to the current byte we’re looking at), we can parse this number and store it in current_number as we go.

Now the last two statements of the above if statement are very significant, as these deal with data bytes that aren’t 0-9, A-F or a-f, ie they aren’t numbers.

  • If the data bytes is a , (0x2c), we store current_number as ptr_data and reset current number back to 0.
  • If the received data is anything else, then store that byte as command.

SAM-BA Commands

Before we can really understand what’s happening we should go through the commands that SAM-BA uses:

The table in the SAM4E datasheet shows what commands we are going to be dealing with.

As you can see, commands are single letters that aren’t A-F or a-f, they either have 0, 1 or 2 numbers to go with them and they all end in # (0x23).

Note the commands N and T. There are two modes that the SAM-BA monitor can run in: normal mode and terminal mode. This relates to how data is sent to and from the PC:

– Normal mode sends data in binary format, that is, if the bootloader sends the number 0x2000008C to the PC, it will be sent as 0x20 0x00 0x00 0x8C.

– Terminal mode sends data in ascii format, that is, if the bootloader sends the number 0x2000008C, it will be sent as 0x32 0x30 0x30 0x30 0x30 0x30 0x38 0x43.

I won’t go into it too much since terminal mode is a bit irrelevant for what we want to do, so for now we’ll only concern ourselves with normal mode.

Otherwise the basic commands there are to write data bytes, read data bytes, write packets of data, read packets of data and to initiate an applet (command G).

In order to keep the bootloader as small as possible, the monitor deals with data as either:

  • Single Bytes/Words/Half Words
  • Packets of Data

SAML21 Memory Addresses

The SAML21 gives every possible memory location a unique address, so the Flash memory has the address 0x00000000 to 0x1FFFFFFF, the SRAM has the address 0x20000000 to 0x22007FFF, the peripherals have their own address (eg: the WDT has the addresses 0x40001C00 to 0x40001FFF) etc. This means that everything in the chip can be referenced in one way or another.

However, the method of addressing these is not always the same. For example, SRAM can be written to directly, whereas Flash has to be written to through the NVM controller.

Due to the way the SAM-BA monitor works, the write command can only write to SRAM whereas the read commands can read from any memory location. If you look through the SAM-BA source code, you won’t find any method of writing to Flash memory. Which begs the question, how does the bootloader write programs to Flash if it is unable to do so?

Applets

The answer to this question is actually very interesting. When the SAM-BA software starts, it sends the SAML21 a program to be written to SRAM. Once written it loads the PC software and reads data to be shown in the Memory Display and then waits for a command. The program that it writes to SRAM performs a series of functions that are referred to as “applets” and performs all the tasks that the SAM-BA software needs to do. The bootloader that is programmed into the SAML21 is only there to perform all the tasks required to load the applets up. This makes the bootloader itself as small as can be.

The application written to SRAM communicates with the bootloader via a “mailbox”. That is stored at a known location in SRAM. The bootloader will write any data required to the mailbox and then sets the program counter to the application in SRAM. This application will then read the mailbox to see what it needs to do, perform its task and then set the program counter back to the bootloader.

The application written to SRAM can be found in the install directory of the SAM-BA PC software under applets > saml21 > sam-ba_applets > flash. Note that different SAM chips have different memory types (NAND flash, NOR flash, SD card etc), and each memory requires its own applet to be loaded. The SAML21 is easy to deal with since it only has Flash memory.

Let’s look at 2 example applets that can be run:

Erase Application Area

When we call the “Erase Application Area” script in the SAM-BA PC software, the monitor calls the application in SRAM using the Call Applet command (G). Once loaded the application will check the mailbox for the command:

This is called for each section of the application memory in Flash, and thus allows the software to erase the entire Application Area of Flash.

Write Data

Another important function of the bootloader that is implemented using the application in SRAM, is writing data to Flash. Again this cannot be done using the SAM-BA monitor application alone, so an applet is called instead. When writing data to the Flash memory, the PC software send packets of data that is stored in SRAM, and the applet will retrieve this packet and write it to the appropriate address:

Conclusion

We’ve now looked at what the SAM-BA bootloader is and what it can do, all that’s left now is to analyse exactly whats happening between the PC software and the bootloader on the microcontroller. In my next post we’ll be looking at the communications that occur between the two so that we can get a complete understanding of  how the SAM-BA bootloader works. Once we have this knowledge, adapting the bootloader for our own needs will be a piece of cake.