Rob Kluin / nRF51822

Fork of nRF51822 by Nordic Semiconductor

Committer:
rgrover1
Date:
Fri Jun 19 15:55:34 2015 +0100
Revision:
343:6675661fa600
Parent:
112:737b08b3b995
Child:
345:dfde56236c36
Synchronized with git rev 6d1bf116
Author: Rohit Grover
fix #1: update license headers for all sources obtained from nordic-SDK using a new template obtained from Nordic.

Who changed what in which revision?

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