Using SparkFun Edge Board with Ambiq Apollo3 SDK

Contributors: Liquid Soulder
Favorited Favorite 4

Example Applications

Having arrived here you should have all the components that you need to write an application for the Apollo3:

  • The SDK that contains useful source files and other definitions
  • An ARM compiler to translate your code into machine instructions
  • Make and a Bash shell to use to build the projects.

Coming up next we will look at two example projects. The first will be a basic demonstration of some hardware capabilities like GPIO, UART, ADCs, and I2C communication and it will be pre-configured to build. The second example will be a simple "Hello World" with the main intent of explaining how to set up your own build process.

The examples live in the SparkFun Edge Board Support Package (BSP), which you (hopefully) got while setting up the toolchain. To ensure that the makefile in the first example works be sure to place your copy of the repo in the $AMB_ROOT/boards/ folder. You can achieve the same effect in a number of ways:

  • Using Git, clone the repo directly into $AMB_ROOT/boards/ so that you can pull updates as they become available
  • Using Git, clone to a location of your preference and make a symbolic link to the $AMB_ROOT/boards/ directory
  • Download the repo as a .ZIP and extract it into the $AMB_ROOT/boards/ directory.

Whichever method you choose you should end up with the directory $AMB_ROOT/boards/SparkFun_Edge_BSP that contains the BSP contents.

Get the SparkFun Edge Board Support Package here or by clicking the download link below:

Example: Edge Test

This example will test the hardware features of the Edge board as a starting point to get acquainted with the features of the SDK. The expected behavior of this example is to turn on all four LEDs and transmit data from one microphone and the accelerometer over the serial connection at 115200 baud. When you press Button 14 the loop will break and the board will turn off to conserve power.

If you've followed the rest of this tutorial then getting this example working should require only a few steps. In your Bash shell navigate to $AMB_ROOT/boards/SparkFun_Edge_AmbiqSDK_BSP/examples/example1_edge_test/gcc. This is where the makefile for the gcc toolchain lives. The only change that you should have to make to it to get everything working is to choose the correct serial port.

  • Arduino provides a pretty convenient and cross-OS way to see all available serial ports - just use the 'Tools->Port' dialogue.
  • On Mac, you can simply list ls /dev/tty.*
  • On Unix-like operating systems you should also be able to show all available serial ports by entering ls /dev/cu* into the Bash shell.
  • On Windows (command prompt, cmd.exe) the mode command will list COMX ports, but they have to have an open connection which sort of defeats the purpose in my opinion.

Now use your favorite text editor to open that file (gcc/Makefile) and replace COM4 with the serial port that your Edge board is connected to (On Windows it will look like COMX, and on Unix-like systems it will be a short string beginning with /dev/cu)

#### Bootloader Configuration
SERIAL_PORT ?= COM4# Or perhaps a Unix-like machine might put '/dev/cu.usbserial-1410' 

Let's make sure that there is a nice area for make to work: enter make clean at the Bash prompt.

Flashing Code to Board

Now to flash your code to the Edge hold down Button 14, press and release reset, and type make bootload into your Bash shell. The process that unfolds should take you through compiling and linking the application, then begin uploading the code.

The uploader script will automatically try to reset the board when it says 'Sending Reset Command,' but if it has trouble it helps to do it manually -- just let go of Button 14 and press reset (some USB-serial bridges seem to work better than others in this scenario). If you have an error like 'could not open port', make sure that the right port is selected and that there are no other serial terminals connected.

Once the code is uploaded, use your favorite serial terminal program to inspect the output (115200 baud).

  • For Windows, the serial terminal will be such as we listed in the introduction - either via Arduino, CoolTerm, or Putty
  • For Mac, you can list the serial output by using screen <device> 115200 ie: screen /dev/tty.usbserial-DN05KQGX 115200
  • Unix systems can also use the screen command as such: screen /dev/device baud-rate

Try hitting Button 14 to exit the main loop and turn off the board - then press 'reset' to start it up again.

To help guide you to your own exploration of the chip let's look at how we used Ambiq's Hardware Abstraction Layer (HAL) to perform GPIO functions. First off we included am_mcu_apollo.h which in turn includes a whole lot of HAL headers like am_hal_gpio.h. Then we looked through the HAL GPIO header and got a feel for how to use it.

  • When setting up the board we use am_hal_gpio_pinconfig() along with a pre-defined pin configuration structure called g_AM_HAL_GPIO_OUTPUT_12 which indicates an output that can drive up to 12 mA. We also use some pin number definitions like AM_BSP_GPIO_LED_RED that come from our Board Support Package in the am_bsp_pins.h file.
  • To set or clear the output of a pin we use am_hal_gpio_output_set() or am_hal_gpio_output_clear() respectively.
  • To read the value of a pin we use am_hal_gpio_state_read() - a catch here is that the return value of this function is an error code. The value on the pin is returned by passing the function a pointer to the variable that you'll use to store the value.

You can explore the HAL in the SDK at $AMB_ROOT/mcu/apollo3/hal to find information about the ADCs, Bluetooth, timers, interrupts, I/O masters (I2C or SPI) and a lot more!

Example: Makefile Project Template

This example will cover what you need to know to start making your own projects on your filesystem and include source and header files of your own for library management. We will go into more detail about what happens when you use make or make bootload.

To get the ball rolling let's look at the first few lines of code in SparkFun_Edge_Project_Template/gcc/Makefile.

# Here are some user modifiable settings. Note that leading spaces are used to separate strings when appending to a variable
TARGET := SparkFun_Edge_Project_Template# this name is the name of the resulting binary file
PROJECT := SparkFun_Edge_Project_Template_gcc

COM_PORT             = COM4
SDKPATH              = # Note that if you copy/paste a windows file path here you need to change backslashes to forward slashes
BOARDPATH            = ${SDKPATH}/boards/SparkFun_TensorFlow_Apollo3_BSP# One day I hope to rename the BSP folder to: SparkFun_Edge_AmbiqSDK_BSP

USER_INCLUDE_DIRS    = -I../src/inc1
USER_INCLUDE_DIRS   += -I../src/inc2

USER_SOURCEDIRS      = ../src
USER_SOURCEDIRS     += ../src/inc1
USER_SOURCEDIRS     += ../src/inc2

USER_MAIN_SRC        = main.c

Here we are declaring, initializing, and sometimes appending to variables that will be known to make when it executes.

  • TARGET: is the prefix of the binary file that will be created
  • PROJECT: is unused
  • COM_PORT: is the serial port to use when uploading code with 'make bootload'
  • SDKPATH: should be the path to the root directory of the SDK
  • BOARDPATH: is the path to the BSP folder

The next two variables USER_INCLUDEDIRS and USER_SOURCEDIRS inform the process where to look for files. The include directories are given to the compiler as flags so they are prefixed with '-I'. The source directories tell make where to look for source files that the user wants to compile. In both cases the append operation '+=' is used to add more lines. It is important to include a space after the '=' sign so that all your paths remain separated.

The last two variables USER_MAIN_SRC and USER_SOURCE_FILES are used to create a list of all the files to compile.

The above variables are all that you should need to set up to have a successful build. You can try it out by making sure you're in the directory SparkFun_Edge_Project_Template/gcc and then entering make into the command prompt. If there are no errors then the /bin directory will contain a '.bin' file with the name that you chose for the TARGET variable. Entering make bootload with Button 14 held down, and hitting reset once prompted, should get your code on the board.

Now let's take a moment to explore the highlights of what exactly gets done with those variables that you defined. A little way down the prefix of compiler executables is listed as a variable along with other values to give t the compiler in the PART, CPU, and FPU flags. Then the suite of suffixes for C / C++ compilation, linking, and other toolchain elements are given short easy names like CC, GCC, CPP, and LD. After this the included directories and files that you defined at the top are combined with those coming from the SDK. Near the end, the makefile automatically assembles a list of recipes that explain the dependencies in the build process. To wrap it all up the makefile actually spits out the commands required to build the executable (.bin) into the shell. As a cherry on top if you used 'make bootload' then it will also create an Over The Air (OTA) image blob, convert it to a wire update blob, and then begin the serial upload process using a few Python scripts.

Now, go boldly into development for this powerful new microcontroller armed with the knowledge of exactly how your application gets from a smattering of source code to a lean mean machine-code package.