6. Code Overview¶
This section provides the code blocks needed to successfully execute this tutorial.
6.1. Header Files¶
In main.c
, add the following header files:
#include "hw_wkup.h"
#include "ad_nvparam.h"
#include "ad_nvms.h"
#include <platform_nvparam.h>
6.2. System Init Code¶
In main.c
, replace system_init()
with the following code:
/* OS signals used for synchronizing OS tasks */
static OS_EVENT signal_flash;
/* Flash memory application task - Function prototype */
static void prvFlashTask( void *pvParameters );
/* Flash memory application task priority */
#define mainFLASH_TASK_PRIORITY ( OS_TASK_PRIORITY_NORMAL )
/* Flag for selecting Flash memory operation */
volatile static bool flash_state = 0;
static void system_init( void *pvParameters )
{
OS_TASK task_h = NULL;
OS_TASK flash_h = NULL;
#if defined CONFIG_RETARGET
extern void retarget_init(void);
#endif
/* Prepare clocks. Note: cm_cpu_clk_set() and cm_sys_clk_set() can only be called
* from a task since they will suspend the task until the XTAL16M has settled and,
* maybe, the PLL is locked.
*/
cm_sys_clk_init(sysclk_XTAL16M);
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();
/* init resources */
resource_init();
#if defined CONFIG_RETARGET
retarget_init();
#endif
/* Initialize the OS event signal */
OS_EVENT_CREATE(signal_flash);
/* Set the desired sleep mode. */
pm_set_sleep_mode(pm_mode_extended_sleep);
/* Start main task here */
OS_TASK_CREATE( "Template", /* The text name assigned to the
task, for debug only; not used
by the kernel. */
prvTemplateTask, /* The function that implements
the task. */
NULL, /* The parameter passed to the
task */
200 * OS_STACK_WORD_SIZE, /* The number of bytes to allocate
to the stack of the task. */
mainTEMPLATE_TASK_PRIORITY, /* The priority assigned to the
task. */
task_h ); /* The task handle */
OS_ASSERT(task_h);
/* Suspend task execution */
OS_TASK_SUSPEND(task_h);
/*
* Task responsible for flash memory operations.
*/
OS_TASK_CREATE( "FLash", /* The text name assigned to the
task, for debug only; not used
by the kernel. */
prvFlashTask, /* The function that implements
the task. */
(void *)flash_h, /* The parameter passed to the
task. */
200 * OS_STACK_WORD_SIZE, /* The number of bytes to allocate
to the stack of the task. */
mainFLASH_TASK_PRIORITY, /* The priority assigned to the
task. */
flash_h ); /* The task handle */
OS_ASSERT(flash_h);
/* The work of the SysInit task is complete */
OS_TASK_DELETE( xHandle );
}
In main()
, slightly modify the task creation of system_init()
.
The stack size should be increased, for instance to 500 bytes. The following code snippet shows how it
should look like:
status = OS_TASK_CREATE("SysInit",
system_init,
( void * ) 0,
500, /* Modified code line! */
OS_TASK_PRIORITY_HIGHEST,
xHandle );
6.3. Wake-Up Timer Code¶
In main.c
(after system_init()
), add the following code
for handling external events via the wake-up controller:
/*
* Callback function to be called after an external event is generated,
* that is, after K1 button on the Pro DevKit is pressed.
*/
void wkup_cb(void)
{
/*
* This function must be called by any user-specified
* interrupt callback, to clear the interrupt flag.
*/
hw_wkup_reset_interrupt();
/*
* Toggle flash status.
*/
flash_state ^= 1;
/*
* Time for resuming [prvFlashTask] task has elapsed.
*/
OS_EVENT_SIGNAL_FROM_ISR(signal_flash);
}
/*
* Function which makes all the necessary initializations for the
* wake-up controller
*/
static void init_wkup(void)
{
/*
* This function must be called first and is responsible
* for the initialization of the hardware block.
*/
hw_wkup_init(NULL);
/*
* Configure the pin(s) that can trigger the device to wake up while
* in sleep mode. The last input parameter determines the triggering
* edge of the pulse (event)
*/
hw_wkup_configure_pin(HW_GPIO_PORT_1, HW_GPIO_PIN_6, true,
HW_WKUP_PIN_STATE_LOW);
/*
* This function defines a delay between the moment at which
* a trigger event is present and the moment at which the controller
* takes this event into consideration. Setting debounce time to [0]
* hardware debouncing mechanism is disabled. Maximum debounce time is 63 ms.
*/
hw_wkup_set_debounce_time(10);
// Check if the chip is either DA14680 or 81
#if dg_configBLACK_ORCA_IC_REV == BLACK_ORCA_IC_REV_A
/*
* Set threshold for event counter. Interrupt is generated after
* the event counter reaches the configured value. This function
* is only supported in DA14680/1 chips.
*/
hw_wkup_set_counter_threshold(1);
#endif
/* Register interrupt handler */
hw_wkup_register_interrupt(wkup_cb, 1);
}
6.4. Hardware Initialization¶
In main.c
, replace both periph_init()
and prvSetupHardware()
with
the following code to configure pins after a power-up/wake-up cycle. Please note that
every time the system enters sleep, it loses all its pin configurations.
/**
* @brief Initialize the peripherals domain after power-up
*
*/
static void periph_init(void)
{
# if dg_configBLACK_ORCA_MB_REV == BLACK_ORCA_MB_REV_D
# define UART_TX_PORT HW_GPIO_PORT_1
# define UART_TX_PIN HW_GPIO_PIN_3
# define UART_RX_PORT HW_GPIO_PORT_2
# define UART_RX_PIN HW_GPIO_PIN_3
# else
# error "Unknown value for dg_configBLACK_ORCA_MB_REV!"
# endif
hw_gpio_set_pin_function(UART_TX_PORT, UART_TX_PIN, HW_GPIO_MODE_OUTPUT,
HW_GPIO_FUNC_UART_TX);
hw_gpio_set_pin_function(UART_RX_PORT, UART_RX_PIN, HW_GPIO_MODE_INPUT,
HW_GPIO_FUNC_UART_RX);
/* This pin drives the D2 Led on the Pro DevKit (for debugging purposes) */
hw_gpio_set_pin_function(HW_GPIO_PORT_1, HW_GPIO_PIN_5,
HW_GPIO_MODE_OUTPUT, HW_GPIO_FUNC_GPIO);
}
/**
* @brief Hardware Initialization
*/
static void prvSetupHardware( void )
{
/* Init hardware */
pm_system_init(periph_init);
init_wkup();
}
6.5. Flash Task Code¶
Code snippet of the prvFlashTask
task responsible for interacting with the externally connected flash
memory of the system. In main.c
, add the following code (for instance, after system_init()
):
/*
* Task responsible for interacting with the externally
* connected flash memory of the system.
*/
static void prvFlashTask( void *pvParameters )
{
uint16_t wd_param_bytes = 0;
uint16_t wd_log_bytes = 0;
uint16_t rd_log_bytes = 0;
/*
* Data to be written during a write access to
* [NVMS_PARAM_PART] partition entry.
*/
uint8_t bd_address_nvparam_wd[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x00};
/*
* Buffer used for storing data during a read access to
* [NVMS_LOG_PART] partition entry.
*/
char log_value_rd[25];
/*
* Data to be written during a write access to
* [NVMS_LOG_PART] partition entry.
*/
char log_value_1_wd[] = "BD address validated!";
char log_value_2_wd[] = "BD address invalidated!";
/*
* Handler for accessing [NVMS_PARAM_PART] partition entry.
*/
nvparam_t param;
/*
* Handler for accessing [NVMS_LOG_PART] partition entry.
*/
nvms_t nvms_var;
/*
* 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();
/*
* Before accessing a partition entry, you should first open it.
*/
nvms_var = ad_nvms_open(NVMS_LOG_PART);
for (;;) {
/*
* Suspend task execution - As soon as WKUP callback function
* is triggered the task resumes its execution.
*/
OS_EVENT_WAIT(signal_flash, OS_EVENT_FOREVER);
/*
* Turn on LED D2 on Pro DevKit indicating the
* beginning of a process.
*/
hw_gpio_set_active(HW_GPIO_PORT_1, HW_GPIO_PIN_5);
/*
* Before accessing a partition entry, you should first open it.
*/
param = ad_nvparam_open("ble_platform");
// Validate the BD address
if (flash_state == 1) {
/*
* Validate the validity flag of BD address entry
* (7th byte)
*/
memset(bd_address_nvparam_wd + 6, 0x00, 1);
/*
* Attempt a write access to [NVMS_PARAM_PART]
* partition entry to write the BD address
* field value.
*
* The function returns the actual number of written data.
*/
wd_param_bytes = ad_nvparam_write(param,
TAG_BLE_PLATFORM_BD_ADDRESS, sizeof(bd_address_nvparam_wd),
bd_address_nvparam_wd);
OS_ASSERT(wd_param_bytes != 0);
/*
* Attempt a write access to [NVMS_LOG_PART] partition
* entry to log the status of the previously written BD
* address (validated/invalidated)
*
* The function returns the actual number of written data.
*/
wd_log_bytes = ad_nvms_write(nvms_var, 0,
(uint8_t *)log_value_1_wd, sizeof(log_value_1_wd));
OS_ASSERT(wd_log_bytes != 0);
// ------------------ Read operations -------------------
memset(log_value_rd, 0x20, sizeof(log_value_rd));
/*
* Attempt a read access to [NVMS_LOG_PART] partition
* entry to read the current status of BD address
* (validated/invalidated).
*
* The function returns the actual number of read data.
*/
rd_log_bytes = ad_nvms_read(nvms_var, 0,
(uint8_t *)log_value_rd, sizeof(log_value_rd));
OS_ASSERT(rd_log_bytes != 0);
/*
* Print the log status on the serial console.
*/
printf("\nLog entry: %s\n\r", log_value_rd);
// Invalidate the BD address
} else if (flash_state == 0) {
/*
* Invalidate the validity flag of BD address entry
* (7th byte)
*/
memset(bd_address_nvparam_wd + 6, 0xFF, 1);
/*
* Attempt a write access to [NVMS_PARAM_PART]
* partition entry to write the BD address
* field value.
*
* The function returns the actual number of written data.
*/
wd_param_bytes = ad_nvparam_write(param,
TAG_BLE_PLATFORM_BD_ADDRESS, sizeof(bd_address_nvparam_wd),
bd_address_nvparam_wd);
OS_ASSERT(wd_param_bytes != 0);
/*
* Attempt a write access to [NVMS_LOG_PART]
* partition entry to log the status of the previously
* written BD address (validated/invalidated)
*
* The function returns the actual number of written data.
*/
wd_log_bytes = ad_nvms_write(nvms_var, 0,
(uint8_t *)log_value_2_wd, sizeof(log_value_2_wd));
OS_ASSERT(wd_log_bytes != 0);
// ----------------- Read operations ------------------
memset(log_value_rd, 0x20, sizeof(log_value_rd));
/*
* Attempt a read access to [NVMS_LOG_PART] partition
* entry to read the current status of BD address
* (validated/invalidated).
*
* The function returns the actual number of read data.
*/
rd_log_bytes = ad_nvms_read(nvms_var, 0,
(uint8_t *)log_value_rd, sizeof(log_value_rd));
OS_ASSERT(rd_log_bytes != 0);
/*
* Print the log status on the serial console
*/
printf("\nLog entry: %s\n\r", log_value_rd);
}
/* Close the already opened adapter */
ad_nvparam_close(param);
/*
* Turn off LED D2 on Pro DevKit indicating the end of
* a process.
*/
hw_gpio_set_inactive(HW_GPIO_PORT_1, HW_GPIO_PIN_5);
} // end of for loop
} // end of task
6.6. Macro Definitions¶
In config/custom_config_qspi.h
, add/modify the following macro definitions:
#define dg_configFLASH_ADAPTER (1)
#define dg_configNVMS_ADAPTER (1)
/*
* Additional mechanism for accessing the [NVMS_PARAM_PART] partition entry.
*/
#define dg_configNVPARAM_ADAPTER (1)