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_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 /* DIRTY WORKAROUND --> https://github.com/mbedmicro/mbed/issues/1045 00080 void GPIOTE_IRQHandler(void) 00081 { 00082 uint8_t i; 00083 uint32_t pins_changed; 00084 uint32_t pins_state = NRF_GPIO->IN; 00085 00086 // Clear event. 00087 NRF_GPIOTE->EVENTS_PORT = 0; 00088 00089 // Check all users. 00090 for (i = 0; i < m_user_count; i++) 00091 { 00092 gpiote_user_t * p_user = &mp_users[i]; 00093 00094 // Check if user is enabled. 00095 if (((1 << i) & m_enabled_users_mask) != 0) 00096 { 00097 uint32_t transition_pins; 00098 uint32_t event_low_to_high; 00099 uint32_t event_high_to_low; 00100 00101 // Find set of pins on which there has been a transition. 00102 transition_pins = (pins_state ^ ~p_user->sense_high_pins) & p_user->pins_mask; 00103 00104 // Toggle SENSE level for all pins that have changed state. 00105 sense_level_toggle(p_user, transition_pins); 00106 00107 // Second read after setting sense. 00108 // Check if any pins have changed while serving this interrupt. 00109 pins_changed = NRF_GPIO->IN ^ pins_state; 00110 if (pins_changed) 00111 { 00112 // Transition pins detected in late stage. 00113 uint32_t late_transition_pins; 00114 00115 pins_state |= pins_changed; 00116 00117 // Find set of pins on which there has been a transition. 00118 late_transition_pins = (pins_state ^ ~p_user->sense_high_pins) & p_user->pins_mask; 00119 00120 // Toggle SENSE level for all pins that have changed state in last phase. 00121 sense_level_toggle(p_user, late_transition_pins); 00122 00123 // Update pins that has changed state since the interrupt occurred. 00124 transition_pins |= late_transition_pins; 00125 } 00126 00127 // Call user event handler if an event has occurred. 00128 event_high_to_low = (~pins_state & p_user->pins_high_to_low_mask) & transition_pins; 00129 event_low_to_high = (pins_state & p_user->pins_low_to_high_mask) & transition_pins; 00130 00131 if ((event_low_to_high | event_high_to_low) != 0) 00132 { 00133 p_user->event_handler(event_low_to_high, event_high_to_low); 00134 } 00135 } 00136 } 00137 } 00138 */ 00139 00140 /**@brief Function for sense disabling for all pins for specified user. 00141 * 00142 * @param[in] user_id User id. 00143 */ 00144 static void pins_sense_disable(app_gpiote_user_id_t user_id) 00145 { 00146 uint32_t pin_no; 00147 00148 for (pin_no = 0; pin_no < 32; pin_no++) 00149 { 00150 if ((mp_users[user_id].pins_mask & (1 << pin_no)) != 0) 00151 { 00152 NRF_GPIO->PIN_CNF[pin_no] &= ~GPIO_PIN_CNF_SENSE_Msk; 00153 NRF_GPIO->PIN_CNF[pin_no] |= GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos; 00154 } 00155 } 00156 } 00157 00158 00159 uint32_t app_gpiote_init(uint8_t max_users, void * p_buffer) 00160 { 00161 if (p_buffer == NULL) 00162 { 00163 return NRF_ERROR_INVALID_PARAM; 00164 } 00165 00166 // Check that buffer is correctly aligned. 00167 if (!is_word_aligned(p_buffer)) 00168 { 00169 return NRF_ERROR_INVALID_PARAM; 00170 } 00171 00172 // Initialize file globals. 00173 mp_users = (gpiote_user_t *)p_buffer; 00174 m_user_array_size = max_users; 00175 m_user_count = 0; 00176 m_enabled_users_mask = 0; 00177 00178 memset(mp_users, 0, m_user_array_size * sizeof(gpiote_user_t)); 00179 00180 // Initialize GPIOTE interrupt (will not be enabled until app_gpiote_user_enable() is called). 00181 NRF_GPIOTE->INTENCLR = 0xFFFFFFFF; 00182 00183 NVIC_ClearPendingIRQ(GPIOTE_IRQn ); 00184 NVIC_SetPriority(GPIOTE_IRQn , APP_IRQ_PRIORITY_HIGH); 00185 NVIC_EnableIRQ(GPIOTE_IRQn ); 00186 00187 return NRF_SUCCESS; 00188 } 00189 00190 00191 uint32_t app_gpiote_user_register(app_gpiote_user_id_t * p_user_id, 00192 uint32_t pins_low_to_high_mask, 00193 uint32_t pins_high_to_low_mask, 00194 app_gpiote_event_handler_t event_handler) 00195 { 00196 // Check state and parameters. 00197 if (mp_users == NULL) 00198 { 00199 return NRF_ERROR_INVALID_STATE; 00200 } 00201 if (event_handler == NULL) 00202 { 00203 return NRF_ERROR_INVALID_PARAM; 00204 } 00205 if (m_user_count >= m_user_array_size) 00206 { 00207 return NRF_ERROR_NO_MEM; 00208 } 00209 00210 // Allocate new user. 00211 mp_users[m_user_count].pins_mask = pins_low_to_high_mask | pins_high_to_low_mask; 00212 mp_users[m_user_count].pins_low_to_high_mask = pins_low_to_high_mask; 00213 mp_users[m_user_count].pins_high_to_low_mask = pins_high_to_low_mask; 00214 mp_users[m_user_count].event_handler = event_handler; 00215 00216 *p_user_id = m_user_count++; 00217 00218 // Make sure SENSE is disabled for all pins. 00219 pins_sense_disable(*p_user_id); 00220 00221 return NRF_SUCCESS; 00222 } 00223 00224 00225 uint32_t app_gpiote_user_enable(app_gpiote_user_id_t user_id) 00226 { 00227 uint32_t pin_no; 00228 uint32_t pins_state; 00229 00230 // Check state and parameters. 00231 if (mp_users == NULL) 00232 { 00233 return NRF_ERROR_INVALID_STATE; 00234 } 00235 if (user_id >= m_user_count) 00236 { 00237 return NRF_ERROR_INVALID_PARAM; 00238 } 00239 00240 // Clear any pending event. 00241 NRF_GPIOTE->EVENTS_PORT = 0; 00242 pins_state = NRF_GPIO->IN; 00243 00244 // Enable user. 00245 if (m_enabled_users_mask == 0) 00246 { 00247 NRF_GPIOTE->INTENSET = GPIOTE_INTENSET_PORT_Msk; 00248 } 00249 m_enabled_users_mask |= (1 << user_id); 00250 00251 // Enable sensing for all pins for specified user. 00252 mp_users[user_id].sense_high_pins = 0; 00253 for (pin_no = 0; pin_no < 32; pin_no++) 00254 { 00255 uint32_t pin_mask = (1 << pin_no); 00256 00257 if ((mp_users[user_id].pins_mask & pin_mask) != 0) 00258 { 00259 uint32_t sense; 00260 00261 if ((pins_state & pin_mask) != 0) 00262 { 00263 sense = GPIO_PIN_CNF_SENSE_Low << GPIO_PIN_CNF_SENSE_Pos; 00264 } 00265 else 00266 { 00267 sense = GPIO_PIN_CNF_SENSE_High << GPIO_PIN_CNF_SENSE_Pos; 00268 mp_users[user_id].sense_high_pins |= pin_mask; 00269 } 00270 00271 NRF_GPIO->PIN_CNF[pin_no] &= ~GPIO_PIN_CNF_SENSE_Msk; 00272 NRF_GPIO->PIN_CNF[pin_no] |= sense; 00273 } 00274 } 00275 00276 return NRF_SUCCESS; 00277 } 00278 00279 00280 uint32_t app_gpiote_user_disable(app_gpiote_user_id_t user_id) 00281 { 00282 // Check state and parameters. 00283 if (mp_users == NULL) 00284 { 00285 return NRF_ERROR_INVALID_STATE; 00286 } 00287 if (user_id >= m_user_count) 00288 { 00289 return NRF_ERROR_INVALID_PARAM; 00290 } 00291 00292 // Disable sensing for all pins for specified user. 00293 pins_sense_disable(user_id); 00294 00295 // Disable user. 00296 m_enabled_users_mask &= ~(1UL << user_id); 00297 if (m_enabled_users_mask == 0) 00298 { 00299 NRF_GPIOTE->INTENCLR = GPIOTE_INTENSET_PORT_Msk; 00300 } 00301 00302 return NRF_SUCCESS; 00303 } 00304 00305 00306 uint32_t app_gpiote_pins_state_get(app_gpiote_user_id_t user_id, uint32_t * p_pins) 00307 { 00308 gpiote_user_t * p_user; 00309 00310 // Check state and parameters. 00311 if (mp_users == NULL) 00312 { 00313 return NRF_ERROR_INVALID_STATE; 00314 } 00315 if (user_id >= m_user_count) 00316 { 00317 return NRF_ERROR_INVALID_PARAM; 00318 } 00319 00320 // Get pins. 00321 p_user = &mp_users[user_id]; 00322 *p_pins = NRF_GPIO->IN & p_user->pins_mask; 00323 00324 return NRF_SUCCESS; 00325 } 00326 00327 #if defined(SVCALL_AS_NORMAL_FUNCTION) || defined(SER_CONNECTIVITY) 00328 uint32_t app_gpiote_input_event_handler_register(const uint8_t channel, 00329 const uint32_t pin, 00330 const uint32_t polarity, 00331 app_gpiote_input_event_handler_t event_handler) 00332 { 00333 (void)sense_level_toggle(NULL, pin); 00334 return NRF_ERROR_NOT_SUPPORTED; 00335 } 00336 00337 uint32_t app_gpiote_input_event_handler_unregister(const uint8_t channel) 00338 { 00339 return NRF_ERROR_NOT_SUPPORTED; 00340 } 00341 00342 uint32_t app_gpiote_end_irq_event_handler_register(app_gpiote_input_event_handler_t event_handler) 00343 { 00344 return NRF_ERROR_NOT_SUPPORTED; 00345 } 00346 00347 uint32_t app_gpiote_end_irq_event_handler_unregister(void) 00348 { 00349 return NRF_ERROR_NOT_SUPPORTED; 00350 } 00351 00352 uint32_t app_gpiote_enable_interrupts(void) 00353 { 00354 return NRF_ERROR_NOT_SUPPORTED; 00355 } 00356 00357 uint32_t app_gpiote_disable_interrupts(void) 00358 { 00359 return NRF_ERROR_NOT_SUPPORTED; 00360 } 00361 #endif // SVCALL_AS_NORMAL_FUNCTION || SER_CONNECTIVITY
Generated on Tue Jul 12 2022 16:21:02 by
