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