Chapter 6 Platform API Reference

This chapter describes the platform API.

6.1 Configuration & Information

6.1.1 platform_config

Configure some platform functionalities.

6.1.1.1 Prototype

void platform_config(const platform_cfg_item_t item,
                     const uint32_t flag);

6.1.1.2 Parameters

  • const platform_cfg_item_t item

    Specify the item to be configured. It can be one of following values:

    • PLATFORM_CFG_LOG_HCI: Print host controller interface messages. Default: Disabled.

      Only available on ING918. HCI logging is only intended for a quick check on BLE behavior. Please consider using tracing (see Debugging & Tracing).

    • PLATFORM_CFG_POWER_SAVING: Power saving. Default: Disabled.

    • PLATFORM_CFG_TRACE_MASK: Bit map of selected trace items. Default: 0.

      typedef enum
      {
          PLATFORM_TRACE_ID_EVENT                 = 0,
          PLATFORM_TRACE_ID_HCI_CMD               = 1,
          PLATFORM_TRACE_ID_HCI_EVENT             = 2,
          PLATFORM_TRACE_ID_HCI_ACL               = 3,
          PLATFORM_TRACE_ID_LLCP                  = 4,
          //..
      } platform_trace_item_t;
    • PLATFORM_CFG_RT_RC_EN: Enable/Disable real-time RC clock. Default: Enabled.

    • PLATFORM_CFG_RT_OSC_EN: Enable/Disable real-time crystal oscillator. Default: Enabled.

    • PLATFORM_CFG_RT_CLK: Real-time clock selection. Flag is platform_rt_clk_src_t. Default: PLATFORM_RT_RC

      typedef enum
      {
          PLATFORM_RT_OSC,           // External real-time crystal oscillator
          PLATFORM_RT_RC             // Internal real-time RC clock
      } platform_rt_clk_src_t;

      For ING918, When modifying this configuration, both RT_RC and RT_OSC should be enabled and run:

        * For RT_OSC, wait until status of RT_OSC is OK;
        * For RT_RC, wait 100μs after enabled.

      And wait another 100μs before disabling the unused clock.

    • PLATFORM_CFG_RT_CLK_ACC: Configure real-time clock accuracy in ppm.

    • PLATFORM_CFG_RT_CALI_PERIOD: Real-time clock auto-calibration period in seconds. Default: 3600 * 2 (2 hours).

    • PLATFORM_CFG_DEEP_SLEEP_TIME_REDUCTION: Sleep time reduction (deep sleep mode) in micro seconds. ING918 Default: ~550μs.

    • PLATFORM_CFG_SLEEP_TIME_REDUCTION: Sleep time reduction (other sleep mode) in micro seconds. ING918 Default: ~450μs.

    • PLATFORM_CFG_LL_DBG_FLAGS: Link layer flags. Combination of bits in ll_cfg_flag_t.

      typedef enum
      {
          LL_FLAG_DISABLE_CTE_PREPROCESSING = 1,  // disable CTE processing
          LL_FLAG_LEGACY_ONLY_INITIATING = 4,     // initiating only using legacy ADV
          LL_FLAG_LEGACY_ONLY_SCANNING = 8,       // scanning only using legacy ADV
      } ll_cfg_flag_t;
    • PLATFORM_CFG_LL_LEGACY_ADV_INTERVAL: Link layer legacy advertising intervals for high duty cycle (higher 16bits) and normal duty cycle (lower 16bits) in micro seconds. Default for high duty cycle: 1250; default for normal duty cycle: 1500.

    • PLATFORM_CFG_RTOS_ENH_TICK: Enable enhanced ticks for RTOS. Default: Disabled. When enabled, ticks becomes more accurate when peripherals are generating interrupt requests frequently.

    • PLATFORM_CFG_LL_DELAY_COMPENSATION: Delay compensation for Link Layer.

      When system runs at a lower frequency, more time (in μs) is needed by Link Layer to schedule RF tasks. For example, if ING916 runs at 24MHz, a compensation of ~2500 μs is needed.

    • PLATFORM_CFG_24M_OSC_TUNE: 24M OSC tunning. Not available for ING918.

      For ING916, tunning value may vary in 0x16~0x2d.

    • PLATFORM_CFG_ALWAYS_CALL_WAKEUP: Always trigger PLATFORM_CB_EVT_ON_DEEP_SLEEP_WAKEUP event no matter if deep sleep procedure is completed or aborted (failed). Default for ING918: Disabled for backward compatibility. Default for ING916: Enabled.

    • PLATFORM_CFG_FAST_DEEP_SLEEP_TIME_REDUCTION: Sleep time reduction for fast deep sleep mode in micro seconds. Not available for ING918.

      This configuration must be less or equal to PLATFORM_CFG_DEEP_SLEEP_TIME_REDUCTION. When equal to PLATFORM_CFG_DEEP_SLEEP_TIME_REDUCTION, fast deep sleep mode is not used.

      Default for ING916: ~2000μs.

    • PLATFORM_CFG_AUTO_REDUCE_CLOCK_FREQ: Automatically reduce CPU clock frequency in these circumstances:

      • The default IDLE procedure,
      • When entering sleep modes.

      Not available for ING918. Default for ING916: Enabled.

  • const uint32_t flag

    To disable or enable an item. It can be one of following values:

    • PLATFORM_CFG_ENABLE
    • PLATFORM_CFG_DISABLE

6.1.1.3 Return Value

Void.

6.1.1.4 Remarks

Void.

6.1.1.5 Example

// On ING918, Enable HCI logging
platform_config(PLATFORM_CFG_LOG_HCI, PLATFORM_CFG_ENABLE);

6.1.2 platform_get_version

Get version number of platform.

6.1.2.1 Prototype

const platform_ver_t *platform_get_version(void);

6.1.2.2 Parameters

Void.

6.1.2.3 Return Value

Pointer to platform_ver_t.

6.1.2.4 Remarks

Platform version number has three parts, major, minor and patch:

typedef struct platform_ver
{
    unsigned short major;
    char  minor;
    char  patch;
} platform_ver_t;

6.1.2.5 Example

const platform_ver_t *ver = platform_get_version();
printf("Platform version: %d.%d.%d\n", ver->major, ver->minor, ver->patch);

6.1.3 platform_read_info

Read platform information.

6.1.3.1 Prototype

uint32_t platform_read_info(const platform_info_item_t item);

6.1.3.2 Parameters

  • const platform_info_item_t item

    Information item.

    • PLATFORM_INFO_RT_OSC_STATUS: Read status of real-time crystal oscillator. Value 0: not OK; Non-0: OK.

    For ING916: this clock become running after selected as real time clock source.

    • PLATFORM_INFO_RT_CLK_CALI_VALUE: Read current real time clock calibration result.

    • PLATFOFM_INFO_IRQ_NUMBER: Get the underline IRQ number of a platform IRQ.

      For example, get the underline IRQ number of UART0:

      platform_read_info(
          PLATFOFM_INFO_IRQ_NUMBER + PLATFORM_CB_IRQ_UART0)

6.1.3.3 Return Value

Value of the information item.

6.1.3.4 Remarks

Void.

6.1.3.5 Example

platform_read_info(PLATFORM_INFO_RT_OSC_STATUS);

6.1.4 platform_switch_app

Switch to a secondary app.

6.1.4.1 Prototype

void platform_switch_app(const uint32_t app_addr);

6.1.4.2 Parameters

  • const uint32_t app_addr

    Entry address of the secondary app.

6.1.4.3 Return Value

Void.

6.1.4.4 Remarks

When calling this function, the code after it will not be executed.

6.1.4.5 Example

platform_switch_app(0x80000);

6.2 Events & Interrupts

6.2.1 platform_set_evt_callback_table

Register a callback function table for all platform events.

6.2.1.1 Prototype

void platform_set_evt_callback_table(
    const platform_evt_cb_table_t *table);

6.2.1.2 Parameters

  • const platform_evt_cb_table_t *table

    Address of the callback function table.

6.2.1.3 Return Value

Void.

6.2.1.4 Remarks

This function shall only be called in app_main. If platform_set_evt_callback is used, this function shall not be used.

Comparing to platform_set_evt_callback, use this function can save a block of RAM of sizeof(platform_evt_cb_table_t) bytes.

6.2.1.5 Example

static const platform_evt_cb_table_t evt_cb_table =
{
    .callbacks = {
        [PLATFORM_CB_EVT_HARD_FAULT] = {
            .f = (f_platform_evt_cb)cb_hard_fault,
        },
        [PLATFORM_CB_EVT_PROFILE_INIT] = {
            .f = setup_profile,
        },
        // ...
    }
};

int app_main()
{
    // ...
    platform_set_evt_callback_table(&evt_cb_table);
    // ...
}

6.2.2 platform_set_irq_callback_table

Register a callback function table for all platform interrupt requests.

6.2.2.1 Prototype

void platform_set_irq_callback_table(
    const platform_irq_cb_table_t *table);

6.2.2.2 Parameters

  • const platform_irq_cb_table_t *table

    Address of the callback function table.

6.2.2.3 Return Value

Void.

6.2.2.4 Remarks

This function shall only be called in app_main. If platform_set_irq_callback is used, this function shall not be used.

Comparing to platform_set_irq_callback, use this function can save a block of RAM of sizeof(platform_irq_cb_table_t) bytes.

6.2.2.5 Example

static const platform_irq_cb_table_t irq_cb_table =
{
    .callbacks = {
        [PLATFORM_CB_IRQ_UART0] = {
            .f = (f_platform_irq_cb)cb_irq_uart,
            .user_data = APB_UART0
        },
        // ...
    }
};

int app_main()
{
    // ...
    platform_set_irq_callback_table(&irq_cb_table);
    // ...
}

6.2.3 platform_set_evt_callback

Registers callback functions to platform events.

6.2.3.1 Prototype

void platform_set_evt_callback(platform_evt_callback_type_t type,
                               f_platform_evt_cb f,
                               void *user_data);

6.2.3.2 Parameters

  • platform_evt_callback_type_t type

    Specify the event type to which the callback function is registered. It can be one of following values:

    • PLATFORM_CB_EVT_PUTC: Ouput ASCII character event

      When platform want to output ASCII characters for logging, this event is fired. Parameter void *data passed into the callback function is casted from char *.

      Wizard can automatically generate code that redirects platform log to UART if Print to UART is checked on Common Function when creating a new project.

    • PLATFORM_CB_EVT_PROFILE_INIT: Profile initialization event

      When host initializes, this event is fired to request app to initialize GATT profile.

      Wizard can automatically generate code for this event when creating a new project.

    • PLATFORM_CB_EVT_ON_DEEP_SLEEP_WAKEUP: Wakeup from deep sleep event

      When waking up from deep sleep, this event is fired. During deep sleep, peripheral interfaces (such as UART, I2C, etc) are all powered off. So, when waking up, these interfaces might need to be re-initialized.

      Wizard can automatically generate code for event if Deep Sleep is checked on Common Function when creating a new project.

      Parameter void *data passed into the callback function is casted from platform_wakeup_call_info_t *.

      RTOS is not resumed yet, some ROTS APIs are not usable; Some platform APIs (such as platform_get_us_time) might be unusable either.

    • PLATFORM_CB_EVT_ON_IDLE_TASK_RESUMED: OS is fully resumed from power saving modes.

      The callback is invoked after PLATFORM_CB_EVT_ON_DEEP_SLEEP_WAKEUP if its reason is PLATFORM_WAKEUP_REASON_NORMAL. For NoOS variants, the callback is invoked by platform_os_idle_resumed_hook(). This event is different with PLATFORM_CB_EVT_ON_DEEP_SLEEP_WAKEUP:

      • all OS functionalities are resumed (For NoOS variants, this depends on the proper use of platform_os_idle_resumed_hook())
      • all platform APIs are functional
      • callback is invoked in the idle task.

      Parameter void *data is always NULL.

    • PLATFORM_CB_EVT_QUERY_DEEP_SLEEP_ALLOWED: Query if deep sleep is allowed event

      When platform prepares to enter deep sleep mode, this event is fired to query app if deep sleep is allow at this moment. Callback function can reject deep sleep by returning 0, and allow it by returning a non-0 value.

      Wizard can automatically generate code for event if Deep Sleep is checked on Common Function when creating a new project.

    • PLATFORM_CB_EVT_HARD_FAULT: Hard fault occurs

      When hard fault occurs, this event is fired. Parameter void *data passed into the callback function is casted from hard_fault_info_t *. If this callback is not defined, CPU enters a dead loop when hard fault occurs.

    • PLATFORM_CB_EVT_ASSERTION: Software assertion fails

      When software assertion fails, this event is fired. Parameter void *data passed into the callback function is casted from assertion_info_t *. If this callback is not defined, CPU enters a dead loop when assertion occurs.

    • PLATFORM_CB_EVT_LLE_INIT: Link layer engine initialized.

      When link layer engine initialized, this event is fired.

    • PLATFORM_CB_EVT_HEAP_OOM: Out of memory.

      When allocation on heap fails (heap out of memory), this event is fired. If this event is fired and no callback is defined, CPU enters a dead loop.

    • PLATFORM_CB_EVT_TRACE: Trace output.

      When a trace item is emitted, this event is fired. Apps can define a callback function for this event to save or log trace output. param to the callback is casted from platform_trace_evt_t * (See Debugging & Tracing).

      typedef struct
      {
          const void *data1;
          const void *data2;
          uint16_t len1;
          uint16_t len2;
      } platform_evt_trace_t;

      A trace item is a combination of data1 and data2. Note:

      1. len1 or len2 might be 0, but not both;

      2. If callback function finds that it can’t output data of size len1 + len2, then, both data1 & data2 should be discarded to avoid trace item corruption.

    • PLATFORM_CB_EVT_EXCEPTION: Hardware exceptions.

      Parameter void *data is casted from platform_exception_id_t *.

    • PLATFORM_CB_EVT_IDLE_PROC: Customized IDLE procedure.

      See “Programmer’s Guide - Power Saving”23.

    • PLATFORM_CB_EVT_HCI_RECV: Take over HCI and isolate the built-in Host completely.

      When defined:

      • HCI events and ACL data are passed to this callback;
      • PLATFORM_CB_EVT_PROFILE_INIT is ignored.

      Parameter void *data is casted from const platform_hci_recv_t *. See also platform_get_link_layer_interf.

  • f_platform_evt_cb f

    The callback function registered to event type. f_platform_evt_cb is:

    typedef uint32_t (*f_platform_evt_cb)(void *data, void *user_data);
  • void *user_data

    This is passed to callback function’s user_data unchanged.

6.2.3.3 Return Value

Void.

6.2.3.4 Remarks

It is not required to register callback functions to each event.

If no callback function is registered to PLATFORM_CB_EVT_PUTC event, all platform log including platform_printf is discarded.

If no callback function is registered to PLATFORM_CB_EVT_PROFILE_INIT event, BLE device’s profile is empty.

If no callback function is registered to PLATFORM_CB_EVT_ON_DEEP_SLEEP_WAKEUP event, app will not be notified when waking up from deep sleep.

If no callback function is registered to PLATFORM_CB_EVT_QUERY_DEEP_SLEEP_ALLOWED event, deep sleep is disabled.

6.2.3.5 Example

uint32_t cb_putc(char *c, void *dummy)
{
    // TODO: output char c to UART
    return 0;
}

......

platform_set_evt_callback(PLATFORM_CB_EVT_PUTC, (f_platform_evt_cb)cb_putc,
                          NULL);

6.2.4 platform_set_irq_callback

Registers callback functions to interrupt requests.

Developers do not need to define IRQ handlers in apps, but use callback functions instead.

6.2.4.1 Prototype

void platform_set_irq_callback(platform_irq_callback_type_t type,
                               f_platform_irq_cb f,
                               void *user_data);

6.2.4.2 Parameters

  • platform_irq_callback_type_t type

    Specify the IRQ type to which the callback function is registered. Values vary for different chip families. Take ING918 as an example:

    PLATFORM_CB_IRQ_RTC,
    PLATFORM_CB_IRQ_TIMER0,
    PLATFORM_CB_IRQ_TIMER1,
    PLATFORM_CB_IRQ_TIMER2,
    PLATFORM_CB_IRQ_GPIO,
    PLATFORM_CB_IRQ_SPI0,
    PLATFORM_CB_IRQ_SPI1,
    PLATFORM_CB_IRQ_UART0,
    PLATFORM_CB_IRQ_UART1,
    PLATFORM_CB_IRQ_I2C0,
    PLATFORM_CB_IRQ_I2C1
  • f_platform_irq_cb f

    The callback function registered to IRQ type. f_platform_irq_cb is:

    typedef uint32_t (*f_platform_irq_cb)(void *user_data);
  • void *user_data

    This is passed to callback function’s user_data unchanged.

6.2.4.3 Return Value

Void.

6.2.4.4 Remarks

When a callback function is registered to an IRQ, the IRQ is enabled automatically. See also platform_enable_irq.

6.2.4.5 Example

uint32_t cb_irq_uart0(void *dummy)
{
    // TODO: add UART0 IRQ handling code
    return 0;
}

......

platform_set_irq_callback(
    PLATFORM_CB_IRQ_UART0,
    cb_irq_uart0,
    NULL);

6.2.5 platform_enable_irq

Enable or disable a specified IRQ.

6.2.5.1 Prototype

void platform_enable_irq(
    platform_irq_callback_type_t type,
    uint8_t flag);

6.2.5.2 Parameters

  • platform_irq_callback_type_t type:

    The IRQ to be configured.

  • uint8_t flag:

    Enable (1) or disable (0).

6.2.5.3 Return Value

Void.

6.2.5.4 Remarks

“Enabling” or “disabling” an interrupt here is from the perspective of CPU. Take UART as an example, UART itself has to be configured to generate interrupts for Rx, Tx, or timeout, which is out of the scope of this function.

6.2.5.5 Example

To enable the interrupt request from UART0:

platform_enable_irq(
    PLATFORM_CB_IRQ_UART0,
    1);

6.3 Clocks

See also “The Real-time Clock”24 in “Programmer’s Guide - Power Saving”25.

6.3.1 platform_calibrate_rt_clk

Calibrate real-time clock and get the calibration value.

6.3.1.1 Prototype

uint32_t platform_calibrate_rt_clk(void);

6.3.2 platform_rt_rc_auto_tune

Automatically tune the internal real-time RC clock, and get the tuning value.

For ING918, this function tunes the internal real-time RC clock to 50kHz26. For others, it tunes the internal real-time RC clock to 32768Hz.

6.3.2.1 Prototype

uint16_t platform_rt_rc_auto_tune(void);

6.3.2.2 Parameters

Void.

6.3.2.3 Return Value

The 16-bits tuning value.

6.3.2.4 Remarks

This function must be called if the app enables power saving mode, and the real-time RC clock is used as the clock source.

This operation costs ~250ms. It is recommended to call this once and store the returned value for later usage.

6.3.2.5 Example

// the simplest example: call this function in the
// callback function of `PLATFORM_CB_EVT_PROFILE_INIT`
// without saving the returned value.
uint32_t setup_profile(void *user_data)
{
    platform_rt_rc_auto_tune();
    ...
}

6.3.3 platform_rt_rc_auto_tune2

Automatically tune the internal real-time RC clock to a specific frequency, and get the tuning value.

6.3.3.1 Prototype

uint16_t platform_rt_rc_auto_tune2(
    uint32_t target_frequency);

6.3.3.2 Parameters

  • uint32_t target_frequency

    Target frequency in Hertz.

6.3.3.3 Return Value

The 16-bits tuning value.

6.3.4 platform_rt_rc_tune

Tune internal the real-time RC clock with the tune value.

6.3.4.1 Prototype

void platform_rt_rc_tune(uint16_t value);

6.3.4.2 Parameters

6.3.4.3 Return Value

Void.

6.3.4.4 Remarks

void.

6.3.4.5 Example

platform_rt_rc_tune(value);

6.4 RF

6.4.1 platform_set_rf_clk_source

Select RF clock source. This function is for internal use.

6.4.2 platform_set_rf_init_data

Customize RF initialization data. This function is for internal use.

6.4.3 platform_set_rf_power_mapping

Power level is represented by an index internally. There is a power mapping table which lists the actual Tx power level of an index. Take ING918 as an example, power index is in a range of [0..63], and power mapping table is an array of 64 entries, each entry giving the Tx power level in 0.01 dBm.

For applications that need better power level control, actual power level can be measured for each index. Update the mapping with this function, then the stack can determine the proper index for a request power level.

6.4.3.1 Prototype

void platform_set_rf_power_mapping(
    const int16_t *rf_power_mapping);

6.4.3.2 Parameters

  • const int16_t *rf_power_mapping

    The new power mapping table.

6.4.3.3 Return Value

Void.

6.4.3.4 Remarks

Void.

6.4.3.5 Example


static const int16_t power_mapping[] =
{
    -6337,  // index 0: -63.37dBm
    // ...
    603     // index 63: 6.03dBm
};


platform_set_rf_power_mapping(
    power_mapping);

6.4.4 platform_patch_rf_init_data

Patch part of the internal RF initialization data. This function is for internal use.

6.5 Memory & RTOS

6.5.1 platform_call_on_stack

Call a function on a separate dedicated stack. This is useful when a function that uses a lot of stack needs to be called, occasionally.

6.5.1.1 Prototype

void platform_call_on_stack(
    f_platform_function f,
    void *user_data,
    void *stack_start,
    uint32_t stack_size);

6.5.1.2 Parameters

  • f_platform_function f

    The function to be called.

  • void *user_data

    User data to be passed to f.

  • void *stack_start

    Start (lowest) address of the dedicated stack.

  • uint32_t stack_size

    Size of the dedicated stack in bytes.

6.5.1.3 Return Value

Void.

6.5.1.4 Remarks

Although stack_size is provided, this function does not protect the stack from overwritten by f.

6.5.2 platform_get_current_task

Get the current task from which this API is called.

6.5.2.1 Prototype

platform_task_id_t platform_get_current_task(void);

6.5.2.2 Parameters

Void.

6.5.2.3 Return Value

typedef enum
{
    PLATFORM_TASK_CONTROLLER,
    PLATFORM_TASK_HOST,
    PLATFORM_TASK_RTOS_TIMER,
} platform_task_id_t;

6.5.2.4 Remarks

This API is only available in bundles with built-in RTOS.

6.5.3 platform_get_gen_os_driver

Get the generic OS driver. For “NoOS” variants, driver provided by app is returned; for bundles with built-in RTOS, an emulated driver is returned.

6.5.3.1 Prototype

const void *platform_get_gen_os_driver(void);

6.5.3.2 Parameters

Void.

6.5.3.3 Return Value

Return value is casted from const gen_os_driver_t *. Developers can cast the return value back to const gen_os_driver_t * and use API in it.

6.5.3.4 Remarks

gen_os_driver_t is an abstract layer over RTOS. Using API in it instead of RTOS API can make apps cross RTOS (independent of underlying RTOS).

6.5.4 platform_get_heap_status

Get current heap status, such as available size, etc.

6.5.4.1 Prototype

void platform_get_heap_status(platform_heap_status_t *status);

6.5.4.2 Parameters

  • platform_heap_status_t *status

    Heap status.

6.5.4.3 Return Value

Void.

6.5.4.4 Remarks

Heap status is defined as:

typedef struct
{
    uint32_t bytes_free;                // total free bytes
    uint32_t bytes_minimum_ever_free;   // minimum of bytes_free from startup
} platform_heap_status_t;

6.5.4.5 Example

platform_heap_status_t status;
platform_get_heap_status(&status);

6.5.5 platform_get_task_handle

Get RTOS handle of a specific platform task.

6.5.5.1 Prototype

uintptr_t platform_get_task_handle(
    platform_task_id_t id);

6.5.5.2 Parameters

  • platform_task_id_t id

    Platform task ID.

6.5.5.3 Return Value

Task handle if such task is known to platform else 0. For example, in the case of “NoOS” variants, platform does not know the handle of PLATFORM_TASK_RTOS_TIMER, so 0 is returned.

6.5.6 platform_install_task_stack

Install a new RTOS stack for a specific platform task.

Use this to enlarge stack when the default stack size is not enough for internal tasks. For example, user developed RTOS timer callbacks might require a larger stack space.

Developers can check RTOS documentation for how to check stack usages. For example, uxTaskGetStackHighWaterMark in FreeRTOS is used to query how close a task has come to overflowing the stack space allocated to it.

6.5.6.1 Prototype

void platform_install_task_stack(
    platform_task_id_t id,
    void *start,
    uint32_t size);

6.5.6.2 Parameters

  • platform_task_id_t id

    Task identifier.

  • void *start

    Start (lowest) address of the stack. Address shall be properly aligned for underlying CPU.

  • uint32_t size

    Size of the new stack in bytes.

6.5.6.3 Return Value

Void.

6.5.6.4 Remarks

This function shall only be called in app_main.

For NoOS variants, RTOS stacks can be replaced (modify its size, etc) when implementing the generic OS interface.

6.5.7 platform_install_isr_stack

Install a new stack for ISR.

6.5.7.1 Prototype

void platform_install_isr_stack(void *top);

6.5.7.2 Parameters

  • void *top

    Top of the new stack, which must be properly aligned for the underlying CPU.

6.5.7.3 Return Value

Void.

6.5.7.4 Remarks

In case apps need a much larger stack than the default one in ISR, a new stack can be installed to replace the default one.

This function is only allowed to be called in app_main. The new stack is put into use after app_main returns.

6.5.7.5 Example

uint32_t new_stack[2048];
...
platform_install_isr_stack(new_stack + sizeof(new_stack) / sizeof(new_stack[0]));

6.6 Time & Timers

API for reading current time (timer counter):

  • platform_get_timer_counter
  • platform_get_us_time

API for using timers with 625μs resolution:

  • platform_set_abs_timer
  • platform_set_timer
  • platform_delete_timer

API for using timer with 1μs resolution:

  • platform_create_us_timer
  • platform_cancel_us_timer

Both types of timers can be used with power saving, i.e. it just works as expected when power saving is enabled. A comparison of of these two types of timers is shown in Table 6.1.

Table 6.1: Two Types of Platform Timers
Type 625μs resolution 1μs resolution
Callback Invoked from a task-like context Invoked from an ISR
Identifier Callback function pointer Timer handle

6.6.1 platform_cancel_us_timer

Cancel a platform timer previously created by platform_create_us_timer.

6.6.1.1 Prototype

int platform_cancel_us_timer(
    platform_us_timer_handle_t timer_handle);

6.6.1.2 Parameters

  • platform_us_timer_handle_t timer_handle

    Handle of the timer.

6.6.1.3 Return Value

This function returns 0 if the specified time is canceled successfully. Otherwise, a non-0 value is returned, which also means the callback function of the timer is executing.

6.6.2 platform_create_us_timer

Setup a single-shot platform timer with 1 microsecond (μs) resolution.

6.6.2.1 Prototype

platform_us_timer_handle_t platform_create_us_timer(
    uint64_t abs_time,
    f_platform_us_timer_callback callback,
    void *param);

6.6.2.2 Parameters

  • uint64_t abs_time

    When platform_get_us_timer() == abs_time, the callback is invoked.

  • f_platform_us_timer_callback callback

    The callback function. The signature is:

    typedef void * (* f_platform_us_timer_callback)(
        platform_us_timer_handle_t timer_handle,
        uint64_t time_us,
        void *param);

    Where, timer_handle is the returned value of platform_create_us_timer, i.e. , time_us is current value of platform_get_us_timer when invoking the callback, and param is the user parameter when creating this timer.

  • void *param

    User parameter.

6.6.2.3 Return Value

This function returns a handle of the created timer. A non-NULL value is returned when the timer is successfully created. Otherwise, NULL is returned.

6.6.2.4 Remarks

Although abs_time is in microsecond (μs), callback is not guaranteed to be invoked with such resolution.

This type of timers are much like platform_set_timer, except that:

  1. resolution is higher;
  2. callback is invoked in the context of an ISR.

DO NOT call platform_create_us_timer again in callback.

6.6.3 platform_delete_timer

Delete a previously platform timer created by platform_set_timer or platform_set_abs_timer.

6.6.3.1 Prototype

void platform_delete_timer(f_platform_timer_callback callback)

6.6.3.2 Parameters

  • f_platform_timer_callback callback

    The callback function, which is also an identifier for the timer.

6.6.3.3 Return Value

Void.

6.6.3.4 Remarks

When calling this function, the callback might already be queued for invoking in the task. Therefore, the callback might still be invoked after this function is called.

6.6.4 platform_get_timer_counter

Read the counter of platform timer at 625μs resolution.

6.6.4.1 Prototype

uint32_t platform_get_timer_counter(void);

6.6.4.2 Parameters

Void.

6.6.4.3 Return Value

A full 32 bits value represents current counter, which is roughly platform_get_us_time() / 625.

6.6.5 platform_get_us_time

Read the internal time counting from BLE initialization.

6.6.5.1 Prototype

int64_t platform_get_us_time(void);

6.6.5.2 Parameters

Void.

6.6.5.3 Return Value

Value of the internal time counter counting at 1μs. This counter wraps around every ~21.8 years.

6.6.5.4 Remarks

This counter restarts after shutdown.

6.6.5.5 Example

uint64_t now = platform_get_us_time();

6.6.6 platform_set_abs_timer

Setup a single-shot platform timer triggered at an absolute time with 625μs resolution.

6.6.6.1 Prototype

void platform_set_abs_timer(
    f_platform_timer_callback callback,
    uint32_t abs_time);

6.6.6.2 Parameters

  • f_platform_timer_callback callback

    The callback function when the timer expired, and is called in a RTOS task-like27 context, but not an ISR.

  • uint32_t abs_time

    when platform_get_timer_counter() == abs_time, callback is invoked. If abs_time just passes platform_get_timer_counter(), callback is invoked immediately, for example, abs_time is platform_get_timer_counter() - 1.

6.6.6.3 Return Value

Void.

6.6.6.4 Remarks

This function always succeeds, except when running out of memory.

6.6.6.5 Example

Use this function to emulate a periodic timer.


#define PERIOD  100
static uint32_t last_timer = 0;

void platform_timer_callback(void)
{
    last_timer += PERIOD;
    platform_set_abs_timer(platform_timer_callback, last_timer);

    // do periodic job
    // ...
}

last_timer = platform_get_timer_counter() + PERIOD;
platform_set_abs_timer(platform_timer_callback, last_timer);

6.6.7 platform_set_timer

Setup a single-shot platform timer after a delay from “now” with 625μs resolution.

6.6.7.1 Prototype

void platform_set_timer(
    f_platform_timer_callback callback,
    uint32_t delay);

6.6.7.2 Parameters

  • f_platform_timer_callback callback

    The callback function when the timer expired, and is called in a RTOS task-like context, but not an ISR.

  • uint32_t delay

    Time delay before the timer expires (unit: 625μs).

    Valid Range: 0~0x7fffffff. When delay is 0, the timer is cleared.

6.6.7.3 Return Value

Void.

6.6.7.4 Remarks

This function always succeeds, except when running out of memory.

platform_set_timer(f, 100) is equivalent to:

platform_set_abs_timer(f,
    platform_get_timer_counter() + 100);

platform_set_timer(f, 0) is equivalent to:

platform_delete_timer(f);

but not

platform_set_abs_timer(f,
    platform_get_timer_counter() + 0);

Since callback is also the identifier of the timer, below two lines defines only a timer expiring after 200 units but not two separate timers:

platform_set_timer(f, 100);
platform_set_timer(f, 200); // update the timer, but not creating a new one

If f is used once again in platform_set_abs_timer, then the timer is updated again:

platform_set_abs_timer(f, ...);

6.7 Utilities

6.7.1 platform_hrng

Generate random bytes by using hardware random-number generator.

6.7.1.1 Prototype

void  platform_hrng(uint8_t *bytes, const uint32_t len);

6.7.1.2 Parameters

  • uint8_t *bytes

    Random data output.

  • const uint32_t len

    Number of random bytes to be generated.

6.7.1.3 Return Value

Void.

6.7.1.4 Remarks

Time consumption to generate a fix length of data is undetermined.

6.7.1.5 Example

uint32_t strong_random;
platform_hrng(&strong_random, sizeof(strong_random));

6.7.2 platform_rand

Generate a pseudo random integer by internal PRNG.

6.7.2.1 Prototype

int platform_rand(void);

6.7.2.2 Parameters

Void.

6.7.2.3 Return Value

A pseudo random integer in range of 0 to RAND_MAX.

6.7.2.4 Remarks

Seed of the internal PRNG is initialized by HRNG at startup. This function can be used as a replacement of rand() in standard library.

6.7.2.5 Example

printf("rand: %d\n", platform_rand());

6.7.3 platform_read_persistent_reg

Read value from the persistent register. See also platform_write_persistent_reg.

6.7.3.1 Prototype

uint32_t platform_read_persistent_reg(void);

6.7.3.2 Parameters

Void.

6.7.3.3 Return Value

The value written by platform_write_persistent_reg.

6.7.3.4 Remarks

Void.

6.7.3.5 Example

platform_read_persistent_reg();

6.7.4 platform_reset

Reset platform (SoC).

6.7.4.1 Prototype

void platform_reset(void);

6.7.4.2 Parameters

Void.

6.7.4.3 Return Value

Void.

6.7.4.4 Remarks

When calling this function, the code after it will not be executed.

6.7.4.5 Example

  if (out-of-memory)
    platform_reset();

6.7.5 platform_shutdown

Bring the whole system into shutdown state, and reboot after a specified duration. Optionally, a portion of memory can be retained during shutdown, and apps can continue to use it after reboot.

Note that this function will NOT return except that shutdown procedure fails to initiate. Possible causes for failures include:

  1. External wake-up signal is issued;
  2. Input parameters are not proper;
  3. Internal components are busy.

6.7.5.1 Prototype

void platform_shutdown(const uint32_t duration_cycles,
                       const void *p_retention_data,
                       const uint32_t data_size);

6.7.5.2 Parameters

  • const uint32_t duration_cycles

    Duration (measured in cycles of real-time clock) before power on again (reboot). The minimum duration is 825 cycles (about 25.18ms). If 0 is used, the system will stay in shutdown state until external wake-up signal is issued.

  • const void *p_retention_data

    Pointer to the start of data to be retained. Only data within SYSTEM memory can be retained. This parameter can be set to NULL when data_size is 0.

  • data_size

    Size of the data to be retained. Set to 0 when memory retention is not needed.

6.7.5.3 Return Value

Void.

6.7.5.4 Remarks

Void.

6.7.5.5 Example

// Shutdown the system and reboot after 1s.
platform_shutdown(32768, NULL, 0);

6.7.6 platform_write_persistent_reg

Write a value to the persistent register. This value is kept even in power saving, shutdown mode, or when switching to another app.

Only a few bits are saved as shown in Table 6.2.

Table 6.2: Persistent Register Bit Size
Chip Family Register Size (bit)
ING918 4
ING916 5

6.7.6.1 Prototype

void platform_write_persistent_reg(const uint8_t value);

6.7.6.2 Parameters

  • const uint8_t value

    The value.

6.7.6.3 Return Value

Void.

6.7.6.4 Remarks

Void.

6.7.6.5 Example

platform_write_persistent_reg(1);

6.8 Debugging & Tracing

6.8.1 platform_printf

The printf function stored in platform binary.

6.8.1.1 Prototype

 void  platform_printf(const char *format, ...);

6.8.1.2 Parameters

  • const char *format

    Format string.

  • ...

    Variable arguments for format string.

6.8.1.3 Return Value

Void.

6.8.1.4 Remarks

There are pros & cons to use this function.

Pros:

  • This function is located in platform binary, app binary size can be saved.

Cons:

  • Output is directed PLATFORM_CB_EVT_PUTC event, so its callback function must be defined.

6.8.1.5 Example

platform_printf("Hello world");

6.8.2 platform_raise_assertion

Raise a software assertion.

6.8.2.1 Prototype

void  platform_raise_assertion(const char *file_name, int line_no);

6.8.2.2 Parameters

  • const char *file_name

    File name where the assertion occurred.

  • int line_no

    Line number where the assertion occurred.

6.8.2.3 Return Value

Void.

6.8.2.4 Remarks

Void.

6.8.2.5 Example

  if (NULL == ptr)
    platform_raise_assertion(__FILE__, __LINE__);

6.8.3 platform_trace_raw

Output a block of raw data to TRACE. ID is PLATFORM_TRACE_ID_RAW.

6.8.3.1 Prototype

void platform_trace_raw(
    const void *buffer,
    const int byte_len);

6.8.3.2 Parameters

  • const void *buffer

    Pointer of the buffer.

  • const int byte_len

    Length of data buffer in bytes.

6.9 Others

6.9.2 sysSetPublicDeviceAddr

Set the public address of device.

The public address of a BLE device is a 48-bit extended unique identifier (EUI-48) created in accordance with the IEEE 802-2014 standard28.

INGCHIPS 91x DO NOT have public addresses. This function should ONLY be used for debugging or testing, and NEVER be used in final products.

6.9.2.1 Prototype

void sysSetPublicDeviceAddr(const unsigned char *addr);

6.9.2.2 Parameters

  • const unsigned char *addr

    New public address.

6.9.2.3 Return Value

Void.

6.9.2.4 Remarks

In order to avoid potential issues, this function should be called before calling any GAP functions. It is recommended to call this function in app_main or PLATFORM_CB_EVT_PROFILE_INIT event callback function.

6.9.2.5 Example

const unsigned char pub_addr[] = {1,2,3,4,5,6};
sysSetPublicDeviceAddr(pub_addr);