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 nRF51822 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 Function for incrementing a queue index, and handle wrap-around. 00039 * 00040 * @param[in] index Old index. 00041 * 00042 * @return New (incremented) index. 00043 */ 00044 static __INLINE uint8_t next_index(uint8_t index) 00045 { 00046 return (index < m_queue_size) ? (index + 1) : 0; 00047 } 00048 00049 00050 static __INLINE uint8_t app_sched_queue_full() 00051 { 00052 uint8_t tmp = m_queue_start_index; 00053 return next_index(m_queue_end_index) == tmp; 00054 } 00055 00056 /**@brief Macro for checking if a queue is full. */ 00057 #define APP_SCHED_QUEUE_FULL() app_sched_queue_full() 00058 00059 00060 static __INLINE uint8_t app_sched_queue_empty() 00061 { 00062 uint8_t tmp = m_queue_start_index; 00063 return m_queue_end_index == tmp; 00064 } 00065 00066 /**@brief Macro for checking if a queue is empty. */ 00067 #define APP_SCHED_QUEUE_EMPTY() app_sched_queue_empty() 00068 00069 00070 uint32_t app_sched_init(uint16_t event_size, uint16_t queue_size, void * p_event_buffer) 00071 { 00072 uint16_t data_start_index = (queue_size + 1) * sizeof(event_header_t); 00073 00074 // Check that buffer is correctly aligned 00075 if (!is_word_aligned(p_event_buffer)) 00076 { 00077 return NRF_ERROR_INVALID_PARAM; 00078 } 00079 00080 // Initialize event scheduler 00081 m_queue_event_headers = p_event_buffer; 00082 m_queue_event_data = &((uint8_t *)p_event_buffer)[data_start_index]; 00083 m_queue_end_index = 0; 00084 m_queue_start_index = 0; 00085 m_queue_event_size = event_size; 00086 m_queue_size = queue_size; 00087 00088 return NRF_SUCCESS; 00089 } 00090 00091 00092 uint32_t app_sched_event_put(void * p_event_data, 00093 uint16_t event_data_size, 00094 app_sched_event_handler_t handler) 00095 { 00096 uint32_t err_code; 00097 00098 if (event_data_size <= m_queue_event_size) 00099 { 00100 uint16_t event_index = 0xFFFF; 00101 00102 CRITICAL_REGION_ENTER(); 00103 00104 if (!APP_SCHED_QUEUE_FULL()) 00105 { 00106 event_index = m_queue_end_index; 00107 m_queue_end_index = next_index(m_queue_end_index); 00108 } 00109 00110 CRITICAL_REGION_EXIT(); 00111 00112 if (event_index != 0xFFFF) 00113 { 00114 // NOTE: This can be done outside the critical region since the event consumer will 00115 // always be called from the main loop, and will thus never interrupt this code. 00116 m_queue_event_headers[event_index].handler = handler; 00117 if ((p_event_data != NULL) && (event_data_size > 0)) 00118 { 00119 memcpy(&m_queue_event_data[event_index * m_queue_event_size], 00120 p_event_data, 00121 event_data_size); 00122 m_queue_event_headers[event_index].event_data_size = event_data_size; 00123 } 00124 else 00125 { 00126 m_queue_event_headers[event_index].event_data_size = 0; 00127 } 00128 00129 err_code = NRF_SUCCESS; 00130 } 00131 else 00132 { 00133 err_code = NRF_ERROR_NO_MEM; 00134 } 00135 } 00136 else 00137 { 00138 err_code = NRF_ERROR_INVALID_LENGTH; 00139 } 00140 00141 return err_code; 00142 } 00143 00144 00145 /**@brief Function for reading the next event from specified event queue. 00146 * 00147 * @param[out] pp_event_data Pointer to pointer to event data. 00148 * @param[out] p_event_data_size Pointer to size of event data. 00149 * @param[out] p_event_handler Pointer to event handler function pointer. 00150 * 00151 * @return NRF_SUCCESS if new event, NRF_ERROR_NOT_FOUND if event queue is empty. 00152 */ 00153 static uint32_t app_sched_event_get(void ** pp_event_data, 00154 uint16_t * p_event_data_size, 00155 app_sched_event_handler_t * p_event_handler) 00156 { 00157 uint32_t err_code = NRF_ERROR_NOT_FOUND; 00158 00159 if (!APP_SCHED_QUEUE_EMPTY()) 00160 { 00161 uint16_t event_index; 00162 00163 // NOTE: There is no need for a critical region here, as this function will only be called 00164 // from app_sched_execute() from inside the main loop, so it will never interrupt 00165 // app_sched_event_put(). Also, updating of (i.e. writing to) the start index will be 00166 // an atomic operation. 00167 event_index = m_queue_start_index; 00168 m_queue_start_index = next_index(m_queue_start_index); 00169 00170 *pp_event_data = &m_queue_event_data[event_index * m_queue_event_size]; 00171 *p_event_data_size = m_queue_event_headers[event_index].event_data_size; 00172 *p_event_handler = m_queue_event_headers[event_index].handler; 00173 00174 err_code = NRF_SUCCESS; 00175 } 00176 00177 return err_code; 00178 } 00179 00180 00181 void app_sched_execute(void) 00182 { 00183 void * p_event_data; 00184 uint16_t event_data_size; 00185 app_sched_event_handler_t event_handler; 00186 00187 // Get next event (if any), and execute handler 00188 while ((app_sched_event_get(&p_event_data, &event_data_size, &event_handler) == NRF_SUCCESS)) 00189 { 00190 event_handler(p_event_data, event_data_size); 00191 } 00192 }
Generated on Tue Jul 12 2022 19:22:46 by
1.7.2
