MCUXpresso SDK API Reference Manual  Rev. 0
NXP Semiconductors
 All Data Structures Functions Variables Typedefs Enumerations Enumerator Groups Pages
Architectural Overview

This chapter provides the architectural overview for the MCUXpresso DSC Software Development Kit (MCUXpresso DSC SDK). It describes each layer within the architecture and its associated components.

Overview

The MCUXpresso DSC SDK architecture consists of four key components listed below.

  1. Device-specific support files, such as header files, start-up and linker files.
  2. Peripheral Drivers
  3. Stacks and Middleware that integrated within the MCUXpresso DSC SDK
  4. Demo Applications based on the MCUXpresso DSC SDK
DSC_SDK_Block_Diagram.jpg
MCUXpresso DSC SDK Block Diagram

1. Device-specific support files

  • Each supported MCU device in the MCUXpresso DSC SDK has a dedicated System-on Chip (SoC) memory-mapped header file. This header file contains the memory map and register base address for each peripheral and the tables with associated IRQ/vector numbers. The SoC header file provides access to the peripheral registers through pointers and predefined bit masks.
  • In addition to the SoC memory-mapped header file, the MCUXpresso DSC SDK includes a dedicated feature header file for each device. The feature header file allows NXP to deliver a single software driver for a given peripheral. The feature file ensures that the driver is properly compiled for the target SOC.
  • Each device has its own dedicated start-up and linker files for the supported IDE/toolchain.

2. Peripheral Drivers

The MCUXpresso DSC SDK peripheral drivers mainly consist of low-level functional APIs for the MCU product family on-chip peripherals and also of high-level transactional APIs for some bus drivers/DMA driver/eDMA driver to quickly enable the peripherals and perform transfers.

All MCUXpresso DSC SDK peripheral drivers only depend on the soc header file, device feature files, fsl_common.h, and fsl_clock.h files so that users can easily pull selected drivers and their dependencies into projects. With the exception of the clock/power-relevant peripherals, each SOC has its own driver. Peripheral drivers handle the peripheral clock gating/ungating inside the drivers during initialization and deinitialization respectively.

Low-level functional APIs provide common peripheral functionality, abstracting the hardware peripheral register accesses into a set of stateless basic functional operations. These APIs primarily focus on the control, configuration, and function of basic peripheral operations. The APIs hide the register access details and various MCU peripheral instantiation differences so that the application can be abstracted from the low-level hardware details. The API prototypes are intentionally similar to help ensure easy portability across supported MCUXpresso SDK devices.

Transactional APIs provide a quick method for customers to utilize higher-level functionality of the peripherals. The transactional APIs utilize interrupts and perform asynchronous operations without user intervention. Transactional APIs operate on high-level logic that requires data storage for internal operation context handling. However, the Peripheral Drivers do not allocate this memory space. Rather, the user passes in the memory to the driver for internal driver operation. Transactional APIs ensure the INTC is enabled properly inside the drivers. The transactional APIs do not meet all customer needs, but provide a baseline for development of custom user APIs.

Note that the transactional drivers never disable an INTC after use. This is due to the shared nature of interrupt vectors on devices. It is up to the user to ensure that INTC interrupts are properly disabled after usage is complete.

Interrupt handling for transactional APIs

A double weak mechanism is introduced for drivers with transactional API. The double weak indicates two levels of weak vector entries. See the examples below:

__attribute__((weak)) static void QSPI0_XMIT_DriverIRQHandler(void)
{
default_interrupt();
}
#pragma interrupt alignsp saveall
__attribute__((weak)) void ivINT_QSPI0_XMIT(void);
__attribute__((weak)) void ivINT_QSPI0_XMIT(void)
{
QSPI0_XMIT_DriverIRQHandler();
}
#pragma interrupt off

The first level of the weak implementation(ivINT_IRQType) are the functions defined in the vector table. In the devices/<DEVICE_NAME>/<TOOLCHAIN>/<DEVICE_NAME>_Vectors.c file, the implementation of the first layer weak function calls the second layer of weak function. The implementation of the second layer weak function (ex. SPI0_DriverIRQHandler) calls default interrupt handler function default_interrupt. The MCUXpresso DSC SDK drivers with transactional APIs provide the reimplementation of the second layer function inside of the peripheral driver. If the MCUXpresso DSC SDK drivers with transactional APIs are linked into the image, the SPI0_DriverIRQHandler is replaced with the function implemented in the MCUXpresso DSC SDK SPI driver.

Figure belows shows the code path executed when QSPI interrupt happens

  • Entry of the vector table for QSPI is not re-defined in user application code
  • QSPI driver is not added into project
DSC_SDK_Double_Weak_No_Redefine.jpg
No Redefine Vector Entry

Figure belows shows the code path executed when QSPI interrupt happens

  • Entry of the vector table for QSPI is not re-defined in user application code
  • QSPI driver is added into project
DSC_SDK_Double_Weak_Driver_Redefine.jpg
Driver Redefine Vector Entry

Figure belows shows the code path executed when QSPI interrupt happens

  • Entry of the vector table for QSPI is re-defined in user application code, for example, the main.c file
DSC_SDK_Double_Weak_App_Redefine.jpg
User Redefine Vector Entry

The reason for implementing the double weak functions is to provide a better user experience when using the transactional APIs. For drivers with a transactional function, call the transactional APIs and the drivers complete the interrupt-driven flow. Users are not required to redefine the vector entries out of the box. At the same time, if users are not satisfied by the second layer weak function implemented in the MCUXpresso DSC SDK drivers, users can redefine the first layer weak function and implement their own interrupt handler functions to suit their implementation.

The limitation of the double weak mechanism is that it cannot be used for peripherals that share the same vector entry. For this use case, redefine the first layer weak function to enable the desired peripheral interrupt functionality. For example, if the MCU’s UART0 and UART1 share the same vector entry, redefine the UART0_UART1_IRQHandler according to the use case requirements.

3. Stacks and Middleware

See the relevant doc for stack and middleware in MCUXpresso DSC SDK package.

4. Demo Application

See the Getting Started with MCUXpresso SDK document (MCUXSDKGSUG) for each board.