6. Code Overview

This section provides the code blocks needed to successfully execute this tutorial.

6.1. Header Files

In main.c file, add the following header files:

#include "hw_pdc.h"
#include "hw_wkup.h"
#include "hw_sys.h"
#include "ad_nvms.h"

6.2. System Init Code

In main.c file, replace the system_init() routine with the following code:

/* Task priorities */
#define  mainFLASH_TASK_PRIORITY   ( OS_TASK_PRIORITY_NORMAL )


/* Retained symbols */
__RETAINED static OS_EVENT signal_FLASH;

/* Flash task handle */
__RETAINED static OS_TASK prvFLASHTask_h;

uint32_t pdc_wkup_combo_id  __attribute__((unused));

/*
 * Task functions
 */
static void prvFLASH_Task(void *pvParameters);

static void system_init(void *pvParameters)
{
        OS_BASE_TYPE status;

        REG_SETF(GPREG, DEBUG_REG, SYS_CPU_FREEZE_EN, 0);

#if defined CONFIG_RETARGET
        extern void retarget_init(void);
#endif /* CONFIG_RETARGET */

        /*
         * Prepare clocks. Note: cm_cpu_clk_set() and cm_sys_clk_set() can be called
         * only from a task since they will suspend the task until the XTAL32M has
         * settled and, maybe, the PLL is locked.
         */
        cm_sys_clk_init(sysclk_XTAL32M);
        cm_apb_set_clock_divider(apb_div1);
        cm_ahb_set_clock_divider(ahb_div1);
        cm_lp_clk_init();

        /* Prepare the hardware to run this demo */
        prvSetupHardware();

#if defined CONFIG_RETARGET
        retarget_init();
#endif /* CONFIG_RETARGET */


        OS_EVENT_CREATE(signal_FLASH);


        /*
         * Upon a wakeup cycle, wait for the XTAL32M crystal to settle.
         * BLE, USB and UART blocks require the XTAL32M to be up and
         * running to work properly.
         */
        pm_set_wakeup_mode(true);


        /* Set the desired sleep mode. */
        pm_sleep_mode_set(pm_mode_extended_sleep);

        /*
         * Set the desired wakeup mode.
         *
         * \warning When set is Ultra-Fast wakeup mode, sleep voltage should be 0.9V
         *          and not less than that.
         *
         **/
        pm_set_sys_wakeup_mode(pm_sys_wakeup_mode_fast);

        /* FLASH task  */
        status = OS_TASK_CREATE("flash",   /* The text name assigned to the task, for
                                              debug only; not used by the kernel. */
                        prvFLASH_Task,     /* The function that implements the task. */
                        NULL,              /* The parameter passed to the task. */
                        1024 * OS_STACK_WORD_SIZE,  /* Stack size allocated for the task
                                                       in bytes. */
                        mainFLASH_TASK_PRIORITY, /* The priority assigned to the task. */
                        prvFLASHTask_h );        /* The task handle. */
        OS_ASSERT(status == OS_TASK_CREATE_SUCCESS);

        /* The work of the SysInit task is done */
        OS_TASK_DELETE(xHandle);
}

In main.c file, replace the main() routine with the following code:

/**
 * @brief Basic initialization and creation of the system initialization task.
 */
int main(void)
{
        OS_BASE_TYPE status;

        /* Create SysInit task. */
        status = OS_TASK_CREATE("SysInit",  /* The text name assigned to the task, for
                                               debug only; not used by the kernel. */
                        system_init,     /* The System Initialization task. */
                        ( void * ) 0,    /* The parameter passed to the task. */
                        1024, /* Stack size allocated for the task in bytes. */
                        OS_TASK_PRIORITY_HIGHEST, /* The priority assigned to the task. */
                        xHandle );         /* The task handle. */
        OS_ASSERT(status == OS_TASK_CREATE_SUCCESS);

        /* Start the tasks and timer running. */
        vTaskStartScheduler();

        /* If all is well, the scheduler will now be running, and the following
         line will never be reached.  If the following line does execute, then
         there was insufficient FreeRTOS heap memory available for the idle and/or
         timer tasks     to be created.  See the memory management section on the
         FreeRTOS web site for more details. */
        for (;;);
}

6.3. Task Code for QSPI FLASH Memory

In main.c file and after system_init(), add the following code used for interacting with the QSPI FLASH memory.

#define FLASH_TEST_DATA_SIZE       (1024)
#define FLASH_READ_DATA_SIZE       (64)

/* The source test buffer that contains the Lorem Ipsum text */
const uint8_t e_src_buff[FLASH_TEST_DATA_SIZE] = {
        'L', 'o', 'r', 'e', 'm', ' ', 'i', 'p', 's', 'u', 'm', ' ', 'd', 'o', 'l', 'o',
        'r', ' ', 's', 'i', 't', ' ', 'a', 'm', 'e', 't', ',', ' ', 'c', 'o', 'n', 's',
        'e', 'c', 't', 'e', 't', 'u', 'r', ' ', 'a', 'd', 'i', 'p', 'i', 's', 'c', 'i',
        'n', 'g', ' ', 'e', 'l', 'i', 't', '.', ' ', 'D', 'o', 'n', 'e', 'c', ' ', 'd',
        'i', 'g', 'n', 'i', 's', 's', 'i', 'm', ' ', 'l', 'a', 'c', 'u', 's', ' ', 'a',
        ' ', 'p', 'o', 's', 'u', 'e', 'r', 'e', ' ', 'm', 'a', 'x', 'i', 'm', 'u', 's',
        '.', ' ', 'A', 'l', 'i', 'q', 'u', 'a', 'm', ' ', 'e', 'r', 'a', 't', ' ', 'v',
        'o', 'l', 'u', 't', 'p', 'a', 't', '.', ' ', 'P', 'r', 'o', 'i', 'n', ' ', 'e',
        'l', 'e', 'm', 'e', 'n', 't', 'u', 'm', ' ', 't', 'e', 'l', 'l', 'u', 's', ' ',
        'u', 't', ' ', 'a', 'c', 'c', 'u', 'm', 's', 'a', 'n', ' ', 'f', 'e', 'u', 'g',
        'i', 'a', 't', '.', ' ', 'D', 'u', 'i', 's', ' ', 'v', 'e', 'l', ' ', 'f', 'e',
        'l', 'i', 's', ' ', 'n', 'i', 's', 'i', '.', ' ', 'C', 'u', 'r', 'a', 'b', 'i',
        't', 'u', 'r', ' ', 'f', 'e', 'u', 'g', 'i', 'a', 't', ' ', 'r', 'i', 's', 'u',
        's', ' ', 'e', 'u', ' ', 'l', 'a', 'c', 'i', 'n', 'i', 'a', ' ', 'v', 'o', 'l',
        'u', 't', 'p', 'a', 't', '.', ' ', 'U', 't', ' ', 'v', 'i', 'v', 'e', 'r', 'r',
        'a', ' ', 'a', 'r', 'c', 'u', ' ', 'f', 'i', 'n', 'i', 'b', 'u', 's', ' ', 'm',
        'a', 't', 't', 'i', 's', ' ', 'd', 'i', 'c', 't', 'u', 'm', '.', ' ', 'P', 'e',
        'l', 'l', 'e', 'n', 't', 'e', 's', 'q', 'u', 'e', ' ', 'i', 'n', 't', 'e', 'r',
        'd', 'u', 'm', ' ', 'm', 'i', ' ', 'a', ' ', 'f', 'e', 'l', 'i', 's', ' ', 't',
        'e', 'm', 'p', 'u', 's', ' ', 'a', 'u', 'c', 't', 'o', 'r', '.', ' ', 'N', 'u',
        'n', 'c', ' ', 'e', 't', ' ', 'p', 'h', 'a', 'r', 'e', 't', 'r', 'a', ' ', 'm',
        'i', '.', ' ', 'I', 'n', ' ', 'u', 'l', 'l', 'a', 'm', 'c', 'o', 'r', 'p', 'e',
        'r', ' ', 'b', 'i', 'b', 'e', 'n', 'd', 'u', 'm', ' ', 'u', 'r', 'n', 'a', ',',
        ' ', 'u', 't', ' ', 'c', 'o', 'n', 'g', 'u', 'e', ' ', 'u', 'r', 'n', 'a', ' ',
        'e', 'g', 'e', 's', 't', 'a', 's', ' ', 'e', 'g', 'e', 't', '.', ' ', 'I', 'n',
        ' ', 'h', 'a', 'c', ' ', 'h', 'a', 'b', 'i', 't', 'a', 's', 's', 'e', ' ', 'p',
        'l', 'a', 't', 'e', 'a', ' ', 'd', 'i', 'c', 't', 'u', 'm', 's', 't', '.', ' ',
        'M', 'o', 'r', 'b', 'i', ' ', 'l', 'u', 'c', 't', 'u', 's', ' ', 't', 'r', 'i',
        's', 't', 'i', 'q', 'u', 'e', ' ', 'u', 'r', 'n', 'a', ',', ' ', 'n', 'o', 'n',
        ' ', 'c', 'o', 'n', 'v', 'a', 'l', 'l', 'i', 's', ' ', 'a', 'n', 't', 'e', ' ',
        'e', 'u', 'i', 's', 'm', 'o', 'd', ' ', 'v', 'i', 't', 'a', 'e', '.', ' ', 'A',
        'l', 'i', 'q', 'u', 'a', 'm', ' ', 'c', 'u', 'r', 's', 'u', 's', ' ', 'm', 'a',
        'u', 'r', 'i', 's', ' ', 'n', 'o', 'n', ' ', 't', 'u', 'r', 'p', 'i', 's', ' ',
        'f', 'a', 'c', 'i', 'l', 'i', 's', 'i', 's', ',', ' ', 'p', 'o', 's', 'u', 'e',
        'r', 'e', ' ', 'u', 'l', 'l', 'a', 'm', 'c', 'o', 'r', 'p', 'e', 'r', ' ', 'v',
        'e', 'l', 'i', 't', ' ', 'c', 'u', 'r', 's', 'u', 's', '.', ' ', 'M', 'a', 'u',
        'r', 'i', 's', ' ', 'v', 'e', 'l', ' ', 'v', 'o', 'l', 'u', 't', 'p', 'a', 't',
        ' ', 'm', 'e', 't', 'u', 's', '.', ' ', 'P', 'e', 'l', 'l', 'e', 'n', 't', 'e',
        's', 'q', 'u', 'e', ' ', 'd', 'i', 'c', 't', 'u', 'm', ' ', 'q', 'u', 'i', 's',
        ' ', 'l', 'i', 'g', 'u', 'l', 'a', ' ', 'i', 'd', ' ', 'e', 'u', 'i', 's', 'm',
        'o', 'd', '.', ' ', 'I', 'n', ' ', 'v', 'e', 's', 't', 'i', 'b', 'u', 'l', 'u',
        'm', ' ', 'o', 'l', 'o', 'r', ' ', 'v', 'e', 'l', ' ', 'm', 'e', 't', 'u', 's',
        ' ', 't', 'i', 'n', 'c', 'i', 'd', 'u', 'n', 't', ',', ' ', 'i', 'n', ' ', 's',
        'o', 'l', 'l', 'i', 'c', 'i', 't', 'u', 'd', 'i', 'n', ' ', 'r', 'i', 's', 'u',
        's', ' ', 't', 'i', 'n', 'c', 'i', 'd', 'u', 'n', 't', '.', ' ', 'A', 'e', 'n',
        'e', 'a', 'n', ' ', 't', 'r', 'i', 's', 't', 'i', 'q', 'u', 'e', ' ', 'n', 'i',
        's', 'i', ' ', 'q', 'u', 'a', 'm', ',', ' ', 'a', ' ', 'u', 'l', 't', 'r', 'i',
        'c', 'i', 'e', 's', ' ', 'r', 'i', 's', 'u', 's', ' ', 't', 'e', 'm', 'p', 'u',
        's', ' ', 'a', '.', ' ', 'M', 'o', 'r', 'b', 'i', ' ', 't', 'u', 'r', 'p', 'i',
        's', ' ', 'v', 'e', 'l', 'i', 't', ',', ' ', 's', 'c', 'e', 'l', 'e', 'r', 'i',
        's', 'q', 'u', 'e', ' ', 'q', 'u', 'i', 's', ' ', 'n', 'e', 'q', 'u', 'e', ' ',
        'v', 'u', 'l', 'p', 'u', 't', 'a', 't', 'e', ',', ' ', 's', 'u', 's', 'c', 'i',
        'p', 'i', 't', ' ', 'p', 'o', 'r', 't', 't', 'i', 't', 'o', 'r', ' ', 'm', 'e',
        't', 'u', 's', '.', ' ', 'M', 'a', 'u', 'r', 'i', 's', ' ', 'p', 'u', 'l', 'v',
        'i', 'n', 'a', 'r', ' ', 'd', 'a', 'p', 'i', 'b', 'u', 's', ' ', 'v', 'e', 'l',
        'i', 't', ',', ' ', 'i', 'n', ' ', 's', 'u', 's', 'c', 'i', 'p', 'i', 't', ' ',
        'm', 'a', 'u', 'r', 'i', 's', '.', ' ', 'M', 'o', 'r', 'b', 'i', ' ', 's', 'o',
        'd', 'a', 'l', 'e', 's', ' ', 'e', 's', 't', ' ', 'm', 'a', 's', 's', 'a', ',',
        ' ', 'n', 'e', 'c', ' ', 't', 'e', 'm', 'p', 'o', 'r', ' ', 'e', 's', 't', ' ',
        'c', 'o', 'n', 's', 'e', 'c', 't', 'e', 't', 'u', 'r', ' ', 'e', 't', '.', ' ',
        'F', 'u', 's', 'c', 'e', ' ', 'n', 'o', 'n', ' ', 'e', 'n', 'i', 'm', ' ', 'a',
        'l', 'i', 'q', 'u', 'e', 't', ',', ' ', 'b', 'l', 'a', 'n', 'd', 'i', 't', ' ',
        'd', 'u', 'i', ' ', 'a', 't', ',', ' ', 'v', 'i', 'v', 'e', 'r', 'r', 'a', ' ',
        'n', 'u', 'l', 'l', 'a', '.', ' ', 'C', 'r', 'a', 's', ' ', 's', 'e', 'd', '.'
};


/**
 * @brief Prints FLASH data
 *
 * \param [in] pageBuff A pointer to the buffer which contains the page data
 * \param [in] len      The data length
 *
 */
static void printout_data(uint8_t *pageBuff, uint16_t len)
{
        uint16_t i;
        for (i = 0; i < len; i++) {
                if (!(i % 8)) printf("\r\n");
                printf("%c", pageBuff[i]);
        }
        printf("\r\n");
}



static uint32_t FLASH_reader(nvms_t hdr, uint32_t offset, uint8_t *buff)
{
        ASSERT_WARNING(offset < ad_nvms_get_size(hdr))

        int num_bytes;

        /* Perform a FLASH read operation to the selected partition */
        num_bytes = ad_nvms_read(hdr, offset, buff, FLASH_READ_DATA_SIZE);

        if (num_bytes >= 0) {
                /*
                 * When the maximum data size has been reached, roll over to the
                 * starting address.
                 */
                offset = (offset + FLASH_READ_DATA_SIZE) % FLASH_TEST_DATA_SIZE;
        } else {
                printf("Unsuccessful FLASH write operation\n\r");
        }

        return offset;
}


/**
 * @brief Task responsible for performing FLASH related operations
 */
static void prvFLASH_Task(void *pvParameters)
{
        nvms_t FLASH_h;
        uint32_t offset = 0;

        /* Data read from LOG partition */
        uint8_t r_data[FLASH_READ_DATA_SIZE];


        printf("\n\r***FLASH Demonstration Example***\n\r");

        /*
         * FLASH adapter initialization should be done once at the beginning.
         * Alternatively, this function could be called during system
         * initialization in system_init().
         */
        ad_nvms_init();

        /* Open the partition of interest */
        FLASH_h = ad_nvms_open(NVMS_LOG_PART);


        /* Perform a FLASH write operation to LOG partition entry */
        int num_bytes = ad_nvms_write(FLASH_h, 0x0, e_src_buff, FLASH_TEST_DATA_SIZE);
        OS_ASSERT(num_bytes >= 0);


        for (;;) {
                /*
                 * Suspend task execution - As soon as the WKUP callback
                 * function is triggered, the task resumes its execution.
                 */
                OS_EVENT_WAIT(signal_FLASH, OS_EVENT_FOREVER);


                /* Read data from FLASH memory */
                offset = FLASH_reader(FLASH_h, offset, r_data);

                printf("\n\rFLASH partition offset 0x%04lX\n\r", offset);
                /* Print on the serial console the currently read data */
                printout_data(r_data, FLASH_READ_DATA_SIZE);

        }
}

6.4. Wake-Up Timer Code

In main.c file and after system_init() routine, add the following code used for handling external events via the wake-up controller:

/* WKUP KEY interrupt handler */
static void wkup_cb(void)
{

        /* Clear the WKUP interrupt flag!!! */
        hw_wkup_reset_interrupt();


        /*
         * Avoid using printf() within ISR context!!! It may crash your code.
         * Instead, use notifications to notify a task to perform an action!!
         */

        /*
         * Notify [prvFLASH_Task] task that time for
         * performing FLASH operations has elapsed.
         */
        OS_EVENT_SIGNAL_FROM_ISR(signal_FLASH);

}


/* Initialize the WKUP controller */
static void wkup_init(void)
{

        /* Initialize the WKUP controller */
        hw_wkup_init(NULL);

        /*
         * Set debounce time expressed in ms. Maximum allowable value is 63 ms.
         * A value set to 0 disables the debounce functionality.
         */
        hw_wkup_set_debounce_time(10);

        /*
         * Enable interrupts produced by the KEY block of the wakeup controller (debounce
         * circuitry) and register a callback function to hit following a KEY event.
         */
        hw_wkup_register_key_interrupt(wkup_cb, 1);


        /*
         * Set the polarity (rising/falling edge) that triggers the WKUP controller.
         *
         * \note The polarity is applied both to KEY and GPIO blocks of the controller
         *
         */
        hw_wkup_configure_pin(KEY1_PORT, KEY1_PIN, 1, HW_WKUP_PIN_STATE_LOW);


        /* Enable interrupts of WKUP controller */
        hw_wkup_enable_irq();
}

6.5. Hardware Initialization

In main.c file, replace the prvSetupHardware() routine with the following code used for configuring the pins utilized by the wake-up controller.

/**
 * @brief Hardware Initialization
 */
static void prvSetupHardware(void)
{
        /*
         * The IRQ produced by the KEY sub block of the wakeup controller
         * (debounced IO IRQ) is multiplexed with other trigger sources
         * (VBUS IRQ, SYS2CMAC IRQ, JTAG present) in a single PDC peripheral
         * trigger ID (HW_PDC_PERIPH_TRIG_ID_COMBO).
         */
#if !defined(CONFIG_USE_BLE) && (!dg_configENABLE_DEBUGGER) && (!dg_configUSE_SYS_CHARGER)

        pdc_wkup_combo_id = hw_pdc_add_entry(HW_PDC_LUT_ENTRY_VAL(
                                                      HW_PDC_TRIG_SELECT_PERIPHERAL,
                                                      HW_PDC_PERIPH_TRIG_ID_COMBO,
                                                      HW_PDC_MASTER_CM33, 0));
        OS_ASSERT(pdc_wkup_combo_id != HW_PDC_INVALID_LUT_INDEX);

        /*  */
        hw_pdc_set_pending(pdc_wkup_combo_id);
        hw_pdc_acknowledge(pdc_wkup_combo_id);
#endif

        wkup_init();

        /* Init hardware */
        pm_system_init(periph_init);


        /* Enable the COM power domain before handling any GPIO pin */
        hw_sys_pd_com_enable();

        /* Configure the KEY1 push button on Pro DevKit */
        HW_GPIO_SET_PIN_FUNCTION(KEY1);
        HW_GPIO_PAD_LATCH_ENABLE(KEY1);

        /* Lock the mode of the target GPIO pin */
        HW_GPIO_PAD_LATCH_DISABLE(KEY1);

        /* Disable the COM power domain after handling the GPIO pins */
        hw_sys_pd_com_disable();
}

6.6. Macro Definitions

In config/custom_config_xxx.h file, set the following macro definitions to the appropriate value:

/*******************************************************
 * Peripheral specific config
 */
#define dg_configFLASH_ADAPTER                  (1)
#define dg_configNVMS_ADAPTER                   (1)

/*
 * This feature is required when accessing the [NVMS_GENERIC_PART]
 * partition entry.
 */
#define dg_configNVMS_VES                       (0)