3. BSP

3.1. Drivers

3.1.1. Introduction

The SDK provides Low Level Drivers (LLD) for each of the available hardware peripherals of the DA1470x device.

The LLDs expose simple APIs for accessing and using the device peripherals without detailed knowledge of the hardware implementation, such as bits and their position within hardware registers.

For each hardware peripheral, a dedicated header file describes the API functions of the peripheral, lists capabilities and defines control structures which are needed to interact with its particular LLD.

All LLD API functions share some common characteristics:

  • They all start with hw_.

  • They are declared inside sdk/bsp/peripherals/include/hw_*.h header files.

  • They are documented using Doxygen style comments, which describe their input and output parameters, any data types they may use, etc.

The SmartSnippets™ DA1470x SDK Documentation (generated with Doxygen) provides a helpful html reference for the LLD API, as well as for all other APIs of the SmartSnippets™ DA1470x SDK. The main page (shown in Figure 4) is located at <SDK_ROOT_PATH>/doc/html/index.html and can also be accessed from within SmartSnippets™ Studio (API documentation section of the Welcome page).

../_images/DA1470x_SDK_Doxygen_documentation_mainpage.png

Figure 4 SmartSnippets™ DA1470X SDK Doxygen Documentation main page

Warning

All drivers and adapters in the SmartSnippets™ DA1470x SDK are supplied in full source to aid debugging. However, modifying the drivers is not recommended.

Warning

It is recommended to only use the LLD functions in order to access the device peripherals, as the LLDs are tested and verified. Direct access to hardware resources (e.g. registers or peripheral interfaces) might lead to conflicts with lower level FW functions accessing the same resources through LLDs and therefore lead to system instability.

3.1.2. List of provided LLD APIs

Table 2 LLDs overview

Filename

Description

hw_aes.h

Crypto engine (AES-specific functions).

hw_aes_hash.h

Crypto engine (AES/HASH common functions).

hw_bod.h

Brown-Out Detection circuit.

hw_bsr.h

Busy Status register.

hw_cache.h

Cache controller.

hw_charger.h

Battery Charger.

hw_clk.h

Clock generator.

hw_cpm.h

Clock & Power manager helper functions.

hw_crypto.h

Crypto engine (core functions).

hw_dcache.h

Data Cache controller.

hw_dma.h

Direct Memory Access (DMA) controller.

hw_emmc.h

Embedded Multi-Media Card (eMMC) Host controller.

hw_gpadc.h

General purpose Analog-to-Digital Converter (GPADC).

hw_gpio.h

General Purpose Input/Ouput (GPIO) controller.

hw_hard_fault.h

Hard-Fault Handler.

hw_hash.h

Crypto engine (HASH-specific functions).

hw_i2c.h

I2C controllers.

hw_i3c.h

I3C controller.

hw_iso7816.h

ISO7816 Uart controller.

hw_lcdc.h

LCD controller.

hw_led.h

LED driver.

hw_memctrl.h

Memory controller.

hw_mpu.h

Memory Protection Unit.

hw_oqspi.h

Octa/Quad SPI Flash Controller.

hw_otpc.h

One-Time Programmable (OTP) memory controller.

hw_pcm.h

PCM interface (Audio unit).

hw_pd.h

Power Domains (on/off/status functions).

hw_pdc.h

Power Domain Controller.

hw_pdm.h

PDM interface (Audio unit).

hw_pmu.h

Power Management Unit.

hw_qspi.h

Quad SPI Flash/RAM controller.

hw_rtc.h

Real Time Clock controller.

hw_sdadc.h

Sigma-Delta Analog-to-Digital Converter (SigmaDeltaADC) controller.

hw_sdhc.h

Secure Digital Input/Output (SDIO) Host controller.

hw_spi.h

SPI controllers.

hw_src.h

Sample Rate Converter (SRC) (Audio unit).

hw_sys.h

System-wide / miscellaneous functions.

hw_sys_regs.h

Register-configuration common functions.

hw_timer.h

General purpose timers.

hw_trng.h

True Random Number Generator controller.

hw_uart.h

UART controllers.

hw_usb.h

USB controller.

hw_usb_charger.h

USB Charger Detection circuit.

hw_usb_dev_framework_defs.h

USB framework type definitions.

hw_vad.h

Voice Activity Detection engine.

hw_watchdog.h

Watchdog timer.

hw_wkup.h

Wake-Up controller.

3.2. Board Abstraction Layer

3.2.1. Introduction

In order to easily port basic SDK interfacing functions (serial port, buttons etc.) on different boards, the SDK defines a set of Input/Output-related macros, useful for this kind of I/O configuration. These macros are placed in a predefined board configuration header, aligned with the supported DKs. If there is a need for the application to support a custom board, then a separate header file needs to be created. The latter will override the one provided by the SDK. The application needs to follow the next steps:

  1. Add #define dg_configUSE_BOARD in the custom header file.

  2. Create a header file e.g my_board.h using the same macro-names as in the code snippet below.

  3. Update the compiler’s include-directories.

The SDK includes board configuration files for all the supported development kits located in bsp/config/boards folder. The contents of the configuration file for the proDK development kit (bsp/config/boards/brd_prodk_da1470x.h) are shown below:

Code 2 proDK Board configuration file
/* Serial port configuration section */
#define SER1_UART       (HW_UART2)

#define SER1_TX_PORT    (HW_GPIO_PORT_0)
#define SER1_TX_PIN     (HW_GPIO_PIN_8)
#define SER1_TX_MODE    (HW_GPIO_MODE_OUTPUT)
#define SER1_TX_FUNC    (HW_GPIO_FUNC_UART2_TX)

#define SER1_RX_PORT    (HW_GPIO_PORT_2)
#define SER1_RX_PIN     (HW_GPIO_PIN_1)
#define SER1_RX_MODE    (HW_GPIO_MODE_INPUT)
#define SER1_RX_FUNC    (HW_GPIO_FUNC_UART2_RX)

#define SER1_RTS_PORT   (HW_GPIO_PORT_0)
#define SER1_RTS_PIN    (HW_GPIO_PIN_29)
#define SER1_RTS_MODE   (HW_GPIO_MODE_OUTPUT)
#define SER1_RTS_FUNC   (HW_GPIO_FUNC_UART2_RTSN)

#define SER1_CTS_PORT   (HW_GPIO_PORT_0)
#define SER1_CTS_PIN    (HW_GPIO_PIN_11)
#define SER1_CTS_MODE   (HW_GPIO_MODE_INPUT)
#define SER1_CTS_FUNC   (HW_GPIO_FUNC_UART2_CTSN)

/* KEY configuration section */
#define KEY1_PORT       (HW_GPIO_PORT_1)
#define KEY1_PIN        (HW_GPIO_PIN_22)
#define KEY1_MODE       (HW_GPIO_MODE_INPUT_PULLUP)
#define KEY1_FUNC       (HW_GPIO_FUNC_GPIO)

#define KEY2_PORT       (HW_GPIO_PORT_1)
#define KEY2_PIN        (HW_GPIO_PIN_23)
#define KEY2_MODE       (HW_GPIO_MODE_INPUT_PULLUP)
#define KEY2_FUNC       (HW_GPIO_FUNC_GPIO)

3.3. Wake-Up Controller

3.3.1. Introduction

The Wake-Up Controller HW block belongs to the Sleep power domain (PD_SLP) and can be programmed to wake up the DA1470x from the Extended and Deep Sleep (clocked). It consists of two parallel circuits that produce two different event sources: the KEY_WAKEUP and the GPIO_WAKEUP. Apart from waking up the system, the Wake-Up Controller can also be used to provide information about a change in the voltage level of a GPIO input pin, while the system is active. In case DA1470X has to wake up from hibernation, then the Wake-Up from Hibernation Controller has to be used. Please refer to chapter Wake-Up from Hibernation Controller for more details.

  • KEY_WAKEUP:

    Is used to monitor GPIOs levels and triggers the interrupt KEY_WKUP_GPIO_IRQ when a level is changed. A debounce counter can be programmed to debounce the GPIO changed level before the interrupt is triggered. If wkup_enable_irq is set, both M33 and PDC are able to catch the interrupt. KEY_WKUP_GPIO_IRQ is kept asserted until acknowledged by SW, so M33 is capable of receiving it even if it was triggered during sleep.

    Note

    M33 should be programmed to accept and acknowledge this interrupt in order for Wake-Up Controller to be able to trigger it again.

    Note

    This circuit can wake up M33 from Extended and Deep Sleep mode (clocked) if PDC is programmed accordingly.

    Note

    M33 and PDC are not aware of which GPIO pin triggered the KEY_WKUP_GPIO_IRQ.

  • GPIO_WAKEUP:

    Is used to monitor the GPIO edges (positive or negative) and levels (high or low). In contrast to the KEY_WAKEUP circuit, the GPIO pin which triggered the Wake-Up Controller is stored to WKUP_STATUS_P0_REG or WKUP_STATUS_P1_REG or WKUP_STATUS_P2_REG depending on the GPIO port of the pin. This circuit produces three signals, the interrupts GPIO_P0_IRQ, GPIO_P1_IRQ and GPIO_P2_IRQ towards M33 and a bus signal towards PDC which delivers the contents of the WKUP_STATUS_X_REG. M33 can access WKUP_STATUS_X_REG and is able to identify the GPIO pin and execute the corresponding ISR routine. PDC can identify as well the triggering source through the signal and execute the corresponding PDC entry.

    Note

    M33 should clear the WKUP_STATUS_X_REG in order to acknowledge the interrupt otherwise the interrupt will remain asserted.

    Note

    This circuit can wake up the system from any clocked sleep (Deep or Extended Sleep) if PDC is programmed accordingly.

Both circuits can be configured to trigger either M33 or PDC or both. If there is no PDC LUT entry then PDC will not take any action. The same applies in M33, if the interrupts are not enabled in NVIC then M33 will not be notified.

3.3.2. Low level driver

Low level Wake-Up Controller handling is implemented in the hw_wkup Low Level Driver (LLD):

  • <SDK_ROOT_PATH>/sdk/bsp/peripherals/include/hw_wkup.h

  • <SDK_ROOT_PATH>/sdk/bsp/peripherals/src/hw_wkup_v2.c

Because Wake-Up Controller API is very extensive we will focus on the description of very basic functions.

  • Initialize the Wake-Up Controller. See:

    • hw_wkup_init() to initialize the GPIO ports (necessary step for both circuits)

    • hw_wkup_configure() to configure the GPIO we are interesting in (necessary step for both circuits)

    • hw_wkup_set_key_debounce_time to set a debounce timer for the KEY_WAKEUP path.

  • Configure GPIO ports. See:

    • void hw_wkup_set_trigger() to configure a GPIO to trigger a wake up event. The following configurations are possible:
      • high/low level for KEY_WAKEUP path if trigger is HW_WKUP_TRIG_LEVEL_HI_DEB/HW_WKUP_TRIG_LEVEL_LO_DEB

      • high/low level for GPIO_WAKUP path if trigger is HW_WKUP_TRIG_LEVEL_HI/HW_WKUP_TRIG_LEVEL_LO.

      • high/low edge for GPIO_WAKUP path if trigger is HW_WKUP_TRIG_EDGE_HI/HW_WKUP_TRIG_EDGE_LO.

      • not used by wake up controller if trigger is HW_WKUP_TRIG_DISABLED

  • Register interrupts. See:

    • hw_wkup_register_key_interrupt() to register an ISR routine for the KEY_WAKEUP path.

    • hw_wkup_register_gpio_p0_interrupt() to register a callback function in order to serve the GPIO_WAKEUP interrupt events of the GPIO port 0.

    • hw_wkup_register_gpio_p1_interrupt() to register a callback function in order to serve the GPIO_WAKEUP interrupt events of the GPIO port 1.

    • hw_wkup_register_gpio_p2_interrupt() to register a callback function in order to serve the GPIO_WAKEUP interrupt events of the GPIO port 2.

  • Read/clear WKUP_STATUS_X_REG valid only for GPIO_WAKEUP path. See:

    • hw_wkup_get_gpio_status()

    • hw_wkup_clear_gpio_status()

  • Clear/reset KEY_WAKEUP path interrupt. See:

    • hw_wkup_reset_key_interrupt Use this to clear interrupt in KEY_WAKUP path.

3.3.3. Using Wake-Up Controller in an application

This section describes how to setup Wake-Up Controller to fire an interrupt targeting M33.

First configure Wake-Up Controller for KEY_WAKEUP path.

Code 4 Setup wake up controller for KEY_WAKEUP input
#include "hw_wkup.h"

// user defined KEY_WKUP_GPIO_IRQ handler
void wkup_handler(void);

// initialize wake-up ctrl
hw_wkup_init(NULL);

// set debounce time to 10 ms
hw_wkup_set_key_debounce_time(10);


// set user defined KEY_WKUP_GPIO_IRQ handler
hw_wkup_register_key_interrupt(wkup_handler, 1);

// enable KEY_WKUP_GPIO_IRQ to controller
hw_wkup_enable_key_irq();

// configure Wake-Up Controller to fire KEY_WKUP_GPIO_IRQ when P0_6 goes low
hw_wkup_set_trigger(HW_GPIO_PORT_0,
                    HW_GPIO_PIN_6,
                    HW_WKUP_TRIG_LEVEL_LO_DEB);

A button press will assert the KEY_WKUP_GPIO_IRQ which is routed both to PDC HW block and M33 NVIC. The configuration applied so far is effective while M33 is active: as long as M33 is active and KEY_WKUP_GPIO_IRQ is enabled in NVIC, M33 will fire the corresponding ISR. However a button press will not have any effect if M33 is in sleep mode since we have not programmed a PDC LUT entry to wake up M33 from that trigger source.

The following snippet describes how we can configure Wake-Up Controller to fire GPIO_Px_IRQ to M33.

Code 6 Setup wake up controller for GPIO_WAKEUP edge trigger
#include "hw_wkup.h"

// user defined GPIO_P0_IRQ handler
void wkup_gpio_handler(void) {

    /* just do something*/

    //clear the status of GPIO 0-0
    hw_wkup_clear_gpio_status(HW_GPIO_PORT_0, 0x1);
};

hw_wkup_init(NULL);

// set user defined GPIO_P0_IRQ handler
hw_wkup_register_gpio_p0_interrupt(wkup_gpio_handler, 1);

// configure Wake-Up Controller to fire GPIO_P0_IRQ when P0_0 goes low
hw_wkup_set_trigger(HW_GPIO_PORT_0,
                    HW_GPIO_PIN_0,
                    HW_WKUP_TRIG_EDGE_LO);

A button press will assert the GPIO_P0_IRQ which is routed both to PDC HW block and M33 NVIC. The configuration applied so far is effective while M33 is active: as long as M33 is active and GPIO_P0_IRQ is enabled in NVIC, M33 will fire the corresponding ISR. However a button press will not have any effect if M33 is in sleep mode since we have not programmed a PDC LUT entry to wake up M33 from that trigger source.

3.3.4. Wake-Up from Hibernation Controller

Low Level Driver (LLD) is located at the same files with Wake-Up Controller. Its HW block belongs to Always-On power domain (PD_AON). Only four specific GPIO and VBUS_AVAILABLE can wake up the device from a hibernation state. GPIO can trigger wake up only at a rising edge pulse. These pins are P0_20, P0_29, P1_04 and P0_28.

Its API consists of the next two functions:

  • hw_wkup_configure_hibernation() to configure which GPIO will wake up the system from hibernation, and whether an external pull down resistor is connected on it.

  • hw_wkup_set_hibernation_mode() to configure whether the system will go to hibernation sleep mode or not.

3.4. PDC

Power Domain Controller (PDC) is the HW block which:

  • coordinates the state of the system’s power domains.

  • provides master to master signaling services.

  • manages the 32 MHz crystal oscillator.

PDC registers belong to the sleep power domain (PD_SLP).

3.4.1. Power domains overview

Apart from the Always-On power domain, DA1470x’s power domains can be divided into the following categories:

  • Power domains which contain masters

  • Power domains which do not contain masters but can be controlled by PDC

3.4.1.1. Master power domains

The DA1470X SoC contains three processing units which function as masters in the AMBA bus matrix. Masters are assigned to distinct power domains. The following table shows the masters and their corresponding power domains:

Table 4 Master power domains

Master

Power Domain

Description

ARM Cortex-M33

PD_SYS

  • System CPU - the main application processor

  • Octa/Quad SPI controller (XiP)

  • Cache, OTP, ROM, USB, DMA

  • Crypto blocks, ADC, SPI3

  • Display Controller, APP ADC

  • Charge Detection, Charger FSM

ARM Cortex-M0+

PD_SNC

  • Sensor Node Controller for sensor manipulation

  • All serial interfaces except SPI3

  • GP ADC

ARM Cortex-M0+

PD_RAD

  • CMAC CPU - the BLE controller

  • Modem, RFMON, RFCU

3.4.1.2. Non-master power domains

The following table contains the DA1470x power domains which do not contain masters:

Table 6 Non-master power domains

Power Domain

Description

PD_TMR

Timer Power Domain. It contains:

  • TIMER, TIMER2, TIMER3, TIMER4, TIMER5, TIMER6

PD_MEM

Memory Power Domain. It contains:

  • Memory controller

  • XTAL32M FSM, PLL160M regs, PLL48M regs, Clock calibration

  • GPIO multiplexing

  • APB-32 slow

SW can configure how PDC manages PD_TMR state.

SW cannot configure how PDC manages PD_MEM state. PDC HW is solely responsible for that. PDC HW will automatically:

  • turn PD_MEM on when any master power domain is turned on and

  • turn PD_MEM off when all master power domains have been turned off.

The rest DA1470x power domains are controlled only by SW.

3.4.2. HW overview

At each instant a master power domain can be on or off depending on the processing requirements of the system (e.g. BLE stack, clock calibration) and the application. Master power domains are turned on by PDC when a pre-configured event is triggered to wake up the respective master. Several events can be used as PDC trigger sources, for example:

  • The state of a GPIO changes.

  • A timer expires.

The PDC Look Up Table (LUT) contains the mapping between the trigger sources and the masters to be woken up. Each LUT entry describes a specific trigger source and target master pair. The same trigger source can be used in different entries i.e. the same trigger can wake up multiple masters. Similarly the same master can be targeted by different entries i.e. a master can be woken up by multiple trigger sources. For more detailed information about PDC LUT please refer to datasheet [Ref_01].

Note

Setting up a trigger in the PDC LUT and configuring the trigger source to generate the trigger event are two separate concerns. SW must do both. E.g. in order to wake up M33 from an RTC alarm the SW must both:

  • Setup RTC to fire an interrupt when the alarm is activated.

  • Add a PDC LUT entry to wakeup M33 from the RTC alarm.

Apart from the trigger source and the master to be woken up, each PDC LUT entry contains additional instructions about the course of action to be taken when a master power domain is enabled:

  • Turn on additional power domains (non-master: PD_TMR, or master: PD_SNC) which are required by the master to do its work. E.g. if M33 is the master to be woken up and it needs to enable UART then we also need to have PD_SNC enabled.

  • Enable XTAL32M. Once enabled XTAL32M will be kept enabled until all masters go to sleep.

When a PDC LUT entry is triggered, it is marked as pending in PDC_PENDING_REG and the SW running in the respective master has to acknowledge this through PDC_ACKNOWLEDGE_REG. PDC HW also internally tracks which LUT entries have been activated for each master.

A PDC LUT can be triggered by SW through PDC_SET_PENDING_REG.

The activated PDC LUT entries for a master are effective until the master finishes processing (i.e. until it has no work to do and it could enter low power mode). A master signals PDC about having finished processing as follows:

  • M33, SNC and CMAC execute the WFI instruction while SCR.DEEPSLEEP = 1.

PDC will turn off the power domain of the master that finished processing and it will “release” all activated entries for that master. It will let each power domain requested by those entries to go down provided that no other activated LUT entry (for some other master) is still requesting that power domain. When the last active master goes to sleep, the PDC turns off the PD_MEM and activates the “goto sleep” HW FSM. Given the whole device is in sleep mode, when a PDC trigger fires:

  • the wake-up HW FSM will be activated

  • PDC will turn PD_MEM on

  • PDC will perform the actions requested by the triggered PDC LUT entries.

3.4.3. SW overview

M33 is responsible for setting up the PDC.

M33 is the only master allowed to modify PDC configuration.

M33 does not use the PDC IRQ. The SDK keeps this interrupt disabled. M33 acknowledges all pending PDC LUT entries (which target M33) before attempting to enter sleep (in function goto_deepsleep()).

The system sleep entry and exit procedure is depicted in the following diagram.

../_images/pdc-deepsleep_da1470x.png

Figure 6 DA1470x system sleep entry and exit

3.4.4. Low level driver

Low level PDC handling is implemented in the hw_pdc Low Level Driver (LLD):

  • <SDK_ROOT_PATH>/sdk/bsp/peripherals/include/hw_pdc.h

  • <SDK_ROOT_PATH>/sdk/bsp/peripherals/src/hw_pdc.c

The PDC LLD provides preprocessor macros to construct valid PDC LUT entries. See:

  • HW_PDC_LUT_ENTRY_VAL() generic macro as well as

  • HW_PDC_TRIGGER_FROM_<x>() per trigger source type macros

The PDC LLD provides APIs to:

  • Read/modify a LUT entry at a given index. See:

    • hw_pdc_read_entry()

    • hw_pdc_write_entry()

  • Add/remove a LUT entry taking into account that the LUT may already be populated with some entries. See:

    • hw_pdc_add_entry()

    • hw_pdc_remove_entry()

  • Query if PDC LUT entries are pending. See:

    • hw_pdc_get_pending()

    • hw_pdc_get_pending_cm33()

    • hw_pdc_get_pending_cmac()

    • hw_pdc_get_pending_snc()

    • hw_pdc_is_pending()

  • Trigger a PDC LUT entry by SW. See:

    • hw_pdc_set_pending()

  • Acknowledge a pending PDC LUT entry. See:

    • hw_pdc_acknowledge()

PDC LLD does not handle system level concerns as:

  • Concurrent access from different FreeRTOS tasks.

  • Keeping a master power domain alive while the PDC LUT is being modified. If all entries which keep a master alive get invalidated, its power domain will be immediately turned off terminating its execution.

3.4.5. PDC LLD integration into the system

PDC LUT configuration is applied both:

  • Statically during startup for setting up entries required by any FreeRTOS BLE application.

  • Dynamically according to the application’s needs.

PDC LLD is used by the following M33 software modules:

  • System startup code

  • Clock manager

  • Power manager

  • SNC API

3.4.5.1. System startup

During startup the PDC lookup table is statically populated with the entries required by all FreeRTOS BLE applications (see configure_pdc() in sdk/bsp/startup/DA1470x/system_da1470x.c):

  1. Wake up system CPU from TIMER2 (used by FreeRTOS port as the low power timer). Identified as HW_PDC_PERIPH_TRIG_ID_TIMER2 in the LLD.

  2. Wake up system CPU when signaled from CMAC controller by signal CMAC2SYS IRQ through the mailbox mechanism. Identified as HW_PDC_PERIPH_TRIG_ID_CMAC2SYS in the LLD.

  3. Wake up CMAC controller through the mailbox mechanism. For this purpose signal``SYS2CMAC IRQ`` is used. It is multiplexed together with``MAC_TIMER`` present signal in the same PDC trigger (identified as HW_PDC_PERIPH_TRIG_ID_MAC_TIMER in the LLD).

  4. Wake up system CPU from SNC and SNC from system CPU, used in mailbox mechanism. SNC2SYS IRQ and SYS2SNC IRQ signals are used to wake up CM33 and SNC. Identified as HW_PDC_PERIPH_TRIG_ID_SNC2SYS and as HW_PDC_PERIPH_TRIG_ID_SYS2SNC in the LLD.

  5. Wake up SNC from TIMER3 (used by FreeRTOS port as the SNC low power timer). Identified as HW_PDC_PERIPH_TRIG_ID_TIMER3 in the LLD.

All the above entries are also SW-triggered in order to prepare for sleep. We let PDC keep M33 alive and stop forcing PD_SYS to be always on through PMU_CTRL_REG.SYS_SLEEP.

3.4.5.2. Clock manager

Upon wake-up or whenever XTAL32M is going to be used as a system clock, clock manager starts XTAL32M by SW-triggering the RTOS timer PDC entry. In case there is no such entry, PDC LUT table is searched for an entry that starts XTAL32M and system CPU. If none is found a new one will be added.

3.4.5.3. Power manager

When power manager needs to wake-up CMAC it SW-triggers the corresponding PDC entry (created during startup) to accomplish that.

Power manager checks if the COMBO trigger is pending in order to detect if M33 has been woken-up by a debugger.

For more details regarding M33 – SNC communication refer to Section 5.9.2.

3.4.6. Using PDC in an application

This section describes how to setup a PDC trigger targeting M33. The example will show how to wake up M33 from a debounced button press.

First we need to setup the peripheral (Wake-Up Controller) to fire the corresponding interrupt (debounced IO IRQ - KEY_WKUP_GPIO_IRQ) which will serve as the PDC trigger source. Please refer to Using Wake-Up Controller in an application for more details on this.

In order to actually wake up M33 we need to instruct PDC what to do upon detecting that the trigger has fired. The following code snippet shows how this is accomplished.

Code 7 Setup PDC entry to wake up M33 from debounced input
uint32_t idx = HW_PDC_INVALID_LUT_INDEX;

idx = hw_pdc_add_entry(HW_PDC_LUT_ENTRY_VAL(
                           HW_PDC_TRIG_SELECT_PERIPHERAL,
                           HW_PDC_PERIPH_TRIG_ID_COMBO,
                           HW_PDC_MASTER_CM33,
                           HW_PDC_LUT_ENTRY_EN_XTAL));
hw_pdc_set_pending(idx);
hw_pdc_acknowledge(idx);

Notice that the “debounced IO IRQ” is multiplexed with other trigger sources (VBUS IRQ, JTAG present) in a single PDC peripheral trigger ID (HW_PDC_PERIPH_TRIG_ID_COMBO).

Warning

In the typical FreeRTOS/BLE application you do not actually need to create a PDC entry for a debounced input IRQ because such an entry should already exist. A COMBO triggered PDC entry always gets created during system start up because M33 needs to wake up from VBUS IRQ.

The constructed PDC entry will wake up M33 (possibly after the “wake up” HW FSM is first triggered if all masters had previously gone to sleep and the whole device had entered sleep mode) and M33 SW will see KEY_WKUP_GPIO_IRQ pending in NVIC as soon as M33 starts to execute.

The constructed PDC entry might also request that the 32 MHz crystal oscillator should be started. When this entry gets activated, the PDC will enable the crystal, provided that it has not already been started by any other entry, which required the XTAL32M since the last system wake up(including the entry that triggered the device wake up).The PDC entry will enable 32 MHz crystal oscillator if value of macro dg_configENABLE_XTAL32M_ON_WAKEUP equals to 1.

The above code snippet also triggers by SW the PDC LUT entry and then it acknowledges the pending entry. The former action guarantees that PD_SYS stays on in case the application invalidates all other activated PDC entries which are keeping M33 alive. Acknowledging the newly created (and activated) PDC entry is recommended although not strictly needed since M33 will automatically acknowledge all pending PDC entries before its next attempt to enter sleep mode.

3.5. RTC

Real Time Clock (RTC) is a HW block which provides complete clock and calendar information, generates one-time or recurring alarms and detects when a particular event occurs. For more details please refer to [Ref_01].

The SmartSnippets™ DA1470X SDK provides an extended API with features such as the ability to configure the RTC time and calendar registers, reading the corresponding values, setting alarms, enabling interrupts and setting up the event controller for configuring and enabling the RTC to PDC event.

See also

For more information about the RTC LLD API please refer to the SmartSnippets™ DA1470x SDK Documentation.

3.5.1. Application use

From an application point of view RTC can be used to track the time and date, utilize the alarm functionality or just the event detection.

3.6. System Clocks

Table 8 System Clocks

Clocks

Description

XTAL32K

Crystal oscillator for the low power clock (32.786KHz). Crystal tolerance should be up to +/-250ppm.

XTAL32M

Crystal oscillator for radio activity and/or PLL use. Crystal tolerance should be up to +/-15ppm or +/-40ppm untrimmed.

RCX

XTAL32K replacement (15KHz typical) with precision of < 500 ppm.

RCLP

RC oscillator (32KHz/512kHz) for clocking the HW-FSM at power up.

RCHS

RC oscillator (32MHz/64MHz/96MHz) for the system clock at 96MHz.

PLL160

PLL (160MHz) which will increase the system clock to 160MHz.

PLL48

PLL (48MHz) for USB operation.

The RCHS at 96 MHz is the default system clock and it has low jitter, when trimmed, so that it meets the specification for the UART peripherals. However, RCHS is affected by aging and great temperature changes and requires recalibration. M33 checks periodically if temperature has changed and performs RCHS frequency calibration if needed. The procedure of the RCHS calibration is depicted in Figure 23 and Figure 24.

3.6.1. Low Power Clocks

During sleep one of the two low power clocks, RCX or XTAL32K, is used since they have precision of < 500 ppm. XTAL32K uses an external crystal oscillator, generates 32.768 kHz and it is tolerant to voltage and temperature changes. The enhanced RC oscillator (RCX) is a simple RC oscillator and generates a typical frequency of 15 kHz. The RCX oscillator can be used to replace the 32.768 kHz crystal, since it has a precision of < 500 ppm, while its output frequency is quite stable over temperature.

Note

In the case of using the RCX as a low power clock, the frequency calibration should be implemented at a frequency that ensures Bluetooth® LE connection maintenance.

3.7. Power

Table 10 Power Definitions

Power

Definition

DCDC

Direct Current to Direct Current Converter.

LDO

Low Drop Out regulator. Power source during the active or sleep period.

VBAT

Battery supply voltage. It is the main power input to the system.

VBUS

USB bus supply voltage. It is the main power input to the system while charging the battery or during development.

VSYS

Main (internal) supply rail of the system. It is powered by either VBUS or VBAT (depending on which one is higher) and it provides power to all other power rails of the system.

VLED

Stepped up voltage output for supplying external LEDs. It is powered by the Boost DCDC converter, unless VSYS is high enough.