MAX32665 SDK Documentation  0.2
Software Development Kit Overview and API Documentation
API Overview and Usage

Introduction

This document describes the MAX32665 Firmware SDK and gives a broad overview for new developers. This modular, flexible SDK increases the reusability of code between devices and gives the developer a robust framework for creating custom applications, hardware platforms, and libraries.

The MAX32665 Firmware SDK consists of example applications and peripheral drivers which use a common API. These components are contained in a directory tree, and the structure of the directory hierarchy is shown in Figure 1. The directory Applications holds the example applications and may contain any custom applications that the user creates. The Libraries directory contains the core CMSIS libraries, the chip-specific peripheral drivers, and the board support files.

Additional libraries may be included with the SDK, and the build environment allows for user-created libraries to be included into an application.

FirmwareSDKDirStruct.png
MAX32665 Firmware SDK Directory Structure

CMSIS

CMSIS is the Cortex Microcontroller Software Interface Standard produced by ARM and is used in this SDK. It is a standardized hardware abstraction layer that separates the complexity of the hardware from the software developer.

Figure 2 shows the hierarchy of the SDK libraries and APIs. The application layer primarily interacts with the peripheral drivers and the board drivers, but can also directly use the pointers and definitions in the CMSIS layer to manipulate the hardware.

FirmwareSDKHierarchy.png
MAX32665 Firmware SDK Hierarchy

Register-level Header Files

The MAX32665 microcontrollers contain multiple peripherals which can be configured through memory-mapped registers. The directory Libraries/CMSIS/Device/Maxim/<Device>/Include contains one header file per peripheral which defines a structure containing the registers for the peripheral. The header file also contains a set of C pre-processor definitions for each register to read and manipulate the bits within the associated register.

#define MXC_F_ADC_CTRL_CPU_ADC_START 1
typedef struct {
__IO uint32_t ctrl; /* 0x0000 UART Control Register */
__IO uint32_t baud; /* 0x0004 UART Baud Control Register */
__IO uint32_t tx_fifo_ctrl; /* 0x0008 UART TX FIFO Control Register */
/* .. registers omitted .. */
#define MXC_R_UART_OFFS_CTRL ((uint32_t)0x00000000UL)
#define MXC_R_UART_OFFS_BAUD ((uint32_t)0x00000004UL)
#define MXC_R_UART_OFFS_TX_FIFO_CTRL ((uint32_t)0x00000008UL)
#define MXC_F_UART_CTRL_UART_EN_POS 0
#define MXC_F_UART_CTRL_UART_EN ((uint32_t)(0x00000001UL << \\
MXC_F_UART_CTRL_UART_EN_POS))
#define MXC_F_UART_CTRL_RX_FIFO_EN_POS 1
#define MXC_F_UART_CTRL_RX_FIFO_EN ((uint32_t)(0x00000001UL << \\
MXC_F_UART_CTRL_RX_FIFO_EN_POS))
#define MXC_V_UART_CTRL_DATA_SIZE_5_BITS ((uint32_t)(0x00000000UL))
#define MXC_V_UART_CTRL_DATA_SIZE_6_BITS ((uint32_t)(0x00000001UL))
#define MXC_S_UART_CTRL_DATA_SIZE_5_BITS \\
((uint32_t)(MXC_V_UART_CTRL_DATA_SIZE_5_BITS << MXC_F_UART_CTRL_DATA_SIZE_POS))
#define MXC_S_UART_CTRL_DATA_SIZE_6_BITS \\
((uint32_t)(MXC_V_UART_CTRL_DATA_SIZE_6_BITS << MXC_F_UART_CTRL_DATA_SIZE_POS))

The example above shows a peripheral with several control registers. The “_R_” denotes a register definition, “_F_” denotes a field definition, “_V_” denotes a value definition, and “_S_” denotes a setting definition. Register definitions give the address offset in bytes from the start of the register struct. Field definitions with the “_POS” suffix denote the bit position of the field, or a mask for all of the bits in the field without the suffix. Settings are values that have been shifted into the proper bit position within a register. Also included with the register files is a device specific file that contains all of the unique addresses of the peripherals, definitions for memory sizes and locations, as well as interrupt vector numbers.

Startup Code

The directory Libraries/CMSIS/Device/Maxim/<Device>/Source contains the chip-specific startup file system_MAX32665.c. The routines in this file contain the compiler-agnostic CMSIS startup routines PreInit and SystemInit. Additionally, the Maxim CMSIS environment defines Board_Init in this file. The code PreInit and SystemInit handles device-specific configuration, and Board_Init is used to set up the board-specific configuration.

All three functions are defined as weak symbols and can be overridden by the application by simply declaring a function of the same name. This will not be necessary for most applications, but may be needed for unusual use cases. If these functions are overridden, care should be taken to copy all unmodified code from the weak functions or erroneous system behavior may result.

Each compiler has a unique directory for the startup code, which can be found in the Libraries/CMSIS/Device/Maxim/<Device>/Source/<Compiler> directory. The file startup_MAX32665.s contains the ARM NVIC interrupt vector table and the Reset_Handler function. Reset_Handler is the first function run by the CPU when reset is released. It performs initialization of static memory allocations and other C run-time setup, eventually transferring control to main.

Peripheral Drivers

Each peripheral of the microcontroller comes with a driver that provides an interface between the application and the hardware.

The drivers have a header file with definitions and function declarations. Descriptions for each API function are given in the header file and can also be found in this documentation. Most of the peripherals have associated examples illustrating a typical use case. The peripheral drivers are located in the directory Libraries/MAX32665PeriphDriver, with the header files located in the subdirectory Include.

Most use cases can be accomplished with the provided drivers, but specific modifications can be made using CMSIS device pointers and definitions from the register files.

System Layer

A driver, mxc_sys.c, is provided which controls the system level initialization to support many peripherals which require chip-specific configuration. This includes any pin or clock setup required to operate properly. While these functions are available to the application, most of the peripheral drivers will call these functions when necessary.

Board Support Package

The directory Libraries/Boards contains board-specific configuration files. All evaluation kits are supported by the configurations contained in the SDK. Each board configuration is located in a subdirectory of Libraries/Boards and common code is located in the two subdirectories Include and Source.

Custom boards created by developers should be added to this directory and modeled after the existing boards.

Synchronous vs. Asynchronous APIs

Many of the peripheral APIs included in the SDK are provided in both a synchronous and asynchronous form. The synchronous, or "blocking", calls will not return until the data has been written to or read from the underlying hardware. Note that writing to the hardware does not necessarily mean that the hardware has completed operating on the data.

The asynchronous calls will return immediately with a return status that indicates whether or not the request was queued successfully. If the request could not be processed for some reason, and appropriate error code will be returned. Otherwise, the callback registered by the asynchronous call will execute upon completion of the request. This callback will execute within the interrupt context of the driver.

When the API provides an asynchronous interface, the suffix _Async will be appended to the function name.

int SPIM_Trans(mxc_spim_regs_t *spim, spim_req_t *req);
int SPIM_TransAsync(mxc_spim_regs_t *spim, spim_req_t *req);

You must not interleave synchronous and asynchronous calls on any one peripheral. Doing so may cause unexpected or incorrect behavior. However, when using two different instances of a peripheral (e.g. SPI0 and SPI1), one instance may use the synchronous form while the other instance uses the asynchronous form.

Asynchronous callbacks are implemented with interrupts, and these interrupts need to be connected to the driver’s interrupt handler. This connection is demonstrated in the following code, which overrides the weak ISR function for SPI Master #0.

void SPIM0_IRQHandler(void)
{
SPIM_Handler(MXC_SPIM0);
}

Once an asynchronous request has been registered, it may be cancelled before completion with the API calls ending in _AbortAsync. The callback will be activated with the error code of Error Codes E_ABORT. Partial data may be available from an aborted request, and the application should check for this case.

Low-power API Considerations

The MAX32665 family of devices incorporates several low-power modes, which are managed by the Low-Power (prefixed by LP_) driver. These low-power modes are fully explained in the product's User’s Guide.

The low-power mode support for the MAX32665 SDK includes provisions for each driver to signal its readiness to enter a low-power mode. This information is important when asynchronous requests are pending, so that data-on-the-wire is not lost or corrupted by the microcontroller going into a low-power mode which deprives the peripheral of power or a clock signal.

Each API which is sensitive to low-power entry includes an API call ending in _PrepForSleep. For example, the UART API call is UART_PrepForSleep(). Before entry into LP1 or LP0, any application using a UART should call this function with the appropriate UART peripheral instance pointer (e.g. MXC_UART1). If the return code is not E_NO_ERROR, then the calling application should delay entry into LP1 or LP0 until this function returns E_NO_ERROR.

One common use of this API is to ensure that the console text output has been completely sent to a remote terminal.

//configure wake-up on GPIO
LP_ConfigGPIOWakeUpDetect(&gpioLP1, 0, LP_WEAK_PULL_UP);
printf("Enter LP1. Press SW2 to wake-up.\n");
while (Console_PrepForSleep()!= E_NO_ERROR);
LP_EnterLP1();

The while loop blocks until Console_PrepForSleep() reports that the UART is idle (i.e. the FIFO is empty and the stop bit has been shifted out the UART's TX pin).

The same call can be used to check that peripherals are not currently receiving data, as this may not be apparent to the main application until an interrupt or callback occurs.

Debug Assertions

The MAX32665 SDK provides macros which can generate run-time assertions during application development. These assertions will check failure cases which should not occur after application development and debugging has concluded, and will halt program execution in a manner configurable by the developer.

Since these assertions may reduce system performance, they can be disabled after the development and debugging phase. The assertions themselves will remain in the source code files, but they will not be checked and have no time penalty associated with them when disabled.

As an example, the following SDK library code utilizes assertions to trap error conditions during development.

int GPIO_Config(const gpio_cfg_t *cfg)
{
unsigned int pin;
int err = E_NO_ERROR;
MXC_ASSERT(cfg);
MXC_ASSERT(cfg->port < MXC_GPIO_NUM_PORTS);
/* .. more code follows .. */

These checks could be very time consuming when the application is running in production, so a C pre-processor definition is used to enable them only during debugging. This can be found in the Makefile.

# Enable assertion checking for development
PROJ_CFLAGS+=-DMXC_ASSERT_ENABLE

Once the application is fully debugged, the –DMXC_ASSERT_ENABLE definition can be removed. This removes all the logic within the MXC_ASSERT() statement from being generated at compile time.

Makefile Structure and Building Projects

Makefiles are used to build the libraries and example applications in the MAX32665 SDK. The SDK build environment relies on the GNU Make program.

The build process starts at the project Makefile, typically located in the root directory of the project. In this Makefile, many important make variables are set. The following table describes the names and the purpose of each.

Variable Description
PROJECT Defines the name of the application, which is also used as the output filename.
TARGET Sets the target processor (e.g. MAX32665, MAX32630).
TARGET_REV May be used to configure the drivers for a prior version of silicon.
COMPILER Selects the compiler initialization and linker map for this project.
BOARD Specifies the target board (system) for additional support drivers.
SRCS Holds a list of source files for this application.
PROJ_CFLAGS Adds extra C pre-processor definitions to the build.
MXC_OPTIMIZE_CFLAGSIf defined, overrides default optimization level. (e.g. -O0, -O2)

Other, less used options are below these core set of variables. They should not need to be modified for most applications.

Libraries used by the application will appear next in the Makefile. Each library resides in the Libraries directory, or a user-specified path, and is compiled into object files which reside in the build directory. These object files are then linked into static libraries, which will ultimately be linked with application code.

Building a project is straightforward; change directories into the example application and type make.

$ cd Firmware/MAX32665/Applications/EvKitExamples/SysTick
$ make
make -C ../../../Libraries/MAX32665PeriphDriver lib BUILD_DIR=/c/Maxim/Firmware/MAX32665/Applications/EvKitExamples/SysTick/build/PeriphDriver
make[1]: Entering directory '/c/Maxim/Firmware/MAX32665/Libraries/MAX32665PeriphDriver'
CC Source/clkman.c
CC Source/crc.c
CC Source/flc.c
CC Source/gpio.c
< ... >
AS /c/Maxim/Firmware/MAX32665/Libraries/CMSIS/Device/Maxim/MAX32665/Source/GCC/startup_MAX32665.S
CC /c/Maxim/Firmware/MAX32665/Libraries/CMSIS/Device/Maxim/MAX32665/Source/heap.c
CC /c/Maxim/Firmware/MAX32665/Libraries/CMSIS/Device/Maxim/MAX32665/Source/system_MAX32665.c
LD /c/Maxim/Firmware/MAX32665/Applications/EvKitExamples/SysTick/build/MAX32665.elf
$ ls –l build/MAX32665.elf
-rw-rw-rw- 1 joe.user allusers 551278 Aug 4 16:57 build/MAX32665.elf*
Note
It is not advisable to store your locally-developed application or modified examples in the evaluation kit installation directory, typically C:\Maxim on Windows, as updated versions of the ARM Cortex Toolchain may overwrite or remove these files and directories.