GGTA team / nRF51822

Fork of nRF51822 by Nordic Semiconductor

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers app_gpiote.c Source File

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