Nordic stack and drivers for the mbed BLE API

Dependents:   Sensen-classic-v8-IAQ_copy_4

Fork of nRF51822 by Nordic Semiconductor

Committer:
Vincent Coubard
Date:
Wed Sep 14 14:39:43 2016 +0100
Revision:
638:c90ae1400bf2
Sync with bdab10dc0f90748b6989c8b577771bb403ca6bd8 from ARMmbed/mbed-os.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Vincent Coubard 638:c90ae1400bf2 1 /*
Vincent Coubard 638:c90ae1400bf2 2 * Copyright (c) Nordic Semiconductor ASA
Vincent Coubard 638:c90ae1400bf2 3 * All rights reserved.
Vincent Coubard 638:c90ae1400bf2 4 *
Vincent Coubard 638:c90ae1400bf2 5 * Redistribution and use in source and binary forms, with or without modification,
Vincent Coubard 638:c90ae1400bf2 6 * are permitted provided that the following conditions are met:
Vincent Coubard 638:c90ae1400bf2 7 *
Vincent Coubard 638:c90ae1400bf2 8 * 1. Redistributions of source code must retain the above copyright notice, this
Vincent Coubard 638:c90ae1400bf2 9 * list of conditions and the following disclaimer.
Vincent Coubard 638:c90ae1400bf2 10 *
Vincent Coubard 638:c90ae1400bf2 11 * 2. Redistributions in binary form must reproduce the above copyright notice, this
Vincent Coubard 638:c90ae1400bf2 12 * list of conditions and the following disclaimer in the documentation and/or
Vincent Coubard 638:c90ae1400bf2 13 * other materials provided with the distribution.
Vincent Coubard 638:c90ae1400bf2 14 *
Vincent Coubard 638:c90ae1400bf2 15 * 3. Neither the name of Nordic Semiconductor ASA nor the names of other
Vincent Coubard 638:c90ae1400bf2 16 * contributors to this software may be used to endorse or promote products
Vincent Coubard 638:c90ae1400bf2 17 * derived from this software without specific prior written permission.
Vincent Coubard 638:c90ae1400bf2 18 *
Vincent Coubard 638:c90ae1400bf2 19 *
Vincent Coubard 638:c90ae1400bf2 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
Vincent Coubard 638:c90ae1400bf2 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
Vincent Coubard 638:c90ae1400bf2 22 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
Vincent Coubard 638:c90ae1400bf2 23 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
Vincent Coubard 638:c90ae1400bf2 24 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
Vincent Coubard 638:c90ae1400bf2 25 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
Vincent Coubard 638:c90ae1400bf2 26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
Vincent Coubard 638:c90ae1400bf2 27 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
Vincent Coubard 638:c90ae1400bf2 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
Vincent Coubard 638:c90ae1400bf2 29 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Vincent Coubard 638:c90ae1400bf2 30 *
Vincent Coubard 638:c90ae1400bf2 31 */
Vincent Coubard 638:c90ae1400bf2 32
Vincent Coubard 638:c90ae1400bf2 33 #include "app_scheduler.h"
Vincent Coubard 638:c90ae1400bf2 34 #include <stdlib.h>
Vincent Coubard 638:c90ae1400bf2 35 #include <stdint.h>
Vincent Coubard 638:c90ae1400bf2 36 #include <string.h>
Vincent Coubard 638:c90ae1400bf2 37 #include "nrf_soc.h"
Vincent Coubard 638:c90ae1400bf2 38 #include "nrf_assert.h"
Vincent Coubard 638:c90ae1400bf2 39 #include "app_util.h"
Vincent Coubard 638:c90ae1400bf2 40 #include "app_util_platform.h"
Vincent Coubard 638:c90ae1400bf2 41
Vincent Coubard 638:c90ae1400bf2 42 /**@brief Structure for holding a scheduled event header. */
Vincent Coubard 638:c90ae1400bf2 43 typedef struct
Vincent Coubard 638:c90ae1400bf2 44 {
Vincent Coubard 638:c90ae1400bf2 45 app_sched_event_handler_t handler; /**< Pointer to event handler to receive the event. */
Vincent Coubard 638:c90ae1400bf2 46 uint16_t event_data_size; /**< Size of event data. */
Vincent Coubard 638:c90ae1400bf2 47 } event_header_t;
Vincent Coubard 638:c90ae1400bf2 48
Vincent Coubard 638:c90ae1400bf2 49 STATIC_ASSERT(sizeof(event_header_t) <= APP_SCHED_EVENT_HEADER_SIZE);
Vincent Coubard 638:c90ae1400bf2 50
Vincent Coubard 638:c90ae1400bf2 51 static event_header_t * m_queue_event_headers; /**< Array for holding the queue event headers. */
Vincent Coubard 638:c90ae1400bf2 52 static uint8_t * m_queue_event_data; /**< Array for holding the queue event data. */
Vincent Coubard 638:c90ae1400bf2 53 static volatile uint8_t m_queue_start_index; /**< Index of queue entry at the start of the queue. */
Vincent Coubard 638:c90ae1400bf2 54 static volatile uint8_t m_queue_end_index; /**< Index of queue entry at the end of the queue. */
Vincent Coubard 638:c90ae1400bf2 55 static uint16_t m_queue_event_size; /**< Maximum event size in queue. */
Vincent Coubard 638:c90ae1400bf2 56 static uint16_t m_queue_size; /**< Number of queue entries. */
Vincent Coubard 638:c90ae1400bf2 57
Vincent Coubard 638:c90ae1400bf2 58 /**@brief Function for incrementing a queue index, and handle wrap-around.
Vincent Coubard 638:c90ae1400bf2 59 *
Vincent Coubard 638:c90ae1400bf2 60 * @param[in] index Old index.
Vincent Coubard 638:c90ae1400bf2 61 *
Vincent Coubard 638:c90ae1400bf2 62 * @return New (incremented) index.
Vincent Coubard 638:c90ae1400bf2 63 */
Vincent Coubard 638:c90ae1400bf2 64 static __INLINE uint8_t next_index(uint8_t index)
Vincent Coubard 638:c90ae1400bf2 65 {
Vincent Coubard 638:c90ae1400bf2 66 return (index < m_queue_size) ? (index + 1) : 0;
Vincent Coubard 638:c90ae1400bf2 67 }
Vincent Coubard 638:c90ae1400bf2 68
Vincent Coubard 638:c90ae1400bf2 69
Vincent Coubard 638:c90ae1400bf2 70 static __INLINE uint8_t app_sched_queue_full()
Vincent Coubard 638:c90ae1400bf2 71 {
Vincent Coubard 638:c90ae1400bf2 72 uint8_t tmp = m_queue_start_index;
Vincent Coubard 638:c90ae1400bf2 73 return next_index(m_queue_end_index) == tmp;
Vincent Coubard 638:c90ae1400bf2 74 }
Vincent Coubard 638:c90ae1400bf2 75
Vincent Coubard 638:c90ae1400bf2 76 /**@brief Macro for checking if a queue is full. */
Vincent Coubard 638:c90ae1400bf2 77 #define APP_SCHED_QUEUE_FULL() app_sched_queue_full()
Vincent Coubard 638:c90ae1400bf2 78
Vincent Coubard 638:c90ae1400bf2 79
Vincent Coubard 638:c90ae1400bf2 80 static __INLINE uint8_t app_sched_queue_empty()
Vincent Coubard 638:c90ae1400bf2 81 {
Vincent Coubard 638:c90ae1400bf2 82 uint8_t tmp = m_queue_start_index;
Vincent Coubard 638:c90ae1400bf2 83 return m_queue_end_index == tmp;
Vincent Coubard 638:c90ae1400bf2 84 }
Vincent Coubard 638:c90ae1400bf2 85
Vincent Coubard 638:c90ae1400bf2 86 /**@brief Macro for checking if a queue is empty. */
Vincent Coubard 638:c90ae1400bf2 87 #define APP_SCHED_QUEUE_EMPTY() app_sched_queue_empty()
Vincent Coubard 638:c90ae1400bf2 88
Vincent Coubard 638:c90ae1400bf2 89
Vincent Coubard 638:c90ae1400bf2 90 uint32_t app_sched_init(uint16_t event_size, uint16_t queue_size, void * p_event_buffer)
Vincent Coubard 638:c90ae1400bf2 91 {
Vincent Coubard 638:c90ae1400bf2 92 uint16_t data_start_index = (queue_size + 1) * sizeof(event_header_t);
Vincent Coubard 638:c90ae1400bf2 93
Vincent Coubard 638:c90ae1400bf2 94 // Check that buffer is correctly aligned
Vincent Coubard 638:c90ae1400bf2 95 if (!is_word_aligned(p_event_buffer))
Vincent Coubard 638:c90ae1400bf2 96 {
Vincent Coubard 638:c90ae1400bf2 97 return NRF_ERROR_INVALID_PARAM;
Vincent Coubard 638:c90ae1400bf2 98 }
Vincent Coubard 638:c90ae1400bf2 99
Vincent Coubard 638:c90ae1400bf2 100 // Initialize event scheduler
Vincent Coubard 638:c90ae1400bf2 101 m_queue_event_headers = p_event_buffer;
Vincent Coubard 638:c90ae1400bf2 102 m_queue_event_data = &((uint8_t *)p_event_buffer)[data_start_index];
Vincent Coubard 638:c90ae1400bf2 103 m_queue_end_index = 0;
Vincent Coubard 638:c90ae1400bf2 104 m_queue_start_index = 0;
Vincent Coubard 638:c90ae1400bf2 105 m_queue_event_size = event_size;
Vincent Coubard 638:c90ae1400bf2 106 m_queue_size = queue_size;
Vincent Coubard 638:c90ae1400bf2 107
Vincent Coubard 638:c90ae1400bf2 108 return NRF_SUCCESS;
Vincent Coubard 638:c90ae1400bf2 109 }
Vincent Coubard 638:c90ae1400bf2 110
Vincent Coubard 638:c90ae1400bf2 111
Vincent Coubard 638:c90ae1400bf2 112 uint32_t app_sched_event_put(void * p_event_data,
Vincent Coubard 638:c90ae1400bf2 113 uint16_t event_data_size,
Vincent Coubard 638:c90ae1400bf2 114 app_sched_event_handler_t handler)
Vincent Coubard 638:c90ae1400bf2 115 {
Vincent Coubard 638:c90ae1400bf2 116 uint32_t err_code;
Vincent Coubard 638:c90ae1400bf2 117
Vincent Coubard 638:c90ae1400bf2 118 if (event_data_size <= m_queue_event_size)
Vincent Coubard 638:c90ae1400bf2 119 {
Vincent Coubard 638:c90ae1400bf2 120 uint16_t event_index = 0xFFFF;
Vincent Coubard 638:c90ae1400bf2 121
Vincent Coubard 638:c90ae1400bf2 122 CRITICAL_REGION_ENTER();
Vincent Coubard 638:c90ae1400bf2 123
Vincent Coubard 638:c90ae1400bf2 124 if (!APP_SCHED_QUEUE_FULL())
Vincent Coubard 638:c90ae1400bf2 125 {
Vincent Coubard 638:c90ae1400bf2 126 event_index = m_queue_end_index;
Vincent Coubard 638:c90ae1400bf2 127 m_queue_end_index = next_index(m_queue_end_index);
Vincent Coubard 638:c90ae1400bf2 128 }
Vincent Coubard 638:c90ae1400bf2 129
Vincent Coubard 638:c90ae1400bf2 130 CRITICAL_REGION_EXIT();
Vincent Coubard 638:c90ae1400bf2 131
Vincent Coubard 638:c90ae1400bf2 132 if (event_index != 0xFFFF)
Vincent Coubard 638:c90ae1400bf2 133 {
Vincent Coubard 638:c90ae1400bf2 134 // NOTE: This can be done outside the critical region since the event consumer will
Vincent Coubard 638:c90ae1400bf2 135 // always be called from the main loop, and will thus never interrupt this code.
Vincent Coubard 638:c90ae1400bf2 136 m_queue_event_headers[event_index].handler = handler;
Vincent Coubard 638:c90ae1400bf2 137 if ((p_event_data != NULL) && (event_data_size > 0))
Vincent Coubard 638:c90ae1400bf2 138 {
Vincent Coubard 638:c90ae1400bf2 139 memcpy(&m_queue_event_data[event_index * m_queue_event_size],
Vincent Coubard 638:c90ae1400bf2 140 p_event_data,
Vincent Coubard 638:c90ae1400bf2 141 event_data_size);
Vincent Coubard 638:c90ae1400bf2 142 m_queue_event_headers[event_index].event_data_size = event_data_size;
Vincent Coubard 638:c90ae1400bf2 143 }
Vincent Coubard 638:c90ae1400bf2 144 else
Vincent Coubard 638:c90ae1400bf2 145 {
Vincent Coubard 638:c90ae1400bf2 146 m_queue_event_headers[event_index].event_data_size = 0;
Vincent Coubard 638:c90ae1400bf2 147 }
Vincent Coubard 638:c90ae1400bf2 148
Vincent Coubard 638:c90ae1400bf2 149 err_code = NRF_SUCCESS;
Vincent Coubard 638:c90ae1400bf2 150 }
Vincent Coubard 638:c90ae1400bf2 151 else
Vincent Coubard 638:c90ae1400bf2 152 {
Vincent Coubard 638:c90ae1400bf2 153 err_code = NRF_ERROR_NO_MEM;
Vincent Coubard 638:c90ae1400bf2 154 }
Vincent Coubard 638:c90ae1400bf2 155 }
Vincent Coubard 638:c90ae1400bf2 156 else
Vincent Coubard 638:c90ae1400bf2 157 {
Vincent Coubard 638:c90ae1400bf2 158 err_code = NRF_ERROR_INVALID_LENGTH;
Vincent Coubard 638:c90ae1400bf2 159 }
Vincent Coubard 638:c90ae1400bf2 160
Vincent Coubard 638:c90ae1400bf2 161 return err_code;
Vincent Coubard 638:c90ae1400bf2 162 }
Vincent Coubard 638:c90ae1400bf2 163
Vincent Coubard 638:c90ae1400bf2 164
Vincent Coubard 638:c90ae1400bf2 165 /**@brief Function for reading the next event from specified event queue.
Vincent Coubard 638:c90ae1400bf2 166 *
Vincent Coubard 638:c90ae1400bf2 167 * @param[out] pp_event_data Pointer to pointer to event data.
Vincent Coubard 638:c90ae1400bf2 168 * @param[out] p_event_data_size Pointer to size of event data.
Vincent Coubard 638:c90ae1400bf2 169 * @param[out] p_event_handler Pointer to event handler function pointer.
Vincent Coubard 638:c90ae1400bf2 170 *
Vincent Coubard 638:c90ae1400bf2 171 * @return NRF_SUCCESS if new event, NRF_ERROR_NOT_FOUND if event queue is empty.
Vincent Coubard 638:c90ae1400bf2 172 */
Vincent Coubard 638:c90ae1400bf2 173 static uint32_t app_sched_event_get(void ** pp_event_data,
Vincent Coubard 638:c90ae1400bf2 174 uint16_t * p_event_data_size,
Vincent Coubard 638:c90ae1400bf2 175 app_sched_event_handler_t * p_event_handler)
Vincent Coubard 638:c90ae1400bf2 176 {
Vincent Coubard 638:c90ae1400bf2 177 uint32_t err_code = NRF_ERROR_NOT_FOUND;
Vincent Coubard 638:c90ae1400bf2 178
Vincent Coubard 638:c90ae1400bf2 179 if (!APP_SCHED_QUEUE_EMPTY())
Vincent Coubard 638:c90ae1400bf2 180 {
Vincent Coubard 638:c90ae1400bf2 181 uint16_t event_index;
Vincent Coubard 638:c90ae1400bf2 182
Vincent Coubard 638:c90ae1400bf2 183 // NOTE: There is no need for a critical region here, as this function will only be called
Vincent Coubard 638:c90ae1400bf2 184 // from app_sched_execute() from inside the main loop, so it will never interrupt
Vincent Coubard 638:c90ae1400bf2 185 // app_sched_event_put(). Also, updating of (i.e. writing to) the start index will be
Vincent Coubard 638:c90ae1400bf2 186 // an atomic operation.
Vincent Coubard 638:c90ae1400bf2 187 event_index = m_queue_start_index;
Vincent Coubard 638:c90ae1400bf2 188 m_queue_start_index = next_index(m_queue_start_index);
Vincent Coubard 638:c90ae1400bf2 189
Vincent Coubard 638:c90ae1400bf2 190 *pp_event_data = &m_queue_event_data[event_index * m_queue_event_size];
Vincent Coubard 638:c90ae1400bf2 191 *p_event_data_size = m_queue_event_headers[event_index].event_data_size;
Vincent Coubard 638:c90ae1400bf2 192 *p_event_handler = m_queue_event_headers[event_index].handler;
Vincent Coubard 638:c90ae1400bf2 193
Vincent Coubard 638:c90ae1400bf2 194 err_code = NRF_SUCCESS;
Vincent Coubard 638:c90ae1400bf2 195 }
Vincent Coubard 638:c90ae1400bf2 196
Vincent Coubard 638:c90ae1400bf2 197 return err_code;
Vincent Coubard 638:c90ae1400bf2 198 }
Vincent Coubard 638:c90ae1400bf2 199
Vincent Coubard 638:c90ae1400bf2 200
Vincent Coubard 638:c90ae1400bf2 201 void app_sched_execute(void)
Vincent Coubard 638:c90ae1400bf2 202 {
Vincent Coubard 638:c90ae1400bf2 203 void * p_event_data;
Vincent Coubard 638:c90ae1400bf2 204 uint16_t event_data_size;
Vincent Coubard 638:c90ae1400bf2 205 app_sched_event_handler_t event_handler;
Vincent Coubard 638:c90ae1400bf2 206
Vincent Coubard 638:c90ae1400bf2 207 // Get next event (if any), and execute handler
Vincent Coubard 638:c90ae1400bf2 208 while ((app_sched_event_get(&p_event_data, &event_data_size, &event_handler) == NRF_SUCCESS))
Vincent Coubard 638:c90ae1400bf2 209 {
Vincent Coubard 638:c90ae1400bf2 210 event_handler(p_event_data, event_data_size);
Vincent Coubard 638:c90ae1400bf2 211 }
Vincent Coubard 638:c90ae1400bf2 212 }