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_gpiote.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 #if NEED_APP_GPIOTE /* disabled by default */ 00014 00015 #include "app_gpiote.h " 00016 #include <stdlib.h> 00017 #include <string.h> 00018 #include "app_util.h " 00019 #include "app_util_platform.h " 00020 #include "nrf_error.h" 00021 #include "nrf_gpio.h" 00022 00023 00024 /**@brief GPIOTE user type. */ 00025 typedef struct 00026 { 00027 uint32_t pins_mask; /**< Mask defining which pins user wants to monitor. */ 00028 uint32_t pins_low_to_high_mask; /**< Mask defining which pins will generate events to this user when toggling low->high. */ 00029 uint32_t pins_high_to_low_mask; /**< Mask defining which pins will generate events to this user when toggling high->low. */ 00030 uint32_t sense_high_pins; /**< Mask defining which pins are configured to generate GPIOTE interrupt on transition to high level. */ 00031 app_gpiote_event_handler_t event_handler; /**< Pointer to function to be executed when an event occurs. */ 00032 } gpiote_user_t; 00033 00034 STATIC_ASSERT(sizeof(gpiote_user_t) <= GPIOTE_USER_NODE_SIZE); 00035 STATIC_ASSERT(sizeof(gpiote_user_t) % 4 == 0); 00036 00037 static uint32_t m_enabled_users_mask; /**< Mask for tracking which users are enabled. */ 00038 static uint8_t m_user_array_size; /**< Size of user array. */ 00039 static uint8_t m_user_count; /**< Number of registered users. */ 00040 static gpiote_user_t * mp_users = NULL; /**< Array of GPIOTE users. */ 00041 00042 00043 /**@brief Function for toggling sense level for specified pins. 00044 * 00045 * @param[in] p_user Pointer to user structure. 00046 * @param[in] pins Bitmask specifying for which pins the sense level is to be toggled. 00047 */ 00048 static void sense_level_toggle(gpiote_user_t * p_user, uint32_t pins) 00049 { 00050 uint32_t pin_no; 00051 00052 for (pin_no = 0; pin_no < NO_OF_PINS; pin_no++) 00053 { 00054 uint32_t pin_mask = (1 << pin_no); 00055 00056 if ((pins & pin_mask) != 0) 00057 { 00058 uint32_t sense; 00059 00060 // Invert sensing. 00061 if ((p_user->sense_high_pins & pin_mask) == 0) 00062 { 00063 sense = GPIO_PIN_CNF_SENSE_High << GPIO_PIN_CNF_SENSE_Pos; 00064 p_user->sense_high_pins |= pin_mask; 00065 } 00066 else 00067 { 00068 sense = GPIO_PIN_CNF_SENSE_Low << GPIO_PIN_CNF_SENSE_Pos; 00069 p_user->sense_high_pins &= ~pin_mask; 00070 } 00071 00072 NRF_GPIO->PIN_CNF[pin_no] &= ~GPIO_PIN_CNF_SENSE_Msk; 00073 NRF_GPIO->PIN_CNF[pin_no] |= sense; 00074 } 00075 } 00076 } 00077 00078 00079 /**@brief Function for handling the GPIOTE interrupt. 00080 */ 00081 void GPIOTE_IRQHandler(void) 00082 { 00083 uint8_t i; 00084 uint32_t pins_changed; 00085 uint32_t pins_state = NRF_GPIO->IN; 00086 00087 // Clear event. 00088 NRF_GPIOTE->EVENTS_PORT = 0; 00089 00090 // Check all users. 00091 for (i = 0; i < m_user_count; i++) 00092 { 00093 gpiote_user_t * p_user = &mp_users[i]; 00094 00095 // Check if user is enabled. 00096 if (((1 << i) & m_enabled_users_mask) != 0) 00097 { 00098 uint32_t transition_pins; 00099 uint32_t event_low_to_high; 00100 uint32_t event_high_to_low; 00101 00102 // Find set of pins on which there has been a transition. 00103 transition_pins = (pins_state ^ ~p_user->sense_high_pins) & p_user->pins_mask; 00104 00105 // Toggle SENSE level for all pins that have changed state. 00106 sense_level_toggle(p_user, transition_pins); 00107 00108 // Second read after setting sense. 00109 // Check if any pins have changed while serving this interrupt. 00110 pins_changed = NRF_GPIO->IN ^ pins_state; 00111 if (pins_changed) 00112 { 00113 // Transition pins detected in late stage. 00114 uint32_t late_transition_pins; 00115 00116 pins_state |= pins_changed; 00117 00118 // Find set of pins on which there has been a transition. 00119 late_transition_pins = (pins_state ^ ~p_user->sense_high_pins) & p_user->pins_mask; 00120 00121 // Toggle SENSE level for all pins that have changed state in last phase. 00122 sense_level_toggle(p_user, late_transition_pins); 00123 00124 // Update pins that has changed state since the interrupt occurred. 00125 transition_pins |= late_transition_pins; 00126 } 00127 00128 // Call user event handler if an event has occurred. 00129 event_high_to_low = (~pins_state & p_user->pins_high_to_low_mask) & transition_pins; 00130 event_low_to_high = (pins_state & p_user->pins_low_to_high_mask) & transition_pins; 00131 00132 if ((event_low_to_high | event_high_to_low) != 0) 00133 { 00134 p_user->event_handler(event_low_to_high, event_high_to_low); 00135 } 00136 } 00137 } 00138 } 00139 00140 00141 /**@brief Function for sense disabling for all pins for specified user. 00142 * 00143 * @param[in] user_id User id. 00144 */ 00145 static void pins_sense_disable(app_gpiote_user_id_t user_id) 00146 { 00147 uint32_t pin_no; 00148 00149 for (pin_no = 0; pin_no < 32; pin_no++) 00150 { 00151 if ((mp_users[user_id].pins_mask & (1 << pin_no)) != 0) 00152 { 00153 NRF_GPIO->PIN_CNF[pin_no] &= ~GPIO_PIN_CNF_SENSE_Msk; 00154 NRF_GPIO->PIN_CNF[pin_no] |= GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos; 00155 } 00156 } 00157 } 00158 00159 00160 uint32_t app_gpiote_init(uint8_t max_users, void * p_buffer) 00161 { 00162 if (p_buffer == NULL) 00163 { 00164 return NRF_ERROR_INVALID_PARAM; 00165 } 00166 00167 // Check that buffer is correctly aligned. 00168 if (!is_word_aligned(p_buffer)) 00169 { 00170 return NRF_ERROR_INVALID_PARAM; 00171 } 00172 00173 // Initialize file globals. 00174 mp_users = (gpiote_user_t *)p_buffer; 00175 m_user_array_size = max_users; 00176 m_user_count = 0; 00177 m_enabled_users_mask = 0; 00178 00179 memset(mp_users, 0, m_user_array_size * sizeof(gpiote_user_t)); 00180 00181 // Initialize GPIOTE interrupt (will not be enabled until app_gpiote_user_enable() is called). 00182 NRF_GPIOTE->INTENCLR = 0xFFFFFFFF; 00183 00184 NVIC_ClearPendingIRQ(GPIOTE_IRQn); 00185 NVIC_SetPriority(GPIOTE_IRQn, APP_IRQ_PRIORITY_HIGH); 00186 NVIC_EnableIRQ(GPIOTE_IRQn); 00187 00188 return NRF_SUCCESS; 00189 } 00190 00191 00192 uint32_t app_gpiote_user_register(app_gpiote_user_id_t * p_user_id, 00193 uint32_t pins_low_to_high_mask, 00194 uint32_t pins_high_to_low_mask, 00195 app_gpiote_event_handler_t event_handler) 00196 { 00197 // Check state and parameters. 00198 if (mp_users == NULL) 00199 { 00200 return NRF_ERROR_INVALID_STATE; 00201 } 00202 if (event_handler == NULL) 00203 { 00204 return NRF_ERROR_INVALID_PARAM; 00205 } 00206 if (m_user_count >= m_user_array_size) 00207 { 00208 return NRF_ERROR_NO_MEM; 00209 } 00210 00211 // Allocate new user. 00212 mp_users[m_user_count].pins_mask = pins_low_to_high_mask | pins_high_to_low_mask; 00213 mp_users[m_user_count].pins_low_to_high_mask = pins_low_to_high_mask; 00214 mp_users[m_user_count].pins_high_to_low_mask = pins_high_to_low_mask; 00215 mp_users[m_user_count].event_handler = event_handler; 00216 00217 *p_user_id = m_user_count++; 00218 00219 // Make sure SENSE is disabled for all pins. 00220 pins_sense_disable(*p_user_id); 00221 00222 return NRF_SUCCESS; 00223 } 00224 00225 00226 uint32_t app_gpiote_user_enable(app_gpiote_user_id_t user_id) 00227 { 00228 uint32_t pin_no; 00229 uint32_t pins_state; 00230 00231 // Check state and parameters. 00232 if (mp_users == NULL) 00233 { 00234 return NRF_ERROR_INVALID_STATE; 00235 } 00236 if (user_id >= m_user_count) 00237 { 00238 return NRF_ERROR_INVALID_PARAM; 00239 } 00240 00241 // Clear any pending event. 00242 NRF_GPIOTE->EVENTS_PORT = 0; 00243 pins_state = NRF_GPIO->IN; 00244 00245 // Enable user. 00246 if (m_enabled_users_mask == 0) 00247 { 00248 NRF_GPIOTE->INTENSET = GPIOTE_INTENSET_PORT_Msk; 00249 } 00250 m_enabled_users_mask |= (1 << user_id); 00251 00252 // Enable sensing for all pins for specified user. 00253 mp_users[user_id].sense_high_pins = 0; 00254 for (pin_no = 0; pin_no < 32; pin_no++) 00255 { 00256 uint32_t pin_mask = (1 << pin_no); 00257 00258 if ((mp_users[user_id].pins_mask & pin_mask) != 0) 00259 { 00260 uint32_t sense; 00261 00262 if ((pins_state & pin_mask) != 0) 00263 { 00264 sense = GPIO_PIN_CNF_SENSE_Low << GPIO_PIN_CNF_SENSE_Pos; 00265 } 00266 else 00267 { 00268 sense = GPIO_PIN_CNF_SENSE_High << GPIO_PIN_CNF_SENSE_Pos; 00269 mp_users[user_id].sense_high_pins |= pin_mask; 00270 } 00271 00272 NRF_GPIO->PIN_CNF[pin_no] &= ~GPIO_PIN_CNF_SENSE_Msk; 00273 NRF_GPIO->PIN_CNF[pin_no] |= sense; 00274 } 00275 } 00276 00277 return NRF_SUCCESS; 00278 } 00279 00280 00281 uint32_t app_gpiote_user_disable(app_gpiote_user_id_t user_id) 00282 { 00283 // Check state and parameters. 00284 if (mp_users == NULL) 00285 { 00286 return NRF_ERROR_INVALID_STATE; 00287 } 00288 if (user_id >= m_user_count) 00289 { 00290 return NRF_ERROR_INVALID_PARAM; 00291 } 00292 00293 // Disable sensing for all pins for specified user. 00294 pins_sense_disable(user_id); 00295 00296 // Disable user. 00297 m_enabled_users_mask &= ~(1UL << user_id); 00298 if (m_enabled_users_mask == 0) 00299 { 00300 NRF_GPIOTE->INTENCLR = GPIOTE_INTENSET_PORT_Msk; 00301 } 00302 00303 return NRF_SUCCESS; 00304 } 00305 00306 00307 uint32_t app_gpiote_pins_state_get(app_gpiote_user_id_t user_id, uint32_t * p_pins) 00308 { 00309 gpiote_user_t * p_user; 00310 00311 // Check state and parameters. 00312 if (mp_users == NULL) 00313 { 00314 return NRF_ERROR_INVALID_STATE; 00315 } 00316 if (user_id >= m_user_count) 00317 { 00318 return NRF_ERROR_INVALID_PARAM; 00319 } 00320 00321 // Get pins. 00322 p_user = &mp_users[user_id]; 00323 *p_pins = NRF_GPIO->IN & p_user->pins_mask; 00324 00325 return NRF_SUCCESS; 00326 } 00327 00328 #if defined(SVCALL_AS_NORMAL_FUNCTION) || defined(SER_CONNECTIVITY) 00329 uint32_t app_gpiote_input_event_handler_register(const uint8_t channel, 00330 const uint32_t pin, 00331 const uint32_t polarity, 00332 app_gpiote_input_event_handler_t event_handler) 00333 { 00334 (void)sense_level_toggle(NULL, pin); 00335 return NRF_ERROR_NOT_SUPPORTED; 00336 } 00337 00338 uint32_t app_gpiote_input_event_handler_unregister(const uint8_t channel) 00339 { 00340 return NRF_ERROR_NOT_SUPPORTED; 00341 } 00342 00343 uint32_t app_gpiote_end_irq_event_handler_register(app_gpiote_input_event_handler_t event_handler) 00344 { 00345 return NRF_ERROR_NOT_SUPPORTED; 00346 } 00347 00348 uint32_t app_gpiote_end_irq_event_handler_unregister(void) 00349 { 00350 return NRF_ERROR_NOT_SUPPORTED; 00351 } 00352 00353 uint32_t app_gpiote_enable_interrupts(void) 00354 { 00355 return NRF_ERROR_NOT_SUPPORTED; 00356 } 00357 00358 uint32_t app_gpiote_disable_interrupts(void) 00359 { 00360 return NRF_ERROR_NOT_SUPPORTED; 00361 } 00362 #endif // SVCALL_AS_NORMAL_FUNCTION || SER_CONNECTIVITY 00363 00364 #endif // #if NEED_APP_GPIOTE
Generated on Tue Jul 12 2022 13:52:30 by
