Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of BLE_WallbotBLE_Challenge by
app_scheduler.c
00001 /* Copyright (c) 2012 Nordic Semiconductor. All Rights Reserved. 00002 * 00003 * The information contained herein is property of Nordic Semiconductor ASA. 00004 * Terms and conditions of usage are described in detail in NORDIC 00005 * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT. 00006 * 00007 * Licensees are granted free, non-transferable use of the information. NO 00008 * WARRANTY of ANY KIND is provided. This heading must NOT be removed from 00009 * the file. 00010 * 00011 */ 00012 00013 #include "app_scheduler.h " 00014 #include <stdlib.h> 00015 #include <stdint.h> 00016 #include <string.h> 00017 #include "nrf_soc.h" 00018 #include "nrf_assert.h" 00019 #include "app_util.h " 00020 #include "app_util_platform.h " 00021 00022 /**@brief Structure for holding a scheduled event header. */ 00023 typedef struct 00024 { 00025 app_sched_event_handler_t handler; /**< Pointer to event handler to receive the event. */ 00026 uint16_t event_data_size; /**< Size of event data. */ 00027 } event_header_t; 00028 00029 STATIC_ASSERT(sizeof(event_header_t) <= APP_SCHED_EVENT_HEADER_SIZE); 00030 00031 static event_header_t * m_queue_event_headers; /**< Array for holding the queue event headers. */ 00032 static uint8_t * m_queue_event_data; /**< Array for holding the queue event data. */ 00033 static volatile uint8_t m_queue_start_index; /**< Index of queue entry at the start of the queue. */ 00034 static volatile uint8_t m_queue_end_index; /**< Index of queue entry at the end of the queue. */ 00035 static uint16_t m_queue_event_size; /**< Maximum event size in queue. */ 00036 static uint16_t m_queue_size; /**< Number of queue entries. */ 00037 00038 /**@brief Macro for checking if a queue is full. */ 00039 #define APP_SCHED_QUEUE_FULL() (next_index(m_queue_end_index) == m_queue_start_index) 00040 00041 /**@brief Macro for checking if a queue is empty. */ 00042 #define APP_SCHED_QUEUE_EMPTY() (m_queue_end_index == m_queue_start_index) 00043 00044 00045 /**@brief Function for incrementing a queue index, and handle wrap-around. 00046 * 00047 * @param[in] index Old index. 00048 * 00049 * @return New (incremented) index. 00050 */ 00051 static __INLINE uint8_t next_index(uint8_t index) 00052 { 00053 return (index < m_queue_size) ? (index + 1) : 0; 00054 } 00055 00056 00057 uint32_t app_sched_init(uint16_t event_size, uint16_t queue_size, void * p_event_buffer) 00058 { 00059 uint16_t data_start_index = (queue_size + 1) * sizeof(event_header_t); 00060 00061 // Check that buffer is correctly aligned 00062 if (!is_word_aligned(p_event_buffer)) 00063 { 00064 return NRF_ERROR_INVALID_PARAM; 00065 } 00066 00067 // Initialize event scheduler 00068 m_queue_event_headers = p_event_buffer; 00069 m_queue_event_data = &((uint8_t *)p_event_buffer)[data_start_index]; 00070 m_queue_end_index = 0; 00071 m_queue_start_index = 0; 00072 m_queue_event_size = event_size; 00073 m_queue_size = queue_size; 00074 00075 return NRF_SUCCESS; 00076 } 00077 00078 00079 uint32_t app_sched_event_put(void * p_event_data, 00080 uint16_t event_data_size, 00081 app_sched_event_handler_t handler) 00082 { 00083 uint32_t err_code; 00084 00085 if (event_data_size <= m_queue_event_size) 00086 { 00087 uint16_t event_index = 0xFFFF; 00088 00089 CRITICAL_REGION_ENTER(); 00090 00091 if (!APP_SCHED_QUEUE_FULL()) 00092 { 00093 event_index = m_queue_end_index; 00094 m_queue_end_index = next_index(m_queue_end_index); 00095 } 00096 00097 CRITICAL_REGION_EXIT(); 00098 00099 if (event_index != 0xFFFF) 00100 { 00101 // NOTE: This can be done outside the critical region since the event consumer will 00102 // always be called from the main loop, and will thus never interrupt this code. 00103 m_queue_event_headers[event_index].handler = handler; 00104 if ((p_event_data != NULL) && (event_data_size > 0)) 00105 { 00106 memcpy(&m_queue_event_data[event_index * m_queue_event_size], 00107 p_event_data, 00108 event_data_size); 00109 m_queue_event_headers[event_index].event_data_size = event_data_size; 00110 } 00111 else 00112 { 00113 m_queue_event_headers[event_index].event_data_size = 0; 00114 } 00115 00116 err_code = NRF_SUCCESS; 00117 } 00118 else 00119 { 00120 err_code = NRF_ERROR_NO_MEM; 00121 } 00122 } 00123 else 00124 { 00125 err_code = NRF_ERROR_INVALID_LENGTH; 00126 } 00127 00128 return err_code; 00129 } 00130 00131 00132 /**@brief Function for reading the next event from specified event queue. 00133 * 00134 * @param[out] pp_event_data Pointer to pointer to event data. 00135 * @param[out] p_event_data_size Pointer to size of event data. 00136 * @param[out] p_event_handler Pointer to event handler function pointer. 00137 * 00138 * @return NRF_SUCCESS if new event, NRF_ERROR_NOT_FOUND if event queue is empty. 00139 */ 00140 static uint32_t app_sched_event_get(void ** pp_event_data, 00141 uint16_t * p_event_data_size, 00142 app_sched_event_handler_t * p_event_handler) 00143 { 00144 uint32_t err_code = NRF_ERROR_NOT_FOUND; 00145 00146 if (!APP_SCHED_QUEUE_EMPTY()) 00147 { 00148 uint16_t event_index; 00149 00150 // NOTE: There is no need for a critical region here, as this function will only be called 00151 // from app_sched_execute() from inside the main loop, so it will never interrupt 00152 // app_sched_event_put(). Also, updating of (i.e. writing to) the start index will be 00153 // an atomic operation. 00154 event_index = m_queue_start_index; 00155 m_queue_start_index = next_index(m_queue_start_index); 00156 00157 *pp_event_data = &m_queue_event_data[event_index * m_queue_event_size]; 00158 *p_event_data_size = m_queue_event_headers[event_index].event_data_size; 00159 *p_event_handler = m_queue_event_headers[event_index].handler; 00160 00161 err_code = NRF_SUCCESS; 00162 } 00163 00164 return err_code; 00165 } 00166 00167 00168 void app_sched_execute(void) 00169 { 00170 void * p_event_data; 00171 uint16_t event_data_size; 00172 app_sched_event_handler_t event_handler; 00173 00174 // Get next event (if any), and execute handler 00175 while ((app_sched_event_get(&p_event_data, &event_data_size, &event_handler) == NRF_SUCCESS)) 00176 { 00177 event_handler(p_event_data, event_data_size); 00178 } 00179 }
Generated on Tue Jul 12 2022 13:52:30 by
