mirror of https://github.com/ARMmbed/mbed-os.git
add app_common header files for Nordic targets
parent
e4e0873d55
commit
04d0142bd6
|
@ -0,0 +1,187 @@
|
|||
/* Copyright (c) 2012 Nordic Semiconductor. All Rights Reserved.
|
||||
*
|
||||
* The information contained herein is property of Nordic Semiconductor ASA.
|
||||
* Terms and conditions of usage are described in detail in NORDIC
|
||||
* SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
|
||||
*
|
||||
* Licensees are granted free, non-transferable use of the information. NO
|
||||
* WARRANTY of ANY KIND is provided. This heading must NOT be removed from
|
||||
* the file.
|
||||
*
|
||||
*/
|
||||
|
||||
/** @file
|
||||
*
|
||||
* @defgroup app_button Button Handler
|
||||
* @{
|
||||
* @ingroup app_common
|
||||
*
|
||||
* @brief Buttons handling module.
|
||||
*
|
||||
* @details The button handler uses the @ref app_gpiote to detect that a button has been
|
||||
* pushed. To handle debouncing, it will start a timer in the GPIOTE event handler.
|
||||
* The button will only be reported as pushed if the corresponding pin is still active when
|
||||
* the timer expires. If there is a new GPIOTE event while the timer is running, the timer
|
||||
* is restarted.
|
||||
* Use the USE_SCHEDULER parameter of the APP_BUTTON_INIT() macro to select if the
|
||||
* @ref app_scheduler is to be used or not.
|
||||
*
|
||||
* @note The app_button module uses the app_timer module. The user must ensure that the queue in
|
||||
* app_timer is large enough to hold the app_timer_stop() / app_timer_start() operations
|
||||
* which will be executed on each event from GPIOTE module (2 operations), as well as other
|
||||
* app_timer operations queued simultaneously in the application.
|
||||
*
|
||||
* @note Even if the scheduler is not used, app_button.h will include app_scheduler.h, so when
|
||||
* compiling, app_scheduler.h must be available in one of the compiler include paths.
|
||||
*/
|
||||
|
||||
#ifndef APP_BUTTON_H__
|
||||
#define APP_BUTTON_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "app_error.h"
|
||||
#include "app_scheduler.h"
|
||||
#include "nrf_gpio.h"
|
||||
|
||||
#define APP_BUTTON_SCHED_EVT_SIZE sizeof(app_button_event_t) /**< Size of button events being passed through the scheduler (is to be used for computing the maximum size of scheduler events). */
|
||||
#define APP_BUTTON_PUSH 1 /**< Indicates that a button is pushed. */
|
||||
#define APP_BUTTON_RELEASE 0 /**< Indicates that a button is released. */
|
||||
#define APP_BUTTON_ACTIVE_HIGH 1 /**< Indicates that a button is active high. */
|
||||
#define APP_BUTTON_ACTIVE_LOW 0 /**< Indicates that a button is active low. */
|
||||
|
||||
/**@brief Button event handler type. */
|
||||
typedef void (*app_button_handler_t)(uint8_t pin_no, uint8_t button_action);
|
||||
|
||||
/**@brief Type of function for passing events from the Button Handler module to the scheduler. */
|
||||
typedef uint32_t (*app_button_evt_schedule_func_t) (app_button_handler_t button_handler,
|
||||
uint8_t pin_no,
|
||||
uint8_t button_action);
|
||||
|
||||
/**@brief Button configuration structure. */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t pin_no; /**< Pin to be used as a button. */
|
||||
uint8_t active_state; /**< APP_BUTTON_ACTIVE_HIGH or APP_BUTTON_ACTIVE_LOW. */
|
||||
nrf_gpio_pin_pull_t pull_cfg; /**< Pull-up or -down configuration. */
|
||||
app_button_handler_t button_handler; /**< Handler to be called when button is pushed. */
|
||||
} app_button_cfg_t;
|
||||
|
||||
/**@brief Pin transition direction struct. */
|
||||
typedef struct
|
||||
{
|
||||
uint32_t high_to_low; /**Pin went from high to low */
|
||||
uint32_t low_to_high; /**Pin went from low to high */
|
||||
} pin_transition_t;
|
||||
|
||||
/**@brief Macro for initializing the Button Handler module.
|
||||
*
|
||||
* @details It will initialize the specified pins as buttons, and configure the Button Handler
|
||||
* module as a GPIOTE user (but it will not enable button detection). It will also connect
|
||||
* the Button Handler module to the scheduler (if specified).
|
||||
*
|
||||
* @param[in] BUTTONS Array of buttons to be used (type app_button_cfg_t, must be
|
||||
* static!).
|
||||
* @param[in] BUTTON_COUNT Number of buttons.
|
||||
* @param[in] DETECTION_DELAY Delay from a GPIOTE event until a button is reported as pushed.
|
||||
* @param[in] USE_SCHEDULER TRUE if the application is using the event scheduler,
|
||||
* FALSE otherwise.
|
||||
*/
|
||||
/*lint -emacro(506, APP_BUTTON_INIT) */ /* Suppress "Constant value Boolean */
|
||||
#define APP_BUTTON_INIT(BUTTONS, BUTTON_COUNT, DETECTION_DELAY, USE_SCHEDULER) \
|
||||
do \
|
||||
{ \
|
||||
uint32_t ERR_CODE = app_button_init((BUTTONS), \
|
||||
(BUTTON_COUNT), \
|
||||
(DETECTION_DELAY), \
|
||||
(USE_SCHEDULER) ? app_button_evt_schedule : NULL); \
|
||||
APP_ERROR_CHECK(ERR_CODE); \
|
||||
} while (0)
|
||||
|
||||
/**@brief Function for initializing the Buttons.
|
||||
*
|
||||
* @details This function will initialize the specified pins as buttons, and configure the Button
|
||||
* Handler module as a GPIOTE user (but it will not enable button detection).
|
||||
*
|
||||
* @note Normally initialization should be done using the APP_BUTTON_INIT() macro, as that will take
|
||||
* care of connecting the Buttons module to the scheduler (if specified).
|
||||
*
|
||||
* @note app_button_enable() function must be called in order to enable the button detection.
|
||||
*
|
||||
* @param[in] p_buttons Array of buttons to be used (NOTE: Must be static!).
|
||||
* @param[in] button_count Number of buttons.
|
||||
* @param[in] detection_delay Delay from a GPIOTE event until a button is reported as pushed.
|
||||
* @param[in] evt_schedule_func Function for passing button events to the scheduler. Point to
|
||||
* app_button_evt_schedule() to connect to the scheduler. Set to
|
||||
* NULL to make the Buttons module call the event handler directly
|
||||
* from the delayed button push detection timeout handler.
|
||||
*
|
||||
* @return NRF_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
uint32_t app_button_init(app_button_cfg_t * p_buttons,
|
||||
uint8_t button_count,
|
||||
uint32_t detection_delay,
|
||||
app_button_evt_schedule_func_t evt_schedule_func);
|
||||
|
||||
/**@brief Function for enabling button detection.
|
||||
*
|
||||
* @retval NRF_ERROR_INVALID_PARAM GPIOTE has to many users.
|
||||
* @retval NRF_ERROR_INVALID_STATE Button or GPIOTE not initialized.
|
||||
* @retval NRF_SUCCESS Button detection successfully enabled.
|
||||
*/
|
||||
uint32_t app_button_enable(void);
|
||||
|
||||
/**@brief Function for disabling button detection.
|
||||
*
|
||||
* @retval NRF_ERROR_INVALID_PARAM GPIOTE has to many users.
|
||||
* @retval NRF_ERROR_INVALID_STATE Button or GPIOTE not initialized.
|
||||
* @retval NRF_SUCCESS Button detection successfully enabled.
|
||||
*/
|
||||
uint32_t app_button_disable(void);
|
||||
|
||||
/**@brief Function for checking if a button is currently being pushed.
|
||||
*
|
||||
* @param[in] pin_no Button pin to be checked.
|
||||
* @param[out] p_is_pushed Button state.
|
||||
*
|
||||
* @retval NRF_SUCCESS State successfully read.
|
||||
* @retval NRF_ERROR_INVALID_PARAM Invalid pin_no.
|
||||
*/
|
||||
uint32_t app_button_is_pushed(uint8_t pin_no, bool * p_is_pushed);
|
||||
|
||||
|
||||
// Type and functions for connecting the Buttons module to the scheduler:
|
||||
|
||||
/**@cond NO_DOXYGEN */
|
||||
typedef struct
|
||||
{
|
||||
app_button_handler_t button_handler;
|
||||
uint8_t pin_no;
|
||||
uint8_t button_action;
|
||||
} app_button_event_t;
|
||||
|
||||
static __INLINE void app_button_evt_get(void * p_event_data, uint16_t event_size)
|
||||
{
|
||||
app_button_event_t * p_buttons_event = (app_button_event_t *)p_event_data;
|
||||
|
||||
APP_ERROR_CHECK_BOOL(event_size == sizeof(app_button_event_t));
|
||||
p_buttons_event->button_handler(p_buttons_event->pin_no, p_buttons_event->button_action);
|
||||
}
|
||||
|
||||
static __INLINE uint32_t app_button_evt_schedule(app_button_handler_t button_handler,
|
||||
uint8_t pin_no,
|
||||
uint8_t button_action)
|
||||
{
|
||||
app_button_event_t buttons_event;
|
||||
|
||||
buttons_event.button_handler = button_handler;
|
||||
buttons_event.pin_no = pin_no;
|
||||
buttons_event.button_action = button_action;
|
||||
|
||||
return app_sched_event_put(&buttons_event, sizeof(buttons_event), app_button_evt_get);
|
||||
}
|
||||
/**@endcond */
|
||||
|
||||
#endif // APP_BUTTON_H__
|
||||
|
||||
/** @} */
|
|
@ -0,0 +1,84 @@
|
|||
/* Copyright (c) 2013 Nordic Semiconductor. All Rights Reserved.
|
||||
*
|
||||
* Terms and conditions of usage are described in detail in NORDIC
|
||||
* SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
|
||||
*
|
||||
* Licensees are granted free, non-transferable use of the information. NO
|
||||
* WARRANTY of ANY KIND is provided. This heading must NOT be removed from
|
||||
* the file.
|
||||
*
|
||||
*/
|
||||
|
||||
/** @file
|
||||
*
|
||||
* @defgroup app_error Common application error handler
|
||||
* @{
|
||||
* @ingroup app_common
|
||||
*
|
||||
* @brief Common application error handler and macros for utilizing a common error handler.
|
||||
*/
|
||||
|
||||
#ifndef APP_ERROR_H__
|
||||
#define APP_ERROR_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "nrf_error.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**@brief Function for error handling, which is called when an error has occurred.
|
||||
*
|
||||
* @param[in] error_code Error code supplied to the handler.
|
||||
* @param[in] line_num Line number where the handler is called.
|
||||
* @param[in] p_file_name Pointer to the file name.
|
||||
*/
|
||||
void app_error_handler(uint32_t error_code, uint32_t line_num, const uint8_t * p_file_name);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/**@brief Macro for calling error handler function.
|
||||
*
|
||||
* @param[in] ERR_CODE Error code supplied to the error handler.
|
||||
*/
|
||||
#define APP_ERROR_HANDLER(ERR_CODE) \
|
||||
do \
|
||||
{ \
|
||||
app_error_handler((ERR_CODE), __LINE__, (uint8_t*) __FILE__); \
|
||||
} while (0)
|
||||
|
||||
/**@brief Macro for calling error handler function if supplied error code any other than NRF_SUCCESS.
|
||||
*
|
||||
* @param[in] ERR_CODE Error code supplied to the error handler.
|
||||
*/
|
||||
#define APP_ERROR_CHECK(ERR_CODE) \
|
||||
do \
|
||||
{ \
|
||||
const uint32_t LOCAL_ERR_CODE = (ERR_CODE); \
|
||||
if (LOCAL_ERR_CODE != NRF_SUCCESS) \
|
||||
{ \
|
||||
APP_ERROR_HANDLER(LOCAL_ERR_CODE); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/**@brief Macro for calling error handler function if supplied boolean value is false.
|
||||
*
|
||||
* @param[in] BOOLEAN_VALUE Boolean value to be evaluated.
|
||||
*/
|
||||
#define APP_ERROR_CHECK_BOOL(BOOLEAN_VALUE) \
|
||||
do \
|
||||
{ \
|
||||
const bool LOCAL_BOOLEAN_VALUE = (BOOLEAN_VALUE); \
|
||||
if (!LOCAL_BOOLEAN_VALUE) \
|
||||
{ \
|
||||
APP_ERROR_HANDLER(0); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#endif // APP_ERROR_H__
|
||||
|
||||
/** @} */
|
|
@ -0,0 +1,83 @@
|
|||
/* Copyright (c) 2013 Nordic Semiconductor. All Rights Reserved.
|
||||
*
|
||||
* The information contained herein is property of Nordic Semiconductor ASA.
|
||||
* Terms and conditions of usage are described in detail in NORDIC
|
||||
* SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
|
||||
*
|
||||
* Licensees are granted free, non-transferable use of the information. NO
|
||||
* WARRANTY of ANY KIND is provided. This heading must NOT be removed from
|
||||
* the file.
|
||||
*
|
||||
*/
|
||||
|
||||
/**@file
|
||||
*
|
||||
* @defgroup app_fifo FIFO implementation
|
||||
* @{
|
||||
* @ingroup app_common
|
||||
*
|
||||
* @brief FIFO implementation.
|
||||
*/
|
||||
|
||||
#ifndef APP_FIFO_H__
|
||||
#define APP_FIFO_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include "nrf_error.h"
|
||||
|
||||
/**@brief A FIFO instance structure. Keeps track of which bytes to read and write next.
|
||||
* Also it keeps the information about which memory is allocated for the buffer
|
||||
* and its size. This needs to be initialized by app_fifo_init() before use.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t * p_buf; /**< Pointer to FIFO buffer memory. */
|
||||
uint16_t buf_size_mask; /**< Read/write index mask. Also used for size checking. */
|
||||
volatile uint32_t read_pos; /**< Next read position in the FIFO buffer. */
|
||||
volatile uint32_t write_pos; /**< Next write position in the FIFO buffer. */
|
||||
} app_fifo_t;
|
||||
|
||||
/**@brief Function for initializing the FIFO.
|
||||
*
|
||||
* @param[out] p_fifo FIFO object.
|
||||
* @param[in] p_buf FIFO buffer for storing data. The buffer size has to be a power of two.
|
||||
* @param[in] buf_size Size of the FIFO buffer provided, has to be a power of 2.
|
||||
*
|
||||
* @retval NRF_SUCCESS If initialization was successful.
|
||||
* @retval NRF_ERROR_NULL If a NULL pointer is provided as buffer.
|
||||
* @retval NRF_ERROR_INVALID_LENGTH If size of buffer provided is not a power of two.
|
||||
*/
|
||||
uint32_t app_fifo_init(app_fifo_t * p_fifo, uint8_t * p_buf, uint16_t buf_size);
|
||||
|
||||
/**@brief Function for adding an element to the FIFO.
|
||||
*
|
||||
* @param[in] p_fifo Pointer to the FIFO.
|
||||
* @param[in] byte Data byte to add to the FIFO.
|
||||
*
|
||||
* @retval NRF_SUCCESS If an element has been successfully added to the FIFO.
|
||||
* @retval NRF_ERROR_NO_MEM If the FIFO is full.
|
||||
*/
|
||||
uint32_t app_fifo_put(app_fifo_t * p_fifo, uint8_t byte);
|
||||
|
||||
/**@brief Function for getting the next element from the FIFO.
|
||||
*
|
||||
* @param[in] p_fifo Pointer to the FIFO.
|
||||
* @param[out] p_byte Byte fetched from the FIFO.
|
||||
*
|
||||
* @retval NRF_SUCCESS If an element was returned.
|
||||
* @retval NRF_ERROR_NOT_FOUND If there is no more elements in the queue.
|
||||
*/
|
||||
uint32_t app_fifo_get(app_fifo_t * p_fifo, uint8_t * p_byte);
|
||||
|
||||
/**@brief Function for flushing the FIFO.
|
||||
*
|
||||
* @param[in] p_fifo Pointer to the FIFO.
|
||||
*
|
||||
* @retval NRF_SUCCESS If the FIFO flushed successfully.
|
||||
*/
|
||||
uint32_t app_fifo_flush(app_fifo_t * p_fifo);
|
||||
|
||||
#endif // APP_FIFO_H__
|
||||
|
||||
/** @} */
|
|
@ -0,0 +1,226 @@
|
|||
/* Copyright (c) 2012 Nordic Semiconductor. All Rights Reserved.
|
||||
*
|
||||
* The information contained herein is property of Nordic Semiconductor ASA.
|
||||
* Terms and conditions of usage are described in detail in NORDIC
|
||||
* SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
|
||||
*
|
||||
* Licensees are granted free, non-transferable use of the information. NO
|
||||
* WARRANTY of ANY KIND is provided. This heading must NOT be removed from
|
||||
* the file.
|
||||
*
|
||||
*/
|
||||
|
||||
/** @file
|
||||
*
|
||||
* @defgroup app_gpiote GPIOTE Handler
|
||||
* @{
|
||||
* @ingroup app_common
|
||||
*
|
||||
* @brief GPIOTE handler module.
|
||||
*
|
||||
* @details The GPIOTE handler allows several modules ("users") to share the GPIOTE interrupt,
|
||||
* each user defining a set of pins able to generate events to the user.
|
||||
* When a GPIOTE interrupt occurs, the GPIOTE interrupt handler will call the event handler
|
||||
* of each user for which at least one of the pins generated an event.
|
||||
*
|
||||
* The GPIOTE users are responsible for configuring all their corresponding pins, except
|
||||
* the SENSE field, which should be initialized to GPIO_PIN_CNF_SENSE_Disabled.
|
||||
* The SENSE field will be updated by the GPIOTE module when it is enabled or disabled,
|
||||
* and also while it is enabled.
|
||||
*
|
||||
* The module specifies on which pins events should be generated if the pin(s) goes
|
||||
* from low->high or high->low or both directions.
|
||||
*
|
||||
* @note Even if the application is using the @ref app_scheduler, the GPIOTE event handlers will
|
||||
* be called directly from the GPIOTE interrupt handler.
|
||||
*
|
||||
* @warning If multiple users registers for the same pins the behavior for those pins are undefined.
|
||||
*/
|
||||
|
||||
#ifndef APP_GPIOTE_H__
|
||||
#define APP_GPIOTE_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
// #include "nrf.h"
|
||||
#include "app_error.h"
|
||||
#include "app_util.h"
|
||||
|
||||
#ifdef __cpluplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define GPIOTE_USER_NODE_SIZE 20 /**< Size of app_gpiote.gpiote_user_t (only for use inside APP_GPIOTE_BUF_SIZE()). */
|
||||
#define NO_OF_PINS 32 /**< Number of GPIO pins on the nRF51 chip. */
|
||||
|
||||
/**@brief Compute number of bytes required to hold the GPIOTE data structures.
|
||||
*
|
||||
* @param[in] MAX_USERS Maximum number of GPIOTE users.
|
||||
*
|
||||
* @return Required buffer size (in bytes).
|
||||
*/
|
||||
#define APP_GPIOTE_BUF_SIZE(MAX_USERS) ((MAX_USERS) * GPIOTE_USER_NODE_SIZE)
|
||||
|
||||
typedef uint8_t app_gpiote_user_id_t;
|
||||
|
||||
/**@brief GPIOTE event handler type. */
|
||||
typedef void (*app_gpiote_event_handler_t)(uint32_t event_pins_low_to_high,
|
||||
uint32_t event_pins_high_to_low);
|
||||
|
||||
/**@brief GPIOTE input event handler type. */
|
||||
typedef void (*app_gpiote_input_event_handler_t)(void);
|
||||
|
||||
/**@brief Macro for initializing the GPIOTE module.
|
||||
*
|
||||
* @details It will handle dimensioning and allocation of the memory buffer required by the module,
|
||||
* making sure that the buffer is correctly aligned.
|
||||
*
|
||||
* @param[in] MAX_USERS Maximum number of GPIOTE users.
|
||||
*
|
||||
* @note Since this macro allocates a buffer, it must only be called once (it is OK to call it
|
||||
* several times as long as it is from the same location, e.g. to do a reinitialization).
|
||||
*/
|
||||
/*lint -emacro(506, APP_GPIOTE_INIT) */ /* Suppress "Constant value Boolean */
|
||||
#define APP_GPIOTE_INIT(MAX_USERS) \
|
||||
do \
|
||||
{ \
|
||||
static uint32_t app_gpiote_buf[CEIL_DIV(APP_GPIOTE_BUF_SIZE(MAX_USERS), sizeof(uint32_t))];\
|
||||
uint32_t ERR_CODE = app_gpiote_init((MAX_USERS), app_gpiote_buf); \
|
||||
APP_ERROR_CHECK(ERR_CODE); \
|
||||
} while (0)
|
||||
|
||||
/**@brief Function for initializing the GPIOTE module.
|
||||
*
|
||||
* @note Normally initialization should be done using the APP_GPIOTE_INIT() macro, as that will
|
||||
* allocate the buffer needed by the GPIOTE module (including aligning the buffer correctly).
|
||||
*
|
||||
* @param[in] max_users Maximum number of GPIOTE users.
|
||||
* @param[in] p_buffer Pointer to memory buffer for internal use in the app_gpiote
|
||||
* module. The size of the buffer can be computed using the
|
||||
* APP_GPIOTE_BUF_SIZE() macro. The buffer must be aligned to
|
||||
* a 4 byte boundary.
|
||||
*
|
||||
* @retval NRF_SUCCESS Successful initialization.
|
||||
* @retval NRF_ERROR_INVALID_PARAM Invalid parameter (buffer not aligned to a 4 byte
|
||||
* boundary).
|
||||
*/
|
||||
uint32_t app_gpiote_init(uint8_t max_users, void * p_buffer);
|
||||
|
||||
/**@brief Function for registering a GPIOTE user.
|
||||
*
|
||||
* @param[out] p_user_id Id for the new GPIOTE user.
|
||||
* @param[in] pins_low_to_high_mask Mask defining which pins will generate events to this user
|
||||
* when state is changed from low->high.
|
||||
* @param[in] pins_high_to_low_mask Mask defining which pins will generate events to this user
|
||||
* when state is changed from high->low.
|
||||
* @param[in] event_handler Pointer to function to be executed when an event occurs.
|
||||
*
|
||||
* @retval NRF_SUCCESS Successful initialization.
|
||||
* @retval NRF_ERROR_INVALID_PARAM Invalid parameter (buffer not aligned to a 4 byte boundary).
|
||||
* @retval NRF_ERROR_INALID_STATE If @ref app_gpiote_init has not been called on the GPIOTE
|
||||
* module.
|
||||
* @retval NRF_ERROR_NO_MEM Returned if the application tries to register more users
|
||||
* than defined when the GPIOTE module was initialized in
|
||||
* @ref app_gpiote_init.
|
||||
*/
|
||||
uint32_t app_gpiote_user_register(app_gpiote_user_id_t * p_user_id,
|
||||
uint32_t pins_low_to_high_mask,
|
||||
uint32_t pins_high_to_low_mask,
|
||||
app_gpiote_event_handler_t event_handler);
|
||||
|
||||
/**@brief Function for informing the GPIOTE module that the specified user wants to use the GPIOTE module.
|
||||
*
|
||||
* @param[in] user_id Id of user to enable.
|
||||
*
|
||||
* @retval NRF_SUCCESS On success.
|
||||
* @retval NRF_ERROR_INVALID_PARAM Invalid user_id provided, No a valid user.
|
||||
* @retval NRF_ERROR_INALID_STATE If @ref app_gpiote_init has not been called on the GPIOTE
|
||||
* module.
|
||||
*/
|
||||
uint32_t app_gpiote_user_enable(app_gpiote_user_id_t user_id);
|
||||
|
||||
/**@brief Function for informing the GPIOTE module that the specified user is done using the GPIOTE module.
|
||||
*
|
||||
* @param[in] user_id Id of user to enable.
|
||||
*
|
||||
* @return NRF_SUCCESS On success.
|
||||
* @retval NRF_ERROR_INVALID_PARAM Invalid user_id provided, No a valid user.
|
||||
* @retval NRF_ERROR_INALID_STATE If @ref app_gpiote_init has not been called on the GPIOTE
|
||||
* module.
|
||||
*/
|
||||
uint32_t app_gpiote_user_disable(app_gpiote_user_id_t user_id);
|
||||
|
||||
/**@brief Function for getting the state of the pins which are registered for the specified user.
|
||||
*
|
||||
* @param[in] user_id Id of user to check.
|
||||
* @param[out] p_pins Bit mask corresponding to the pins configured to generate events to
|
||||
* the specified user. All bits corresponding to pins in the state
|
||||
* 'high' will have value '1', all others will have value '0'.
|
||||
*
|
||||
* @return NRF_SUCCESS On success.
|
||||
* @retval NRF_ERROR_INVALID_PARAM Invalid user_id provided, No a valid user.
|
||||
* @retval NRF_ERROR_INALID_STATE If @ref app_gpiote_init has not been called on the GPIOTE
|
||||
* module.
|
||||
*/
|
||||
uint32_t app_gpiote_pins_state_get(app_gpiote_user_id_t user_id, uint32_t * p_pins);
|
||||
|
||||
/**@brief Function for registering event handlers for GPIOTE IN events.
|
||||
*
|
||||
* @param[in] channel GPIOTE channel [0..3].
|
||||
* @param[in] pin Pins associated with GPIOTE channel. Changes on following pins will generate events.
|
||||
* @param[in] polarity Specify operation on input that shall trigger IN event.
|
||||
* @param[in] event_handler Event handler invoked on the IN event in the GPIOTE interrupt.
|
||||
*
|
||||
* @return NRF_SUCCESS On success.
|
||||
* @retval NRF_ERROR_INVALID_PARAM Invalid channel or pin number.
|
||||
* @retval NRF_ERROR_NOT_SUPPORTED Driver doesn't support IN events.
|
||||
*/
|
||||
uint32_t app_gpiote_input_event_handler_register(const uint8_t channel,
|
||||
const uint32_t pin,
|
||||
const uint32_t polarity,
|
||||
app_gpiote_input_event_handler_t event_handler);
|
||||
|
||||
/**@brief Function for unregistering event handlers for GPIOTE IN events.
|
||||
*
|
||||
* @return NRF_SUCCESS On success.
|
||||
* @retval NRF_ERROR_NOT_SUPPORTED Driver doesn't support IN events.
|
||||
*/
|
||||
uint32_t app_gpiote_input_event_handler_unregister(const uint8_t channel);
|
||||
|
||||
/**@brief Function for registering event handler invoked at the end of a GPIOTE interrupt.
|
||||
*
|
||||
* @param[in] event_handler Event handler invoked at the end of the GPIOTE interrupt.
|
||||
*
|
||||
* @return NRF_SUCCESS On success.
|
||||
* @retval NRF_ERROR_NOT_SUPPORTED Driver doesn't support IN events.
|
||||
*/
|
||||
uint32_t app_gpiote_end_irq_event_handler_register(app_gpiote_input_event_handler_t event_handler);
|
||||
|
||||
/**@brief Function for unregistering event handler invoked at the end of a GPIOTE interrupt.
|
||||
*
|
||||
* @return NRF_SUCCESS On success.
|
||||
* @retval NRF_ERROR_NOT_SUPPORTED Driver doesn't support IN events.
|
||||
*/
|
||||
uint32_t app_gpiote_end_irq_event_handler_unregister(void);
|
||||
|
||||
/**@brief Function for enabling interrupts in the GPIOTE driver.
|
||||
*
|
||||
* @return NRF_SUCCESS On success.
|
||||
* @retval NRF_ERROR_NOT_SUPPORTED Driver doesn't support.
|
||||
*/
|
||||
uint32_t app_gpiote_enable_interrupts(void);
|
||||
|
||||
/**@brief Function for disabling interrupts in the GPIOTE driver.
|
||||
*
|
||||
* @return NRF_SUCCESS On success.
|
||||
* @retval NRF_ERROR_NOT_SUPPORTED Driver doesn't support.
|
||||
*/
|
||||
uint32_t app_gpiote_disable_interrupts(void);
|
||||
|
||||
#ifdef __cpluplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // APP_GPIOTE_H__
|
||||
|
||||
/** @} */
|
|
@ -0,0 +1,134 @@
|
|||
/* Copyright (c) 2012 Nordic Semiconductor. All Rights Reserved.
|
||||
*
|
||||
* The information contained herein is property of Nordic Semiconductor ASA.
|
||||
* Terms and conditions of usage are described in detail in NORDIC
|
||||
* SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
|
||||
*
|
||||
* Licensees are granted free, non-transferable use of the information. NO
|
||||
* WARRANTY of ANY KIND is provided. This heading must NOT be removed from
|
||||
* the file.
|
||||
*
|
||||
*/
|
||||
|
||||
/** @file
|
||||
*
|
||||
* @defgroup app_scheduler Scheduler
|
||||
* @{
|
||||
* @ingroup app_common
|
||||
*
|
||||
* @brief The scheduler is used for transferring execution from the interrupt context to the main
|
||||
* context.
|
||||
*
|
||||
* @details See @ref ble_sdk_apps_seq_diagrams for sequence diagrams illustrating the flow of events
|
||||
* when using the Scheduler.
|
||||
*
|
||||
* @section app_scheduler_req Requirements:
|
||||
*
|
||||
* @subsection main_context_logic Logic in main context:
|
||||
*
|
||||
* - Define an event handler for each type of event expected.
|
||||
* - Initialize the scheduler by calling the APP_SCHED_INIT() macro before entering the
|
||||
* application main loop.
|
||||
* - Call app_sched_execute() from the main loop each time the application wakes up because of an
|
||||
* event (typically when sd_app_evt_wait() returns).
|
||||
*
|
||||
* @subsection int_context_logic Logic in interrupt context:
|
||||
*
|
||||
* - In the interrupt handler, call app_sched_event_put()
|
||||
* with the appropriate data and event handler. This will insert an event into the
|
||||
* scheduler's queue. The app_sched_execute() function will pull this event and call its
|
||||
* handler in the main context.
|
||||
*
|
||||
* For an example usage of the scheduler, please see the implementations of
|
||||
* @ref ble_sdk_app_hids_mouse and @ref ble_sdk_app_hids_keyboard.
|
||||
*
|
||||
* @image html scheduler_working.jpg The high level design of the scheduler
|
||||
*/
|
||||
|
||||
#ifndef APP_SCHEDULER_H__
|
||||
#define APP_SCHEDULER_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include "app_error.h"
|
||||
|
||||
#define APP_SCHED_EVENT_HEADER_SIZE 8 /**< Size of app_scheduler.event_header_t (only for use inside APP_SCHED_BUF_SIZE()). */
|
||||
|
||||
/**@brief Compute number of bytes required to hold the scheduler buffer.
|
||||
*
|
||||
* @param[in] EVENT_SIZE Maximum size of events to be passed through the scheduler.
|
||||
* @param[in] QUEUE_SIZE Number of entries in scheduler queue (i.e. the maximum number of events
|
||||
* that can be scheduled for execution).
|
||||
*
|
||||
* @return Required scheduler buffer size (in bytes).
|
||||
*/
|
||||
#define APP_SCHED_BUF_SIZE(EVENT_SIZE, QUEUE_SIZE) \
|
||||
(((EVENT_SIZE) + APP_SCHED_EVENT_HEADER_SIZE) * ((QUEUE_SIZE) + 1))
|
||||
|
||||
/**@brief Scheduler event handler type. */
|
||||
typedef void (*app_sched_event_handler_t)(void * p_event_data, uint16_t event_size);
|
||||
|
||||
/**@brief Macro for initializing the event scheduler.
|
||||
*
|
||||
* @details It will also handle dimensioning and allocation of the memory buffer required by the
|
||||
* scheduler, making sure the buffer is correctly aligned.
|
||||
*
|
||||
* @param[in] EVENT_SIZE Maximum size of events to be passed through the scheduler.
|
||||
* @param[in] QUEUE_SIZE Number of entries in scheduler queue (i.e. the maximum number of events
|
||||
* that can be scheduled for execution).
|
||||
*
|
||||
* @note Since this macro allocates a buffer, it must only be called once (it is OK to call it
|
||||
* several times as long as it is from the same location, e.g. to do a reinitialization).
|
||||
*/
|
||||
#define APP_SCHED_INIT(EVENT_SIZE, QUEUE_SIZE) \
|
||||
do \
|
||||
{ \
|
||||
static uint32_t APP_SCHED_BUF[CEIL_DIV(APP_SCHED_BUF_SIZE((EVENT_SIZE), (QUEUE_SIZE)), \
|
||||
sizeof(uint32_t))]; \
|
||||
uint32_t ERR_CODE = app_sched_init((EVENT_SIZE), (QUEUE_SIZE), APP_SCHED_BUF); \
|
||||
APP_ERROR_CHECK(ERR_CODE); \
|
||||
} while (0)
|
||||
|
||||
/**@brief Function for initializing the Scheduler.
|
||||
*
|
||||
* @details It must be called before entering the main loop.
|
||||
*
|
||||
* @param[in] max_event_size Maximum size of events to be passed through the scheduler.
|
||||
* @param[in] queue_size Number of entries in scheduler queue (i.e. the maximum number of
|
||||
* events that can be scheduled for execution).
|
||||
* @param[in] p_event_buffer Pointer to memory buffer for holding the scheduler queue. It must
|
||||
* be dimensioned using the APP_SCHED_BUFFER_SIZE() macro. The buffer
|
||||
* must be aligned to a 4 byte boundary.
|
||||
*
|
||||
* @note Normally initialization should be done using the APP_SCHED_INIT() macro, as that will both
|
||||
* allocate the scheduler buffer, and also align the buffer correctly.
|
||||
*
|
||||
* @retval NRF_SUCCESS Successful initialization.
|
||||
* @retval NRF_ERROR_INVALID_PARAM Invalid parameter (buffer not aligned to a 4 byte
|
||||
* boundary).
|
||||
*/
|
||||
uint32_t app_sched_init(uint16_t max_event_size, uint16_t queue_size, void * p_evt_buffer);
|
||||
|
||||
/**@brief Function for executing all scheduled events.
|
||||
*
|
||||
* @details This function must be called from within the main loop. It will execute all events
|
||||
* scheduled since the last time it was called.
|
||||
*/
|
||||
void app_sched_execute(void);
|
||||
|
||||
/**@brief Function for scheduling an event.
|
||||
*
|
||||
* @details Puts an event into the event queue.
|
||||
*
|
||||
* @param[in] p_event_data Pointer to event data to be scheduled.
|
||||
* @param[in] p_event_size Size of event data to be scheduled.
|
||||
* @param[in] handler Event handler to receive the event.
|
||||
*
|
||||
* @return NRF_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
uint32_t app_sched_event_put(void * p_event_data,
|
||||
uint16_t event_size,
|
||||
app_sched_event_handler_t handler);
|
||||
|
||||
#endif // APP_SCHEDULER_H__
|
||||
|
||||
/** @} */
|
|
@ -0,0 +1,313 @@
|
|||
/* Copyright (c) 2012 Nordic Semiconductor. All Rights Reserved.
|
||||
*
|
||||
* The information contained herein is property of Nordic Semiconductor ASA.
|
||||
* Terms and conditions of usage are described in detail in NORDIC
|
||||
* SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
|
||||
*
|
||||
* Licensees are granted free, non-transferable use of the information. NO
|
||||
* WARRANTY of ANY KIND is provided. This heading must NOT be removed from
|
||||
* the file.
|
||||
*
|
||||
*/
|
||||
|
||||
/** @file
|
||||
*
|
||||
* @defgroup app_timer Application Timer
|
||||
* @{
|
||||
* @ingroup app_common
|
||||
*
|
||||
* @brief Application timer functionality.
|
||||
*
|
||||
* @details It enables the application to create multiple timer instances based on the RTC1
|
||||
* peripheral. Checking for timeouts and invokation of user timeout handlers is performed
|
||||
* in the RTC1 interrupt handler. List handling is done using a software interrupt (SWI0).
|
||||
* Both interrupt handlers are running in APP_LOW priority level.
|
||||
*
|
||||
* @note When calling app_timer_start() or app_timer_stop(), the timer operation is just queued,
|
||||
* and the software interrupt is triggered. The actual timer start/stop operation is
|
||||
* executed by the SWI0 interrupt handler. Since the SWI0 interrupt is running in APP_LOW,
|
||||
* if the application code calling the timer function is running in APP_LOW or APP_HIGH,
|
||||
* the timer operation will not be performed until the application handler has returned.
|
||||
* This will be the case e.g. when stopping a timer from a timeout handler when not using
|
||||
* the scheduler.
|
||||
*
|
||||
* @details Use the USE_SCHEDULER parameter of the APP_TIMER_INIT() macro to select if the
|
||||
* @ref app_scheduler is to be used or not.
|
||||
*
|
||||
* @note Even if the scheduler is not used, app_timer.h will include app_scheduler.h, so when
|
||||
* compiling, app_scheduler.h must be available in one of the compiler include paths.
|
||||
*/
|
||||
|
||||
#ifndef APP_TIMER_H__
|
||||
#define APP_TIMER_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include "app_error.h"
|
||||
#include "app_util.h"
|
||||
#include "app_scheduler.h"
|
||||
#include "compiler_abstraction.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // #ifdef __cplusplus
|
||||
|
||||
#define APP_TIMER_SCHED_EVT_SIZE sizeof(app_timer_event_t) /**< Size of button events being passed through the scheduler (is to be used for computing the maximum size of scheduler events). */
|
||||
#define APP_TIMER_CLOCK_FREQ 32768 /**< Clock frequency of the RTC timer used to implement the app timer module. */
|
||||
#define APP_TIMER_MIN_TIMEOUT_TICKS 5 /**< Minimum value of the timeout_ticks parameter of app_timer_start(). */
|
||||
|
||||
#define APP_TIMER_NODE_SIZE 40 /**< Size of app_timer.timer_node_t (only for use inside APP_TIMER_BUF_SIZE()). */
|
||||
#define APP_TIMER_USER_OP_SIZE 24 /**< Size of app_timer.timer_user_op_t (only for use inside APP_TIMER_BUF_SIZE()). */
|
||||
#define APP_TIMER_USER_SIZE 8 /**< Size of app_timer.timer_user_t (only for use inside APP_TIMER_BUF_SIZE()). */
|
||||
#define APP_TIMER_INT_LEVELS 3 /**< Number of interrupt levels from where timer operations may be initiated (only for use inside APP_TIMER_BUF_SIZE()). */
|
||||
|
||||
#define MAX_RTC_COUNTER_VAL 0x00FFFFFF /**< Maximum value of the RTC counter. */
|
||||
|
||||
/**@brief Compute number of bytes required to hold the application timer data structures.
|
||||
*
|
||||
* @param[in] MAX_TIMERS Maximum number of timers that can be created at any given time.
|
||||
* @param[in] OP_QUEUE_SIZE Size of queues holding timer operations that are pending execution.
|
||||
* NOTE: Due to the queue implementation, this size must be one more
|
||||
* than the size that is actually needed.
|
||||
*
|
||||
* @return Required application timer buffer size (in bytes).
|
||||
*/
|
||||
#define APP_TIMER_BUF_SIZE(MAX_TIMERS, OP_QUEUE_SIZE) \
|
||||
( \
|
||||
((MAX_TIMERS) * APP_TIMER_NODE_SIZE) \
|
||||
+ \
|
||||
( \
|
||||
APP_TIMER_INT_LEVELS \
|
||||
* \
|
||||
(APP_TIMER_USER_SIZE + ((OP_QUEUE_SIZE) + 1) * APP_TIMER_USER_OP_SIZE) \
|
||||
) \
|
||||
)
|
||||
|
||||
/**@brief Convert milliseconds to timer ticks.
|
||||
*
|
||||
* @note This macro uses 64 bit integer arithmetic, but as long as the macro parameters are
|
||||
* constants (i.e. defines), the computation will be done by the preprocessor.
|
||||
*
|
||||
* @param[in] MS Milliseconds.
|
||||
* @param[in] PRESCALER Value of the RTC1 PRESCALER register (must be the same value that was
|
||||
* passed to APP_TIMER_INIT()).
|
||||
*
|
||||
* @note When using this macro, it is the responsibility of the developer to ensure that the
|
||||
* values provided as input result in an output value that is supported by the
|
||||
* @ref app_timer_start function. For example, when the ticks for 1 ms is needed, the
|
||||
* maximum possible value of PRESCALER must be 6, when @ref APP_TIMER_CLOCK_FREQ is 32768.
|
||||
* This will result in a ticks value as 5. Any higher value for PRESCALER will result in a
|
||||
* ticks value that is not supported by this module.
|
||||
*
|
||||
* @return Number of timer ticks.
|
||||
*/
|
||||
#define APP_TIMER_TICKS(MS, PRESCALER)\
|
||||
((uint32_t)ROUNDED_DIV((MS) * (uint64_t)APP_TIMER_CLOCK_FREQ, ((PRESCALER) + 1) * 1000))
|
||||
|
||||
/**@brief Timer id type. */
|
||||
typedef uint32_t app_timer_id_t;
|
||||
|
||||
#define TIMER_NULL ((app_timer_id_t)(0 - 1)) /**< Invalid timer id. */
|
||||
|
||||
/**@brief Application timeout handler type. */
|
||||
typedef void (*app_timer_timeout_handler_t)(void * p_context);
|
||||
|
||||
/**@brief Type of function for passing events from the timer module to the scheduler. */
|
||||
typedef uint32_t (*app_timer_evt_schedule_func_t) (app_timer_timeout_handler_t timeout_handler,
|
||||
void * p_context);
|
||||
|
||||
/**@brief Timer modes. */
|
||||
typedef enum
|
||||
{
|
||||
APP_TIMER_MODE_SINGLE_SHOT, /**< The timer will expire only once. */
|
||||
APP_TIMER_MODE_REPEATED /**< The timer will restart each time it expires. */
|
||||
} app_timer_mode_t;
|
||||
|
||||
/**@brief Macro for initializing the application timer module.
|
||||
*
|
||||
* @details It will handle dimensioning and allocation of the memory buffer required by the timer,
|
||||
* making sure that the buffer is correctly aligned. It will also connect the timer module
|
||||
* to the scheduler (if specified).
|
||||
*
|
||||
* @note This module assumes that the LFCLK is already running. If it isn't, the module will
|
||||
* be non-functional, since the RTC will not run. If you don't use a softdevice, you'll
|
||||
* have to start the LFCLK manually. See the rtc_example's \ref lfclk_config() function
|
||||
* for an example of how to do this. If you use a softdevice, the LFCLK is started on
|
||||
* softdevice init.
|
||||
*
|
||||
*
|
||||
* @param[in] PRESCALER Value of the RTC1 PRESCALER register. This will decide the
|
||||
* timer tick rate. Set to 0 for no prescaling.
|
||||
* @param[in] MAX_TIMERS Maximum number of timers that can be created at any given time.
|
||||
* @param[in] OP_QUEUES_SIZE Size of queues holding timer operations that are pending execution.
|
||||
* @param[in] USE_SCHEDULER TRUE if the application is using the event scheduler,
|
||||
* FALSE otherwise.
|
||||
*
|
||||
* @note Since this macro allocates a buffer, it must only be called once (it is OK to call it
|
||||
* several times as long as it is from the same location, e.g. to do a reinitialization).
|
||||
*/
|
||||
/*lint -emacro(506, APP_TIMER_INIT) */ /* Suppress "Constant value Boolean */
|
||||
#define APP_TIMER_INIT(PRESCALER, MAX_TIMERS, OP_QUEUES_SIZE, USE_SCHEDULER) \
|
||||
do \
|
||||
{ \
|
||||
static uint32_t APP_TIMER_BUF[CEIL_DIV(APP_TIMER_BUF_SIZE((MAX_TIMERS), \
|
||||
(OP_QUEUES_SIZE) + 1), \
|
||||
sizeof(uint32_t))]; \
|
||||
uint32_t ERR_CODE = app_timer_init((PRESCALER), \
|
||||
(MAX_TIMERS), \
|
||||
(OP_QUEUES_SIZE) + 1, \
|
||||
APP_TIMER_BUF, \
|
||||
(USE_SCHEDULER) ? app_timer_evt_schedule : NULL); \
|
||||
APP_ERROR_CHECK(ERR_CODE); \
|
||||
} while (0)
|
||||
|
||||
/**@brief Function for initializing the timer module.
|
||||
*
|
||||
* @note Normally initialization should be done using the APP_TIMER_INIT() macro, as that will both
|
||||
* allocate the buffers needed by the timer module (including aligning the buffers correctly,
|
||||
* and also take care of connecting the timer module to the scheduler (if specified).
|
||||
*
|
||||
* @param[in] prescaler Value of the RTC1 PRESCALER register. Set to 0 for no prescaling.
|
||||
* @param[in] max_timers Maximum number of timers that can be created at any given time.
|
||||
* @param[in] op_queues_size Size of queues holding timer operations that are pending
|
||||
* execution. NOTE: Due to the queue implementation, this size must
|
||||
* be one more than the size that is actually needed.
|
||||
* @param[in] p_buffer Pointer to memory buffer for internal use in the app_timer
|
||||
* module. The size of the buffer can be computed using the
|
||||
* APP_TIMER_BUF_SIZE() macro. The buffer must be aligned to a
|
||||
* 4 byte boundary.
|
||||
* @param[in] evt_schedule_func Function for passing timeout events to the scheduler. Point to
|
||||
* app_timer_evt_schedule() to connect to the scheduler. Set to NULL
|
||||
* to make the timer module call the timeout handler directly from
|
||||
* the timer interrupt handler.
|
||||
*
|
||||
* @retval NRF_SUCCESS Successful initialization.
|
||||
* @retval NRF_ERROR_INVALID_PARAM Invalid parameter (buffer not aligned to a 4 byte
|
||||
* boundary or NULL).
|
||||
*/
|
||||
uint32_t app_timer_init(uint32_t prescaler,
|
||||
uint8_t max_timers,
|
||||
uint8_t op_queues_size,
|
||||
void * p_buffer,
|
||||
app_timer_evt_schedule_func_t evt_schedule_func);
|
||||
|
||||
/**@brief Function for creating a timer instance.
|
||||
*
|
||||
* @param[out] p_timer_id Id of the newly created timer.
|
||||
* @param[in] mode Timer mode.
|
||||
* @param[in] timeout_handler Function to be executed when the timer expires.
|
||||
*
|
||||
* @retval NRF_SUCCESS Timer was successfully created.
|
||||
* @retval NRF_ERROR_INVALID_PARAM Invalid parameter.
|
||||
* @retval NRF_ERROR_INVALID_STATE Application timer module has not been initialized.
|
||||
* @retval NRF_ERROR_NO_MEM Maximum number of timers has already been reached.
|
||||
*
|
||||
* @note This function does the timer allocation in the caller's context. It is also not protected
|
||||
* by a critical region. Therefore care must be taken not to call it from several interrupt
|
||||
* levels simultaneously.
|
||||
*/
|
||||
uint32_t app_timer_create(app_timer_id_t * p_timer_id,
|
||||
app_timer_mode_t mode,
|
||||
app_timer_timeout_handler_t timeout_handler);
|
||||
|
||||
/**@brief Function for starting a timer.
|
||||
*
|
||||
* @param[in] timer_id Id of timer to start.
|
||||
* @param[in] timeout_ticks Number of ticks (of RTC1, including prescaling) to timeout event
|
||||
* (minimum 5 ticks).
|
||||
* @param[in] p_context General purpose pointer. Will be passed to the timeout handler when
|
||||
* the timer expires.
|
||||
*
|
||||
* @retval NRF_SUCCESS Timer was successfully started.
|
||||
* @retval NRF_ERROR_INVALID_PARAM Invalid parameter.
|
||||
* @retval NRF_ERROR_INVALID_STATE Application timer module has not been initialized, or timer
|
||||
* has not been created.
|
||||
* @retval NRF_ERROR_NO_MEM Timer operations queue was full.
|
||||
*
|
||||
* @note The minimum timeout_ticks value is 5.
|
||||
* @note For multiple active timers, timeouts occurring in close proximity to each other (in the
|
||||
* range of 1 to 3 ticks) will have a positive jitter of maximum 3 ticks.
|
||||
* @note When calling this method on a timer which is already running, the second start operation
|
||||
* will be ignored.
|
||||
*/
|
||||
uint32_t app_timer_start(app_timer_id_t timer_id, uint32_t timeout_ticks, void * p_context);
|
||||
|
||||
/**@brief Function for stopping the specified timer.
|
||||
*
|
||||
* @param[in] timer_id Id of timer to stop.
|
||||
*
|
||||
* @retval NRF_SUCCESS Timer was successfully stopped.
|
||||
* @retval NRF_ERROR_INVALID_PARAM Invalid parameter.
|
||||
* @retval NRF_ERROR_INVALID_STATE Application timer module has not been initialized, or timer
|
||||
* has not been created.
|
||||
* @retval NRF_ERROR_NO_MEM Timer operations queue was full.
|
||||
*/
|
||||
uint32_t app_timer_stop(app_timer_id_t timer_id);
|
||||
|
||||
/**@brief Function for stopping all running timers.
|
||||
*
|
||||
* @retval NRF_SUCCESS All timers were successfully stopped.
|
||||
* @retval NRF_ERROR_INVALID_STATE Application timer module has not been initialized.
|
||||
* @retval NRF_ERROR_NO_MEM Timer operations queue was full.
|
||||
*/
|
||||
uint32_t app_timer_stop_all(void);
|
||||
|
||||
/**@brief Function for returning the current value of the RTC1 counter. The
|
||||
* value includes overflow bits to extend the range to 64-bits.
|
||||
*
|
||||
* @param[out] p_ticks Current value of the RTC1 counter.
|
||||
*
|
||||
* @retval NRF_SUCCESS Counter was successfully read.
|
||||
*/
|
||||
uint32_t app_timer_cnt_get(uint64_t * p_ticks);
|
||||
|
||||
/**@brief Function for computing the difference between two RTC1 counter values.
|
||||
*
|
||||
* @param[in] ticks_to Value returned by app_timer_cnt_get().
|
||||
* @param[in] ticks_from Value returned by app_timer_cnt_get().
|
||||
* @param[out] p_ticks_diff Number of ticks from ticks_from to ticks_to.
|
||||
*
|
||||
* @retval NRF_SUCCESS Counter difference was successfully computed.
|
||||
*/
|
||||
uint32_t app_timer_cnt_diff_compute(uint32_t ticks_to,
|
||||
uint32_t ticks_from,
|
||||
uint32_t * p_ticks_diff);
|
||||
|
||||
|
||||
// Type and functions for connecting the timer to the scheduler:
|
||||
|
||||
/**@cond NO_DOXYGEN */
|
||||
typedef struct
|
||||
{
|
||||
app_timer_timeout_handler_t timeout_handler;
|
||||
void * p_context;
|
||||
} app_timer_event_t;
|
||||
|
||||
static __INLINE void app_timer_evt_get(void * p_event_data, uint16_t event_size)
|
||||
{
|
||||
app_timer_event_t * p_timer_event = (app_timer_event_t *)p_event_data;
|
||||
|
||||
APP_ERROR_CHECK_BOOL(event_size == sizeof(app_timer_event_t));
|
||||
p_timer_event->timeout_handler(p_timer_event->p_context);
|
||||
}
|
||||
|
||||
static __INLINE uint32_t app_timer_evt_schedule(app_timer_timeout_handler_t timeout_handler,
|
||||
void * p_context)
|
||||
{
|
||||
app_timer_event_t timer_event;
|
||||
|
||||
timer_event.timeout_handler = timeout_handler;
|
||||
timer_event.p_context = p_context;
|
||||
|
||||
return app_sched_event_put(&timer_event, sizeof(timer_event), app_timer_evt_get);
|
||||
}
|
||||
/**@endcond */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // #ifdef __cplusplus
|
||||
|
||||
#endif // APP_TIMER_H__
|
||||
|
||||
/** @} */
|
|
@ -0,0 +1,55 @@
|
|||
#ifndef __DEBUG_H_
|
||||
#define __DEBUG_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/**
|
||||
* @defgroup app_trace Debug Logger
|
||||
* @ingroup app_common
|
||||
* @{
|
||||
* @brief Enables debug logs/ trace over UART.
|
||||
* @details Enables debug logs/ trace over UART. Tracing is enabled only if
|
||||
* ENABLE_DEBUG_LOG_SUPPORT is defined in the project.
|
||||
*/
|
||||
#ifdef ENABLE_DEBUG_LOG_SUPPORT
|
||||
/**
|
||||
* @brief Module Initialization.
|
||||
*
|
||||
* @details Initializes the module to use UART as trace output.
|
||||
*
|
||||
* @warning This function will configure UART using default board configuration (described in @ref nrf51_setups).
|
||||
* Do not call this function if UART is configured from a higher level in the application.
|
||||
*/
|
||||
void app_trace_init(void);
|
||||
|
||||
/**
|
||||
* @brief Log debug messages.
|
||||
*
|
||||
* @details This API logs messages over UART. The module must be initialized before using this API.
|
||||
*
|
||||
* @note Though this is currently a macro, it should be used used and treated as function.
|
||||
*/
|
||||
#define app_trace_log printf
|
||||
|
||||
/**
|
||||
* @brief Dump auxiliary byte buffer to the debug trace.
|
||||
*
|
||||
* @details This API logs messages over UART. The module must be initialized before using this API.
|
||||
*
|
||||
* @param[in] p_buffer Buffer to be dumped on the debug trace.
|
||||
* @param[in] len Size of the buffer.
|
||||
*/
|
||||
void app_trace_dump(uint8_t * p_buffer, uint32_t len);
|
||||
|
||||
#else // ENABLE_DEBUG_LOG_SUPPORT
|
||||
|
||||
#define app_trace_init(...)
|
||||
#define app_trace_log(...)
|
||||
#define app_trace_dump(...)
|
||||
|
||||
#endif // ENABLE_DEBUG_LOG_SUPPORT
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif //__DEBUG_H_
|
|
@ -0,0 +1,286 @@
|
|||
/* Copyright (c) 2013 Nordic Semiconductor. All Rights Reserved.
|
||||
*
|
||||
* The information contained herein is property of Nordic Semiconductor ASA.
|
||||
* Terms and conditions of usage are described in detail in NORDIC
|
||||
* SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
|
||||
*
|
||||
* Licensees are granted free, non-transferable use of the information. NO
|
||||
* WARRANTY of ANY KIND is provided. This heading must NOT be removed from
|
||||
* the file.
|
||||
*
|
||||
*/
|
||||
|
||||
/**@file
|
||||
*
|
||||
* @defgroup app_uart UART module
|
||||
* @{
|
||||
* @ingroup app_common
|
||||
*
|
||||
* @brief UART module interface.
|
||||
*/
|
||||
|
||||
#ifndef APP_UART_H__
|
||||
#define APP_UART_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "app_util_platform.h"
|
||||
|
||||
#define UART_PIN_DISCONNECTED 0xFFFFFFFF /**< Value indicating that no pin is connected to this UART register. */
|
||||
|
||||
/**@brief UART Flow Control modes for the peripheral.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
APP_UART_FLOW_CONTROL_DISABLED, /**< UART Hw Flow Control is disabled. */
|
||||
APP_UART_FLOW_CONTROL_ENABLED, /**< Standard UART Hw Flow Control is enabled. */
|
||||
APP_UART_FLOW_CONTROL_LOW_POWER /**< Specialized UART Hw Flow Control is used. The Low Power setting allows the nRF51 to Power Off the UART module when CTS is in-active, and re-enabling the UART when the CTS signal becomes active. This allows the nRF51 to safe power by only using the UART module when it is needed by the remote site. */
|
||||
} app_uart_flow_control_t;
|
||||
|
||||
/**@brief UART communication structure holding configuration settings for the peripheral.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t rx_pin_no; /**< RX pin number. */
|
||||
uint8_t tx_pin_no; /**< TX pin number. */
|
||||
uint8_t rts_pin_no; /**< RTS pin number, only used if flow control is enabled. */
|
||||
uint8_t cts_pin_no; /**< CTS pin number, only used if flow control is enabled. */
|
||||
app_uart_flow_control_t flow_control; /**< Flow control setting, if flow control is used, the system will use low power UART mode, based on CTS signal. */
|
||||
bool use_parity; /**< Even parity if TRUE, no parity if FALSE. */
|
||||
uint32_t baud_rate; /**< Baud rate configuration. */
|
||||
} app_uart_comm_params_t;
|
||||
|
||||
/**@brief UART buffer for transmitting/receiving data.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t * rx_buf; /**< Pointer to the RX buffer. */
|
||||
uint32_t rx_buf_size; /**< Size of the RX buffer. */
|
||||
uint8_t * tx_buf; /**< Pointer to the TX buffer. */
|
||||
uint32_t tx_buf_size; /**< Size of the TX buffer. */
|
||||
} app_uart_buffers_t;
|
||||
|
||||
/**@brief Enumeration describing current state of the UART.
|
||||
*
|
||||
* @details The connection state can be fetched by the application using the function call
|
||||
* @ref app_uart_get_connection_state.
|
||||
* When hardware flow control is used
|
||||
* - APP_UART_CONNECTED: Communication is ongoing.
|
||||
* - APP_UART_DISCONNECTED: No communication is ongoing.
|
||||
*
|
||||
* When no hardware flow control is used
|
||||
* - APP_UART_CONNECTED: Always returned as bytes can always be received/transmitted.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
APP_UART_DISCONNECTED, /**< State indicating that the UART is disconnected and cannot receive or transmit bytes. */
|
||||
APP_UART_CONNECTED /**< State indicating that the UART is connected and ready to receive or transmit bytes. If flow control is disabled, the state will always be connected. */
|
||||
} app_uart_connection_state_t;
|
||||
|
||||
/**@brief Enumeration which defines events used by the UART module upon data reception or error.
|
||||
*
|
||||
* @details The event type is used to indicate the type of additional information in the event
|
||||
* @ref app_uart_evt_t.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
APP_UART_DATA_READY, /**< An event indicating that UART data has been received. The data is available in the FIFO and can be fetched using @ref app_uart_get. */
|
||||
APP_UART_FIFO_ERROR, /**< An error in the FIFO module used by the app_uart module has occured. The FIFO error code is stored in app_uart_evt_t.data.error_code field. */
|
||||
APP_UART_COMMUNICATION_ERROR, /**< An communication error has occured during reception. The error is stored in app_uart_evt_t.data.error_communication field. */
|
||||
APP_UART_TX_EMPTY, /**< An event indicating that UART has completed transmission of all available data in the TX FIFO. */
|
||||
APP_UART_DATA, /**< An event indicating that UART data has been received, and data is present in data field. This event is only used when no FIFO is configured. */
|
||||
} app_uart_evt_type_t;
|
||||
|
||||
/**@brief Struct containing events from the UART module.
|
||||
*
|
||||
* @details The app_uart_evt_t is used to notify the application of asynchronous events when data
|
||||
* are received on the UART peripheral or in case an error occured during data reception.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
app_uart_evt_type_t evt_type; /**< Type of event. */
|
||||
union
|
||||
{
|
||||
uint32_t error_communication; /**< Field used if evt_type is: APP_UART_COMMUNICATION_ERROR. This field contains the value in the ERRORSRC register for the UART peripheral. The UART_ERRORSRC_x defines from @ref nrf51_bitfields.h can be used to parse the error code. See also the nRF51 Series Reference Manual for specification. */
|
||||
uint32_t error_code; /**< Field used if evt_type is: NRF_ERROR_x. Additional status/error code if the error event type is APP_UART_FIFO_ERROR. This error code refer to errors defined in nrf_error.h. */
|
||||
uint8_t value; /**< Field used if evt_type is: NRF_ERROR_x. Additional status/error code if the error event type is APP_UART_FIFO_ERROR. This error code refer to errors defined in nrf_error.h. */
|
||||
} data;
|
||||
} app_uart_evt_t;
|
||||
|
||||
/**@brief Function for handling app_uart event callback.
|
||||
*
|
||||
* @details Upon an event in the app_uart module this callback function will be called to notify
|
||||
* the applicatioon about the event.
|
||||
*
|
||||
* @param[in] p_app_uart_event Pointer to UART event.
|
||||
*/
|
||||
|
||||
|
||||
typedef void (* app_uart_event_handler_t) (app_uart_evt_t * p_app_uart_event);
|
||||
|
||||
/**@brief Macro for safe initialization of the UART module in a single user instance when using
|
||||
* a FIFO together with UART.
|
||||
*
|
||||
* @param[in] P_COMM_PARAMS Pointer to a UART communication structure: app_uart_comm_params_t
|
||||
* @param[in] RX_BUF_SIZE Size of desired RX buffer, must be a power of 2 or ZERO (No FIFO).
|
||||
* @param[in] TX_BUF_SIZE Size of desired TX buffer, must be a power of 2 or ZERO (No FIFO).
|
||||
* @param[in] EVENT_HANDLER Event handler function to be called when an event occurs in the
|
||||
* UART module.
|
||||
* @param[in] IRQ_PRIO IRQ priority, app_irq_priority_t, for the UART module irq handler.
|
||||
* @param[out] ERR_CODE The return value of the UART initialization function will be
|
||||
* written to this parameter.
|
||||
*
|
||||
* @note Since this macro allocates a buffer and registers the module as a GPIOTE user when flow
|
||||
* control is enabled, it must only be called once.
|
||||
*/
|
||||
#define APP_UART_FIFO_INIT(P_COMM_PARAMS, RX_BUF_SIZE, TX_BUF_SIZE, EVT_HANDLER, IRQ_PRIO, ERR_CODE) \
|
||||
do \
|
||||
{ \
|
||||
uint16_t APP_UART_UID = 0; \
|
||||
app_uart_buffers_t buffers; \
|
||||
static uint8_t rx_buf[RX_BUF_SIZE]; \
|
||||
static uint8_t tx_buf[TX_BUF_SIZE]; \
|
||||
\
|
||||
buffers.rx_buf = rx_buf; \
|
||||
buffers.rx_buf_size = sizeof (rx_buf); \
|
||||
buffers.tx_buf = tx_buf; \
|
||||
buffers.tx_buf_size = sizeof (tx_buf); \
|
||||
ERR_CODE = app_uart_init(P_COMM_PARAMS, &buffers, EVT_HANDLER, IRQ_PRIO, &APP_UART_UID); \
|
||||
} while (0)
|
||||
|
||||
/**@brief Macro for safe initialization of the UART module in a single user instance.
|
||||
*
|
||||
* @param[in] P_COMM_PARAMS Pointer to a UART communication structure: app_uart_comm_params_t
|
||||
* @param[in] EVENT_HANDLER Event handler function to be called when an event occurs in the
|
||||
* UART module.
|
||||
* @param[in] IRQ_PRIO IRQ priority, app_irq_priority_t, for the UART module irq handler.
|
||||
* @param[out] ERR_CODE The return value of the UART initialization function will be
|
||||
* written to this parameter.
|
||||
*
|
||||
* @note Since this macro allocates registers the module as a GPIOTE user when flow control is
|
||||
* enabled, it must only be called once.
|
||||
*/
|
||||
#define APP_UART_INIT(P_COMM_PARAMS, EVT_HANDLER, IRQ_PRIO, ERR_CODE) \
|
||||
do \
|
||||
{ \
|
||||
uint16_t APP_UART_UID = 0; \
|
||||
ERR_CODE = app_uart_init(P_COMM_PARAMS, NULL, EVT_HANDLER, IRQ_PRIO, &APP_UART_UID); \
|
||||
} while (0)
|
||||
|
||||
/**@brief Function for initializing the UART module. Use this initialization when several instances of the UART
|
||||
* module are needed.
|
||||
*
|
||||
* @details This initialization will return a UART user id for the caller. The UART user id must be
|
||||
* used upon re-initialization of the UART or closing of the module for the user.
|
||||
* If single instance usage is needed, the APP_UART_INIT() macro should be used instead.
|
||||
*
|
||||
* @note Normally single instance initialization should be done using the APP_UART_INIT() or
|
||||
* APP_UART_INIT_FIFO() macro depending on whether the FIFO should be used by the UART, as
|
||||
* that will allocate the buffers needed by the UART module (including aligning the buffer
|
||||
* correctly).
|
||||
|
||||
* @param[in] p_comm_params Pin and communication parameters.
|
||||
* @param[in] p_buffers RX and TX buffers, NULL is FIFO is not used.
|
||||
* @param[in] error_handler Function to be called in case of an error.
|
||||
* @param[in] app_irq_priority Interrupt priority level.
|
||||
* @param[in,out] p_uart_uid User id for the UART module. The p_uart_uid must be used if
|
||||
* re-initialization and/or closing of the UART module is needed.
|
||||
* If the value pointed to by p_uart_uid is zero, this is
|
||||
* considdered a first time initialization. Otherwise this is
|
||||
* considered a re-initialization for the user with id *p_uart_uid.
|
||||
*
|
||||
* @retval NRF_SUCCESS If successful initialization.
|
||||
* @retval NRF_ERROR_INVALID_LENGTH If a provided buffer is not a power of two.
|
||||
* @retval NRF_ERROR_NULL If one of the provided buffers is a NULL pointer.
|
||||
*
|
||||
* Those errors are propagated by the UART module to the caller upon registration when Hardware Flow
|
||||
* Control is enabled. When Hardware Flow Control is not used, those errors cannot occur.
|
||||
* @retval NRF_ERROR_INVALID_STATE The GPIOTE module is not in a valid state when registering
|
||||
* the UART module as a user.
|
||||
* @retval NRF_ERROR_INVALID_PARAM The UART module provides an invalid callback function when
|
||||
* registering the UART module as a user.
|
||||
* Or the value pointed to by *p_uart_uid is not a valid
|
||||
* GPIOTE number.
|
||||
* @retval NRF_ERROR_NO_MEM GPIOTE module has reached the maximum number of users.
|
||||
*/
|
||||
uint32_t app_uart_init(const app_uart_comm_params_t * p_comm_params,
|
||||
app_uart_buffers_t * p_buffers,
|
||||
app_uart_event_handler_t error_handler,
|
||||
app_irq_priority_t irq_priority,
|
||||
uint16_t * p_uart_uid);
|
||||
|
||||
/**@brief Function for getting a byte from the UART.
|
||||
*
|
||||
* @details This function will get the next byte from the RX buffer. If the RX buffer is empty
|
||||
* an error code will be returned and the app_uart module will generate an event upon
|
||||
* reception of the first byte which is added to the RX buffer.
|
||||
*
|
||||
* @param[out] p_byte Pointer to an address where next byte received on the UART will be copied.
|
||||
*
|
||||
* @retval NRF_SUCCESS If a byte has been received and pushed to the pointer provided.
|
||||
* @retval NRF_ERROR_NOT_FOUND If no byte is available in the RX buffer of the app_uart module.
|
||||
*/
|
||||
uint32_t app_uart_get(uint8_t * p_byte);
|
||||
|
||||
/**@brief Function for putting a byte on the UART.
|
||||
*
|
||||
* @details This call is non-blocking.
|
||||
*
|
||||
* @param[in] byte Byte to be transmitted on the UART.
|
||||
*
|
||||
* @retval NRF_SUCCESS If the byte was succesfully put on the TX buffer for transmission.
|
||||
* @retval NRF_ERROR_NO_MEM If no more space is available in the TX buffer.
|
||||
* NRF_ERROR_NO_MEM may occur if flow control is enabled and CTS signal
|
||||
* is high for a long period and the buffer fills up.
|
||||
*/
|
||||
uint32_t app_uart_put(uint8_t byte);
|
||||
|
||||
/**@brief Function for getting the current state of the UART.
|
||||
*
|
||||
* @details If flow control is disabled, the state is assumed to always be APP_UART_CONNECTED.
|
||||
*
|
||||
* When using flow control the state will be controlled by the CTS. If CTS is set active
|
||||
* by the remote side, or the app_uart module is in the process of transmitting a byte,
|
||||
* app_uart is in APP_UART_CONNECTED state. If CTS is set inactive by remote side app_uart
|
||||
* will not get into APP_UART_DISCONNECTED state until the last byte in the TXD register
|
||||
* is fully transmitted.
|
||||
*
|
||||
* Internal states in the state machine are mapped to the general connected/disconnected
|
||||
* states in the following ways:
|
||||
*
|
||||
* - UART_ON = CONNECTED
|
||||
* - UART_READY = CONNECTED
|
||||
* - UART_WAIT = CONNECTED
|
||||
* - UART_OFF = DISCONNECTED.
|
||||
*
|
||||
* @param[out] p_connection_state Current connection state of the UART.
|
||||
*
|
||||
* @retval NRF_SUCCESS The connection state was succesfully retrieved.
|
||||
*/
|
||||
uint32_t app_uart_get_connection_state(app_uart_connection_state_t * p_connection_state);
|
||||
|
||||
/**@brief Function for flushing the RX and TX buffers (Only valid if FIFO is used).
|
||||
* This function does nothing if FIFO is not used.
|
||||
*
|
||||
* @retval NRF_SUCCESS Flushing completed (Current implementation will always succeed).
|
||||
*/
|
||||
uint32_t app_uart_flush(void);
|
||||
|
||||
/**@brief Function for closing the UART module.
|
||||
*
|
||||
* @details This function will close any on-going UART transmissions and disable itself in the
|
||||
* GPTIO module.
|
||||
*
|
||||
* @param[in] app_uart_uid User id for the UART module. The app_uart_uid must be identical to the
|
||||
* UART id returned on initialization and which is currently in use.
|
||||
|
||||
* @retval NRF_SUCCESS If successfully closed.
|
||||
* @retval NRF_ERROR_INVALID_PARAM If an invalid user id is provided or the user id differs from
|
||||
* the current active user.
|
||||
*/
|
||||
uint32_t app_uart_close(uint16_t app_uart_id);
|
||||
|
||||
|
||||
#endif //APP_UART_H__
|
||||
|
||||
/** @} */
|
|
@ -0,0 +1,232 @@
|
|||
/* Copyright (c) 2012 Nordic Semiconductor. All Rights Reserved.
|
||||
*
|
||||
* The information contained herein is property of Nordic Semiconductor ASA.
|
||||
* Terms and conditions of usage are described in detail in NORDIC
|
||||
* SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
|
||||
*
|
||||
* Licensees are granted free, non-transferable use of the information. NO
|
||||
* WARRANTY of ANY KIND is provided. This heading must NOT be removed from
|
||||
* the file.
|
||||
*
|
||||
*/
|
||||
|
||||
/** @file
|
||||
*
|
||||
* @defgroup app_util Utility Functions and Definitions
|
||||
* @{
|
||||
* @ingroup app_common
|
||||
*
|
||||
* @brief Various types and definitions available to all applications.
|
||||
*/
|
||||
|
||||
#ifndef APP_UTIL_H__
|
||||
#define APP_UTIL_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "compiler_abstraction.h"
|
||||
|
||||
enum
|
||||
{
|
||||
UNIT_0_625_MS = 625, /**< Number of microseconds in 0.625 milliseconds. */
|
||||
UNIT_1_25_MS = 1250, /**< Number of microseconds in 1.25 milliseconds. */
|
||||
UNIT_10_MS = 10000 /**< Number of microseconds in 10 milliseconds. */
|
||||
};
|
||||
|
||||
/**@brief Macro for doing static (i.e. compile time) assertion.
|
||||
*
|
||||
* @note If the assertion fails when compiling using Keil, the compiler will report error message
|
||||
* "error: #94: the size of an array must be greater than zero" (while gcc will list the
|
||||
* symbol static_assert_failed, making the error message more readable).
|
||||
* If the supplied expression can not be evaluated at compile time, Keil will report
|
||||
* "error: #28: expression must have a constant value".
|
||||
*
|
||||
* @note The macro is intentionally implemented not using do while(0), allowing it to be used
|
||||
* outside function blocks (e.g. close to global type- and variable declarations).
|
||||
* If used in a code block, it must be used before any executable code in this block.
|
||||
*
|
||||
* @param[in] EXPR Constant expression to be verified.
|
||||
*/
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#define STATIC_ASSERT(EXPR) typedef char __attribute__((unused)) static_assert_failed[(EXPR) ? 1 : -1]
|
||||
#else
|
||||
#define STATIC_ASSERT(EXPR) typedef char static_assert_failed[(EXPR) ? 1 : -1]
|
||||
#endif
|
||||
|
||||
|
||||
/**@brief type for holding an encoded (i.e. little endian) 16 bit unsigned integer. */
|
||||
typedef uint8_t uint16_le_t[2];
|
||||
|
||||
/**@brief type for holding an encoded (i.e. little endian) 32 bit unsigned integer. */
|
||||
typedef uint8_t uint32_le_t[4];
|
||||
|
||||
/**@brief Byte array type. */
|
||||
typedef struct
|
||||
{
|
||||
uint16_t size; /**< Number of array entries. */
|
||||
uint8_t * p_data; /**< Pointer to array entries. */
|
||||
} uint8_array_t;
|
||||
|
||||
/**@brief Perform rounded integer division (as opposed to truncating the result).
|
||||
*
|
||||
* @param[in] A Numerator.
|
||||
* @param[in] B Denominator.
|
||||
*
|
||||
* @return Rounded (integer) result of dividing A by B.
|
||||
*/
|
||||
#define ROUNDED_DIV(A, B) (((A) + ((B) / 2)) / (B))
|
||||
|
||||
/**@brief Check if the integer provided is a power of two.
|
||||
*
|
||||
* @param[in] A Number to be tested.
|
||||
*
|
||||
* @return true if value is power of two.
|
||||
* @return false if value not power of two.
|
||||
*/
|
||||
#define IS_POWER_OF_TWO(A) ( ((A) != 0) && ((((A) - 1) & (A)) == 0) )
|
||||
|
||||
/**@brief To convert ticks to millisecond
|
||||
* @param[in] time Number of millseconds that needs to be converted.
|
||||
* @param[in] resolution Units to be converted.
|
||||
*/
|
||||
#define MSEC_TO_UNITS(TIME, RESOLUTION) (((TIME) * 1000) / (RESOLUTION))
|
||||
|
||||
|
||||
/**@brief Perform integer division, making sure the result is rounded up.
|
||||
*
|
||||
* @details One typical use for this is to compute the number of objects with size B is needed to
|
||||
* hold A number of bytes.
|
||||
*
|
||||
* @param[in] A Numerator.
|
||||
* @param[in] B Denominator.
|
||||
*
|
||||
* @return Integer result of dividing A by B, rounded up.
|
||||
*/
|
||||
#define CEIL_DIV(A, B) \
|
||||
/*lint -save -e573 */ \
|
||||
((((A) - 1) / (B)) + 1) \
|
||||
/*lint -restore */
|
||||
|
||||
/**@brief Function for encoding a uint16 value.
|
||||
*
|
||||
* @param[in] value Value to be encoded.
|
||||
* @param[out] p_encoded_data Buffer where the encoded data is to be written.
|
||||
*
|
||||
* @return Number of bytes written.
|
||||
*/
|
||||
static __INLINE uint8_t uint16_encode(uint16_t value, uint8_t * p_encoded_data)
|
||||
{
|
||||
p_encoded_data[0] = (uint8_t) ((value & 0x00FF) >> 0);
|
||||
p_encoded_data[1] = (uint8_t) ((value & 0xFF00) >> 8);
|
||||
return sizeof(uint16_t);
|
||||
}
|
||||
|
||||
/**@brief Function for encoding a uint32 value.
|
||||
*
|
||||
* @param[in] value Value to be encoded.
|
||||
* @param[out] p_encoded_data Buffer where the encoded data is to be written.
|
||||
*
|
||||
* @return Number of bytes written.
|
||||
*/
|
||||
static __INLINE uint8_t uint32_encode(uint32_t value, uint8_t * p_encoded_data)
|
||||
{
|
||||
p_encoded_data[0] = (uint8_t) ((value & 0x000000FF) >> 0);
|
||||
p_encoded_data[1] = (uint8_t) ((value & 0x0000FF00) >> 8);
|
||||
p_encoded_data[2] = (uint8_t) ((value & 0x00FF0000) >> 16);
|
||||
p_encoded_data[3] = (uint8_t) ((value & 0xFF000000) >> 24);
|
||||
return sizeof(uint32_t);
|
||||
}
|
||||
|
||||
/**@brief Function for decoding a uint16 value.
|
||||
*
|
||||
* @param[in] p_encoded_data Buffer where the encoded data is stored.
|
||||
*
|
||||
* @return Decoded value.
|
||||
*/
|
||||
static __INLINE uint16_t uint16_decode(const uint8_t * p_encoded_data)
|
||||
{
|
||||
return ( (((uint16_t)((uint8_t *)p_encoded_data)[0])) |
|
||||
(((uint16_t)((uint8_t *)p_encoded_data)[1]) << 8 ));
|
||||
}
|
||||
|
||||
/**@brief Function for decoding a uint32 value.
|
||||
*
|
||||
* @param[in] p_encoded_data Buffer where the encoded data is stored.
|
||||
*
|
||||
* @return Decoded value.
|
||||
*/
|
||||
static __INLINE uint32_t uint32_decode(const uint8_t * p_encoded_data)
|
||||
{
|
||||
return ( (((uint32_t)((uint8_t *)p_encoded_data)[0]) << 0) |
|
||||
(((uint32_t)((uint8_t *)p_encoded_data)[1]) << 8) |
|
||||
(((uint32_t)((uint8_t *)p_encoded_data)[2]) << 16) |
|
||||
(((uint32_t)((uint8_t *)p_encoded_data)[3]) << 24 ));
|
||||
}
|
||||
|
||||
/** @brief Function for converting the input voltage (in milli volts) into percentage of 3.0 Volts.
|
||||
*
|
||||
* @details The calculation is based on a linearized version of the battery's discharge
|
||||
* curve. 3.0V returns 100% battery level. The limit for power failure is 2.1V and
|
||||
* is considered to be the lower boundary.
|
||||
*
|
||||
* The discharge curve for CR2032 is non-linear. In this model it is split into
|
||||
* 4 linear sections:
|
||||
* - Section 1: 3.0V - 2.9V = 100% - 42% (58% drop on 100 mV)
|
||||
* - Section 2: 2.9V - 2.74V = 42% - 18% (24% drop on 160 mV)
|
||||
* - Section 3: 2.74V - 2.44V = 18% - 6% (12% drop on 300 mV)
|
||||
* - Section 4: 2.44V - 2.1V = 6% - 0% (6% drop on 340 mV)
|
||||
*
|
||||
* These numbers are by no means accurate. Temperature and
|
||||
* load in the actual application is not accounted for!
|
||||
*
|
||||
* @param[in] mvolts The voltage in mV
|
||||
*
|
||||
* @return Battery level in percent.
|
||||
*/
|
||||
static __INLINE uint8_t battery_level_in_percent(const uint16_t mvolts)
|
||||
{
|
||||
uint8_t battery_level;
|
||||
|
||||
if (mvolts >= 3000)
|
||||
{
|
||||
battery_level = 100;
|
||||
}
|
||||
else if (mvolts > 2900)
|
||||
{
|
||||
battery_level = 100 - ((3000 - mvolts) * 58) / 100;
|
||||
}
|
||||
else if (mvolts > 2740)
|
||||
{
|
||||
battery_level = 42 - ((2900 - mvolts) * 24) / 160;
|
||||
}
|
||||
else if (mvolts > 2440)
|
||||
{
|
||||
battery_level = 18 - ((2740 - mvolts) * 12) / 300;
|
||||
}
|
||||
else if (mvolts > 2100)
|
||||
{
|
||||
battery_level = 6 - ((2440 - mvolts) * 6) / 340;
|
||||
}
|
||||
else
|
||||
{
|
||||
battery_level = 0;
|
||||
}
|
||||
|
||||
return battery_level;
|
||||
}
|
||||
|
||||
/**@brief Function for checking if a pointer value is aligned to a 4 byte boundary.
|
||||
*
|
||||
* @param[in] p Pointer value to be checked.
|
||||
*
|
||||
* @return TRUE if pointer is aligned to a 4 byte boundary, FALSE otherwise.
|
||||
*/
|
||||
static __INLINE bool is_word_aligned(void * p)
|
||||
{
|
||||
return (((uintptr_t)p & 0x03) == 0);
|
||||
}
|
||||
|
||||
#endif // APP_UTIL_H__
|
||||
|
||||
/** @} */
|
|
@ -0,0 +1,52 @@
|
|||
/* Copyright (c) 2013 Nordic Semiconductor. All Rights Reserved.
|
||||
*
|
||||
* The information contained herein is property of Nordic Semiconductor ASA.
|
||||
* Terms and conditions of usage are described in detail in NORDIC
|
||||
* SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
|
||||
*
|
||||
* Licensees are granted free, non-transferable use of the information. NO
|
||||
* WARRANTY of ANY KIND is provided. This heading must NOT be removed from
|
||||
* the file.
|
||||
*
|
||||
*/
|
||||
|
||||
/** @file
|
||||
*
|
||||
* @defgroup crc_compute CRC compute
|
||||
* @{
|
||||
* @ingroup hci_transport
|
||||
*
|
||||
* @brief This module implements the CRC-16 calculation in the blocks.
|
||||
*/
|
||||
|
||||
#ifndef CRC16_H__
|
||||
#define CRC16_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**@brief Function for calculating CRC-16 in blocks.
|
||||
*
|
||||
* Feed each consecutive data block into this function, along with the current value of p_crc as
|
||||
* returned by the previous call of this function. The first call of this function should pass NULL
|
||||
* as the initial value of the crc in p_crc.
|
||||
*
|
||||
* @param[in] p_data The input data block for computation.
|
||||
* @param[in] size The size of the input data block in bytes.
|
||||
* @param[in] p_crc The previous calculated CRC-16 value or NULL if first call.
|
||||
*
|
||||
* @return The updated CRC-16 value, based on the input supplied.
|
||||
*/
|
||||
uint16_t crc16_compute(const uint8_t * p_data, uint32_t size, const uint16_t * p_crc);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif // CRC16_H__
|
||||
|
||||
/** @} */
|
|
@ -0,0 +1,227 @@
|
|||
/* Copyright (c) 2013 Nordic Semiconductor. All Rights Reserved.
|
||||
*
|
||||
* The information contained herein is property of Nordic Semiconductor ASA.
|
||||
* Terms and conditions of usage are described in detail in NORDIC
|
||||
* SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
|
||||
*
|
||||
* Licensees are granted free, non-transferable use of the information. NO
|
||||
* WARRANTY of ANY KIND is provided. This heading must NOT be removed from
|
||||
* the file.
|
||||
*
|
||||
*/
|
||||
|
||||
/**@file
|
||||
*
|
||||
* @defgroup hci_transport HCI Transport
|
||||
* @{
|
||||
* @ingroup app_common
|
||||
*
|
||||
* @brief HCI transport module implementation.
|
||||
*
|
||||
* This module implements certain specific features from the three-wire UART transport layer,
|
||||
* defined by the Bluetooth specification version 4.0 [Vol 4] part D.
|
||||
*
|
||||
* \par Features supported
|
||||
* - Transmission and reception of Vendor Specific HCI packet type application packets.
|
||||
* - Transmission and reception of reliable packets: defined by chapter 6 of the specification.
|
||||
*
|
||||
* \par Features not supported
|
||||
* - Link establishment procedure: defined by chapter 8 of the specification.
|
||||
* - Low power: defined by chapter 9 of the specification.
|
||||
*
|
||||
* \par Implementation specific behaviour
|
||||
* - As Link establishment procedure is not supported following static link configuration parameters
|
||||
* are used:
|
||||
* + TX window size is 1.
|
||||
* + 16 bit CCITT-CRC must be used.
|
||||
* + Out of frame software flow control not supported.
|
||||
* + Parameters specific for resending reliable packets are compile time configurable (clarifed
|
||||
* later in this document).
|
||||
* + Acknowledgement packet transmissions are not timeout driven , meaning they are delivered for
|
||||
* transmission within same context which the corresponding application packet was received.
|
||||
*
|
||||
* \par Implementation specific limitations
|
||||
* Current implementation has the following limitations which will have impact to system wide
|
||||
* behaviour:
|
||||
* - Delayed acknowledgement scheduling not implemented:
|
||||
* There exists a possibility that acknowledgement TX packet and application TX packet will collide
|
||||
* in the TX pipeline having the end result that acknowledgement packet will be excluded from the TX
|
||||
* pipeline which will trigger the retransmission algorithm within the peer protocol entity.
|
||||
* - Delayed retransmission scheduling not implemented:
|
||||
* There exists a possibility that retransmitted application TX packet and acknowledgement TX packet
|
||||
* will collide in the TX pipeline having the end result that retransmitted application TX packet
|
||||
* will be excluded from the TX pipeline.
|
||||
* - Processing of the acknowledgement number from RX application packets:
|
||||
* Acknowledgement number is not processed from the RX application packets having the end result
|
||||
* that unnecessary application packet retransmissions can occur.
|
||||
*
|
||||
* The application TX packet processing flow is illustrated by the statemachine below.
|
||||
*
|
||||
* @image html hci_transport_tx_sm.png "TX - application packet statemachine"
|
||||
*
|
||||
* \par Component specific configuration options
|
||||
*
|
||||
* The following compile time configuration options are available, and used to configure the
|
||||
* application TX packet retransmission interval, in order to suite various application specific
|
||||
* implementations:
|
||||
* - MAC_PACKET_SIZE_IN_BITS Maximum size of a single application packet in bits.
|
||||
* - USED_BAUD_RATE Used uart baudrate.
|
||||
*
|
||||
* The following compile time configuration option is available to configure module specific
|
||||
* behaviour:
|
||||
* - MAX_RETRY_COUNT Max retransmission retry count for applicaton packets.
|
||||
*/
|
||||
|
||||
#ifndef HCI_TRANSPORT_H__
|
||||
#define HCI_TRANSPORT_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include "nrf_error.h"
|
||||
|
||||
#define HCI_TRANSPORT_PKT_HEADER_SIZE (2) /**< Size of transport packet header */
|
||||
|
||||
/**@brief Generic event callback function events. */
|
||||
typedef enum
|
||||
{
|
||||
HCI_TRANSPORT_RX_RDY, /**< An event indicating that RX packet is ready for read. */
|
||||
HCI_TRANSPORT_EVT_TYPE_MAX /**< Enumeration upper bound. */
|
||||
} hci_transport_evt_type_t;
|
||||
|
||||
/**@brief Struct containing events from the Transport layer.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
hci_transport_evt_type_t evt_type; /**< Type of event. */
|
||||
} hci_transport_evt_t;
|
||||
|
||||
/**@brief Transport layer generic event callback function type.
|
||||
*
|
||||
* @param[in] event Transport layer event.
|
||||
*/
|
||||
typedef void (*hci_transport_event_handler_t)(hci_transport_evt_t event);
|
||||
|
||||
/**@brief TX done event callback function result codes. */
|
||||
typedef enum
|
||||
{
|
||||
HCI_TRANSPORT_TX_DONE_SUCCESS, /**< Transmission success, peer transport entity has acknowledged the transmission. */
|
||||
HCI_TRANSPORT_TX_DONE_FAILURE /**< Transmission failure. */
|
||||
} hci_transport_tx_done_result_t;
|
||||
|
||||
/**@brief Transport layer TX done event callback function type.
|
||||
*
|
||||
* @param[in] result TX done event result code.
|
||||
*/
|
||||
typedef void (*hci_transport_tx_done_handler_t)(hci_transport_tx_done_result_t result);
|
||||
|
||||
/**@brief Function for registering a generic event handler.
|
||||
*
|
||||
* @note Multiple registration requests will overwrite any possible existing registration.
|
||||
*
|
||||
* @param[in] event_handler The function to be called by the transport layer upon an event.
|
||||
*
|
||||
* @retval NRF_SUCCESS Operation success.
|
||||
* @retval NRF_ERROR_NULL Operation failure. NULL pointer supplied.
|
||||
*/
|
||||
uint32_t hci_transport_evt_handler_reg(hci_transport_event_handler_t event_handler);
|
||||
|
||||
/**@brief Function for registering a handler for TX done event.
|
||||
*
|
||||
* @note Multiple registration requests will overwrite any possible existing registration.
|
||||
*
|
||||
* @param[in] event_handler The function to be called by the transport layer upon TX done
|
||||
* event.
|
||||
*
|
||||
* @retval NRF_SUCCESS Operation success.
|
||||
* @retval NRF_ERROR_NULL Operation failure. NULL pointer supplied.
|
||||
*/
|
||||
uint32_t hci_transport_tx_done_register(hci_transport_tx_done_handler_t event_handler);
|
||||
|
||||
/**@brief Function for opening the transport channel and initializing the transport layer.
|
||||
*
|
||||
* @warning Must not be called for a channel which has been allready opened.
|
||||
*
|
||||
* @retval NRF_SUCCESS Operation success.
|
||||
* @retval NRF_ERROR_INTERNAL Operation failure. Internal error ocurred.
|
||||
*/
|
||||
uint32_t hci_transport_open(void);
|
||||
|
||||
/**@brief Function for closing the transport channel.
|
||||
*
|
||||
* @note Can be called multiple times and also for not opened channel.
|
||||
*
|
||||
* @retval NRF_SUCCESS Operation success.
|
||||
*/
|
||||
uint32_t hci_transport_close(void);
|
||||
|
||||
/**@brief Function for allocating tx packet memory.
|
||||
*
|
||||
* @param[out] pp_memory Pointer to the packet data.
|
||||
*
|
||||
* @retval NRF_SUCCESS Operation success. Memory was allocated.
|
||||
* @retval NRF_ERROR_NO_MEM Operation failure. No memory available.
|
||||
* @retval NRF_ERROR_NULL Operation failure. NULL pointer supplied.
|
||||
*/
|
||||
uint32_t hci_transport_tx_alloc(uint8_t ** pp_memory);
|
||||
|
||||
/**@brief Function for freeing tx packet memory.
|
||||
*
|
||||
* @note Memory management works in FIFO principle meaning that free order must match the alloc
|
||||
* order.
|
||||
*
|
||||
* @retval NRF_SUCCESS Operation success. Memory was freed.
|
||||
*/
|
||||
uint32_t hci_transport_tx_free(void);
|
||||
|
||||
/**@brief Function for writing a packet.
|
||||
*
|
||||
* @note Completion of this method does not guarantee that actual peripheral transmission would
|
||||
* have completed.
|
||||
*
|
||||
* @note In case of 0 byte packet length write request, message will consist of only transport
|
||||
* module specific headers.
|
||||
*
|
||||
* @note The buffer provided to this function must be allocated through @ref hci_transport_tx_alloc
|
||||
* function.
|
||||
*
|
||||
* @retval NRF_SUCCESS Operation success. Packet was added to the transmission queue
|
||||
* and an event will be send upon transmission completion.
|
||||
* @retval NRF_ERROR_NO_MEM Operation failure. Transmission queue is full and packet was not
|
||||
* added to the transmission queue. User should wait for
|
||||
* a appropriate event prior issuing this operation again.
|
||||
* @retval NRF_ERROR_DATA_SIZE Operation failure. Packet size exceeds limit.
|
||||
* @retval NRF_ERROR_NULL Operation failure. NULL pointer supplied.
|
||||
* @retval NRF_ERROR_INVALID_STATE Operation failure. Channel is not open.
|
||||
* @retval NRF_ERROR_INVALID_ADDR Operation failure. Buffer provided is not allocated through
|
||||
* hci_transport_tx_alloc function.
|
||||
*/
|
||||
uint32_t hci_transport_pkt_write(const uint8_t * p_buffer, uint16_t length);
|
||||
|
||||
/**@brief Function for extracting received packet.
|
||||
*
|
||||
* @note Extracted memory can't be reused by the underlying transport layer untill freed by call to
|
||||
* hci_transport_rx_pkt_consume().
|
||||
*
|
||||
* @param[out] pp_buffer Pointer to the packet data.
|
||||
* @param[out] p_length Length of packet data in bytes.
|
||||
*
|
||||
* @retval NRF_SUCCESS Operation success. Packet was extracted.
|
||||
* @retval NRF_ERROR_NO_MEM Operation failure. No packet available to extract.
|
||||
* @retval NRF_ERROR_NULL Operation failure. NULL pointer supplied.
|
||||
*/
|
||||
uint32_t hci_transport_rx_pkt_extract(uint8_t ** pp_buffer, uint16_t * p_length);
|
||||
|
||||
/**@brief Function for consuming extracted packet described by p_buffer.
|
||||
*
|
||||
* RX memory pointed to by p_buffer is freed and can be reused by the underlying transport layer.
|
||||
*
|
||||
* @param[in] p_buffer Pointer to the buffer that has been consumed.
|
||||
*
|
||||
* @retval NRF_SUCCESS Operation success.
|
||||
* @retval NRF_ERROR_NO_MEM Operation failure. No packet available to consume.
|
||||
* @retval NRF_ERROR_INVALID_ADDR Operation failure. Not a valid pointer.
|
||||
*/
|
||||
uint32_t hci_transport_rx_pkt_consume(uint8_t * p_buffer);
|
||||
|
||||
#endif // HCI_TRANSPORT_H__
|
||||
|
||||
/** @} */
|
|
@ -0,0 +1,132 @@
|
|||
/* Copyright (c) 2013 Nordic Semiconductor. All Rights Reserved.
|
||||
*
|
||||
* The information contained herein is property of Nordic Semiconductor ASA.
|
||||
* Terms and conditions of usage are described in detail in NORDIC
|
||||
* SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
|
||||
*
|
||||
* Licensees are granted free, non-transferable use of the information. NO
|
||||
* WARRANTY of ANY KIND is provided. This heading must NOT be removed from
|
||||
* the file.
|
||||
*
|
||||
*/
|
||||
|
||||
/** @file
|
||||
*
|
||||
* @defgroup memory_pool Memory pool
|
||||
* @{
|
||||
* @ingroup app_common
|
||||
*
|
||||
* @brief Memory pool implementation
|
||||
*
|
||||
* Memory pool implementation, based on circular buffer data structure, which supports asynchronous
|
||||
* processing of RX data. The current default implementation supports 1 TX buffer and 4 RX buffers.
|
||||
* The memory managed by the pool is allocated from static storage instead of heap. The internal
|
||||
* design of the circular buffer implementing the RX memory layout is illustrated in the picture
|
||||
* below.
|
||||
*
|
||||
* @image html memory_pool.png "Circular buffer design"
|
||||
*
|
||||
* The expected call order for the RX APIs is as follows:
|
||||
* - hci_mem_pool_rx_produce
|
||||
* - hci_mem_pool_rx_data_size_set
|
||||
* - hci_mem_pool_rx_extract
|
||||
* - hci_mem_pool_rx_consume
|
||||
*
|
||||
* @warning If the above mentioned expected call order is violated the end result can be undefined.
|
||||
*
|
||||
* \par Component specific configuration options
|
||||
*
|
||||
* The following compile time configuration options are available to suit various implementations:
|
||||
* - TX_BUF_SIZE TX buffer size in bytes.
|
||||
* - RX_BUF_SIZE RX buffer size in bytes.
|
||||
* - RX_BUF_QUEUE_SIZE RX buffer element size.
|
||||
*/
|
||||
|
||||
#ifndef HCI_MEM_POOL_H__
|
||||
#define HCI_MEM_POOL_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include "nrf_error.h"
|
||||
|
||||
/**@brief Function for opening the module.
|
||||
*
|
||||
* @retval NRF_SUCCESS Operation success.
|
||||
*/
|
||||
uint32_t hci_mem_pool_open(void);
|
||||
|
||||
/**@brief Function for closing the module.
|
||||
*
|
||||
* @retval NRF_SUCCESS Operation success.
|
||||
*/
|
||||
uint32_t hci_mem_pool_close(void);
|
||||
|
||||
/**@brief Function for allocating requested amount of TX memory.
|
||||
*
|
||||
* @param[out] pp_buffer Pointer to the allocated memory.
|
||||
*
|
||||
* @retval NRF_SUCCESS Operation success. Memory was allocated.
|
||||
* @retval NRF_ERROR_NO_MEM Operation failure. No memory available for allocation.
|
||||
* @retval NRF_ERROR_NULL Operation failure. NULL pointer supplied.
|
||||
*/
|
||||
uint32_t hci_mem_pool_tx_alloc(void ** pp_buffer);
|
||||
|
||||
/**@brief Function for freeing previously allocated TX memory.
|
||||
*
|
||||
* @note Memory management follows the FIFO principle meaning that free() order must match the
|
||||
* alloc(...) order, which is the reason for omitting exact memory block identifier as an
|
||||
* input parameter.
|
||||
*
|
||||
* @retval NRF_SUCCESS Operation success. Memory was freed.
|
||||
*/
|
||||
uint32_t hci_mem_pool_tx_free(void);
|
||||
|
||||
/**@brief Function for producing a free RX memory block for usage.
|
||||
*
|
||||
* @note Upon produce request amount being 0, NRF_SUCCESS is returned.
|
||||
*
|
||||
* @param[in] length Amount, in bytes, of free memory to be produced.
|
||||
* @param[out] pp_buffer Pointer to the allocated memory.
|
||||
*
|
||||
* @retval NRF_SUCCESS Operation success. Free RX memory block produced.
|
||||
* @retval NRF_ERROR_NO_MEM Operation failure. No suitable memory available for allocation.
|
||||
* @retval NRF_ERROR_DATA_SIZE Operation failure. Request size exceeds limit.
|
||||
* @retval NRF_ERROR_NULL Operation failure. NULL pointer supplied.
|
||||
*/
|
||||
uint32_t hci_mem_pool_rx_produce(uint32_t length, void ** pp_buffer);
|
||||
|
||||
/**@brief Function for setting the length of the last produced RX memory block.
|
||||
*
|
||||
* @warning If call to this API is omitted the end result is that the following call to
|
||||
* mem_pool_rx_extract will return incorrect data in the p_length output parameter.
|
||||
*
|
||||
* @param[in] length Amount, in bytes, of actual memory used.
|
||||
*
|
||||
* @retval NRF_SUCCESS Operation success. Length was set.
|
||||
*/
|
||||
uint32_t hci_mem_pool_rx_data_size_set(uint32_t length);
|
||||
|
||||
/**@brief Function for extracting a packet, which has been filled with read data, for further
|
||||
* processing.
|
||||
*
|
||||
* @param[out] pp_buffer Pointer to the packet data.
|
||||
* @param[out] p_length Length of packet data in bytes.
|
||||
*
|
||||
* @retval NRF_SUCCESS Operation success.
|
||||
* @retval NRF_ERROR_NO_MEM Operation failure. No packet available to extract.
|
||||
* @retval NRF_ERROR_NULL Operation failure. NULL pointer supplied.
|
||||
*/
|
||||
uint32_t hci_mem_pool_rx_extract(uint8_t ** pp_buffer, uint32_t * p_length);
|
||||
|
||||
/**@brief Function for freeing previously extracted packet, which has been filled with read data.
|
||||
*
|
||||
* @param[in] p_buffer Pointer to consumed buffer.
|
||||
*
|
||||
* @retval NRF_SUCCESS Operation success.
|
||||
* @retval NRF_ERROR_NO_MEM Operation failure. No packet available to free.
|
||||
* @retval NRF_ERROR_INVALID_ADDR Operation failure. Not a valid pointer.
|
||||
*/
|
||||
uint32_t hci_mem_pool_rx_consume(uint8_t * p_buffer);
|
||||
|
||||
#endif // HCI_MEM_POOL_H__
|
||||
|
||||
/** @} */
|
|
@ -0,0 +1,32 @@
|
|||
/* Copyright (c) 2013 Nordic Semiconductor. All Rights Reserved.
|
||||
*
|
||||
* The information contained herein is property of Nordic Semiconductor ASA.
|
||||
* Terms and conditions of usage are described in detail in NORDIC
|
||||
* SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
|
||||
*
|
||||
* Licensees are granted free, non-transferable use of the information. NO
|
||||
* WARRANTY of ANY KIND is provided. This heading must NOT be removed from
|
||||
* the file.
|
||||
*
|
||||
*/
|
||||
|
||||
/** @file
|
||||
*
|
||||
* @defgroup memory_pool_internal Memory Pool Internal
|
||||
* @{
|
||||
* @ingroup memory_pool
|
||||
*
|
||||
* @brief Memory pool internal definitions
|
||||
*/
|
||||
|
||||
#ifndef MEM_POOL_INTERNAL_H__
|
||||
#define MEM_POOL_INTERNAL_H__
|
||||
|
||||
#define TX_BUF_SIZE 600u /**< TX buffer size in bytes. */
|
||||
#define RX_BUF_SIZE TX_BUF_SIZE /**< RX buffer size in bytes. */
|
||||
|
||||
#define RX_BUF_QUEUE_SIZE 4u /**< RX buffer element size. */
|
||||
|
||||
#endif // MEM_POOL_INTERNAL_H__
|
||||
|
||||
/** @} */
|
|
@ -0,0 +1,129 @@
|
|||
/* Copyright (c) 2013 Nordic Semiconductor. All Rights Reserved.
|
||||
*
|
||||
* The information contained herein is property of Nordic Semiconductor ASA.
|
||||
* Terms and conditions of usage are described in detail in NORDIC
|
||||
* SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
|
||||
*
|
||||
* Licensees are granted free, non-transferable use of the information. NO
|
||||
* WARRANTY of ANY KIND is provided. This heading must NOT be removed from
|
||||
* the file.
|
||||
*
|
||||
*/
|
||||
|
||||
/** @file
|
||||
*
|
||||
* @defgroup hci_slip SLIP module
|
||||
* @{
|
||||
* @ingroup app_common
|
||||
*
|
||||
* @brief SLIP layer for supporting packet framing in HCI transport.
|
||||
*
|
||||
* @details This module implements SLIP packet framing as described in the Bluetooth Core
|
||||
* Specification 4.0, Volume 4, Part D, Chapter 3 SLIP Layer.
|
||||
*
|
||||
* SLIP framing ensures that all packets sent on the UART are framed as:
|
||||
* <0xC0> SLIP packet 1 <0xC0> <0xC0> SLIP packet 2 <0xC0>.
|
||||
*
|
||||
* The SLIP layer uses events to notify the upper layer when data transmission is complete
|
||||
* and when a SLIP packet is received.
|
||||
*/
|
||||
|
||||
#ifndef HCI_SLIP_H__
|
||||
#define HCI_SLIP_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**@brief Event types from the SLIP Layer. */
|
||||
typedef enum
|
||||
{
|
||||
HCI_SLIP_RX_RDY, /**< An event indicating that an RX packet is ready to be read. */
|
||||
HCI_SLIP_TX_DONE, /**< An event indicating write completion of the TX packet provided in the function call \ref hci_slip_write . */
|
||||
HCI_SLIP_RX_OVERFLOW, /**< An event indicating that RX data has been discarded due to lack of free RX memory. */
|
||||
HCI_SLIP_ERROR, /**< An event indicating that an unrecoverable error has occurred. */
|
||||
HCI_SLIP_EVT_TYPE_MAX /**< Enumeration upper bound. */
|
||||
} hci_slip_evt_type_t;
|
||||
|
||||
/**@brief Structure containing an event from the SLIP layer.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
hci_slip_evt_type_t evt_type; /**< Type of event. */
|
||||
const uint8_t * packet; /**< This field contains a pointer to the packet for which the event relates, i.e. SLIP_TX_DONE: the packet transmitted, SLIP_RX_RDY: the packet received, SLIP_RX_OVERFLOW: The packet which overflow/or NULL if no receive buffer is available. */
|
||||
uint32_t packet_length; /**< Packet length, i.e. SLIP_TX_DONE: Bytes transmitted, SLIP_RX_RDY: Bytes received, SLIP_RX_OVERFLOW: index at which the packet overflowed. */
|
||||
} hci_slip_evt_t;
|
||||
|
||||
/**@brief Function for the SLIP layer event callback.
|
||||
*/
|
||||
typedef void (*hci_slip_event_handler_t)(hci_slip_evt_t event);
|
||||
|
||||
/**@brief Function for registering the event handler provided as parameter and this event handler
|
||||
* will be used by SLIP layer to send events described in \ref hci_slip_evt_type_t.
|
||||
*
|
||||
* @note Multiple registration requests will overwrite any existing registration.
|
||||
*
|
||||
* @param[in] event_handler This function is called by the SLIP layer upon an event.
|
||||
*
|
||||
* @retval NRF_SUCCESS Operation success.
|
||||
*/
|
||||
uint32_t hci_slip_evt_handler_register(hci_slip_event_handler_t event_handler);
|
||||
|
||||
/**@brief Function for opening the SLIP layer. This function must be called before
|
||||
* \ref hci_slip_write and before any data can be received.
|
||||
*
|
||||
* @note Can be called multiple times.
|
||||
*
|
||||
* @retval NRF_SUCCESS Operation success.
|
||||
*
|
||||
* The SLIP layer module will propagate errors from underlying sub-modules.
|
||||
* This implementation is using UART module as a physical transmission layer, and hci_slip_open
|
||||
* executes \ref app_uart_init . For an extended error list, please refer to \ref app_uart_init .
|
||||
*/
|
||||
uint32_t hci_slip_open(void);
|
||||
|
||||
/**@brief Function for closing the SLIP layer. After this function is called no data can be
|
||||
* transmitted or received in this layer.
|
||||
*
|
||||
* @note This function can be called multiple times and also for an unopened channel.
|
||||
*
|
||||
* @retval NRF_SUCCESS Operation success.
|
||||
*/
|
||||
uint32_t hci_slip_close(void);
|
||||
|
||||
/**@brief Function for writing a packet with SLIP encoding. Packet transmission is confirmed when
|
||||
* the HCI_SLIP_TX_DONE event is received by the function caller.
|
||||
*
|
||||
* @param[in] p_buffer Pointer to the packet to transmit.
|
||||
* @param[in] length Packet length, in bytes.
|
||||
*
|
||||
* @retval NRF_SUCCESS Operation success. Packet was encoded and added to the
|
||||
* transmission queue and an event will be sent upon transmission
|
||||
* completion.
|
||||
* @retval NRF_ERROR_NO_MEM Operation failure. Transmission queue is full and packet was not
|
||||
* added to the transmission queue. Application shall wait for
|
||||
* the \ref HCI_SLIP_TX_DONE event. After HCI_SLIP_TX_DONE this
|
||||
* function can be executed for transmission of next packet.
|
||||
* @retval NRF_ERROR_INVALID_ADDR If a NULL pointer is provided.
|
||||
* @retval NRF_ERROR_INVALID_STATE Operation failure. Module is not open.
|
||||
*/
|
||||
uint32_t hci_slip_write(const uint8_t * p_buffer, uint32_t length);
|
||||
|
||||
/**@brief Function for registering a receive buffer. The receive buffer will be used for storage of
|
||||
* received and SLIP decoded data.
|
||||
* No data can be received by the SLIP layer until a receive buffer has been registered.
|
||||
*
|
||||
* @note The lifetime of the buffer must be valid during complete reception of data. A static
|
||||
* buffer is recommended.
|
||||
*
|
||||
* @warning Multiple registration requests will overwrite any existing registration.
|
||||
*
|
||||
* @param[in] p_buffer Pointer to receive buffer. The received and SLIP decoded packet
|
||||
* will be placed in this buffer.
|
||||
* @param[in] length Buffer length, in bytes.
|
||||
*
|
||||
* @retval NRF_SUCCESS Operation success.
|
||||
*/
|
||||
uint32_t hci_slip_rx_buffer_register(uint8_t * p_buffer, uint32_t length);
|
||||
|
||||
#endif // HCI_SLIP_H__
|
||||
|
||||
/** @} */
|
|
@ -0,0 +1,220 @@
|
|||
/* Copyright (c) 2013 Nordic Semiconductor. All Rights Reserved.
|
||||
*
|
||||
* The information contained herein is property of Nordic Semiconductor ASA.
|
||||
* Terms and conditions of usage are described in detail in NORDIC
|
||||
* SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
|
||||
*
|
||||
* Licensees are granted free, non-transferable use of the information. NO
|
||||
* WARRANTY of ANY KIND is provided. This heading must NOT be removed from
|
||||
* the file.
|
||||
*
|
||||
*/
|
||||
|
||||
/**@file
|
||||
*
|
||||
* @defgroup hci_transport HCI Transport
|
||||
* @{
|
||||
* @ingroup app_common
|
||||
*
|
||||
* @brief HCI transport module implementation.
|
||||
*
|
||||
* This module implements certain specific features from the three-wire UART transport layer,
|
||||
* defined by the Bluetooth specification version 4.0 [Vol 4] part D.
|
||||
*
|
||||
* \par Features supported
|
||||
* - Transmission and reception of Vendor Specific HCI packet type application packets.
|
||||
* - Transmission and reception of reliable packets: defined by chapter 6 of the specification.
|
||||
*
|
||||
* \par Features not supported
|
||||
* - Link establishment procedure: defined by chapter 8 of the specification.
|
||||
* - Low power: defined by chapter 9 of the specification.
|
||||
*
|
||||
* \par Implementation specific behaviour
|
||||
* - As Link establishment procedure is not supported following static link configuration parameters
|
||||
* are used:
|
||||
* + TX window size is 1.
|
||||
* + 16 bit CCITT-CRC must be used.
|
||||
* + Out of frame software flow control not supported.
|
||||
* + Parameters specific for resending reliable packets are compile time configurable (clarifed
|
||||
* later in this document).
|
||||
* + Acknowledgement packet transmissions are not timeout driven , meaning they are delivered for
|
||||
* transmission within same context which the corresponding application packet was received.
|
||||
*
|
||||
* \par Implementation specific limitations
|
||||
* Current implementation has the following limitations which will have impact to system wide
|
||||
* behaviour:
|
||||
* - Delayed acknowledgement scheduling not implemented:
|
||||
* There exists a possibility that acknowledgement TX packet and application TX packet will collide
|
||||
* in the TX pipeline having the end result that acknowledgement packet will be excluded from the TX
|
||||
* pipeline which will trigger the retransmission algorithm within the peer protocol entity.
|
||||
* - Delayed retransmission scheduling not implemented:
|
||||
* There exists a possibility that retransmitted application TX packet and acknowledgement TX packet
|
||||
* will collide in the TX pipeline having the end result that retransmitted application TX packet
|
||||
* will be excluded from the TX pipeline.
|
||||
* - Processing of the acknowledgement number from RX application packets:
|
||||
* Acknowledgement number is not processed from the RX application packets having the end result
|
||||
* that unnecessary application packet retransmissions can occur.
|
||||
*
|
||||
* The application TX packet processing flow is illustrated by the statemachine below.
|
||||
*
|
||||
* @image html hci_transport_tx_sm.png "TX - application packet statemachine"
|
||||
*
|
||||
* \par Component specific configuration options
|
||||
*
|
||||
* The following compile time configuration options are available, and used to configure the
|
||||
* application TX packet retransmission interval, in order to suite various application specific
|
||||
* implementations:
|
||||
* - MAC_PACKET_SIZE_IN_BITS Maximum size of a single application packet in bits.
|
||||
* - USED_BAUD_RATE Used uart baudrate.
|
||||
*
|
||||
* The following compile time configuration option is available to configure module specific
|
||||
* behaviour:
|
||||
* - MAX_RETRY_COUNT Max retransmission retry count for applicaton packets.
|
||||
*/
|
||||
|
||||
#ifndef HCI_TRANSPORT_H__
|
||||
#define HCI_TRANSPORT_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include "nrf_error.h"
|
||||
|
||||
/**@brief Generic event callback function events. */
|
||||
typedef enum
|
||||
{
|
||||
HCI_TRANSPORT_RX_RDY, /**< An event indicating that RX packet is ready for read. */
|
||||
HCI_TRANSPORT_EVT_TYPE_MAX /**< Enumeration upper bound. */
|
||||
} hci_transport_evt_type_t;
|
||||
|
||||
/**@brief Struct containing events from the Transport layer.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
hci_transport_evt_type_t evt_type; /**< Type of event. */
|
||||
} hci_transport_evt_t;
|
||||
|
||||
/**@brief Transport layer generic event callback function type.
|
||||
*
|
||||
* @param[in] event Transport layer event.
|
||||
*/
|
||||
typedef void (*hci_transport_event_handler_t)(hci_transport_evt_t event);
|
||||
|
||||
/**@brief TX done event callback function result codes. */
|
||||
typedef enum
|
||||
{
|
||||
HCI_TRANSPORT_TX_DONE_SUCCESS, /**< Transmission success, peer transport entity has acknowledged the transmission. */
|
||||
HCI_TRANSPORT_TX_DONE_FAILURE /**< Transmission failure. */
|
||||
} hci_transport_tx_done_result_t;
|
||||
|
||||
/**@brief Transport layer TX done event callback function type.
|
||||
*
|
||||
* @param[in] result TX done event result code.
|
||||
*/
|
||||
typedef void (*hci_transport_tx_done_handler_t)(hci_transport_tx_done_result_t result);
|
||||
|
||||
/**@brief Function for registering a generic event handler.
|
||||
*
|
||||
* @note Multiple registration requests will overwrite any possible existing registration.
|
||||
*
|
||||
* @param[in] event_handler The function to be called by the transport layer upon an event.
|
||||
*
|
||||
* @retval NRF_SUCCESS Operation success.
|
||||
* @retval NRF_ERROR_NULL Operation failure. NULL pointer supplied.
|
||||
*/
|
||||
uint32_t hci_transport_evt_handler_reg(hci_transport_event_handler_t event_handler);
|
||||
|
||||
/**@brief Function for registering a handler for TX done event.
|
||||
*
|
||||
* @note Multiple registration requests will overwrite any possible existing registration.
|
||||
*
|
||||
* @param[in] event_handler The function to be called by the transport layer upon TX done
|
||||
* event.
|
||||
*
|
||||
* @retval NRF_SUCCESS Operation success.
|
||||
* @retval NRF_ERROR_NULL Operation failure. NULL pointer supplied.
|
||||
*/
|
||||
uint32_t hci_transport_tx_done_register(hci_transport_tx_done_handler_t event_handler);
|
||||
|
||||
/**@brief Function for opening the transport channel and initializing the transport layer.
|
||||
*
|
||||
* @warning Must not be called for a channel which has been allready opened.
|
||||
*
|
||||
* @retval NRF_SUCCESS Operation success.
|
||||
* @retval NRF_ERROR_INTERNAL Operation failure. Internal error ocurred.
|
||||
*/
|
||||
uint32_t hci_transport_open(void);
|
||||
|
||||
/**@brief Function for closing the transport channel.
|
||||
*
|
||||
* @note Can be called multiple times and also for not opened channel.
|
||||
*
|
||||
* @retval NRF_SUCCESS Operation success.
|
||||
*/
|
||||
uint32_t hci_transport_close(void);
|
||||
|
||||
/**@brief Function for allocating tx packet memory.
|
||||
*
|
||||
* @param[out] pp_memory Pointer to the packet data.
|
||||
*
|
||||
* @retval NRF_SUCCESS Operation success. Memory was allocated.
|
||||
* @retval NRF_ERROR_NO_MEM Operation failure. No memory available.
|
||||
* @retval NRF_ERROR_NULL Operation failure. NULL pointer supplied.
|
||||
*/
|
||||
uint32_t hci_transport_tx_alloc(uint8_t ** pp_memory);
|
||||
|
||||
/**@brief Function for freeing tx packet memory.
|
||||
*
|
||||
* @note Memory management works in FIFO principle meaning that free order must match the alloc
|
||||
* order.
|
||||
*
|
||||
* @retval NRF_SUCCESS Operation success. Memory was freed.
|
||||
*/
|
||||
uint32_t hci_transport_tx_free(void);
|
||||
|
||||
/**@brief Function for writing a packet.
|
||||
*
|
||||
* @note Completion of this method does not guarantee that actual peripheral transmission would
|
||||
* have completed.
|
||||
*
|
||||
* @note In case of 0 byte packet length write request, message will consist of only transport
|
||||
* module specific headers.
|
||||
*
|
||||
* @retval NRF_SUCCESS Operation success. Packet was added to the transmission queue
|
||||
* and an event will be send upon transmission completion.
|
||||
* @retval NRF_ERROR_NO_MEM Operation failure. Transmission queue is full and packet was not
|
||||
* added to the transmission queue. User should wait for
|
||||
* a appropriate event prior issuing this operation again.
|
||||
* @retval NRF_ERROR_DATA_SIZE Operation failure. Packet size exceeds limit.
|
||||
* @retval NRF_ERROR_NULL Operation failure. NULL pointer supplied.
|
||||
* @retval NRF_ERROR_INVALID_STATE Operation failure. Channel is not open.
|
||||
*/
|
||||
uint32_t hci_transport_pkt_write(const uint8_t * p_buffer, uint32_t length);
|
||||
|
||||
/**@brief Function for extracting received packet.
|
||||
*
|
||||
* @note Extracted memory can't be reused by the underlying transport layer untill freed by call to
|
||||
* hci_transport_rx_pkt_consume().
|
||||
*
|
||||
* @param[out] pp_buffer Pointer to the packet data.
|
||||
* @param[out] p_length Length of packet data in bytes.
|
||||
*
|
||||
* @retval NRF_SUCCESS Operation success. Packet was extracted.
|
||||
* @retval NRF_ERROR_NO_MEM Operation failure. No packet available to extract.
|
||||
* @retval NRF_ERROR_NULL Operation failure. NULL pointer supplied.
|
||||
*/
|
||||
uint32_t hci_transport_rx_pkt_extract(uint8_t ** pp_buffer, uint32_t * p_length);
|
||||
|
||||
/**@brief Function for consuming extracted packet described by p_buffer.
|
||||
*
|
||||
* RX memory pointed to by p_buffer is freed and can be reused by the underlying transport layer.
|
||||
*
|
||||
* @param[in] p_buffer Pointer to the buffer that has been consumed.
|
||||
*
|
||||
* @retval NRF_SUCCESS Operation success.
|
||||
* @retval NRF_ERROR_NO_MEM Operation failure. No packet available to consume.
|
||||
* @retval NRF_ERROR_INVALID_ADDR Operation failure. Not a valid pointer.
|
||||
*/
|
||||
uint32_t hci_transport_rx_pkt_consume(uint8_t * p_buffer);
|
||||
|
||||
#endif // HCI_TRANSPORT_H__
|
||||
|
||||
/** @} */
|
|
@ -0,0 +1,381 @@
|
|||
/* Copyright (c) 2013 Nordic Semiconductor. All Rights Reserved.
|
||||
*
|
||||
* The information contained herein is property of Nordic Semiconductor ASA.
|
||||
* Terms and conditions of usage are described in detail in NORDIC
|
||||
* SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
|
||||
*
|
||||
* Licensees are granted free, non-transferable use of the information. NO
|
||||
* WARRANTY of ANY KIND is provided. This heading must NOT be removed from
|
||||
* the file.
|
||||
*
|
||||
*/
|
||||
|
||||
/**@file
|
||||
*
|
||||
* @defgroup persistent_storage Persistent Storage Interface
|
||||
* @{
|
||||
* @ingroup app_common
|
||||
* @brief Abstracted flash interface.
|
||||
*
|
||||
* @details In order to ensure that the SDK and application be moved to alternate persistent storage
|
||||
* options other than the default provided with NRF solution, an abstracted interface is provided
|
||||
* by the module to ensure SDK modules and application can be ported to alternate option with ease.
|
||||
*/
|
||||
|
||||
#ifndef PSTORAGE_H__
|
||||
#define PSTORAGE_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* #ifdef __cplusplus */
|
||||
|
||||
#include "pstorage_platform.h"
|
||||
|
||||
|
||||
/**@defgroup ps_opcode Persistent Storage Access Operation Codes
|
||||
* @{
|
||||
* @brief Persistent Storage Access Operation Codes. These are used to report any error during
|
||||
* a persistent storage access operation or any general error that may occur in the
|
||||
* interface.
|
||||
*
|
||||
* @details Persistent Storage Access Operation Codes used in error notification callback
|
||||
* registered with the interface to report any error during an persistent storage access
|
||||
* operation or any general error that may occur in the interface.
|
||||
*/
|
||||
#define PSTORAGE_ERROR_OP_CODE 0x01 /**< General Error Code */
|
||||
#define PSTORAGE_STORE_OP_CODE 0x02 /**< Error when Store Operation was requested */
|
||||
#define PSTORAGE_LOAD_OP_CODE 0x03 /**< Error when Load Operation was requested */
|
||||
#define PSTORAGE_CLEAR_OP_CODE 0x04 /**< Error when Clear Operation was requested */
|
||||
#define PSTORAGE_UPDATE_OP_CODE 0x05 /**< Update an already touched storage block */
|
||||
|
||||
/**@} */
|
||||
|
||||
/**@defgroup pstorage_data_types Persistent Memory Interface Data Types
|
||||
* @{
|
||||
* @brief Data Types needed for interfacing with persistent memory.
|
||||
*
|
||||
* @details Data Types needed for interfacing with persistent memory.
|
||||
*/
|
||||
|
||||
/**@brief Persistent Storage Error Reporting Callback
|
||||
*
|
||||
* @details Persistent Storage Error Reporting Callback that is used by the interface to report
|
||||
* success or failure of a flash operation. Therefore, for any operations, application
|
||||
* can know when the procedure was complete. For store operation, since no data copy
|
||||
* is made, receiving a success or failure notification, indicated by the reason
|
||||
* parameter of callback is an indication that the resident memory could now be reused
|
||||
* or freed, as the case may be.
|
||||
*
|
||||
* @param[in] handle Identifies module and block for which callback is received.
|
||||
* @param[in] op_code Identifies the operation for which the event is notified.
|
||||
* @param[in] result Identifies the result of flash access operation.
|
||||
* NRF_SUCCESS implies, operation succeeded.
|
||||
* @param[in] p_data Identifies the application data pointer. In case of store operation, this
|
||||
* points to the resident source of application memory that application can now
|
||||
* free or reuse. In case of clear, this is NULL as no application pointer is
|
||||
* needed for this operation.
|
||||
* @param[in] data_len Length data application had provided for the operation.
|
||||
*
|
||||
*/
|
||||
typedef void (*pstorage_ntf_cb_t)(pstorage_handle_t * p_handle,
|
||||
uint8_t op_code,
|
||||
uint32_t result,
|
||||
uint8_t * p_data,
|
||||
uint32_t data_len);
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
pstorage_ntf_cb_t cb; /**< Callback registered with the module to be notified of any error occurring in persistent memory management */
|
||||
pstorage_size_t block_size; /**< Desired block size for persistent memory storage, for example, if a module has a table with 10 entries, each entry is size 64 bytes,
|
||||
* it can request 10 blocks with block size 64 bytes. On the other hand, the module can also request one block of size 640 based on
|
||||
* how it would like to access or alter memory in persistent memory.
|
||||
* First option is preferred when single entries that need to be updated often when having no impact on the other entries.
|
||||
* While second option is preferred when entries of table are not changed on individually but have common point of loading and storing
|
||||
* data. */
|
||||
pstorage_size_t block_count; /** Number of blocks requested by the module, minimum values is 1. */
|
||||
} pstorage_module_param_t;
|
||||
|
||||
/**@} */
|
||||
|
||||
/**@defgroup pstorage_routines Persistent Storage Access Routines
|
||||
* @{
|
||||
* @brief Functions/Interface SDK modules use to persistently store data.
|
||||
*
|
||||
* @details Interface for Application & SDK module to load/store information persistently.
|
||||
* Note: that while implementation of each of the persistent storage access function
|
||||
* depends on the system and can specific to system/solution, the signature of the
|
||||
* interface routines should not be altered.
|
||||
*/
|
||||
|
||||
/**@brief Module Initialization Routine.
|
||||
*
|
||||
* @details Initializes module. To be called once before any other APIs of the module are used.
|
||||
*
|
||||
* @retval NRF_SUCCESS on success, else an error code indicating reason for failure.
|
||||
*/
|
||||
uint32_t pstorage_init(void);
|
||||
|
||||
|
||||
/**@brief Register with persistent storage interface.
|
||||
*
|
||||
* @param[in] p_module_param Module registration param.
|
||||
* @param[out] p_block_id Block identifier to identify persistent memory blocks in case
|
||||
* registration succeeds. Application is expected to use the block ids
|
||||
* for subsequent operations on requested persistent memory. Maximum
|
||||
* registrations permitted is determined by configuration parameter
|
||||
* PSTORAGE_MAX_APPLICATIONS.
|
||||
* In case more than one memory blocks are requested, the identifier provided here is
|
||||
* the base identifier for the first block and to identify subsequent block,
|
||||
* application shall use \@ref pstorage_block_identifier_get with this base identifier
|
||||
* and block number. Therefore if 10 blocks of size 64 are requested and application
|
||||
* wishes to store memory in 6th block, it shall use
|
||||
* \@ref pstorage_block_identifier_get with based id and provide a block number of 5.
|
||||
* This way application is only expected to remember the base block identifier.
|
||||
*
|
||||
* @retval NRF_SUCCESS on success, else an error code indicating reason for failure.
|
||||
* @retval NRF_ERROR_INVALID_STATE is returned is API is called without module initialization.
|
||||
* @retval NRF_ERROR_NULL if NULL parameter has been passed.
|
||||
* @retval NRF_ERROR_INVALID_PARAM if invalid parameters are passed to the API.
|
||||
* @retval NRF_ERROR_NO_MEM in case no more registrations can be supported.
|
||||
*/
|
||||
uint32_t pstorage_register(pstorage_module_param_t * p_module_param,
|
||||
pstorage_handle_t * p_block_id);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Function to get block id with reference to base block identifier provided at time of
|
||||
* registration.
|
||||
*
|
||||
* @details Function to get block id with reference to base block identifier provided at time of
|
||||
* registration.
|
||||
* In case more than one memory blocks were requested when registering, the identifier
|
||||
* provided here is the base identifier for the first block and to identify subsequent
|
||||
* block, application shall use this routine to get block identifier providing input as
|
||||
* base identifier and block number. Therefore if 10 blocks of size 64 are requested and
|
||||
* application wishes to store memory in 6th block, it shall use
|
||||
* \@ref pstorage_block_identifier_get with based id and provide a block number of 5.
|
||||
* This way application is only expected to remember the base block identifier.
|
||||
*
|
||||
* @param[in] p_base_id Base block id received at the time of registration.
|
||||
* @param[in] block_num Block Number, with first block numbered zero.
|
||||
* @param[out] p_block_id Block identifier for the block number requested in case the API succeeds.
|
||||
*
|
||||
* @retval NRF_SUCCESS on success, else an error code indicating reason for failure.
|
||||
* @retval NRF_ERROR_INVALID_STATE is returned is API is called without module initialization.
|
||||
* @retval NRF_ERROR_NULL if NULL parameter has been passed.
|
||||
* @retval NRF_ERROR_INVALID_PARAM if invalid parameters are passed to the API.
|
||||
*/
|
||||
uint32_t pstorage_block_identifier_get(pstorage_handle_t * p_base_id,
|
||||
pstorage_size_t block_num,
|
||||
pstorage_handle_t * p_block_id);
|
||||
|
||||
|
||||
/**@brief Routine to persistently store data of length 'size' contained in 'p_src' address
|
||||
* in storage module at 'p_dest' address; Equivalent to Storage Write.
|
||||
*
|
||||
* @param[in] p_dest Destination address where data is to be stored persistently.
|
||||
* @param[in] p_src Source address containing data to be stored. API assumes this to be resident
|
||||
* memory and no intermediate copy of data is made by the API.
|
||||
* @param[in] size Size of data to be stored expressed in bytes. Should be word aligned.
|
||||
* @param[in] offset Offset in bytes to be applied when writing to the block.
|
||||
* For example, if within a block of 100 bytes, application wishes to
|
||||
* write 20 bytes at offset of 12, then this field should be set to 12.
|
||||
* Should be word aligned.
|
||||
*
|
||||
* @retval NRF_SUCCESS on success, else an error code indicating reason for failure.
|
||||
* @retval NRF_ERROR_INVALID_STATE is returned is API is called without module initialization.
|
||||
* @retval NRF_ERROR_NULL if NULL parameter has been passed.
|
||||
* @retval NRF_ERROR_INVALID_PARAM if invalid parameters are passed to the API.
|
||||
* @retval NRF_ERROR_INVALID_ADDR in case data address 'p_src' is not aligned.
|
||||
* @retval NRF_ERROR_NO_MEM in case request cannot be processed.
|
||||
*
|
||||
* @warning No copy of the data is made, and hence memory provided for data source to be written
|
||||
* to flash cannot be freed or reused by the application until this procedure
|
||||
* is complete. End of this procedure is notified to the application using the
|
||||
* notification callback registered by the application.
|
||||
*/
|
||||
uint32_t pstorage_store(pstorage_handle_t * p_dest,
|
||||
uint8_t * p_src,
|
||||
pstorage_size_t size,
|
||||
pstorage_size_t offset);
|
||||
|
||||
/**@brief Routine to update persistently stored data of length 'size' contained in 'p_src' address
|
||||
* in storage module at 'p_dest' address.
|
||||
*
|
||||
* @param[in] p_dest Destination address where data is to be updated.
|
||||
* @param[in] p_src Source address containing data to be stored. API assumes this to be resident
|
||||
* memory and no intermediate copy of data is made by the API.
|
||||
* @param[in] size Size of data to be stored expressed in bytes. Should be word aligned.
|
||||
* @param[in] offset Offset in bytes to be applied when writing to the block.
|
||||
* For example, if within a block of 100 bytes, application wishes to
|
||||
* write 20 bytes at offset of 12, then this field should be set to 12.
|
||||
* Should be word aligned.
|
||||
*
|
||||
* @retval NRF_SUCCESS on success, else an error code indicating reason for failure.
|
||||
* @retval NRF_ERROR_INVALID_STATE is returned is API is called without module initialization.
|
||||
* @retval NRF_ERROR_NULL if NULL parameter has been passed.
|
||||
* @retval NRF_ERROR_INVALID_PARAM if invalid parameters are passed to the API.
|
||||
* @retval NRF_ERROR_INVALID_ADDR in case data address 'p_src' is not aligned.
|
||||
* @retval NRF_ERROR_NO_MEM in case request cannot be processed.
|
||||
*
|
||||
* @warning No copy of the data is made, and hence memory provided for data source to be written
|
||||
* to flash cannot be freed or reused by the application until this procedure
|
||||
* is complete. End of this procedure is notified to the application using the
|
||||
* notification callback registered by the application.
|
||||
*/
|
||||
uint32_t pstorage_update(pstorage_handle_t * p_dest,
|
||||
uint8_t * p_src,
|
||||
pstorage_size_t size,
|
||||
pstorage_size_t offset);
|
||||
|
||||
/**@brief Routine to load persistently stored data of length 'size' from 'p_src' address
|
||||
* to 'p_dest' address; Equivalent to Storage Read.
|
||||
*
|
||||
* @param[in] p_dest Destination address where persistently stored data is to be loaded.
|
||||
* @param[in] p_src Source from where data is to be loaded from persistent memory.
|
||||
* @param[in] size Size of data to be loaded from persistent memory expressed in bytes.
|
||||
* Should be word aligned.
|
||||
* @param[in] offset Offset in bytes to be applied when loading from the block.
|
||||
* For example, if within a block of 100 bytes, application wishes to
|
||||
* load 20 bytes from offset of 12, then this field should be set to 12.
|
||||
* Should be word aligned.
|
||||
*
|
||||
* @retval NRF_SUCCESS on success, else an error code indicating reason for failure.
|
||||
* @retval NRF_ERROR_INVALID_STATE is returned is API is called without module initialization.
|
||||
* @retval NRF_ERROR_NULL if NULL parameter has been passed.
|
||||
* @retval NRF_ERROR_INVALID_PARAM if invalid parameters are passed to the API.
|
||||
* @retval NRF_ERROR_INVALID_ADDR in case data address 'p_dst' is not aligned.
|
||||
* @retval NRF_ERROR_NO_MEM in case request cannot be processed.
|
||||
*/
|
||||
uint32_t pstorage_load(uint8_t * p_dest,
|
||||
pstorage_handle_t * p_src,
|
||||
pstorage_size_t size,
|
||||
pstorage_size_t offset);
|
||||
|
||||
/**@brief Routine to clear data in persistent memory.
|
||||
*
|
||||
* @param[in] p_base_id Base block identifier in persistent memory that needs to cleared;
|
||||
* Equivalent to an Erase Operation.
|
||||
*
|
||||
* @param[in] size Size of data to be cleared from persistent memory expressed in bytes.
|
||||
* This parameter is to provision for clearing of certain blocks
|
||||
* of memory, or all memory blocks in a registered module. If the total size
|
||||
* of the application module is used (blocks * block size) in combination with
|
||||
* the identifier for the first block in the module, all blocks in the
|
||||
* module will be erased.
|
||||
*
|
||||
* @retval NRF_SUCCESS on success, else an error code indicating reason for failure.
|
||||
* @retval NRF_ERROR_INVALID_STATE is returned is API is called without module initialization.
|
||||
* @retval NRF_ERROR_NULL if NULL parameter has been passed.
|
||||
* @retval NRF_ERROR_INVALID_PARAM if invalid parameters are passed to the API.
|
||||
* @retval NRF_ERROR_INVALID_ADDR in case data address 'p_dst' is not aligned.
|
||||
* @retval NRF_ERROR_NO_MEM in case request cannot be processed.
|
||||
*
|
||||
* @note Clear operations may take time. This API however, does not block until the clear
|
||||
* procedure is complete. Application is notified of procedure completion using
|
||||
* notification callback registered by the application. 'result' parameter of the
|
||||
* callback suggests if the procedure was successful or not.
|
||||
*/
|
||||
uint32_t pstorage_clear(pstorage_handle_t * p_base_id, pstorage_size_t size);
|
||||
|
||||
/**
|
||||
* @brief API to get status of number of pending operations with the module.
|
||||
*
|
||||
* @param[out] p_count Number of storage operations pending with the module, if 0,
|
||||
* there are no outstanding requests.
|
||||
*
|
||||
* @retval NRF_SUCCESS on success, else an error code indicating reason for failure.
|
||||
* @retval NRF_ERROR_INVALID_STATE is returned is API is called without module initialization.
|
||||
* @retval NRF_ERROR_NULL if NULL parameter has been passed.
|
||||
*/
|
||||
uint32_t pstorage_access_status_get(uint32_t * p_count);
|
||||
|
||||
#ifdef PSTORAGE_RAW_MODE_ENABLE
|
||||
|
||||
/**@brief Function for registering with persistent storage interface.
|
||||
*
|
||||
* @param[in] p_module_param Module registration param.
|
||||
* @param[out] p_block_id Block identifier to identify persistent memory blocks in case
|
||||
* registration succeeds. Application is expected to use the block ids
|
||||
* for subsequent operations on requested persistent memory.
|
||||
* In case more than one memory blocks are requested, the identifier provided here is
|
||||
* the base identifier for the first block and to identify subsequent block,
|
||||
* application shall use \@ref pstorage_block_identifier_get with this base identifier
|
||||
* and block number. Therefore if 10 blocks of size 64 are requested and application
|
||||
* wishes to store memory in 6th block, it shall use
|
||||
* \@ref pstorage_block_identifier_get with based id and provide a block number of 5.
|
||||
* This way application is only expected to remember the base block identifier.
|
||||
*
|
||||
* @retval NRF_SUCCESS on success, else an error code indicating reason for failure.
|
||||
* @retval NRF_ERROR_INVALID_STATE is returned is API is called without module initialization.
|
||||
* @retval NRF_ERROR_NULL if NULL parameter has been passed.
|
||||
* @retval NRF_ERROR_INVALID_PARAM if invalid parameters are passed to the API.
|
||||
* @retval NRF_ERROR_NO_MEM in case no more registrations can be supported.
|
||||
*/
|
||||
uint32_t pstorage_raw_register(pstorage_module_param_t * p_module_param,
|
||||
pstorage_handle_t * p_block_id);
|
||||
|
||||
/**@brief Raw mode function for persistently storing data of length 'size' contained in 'p_src'
|
||||
* address in storage module at 'p_dest' address; Equivalent to Storage Write.
|
||||
*
|
||||
* @param[in] p_dest Destination address where data is to be stored persistently.
|
||||
* @param[in] p_src Source address containing data to be stored. API assumes this to be resident
|
||||
* memory and no intermediate copy of data is made by the API.
|
||||
* @param[in] size Size of data to be stored expressed in bytes. Should be word aligned.
|
||||
* @param[in] offset Offset in bytes to be applied when writing to the block.
|
||||
* For example, if within a block of 100 bytes, application wishes to
|
||||
* write 20 bytes at offset of 12, then this field should be set to 12.
|
||||
* Should be word aligned.
|
||||
*
|
||||
* @retval NRF_SUCCESS on success, else an error code indicating reason for failure.
|
||||
* @retval NRF_ERROR_INVALID_STATE is returned is API is called without module initialization.
|
||||
* @retval NRF_ERROR_NULL if NULL parameter has been passed.
|
||||
* @retval NRF_ERROR_INVALID_PARAM if invalid parameters are passed to the API.
|
||||
* @retval NRF_ERROR_INVALID_ADDR in case data address 'p_src' is not aligned.
|
||||
* @retval NRF_ERROR_NO_MEM in case request cannot be processed.
|
||||
*
|
||||
* @warning No copy of the data is made, and hence memory provided for data source to be written
|
||||
* to flash cannot be freed or reused by the application until this procedure
|
||||
* is complete. End of this procedure is notified to the application using the
|
||||
* notification callback registered by the application.
|
||||
*/
|
||||
uint32_t pstorage_raw_store(pstorage_handle_t * p_dest,
|
||||
uint8_t * p_src,
|
||||
pstorage_size_t size,
|
||||
pstorage_size_t offset);
|
||||
|
||||
/**@brief Function for clearing data in persistent memory in raw mode.
|
||||
*
|
||||
* @param[in] p_dest Base block identifier in persistent memory that needs to cleared;
|
||||
* Equivalent to an Erase Operation.
|
||||
* @param[in] size Size of data to be cleared from persistent memory expressed in bytes.
|
||||
* This is currently unused. And a clear would mean clearing all blocks,
|
||||
* however, this parameter is to provision for clearing of certain blocks
|
||||
* of memory only and not all if need be.
|
||||
*
|
||||
* @retval NRF_SUCCESS on success, else an error code indicating reason for failure.
|
||||
* @retval NRF_ERROR_INVALID_STATE is returned is API is called without module initialization.
|
||||
* @retval NRF_ERROR_NULL if NULL parameter has been passed.
|
||||
* @retval NRF_ERROR_INVALID_PARAM if invalid parameters are passed to the API.
|
||||
* @retval NRF_ERROR_NO_MEM in case request cannot be processed.
|
||||
*
|
||||
* @note Clear operations may take time. This API however, does not block until the clear
|
||||
* procedure is complete. Application is notified of procedure completion using
|
||||
* notification callback registered by the application. 'result' parameter of the
|
||||
* callback suggests if the procedure was successful or not.
|
||||
*/
|
||||
uint32_t pstorage_raw_clear(pstorage_handle_t * p_dest, pstorage_size_t size);
|
||||
|
||||
#endif // PSTORAGE_RAW_MODE_ENABLE
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* #ifdef __cplusplus */
|
||||
|
||||
|
||||
/**@} */
|
||||
/**@} */
|
||||
|
||||
#endif // PSTORAGE_H__
|
||||
|
Loading…
Reference in New Issue