I don't know

Dependents:   MX106-finaltest

Fork of mbed-src by mbed official

Committer:
mbed_official
Date:
Mon Jul 20 09:00:09 2015 +0100
Revision:
593:78ee8643776a
Parent:
548:1abac31e188e
Child:
627:4fa1328d9c60
Synchronized with git revision a68b724d07788e6389ea4d52c622aad767953758

Full URL: https://github.com/mbedmicro/mbed/commit/a68b724d07788e6389ea4d52c622aad767953758/

[Silicon Labs] Bring EFM32 HAL up to date

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mbed_official 525:c320967f86b9 1 /* mbed Microcontroller Library
mbed_official 525:c320967f86b9 2 * Copyright (c) 2006-2013 ARM Limited
mbed_official 525:c320967f86b9 3 *
mbed_official 525:c320967f86b9 4 * Licensed under the Apache License, Version 2.0 (the "License");
mbed_official 525:c320967f86b9 5 * you may not use this file except in compliance with the License.
mbed_official 525:c320967f86b9 6 * You may obtain a copy of the License at
mbed_official 525:c320967f86b9 7 *
mbed_official 525:c320967f86b9 8 * http://www.apache.org/licenses/LICENSE-2.0
mbed_official 525:c320967f86b9 9 *
mbed_official 525:c320967f86b9 10 * Unless required by applicable law or agreed to in writing, software
mbed_official 525:c320967f86b9 11 * distributed under the License is distributed on an "AS IS" BASIS,
mbed_official 525:c320967f86b9 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
mbed_official 525:c320967f86b9 13 * See the License for the specific language governing permissions and
mbed_official 525:c320967f86b9 14 * limitations under the License.
mbed_official 525:c320967f86b9 15 */
mbed_official 525:c320967f86b9 16
mbed_official 525:c320967f86b9 17 #include "device.h"
mbed_official 525:c320967f86b9 18 #if DEVICE_INTERRUPTIN
mbed_official 525:c320967f86b9 19
mbed_official 525:c320967f86b9 20 #include "gpio_irq_api.h"
mbed_official 525:c320967f86b9 21 #include "mbed_assert.h"
mbed_official 525:c320967f86b9 22 #include "pinmap.h"
mbed_official 525:c320967f86b9 23
mbed_official 525:c320967f86b9 24 #include "em_gpio.h"
mbed_official 525:c320967f86b9 25 #include "em_int.h"
mbed_official 525:c320967f86b9 26 #include "em_cmu.h"
mbed_official 525:c320967f86b9 27 #include "sleep_api.h"
mbed_official 526:7c4bdfe6a168 28 #include "sleepmodes.h"
mbed_official 525:c320967f86b9 29
mbed_official 525:c320967f86b9 30 #define NUM_GPIO_CHANNELS (16)
mbed_official 525:c320967f86b9 31 #define GPIO_LEAST_ACTIVE_SLEEPMODE EM3
mbed_official 525:c320967f86b9 32
mbed_official 525:c320967f86b9 33 /* Macro return index of the LSB flag which is set. */
mbed_official 525:c320967f86b9 34 #if ((__CORTEX_M == 3) || (__CORTEX_M == 4))
mbed_official 525:c320967f86b9 35 #define GPIOINT_MASK2IDX(mask) (__CLZ(__RBIT(mask)))
mbed_official 525:c320967f86b9 36 #elif __CORTEX_M == 0
mbed_official 525:c320967f86b9 37 #define GPIOINT_MASK2IDX(mask) (countTrailingZeros(mask))
mbed_official 525:c320967f86b9 38 __STATIC_INLINE uint32_t countTrailingZeros(uint32_t mask)
mbed_official 525:c320967f86b9 39 {
mbed_official 548:1abac31e188e 40 uint32_t zeros;
mbed_official 548:1abac31e188e 41 for(zeros=0; (zeros<32) && (0 == (mask&0x1)); zeros++, mask>>=1);
mbed_official 548:1abac31e188e 42 return zeros;
mbed_official 525:c320967f86b9 43 }
mbed_official 525:c320967f86b9 44 #else
mbed_official 525:c320967f86b9 45 #error Unsupported architecture.
mbed_official 525:c320967f86b9 46 #endif
mbed_official 525:c320967f86b9 47
mbed_official 525:c320967f86b9 48 static uint32_t channel_ids[NUM_GPIO_CHANNELS] = { 0 }; // Relates pin number with interrupt action id
mbed_official 593:78ee8643776a 49 static uint8_t channel_ports[NUM_GPIO_CHANNELS/2] = { 0 }; // Storing 2 ports in each uint8
mbed_official 525:c320967f86b9 50 static gpio_irq_handler irq_handler;
mbed_official 525:c320967f86b9 51 static void GPIOINT_IRQDispatcher(uint32_t iflags);
mbed_official 525:c320967f86b9 52
mbed_official 525:c320967f86b9 53 static void handle_interrupt_in(uint8_t pin)
mbed_official 525:c320967f86b9 54 {
mbed_official 525:c320967f86b9 55 // Return if pin not linked with an interrupt function
mbed_official 525:c320967f86b9 56 if (channel_ids[pin] == 0) {
mbed_official 525:c320967f86b9 57 return;
mbed_official 525:c320967f86b9 58 }
mbed_official 525:c320967f86b9 59
mbed_official 593:78ee8643776a 60 //we are storing two ports in each uint8, so we must aquire the one we want.
mbed_official 593:78ee8643776a 61 // If pin is odd, the port is encoded in the 4 most significant bits. If pin is even, the port is encoded in the 4 least significant bits
mbed_official 593:78ee8643776a 62 uint8_t isRise = GPIO_PinInGet((pin & 0x1) ? channel_ports[(pin>>1) & 0x7] >> 4 & 0xF : channel_ports[(pin>>1) & 0x7] & 0xF, pin);
mbed_official 525:c320967f86b9 63
mbed_official 525:c320967f86b9 64 // Get trigger event
mbed_official 525:c320967f86b9 65 gpio_irq_event event = IRQ_NONE;
mbed_official 525:c320967f86b9 66 if ((GPIO->EXTIFALL & (1 << pin)) && !isRise) {
mbed_official 525:c320967f86b9 67 event = IRQ_FALL;
mbed_official 525:c320967f86b9 68 } else if ((GPIO->EXTIRISE & (1 << pin)) && isRise) {
mbed_official 525:c320967f86b9 69 event = IRQ_RISE;
mbed_official 525:c320967f86b9 70 }
mbed_official 525:c320967f86b9 71 GPIO_IntClear(pin);
mbed_official 525:c320967f86b9 72 irq_handler(channel_ids[pin], event);
mbed_official 525:c320967f86b9 73 }
mbed_official 525:c320967f86b9 74
mbed_official 525:c320967f86b9 75 void gpio_irq_preinit(gpio_irq_t *obj, PinName pin)
mbed_official 525:c320967f86b9 76 {
mbed_official 525:c320967f86b9 77 MBED_ASSERT(pin != NC);
mbed_official 525:c320967f86b9 78
mbed_official 525:c320967f86b9 79 /* Pin and port index encoded in one uint32.
mbed_official 525:c320967f86b9 80 * The four least significant bits represent the pin number
mbed_official 525:c320967f86b9 81 * The remaining bits represent the port number */
mbed_official 593:78ee8643776a 82 obj->pin = pin;
mbed_official 525:c320967f86b9 83 obj->risingEdge = 0;
mbed_official 525:c320967f86b9 84 obj->fallingEdge = 0;
mbed_official 525:c320967f86b9 85 }
mbed_official 525:c320967f86b9 86
mbed_official 525:c320967f86b9 87 int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id)
mbed_official 525:c320967f86b9 88 {
mbed_official 593:78ee8643776a 89 // Init pins
mbed_official 548:1abac31e188e 90 gpio_irq_preinit(obj, pin);
mbed_official 593:78ee8643776a 91 // Initialize GPIO interrupt dispatcher
mbed_official 525:c320967f86b9 92 NVIC_ClearPendingIRQ(GPIO_ODD_IRQn);
mbed_official 525:c320967f86b9 93 NVIC_EnableIRQ(GPIO_ODD_IRQn);
mbed_official 525:c320967f86b9 94 NVIC_ClearPendingIRQ(GPIO_EVEN_IRQn);
mbed_official 525:c320967f86b9 95 NVIC_EnableIRQ(GPIO_EVEN_IRQn);
mbed_official 525:c320967f86b9 96
mbed_official 525:c320967f86b9 97 /* Relate pin to interrupt action id */
mbed_official 593:78ee8643776a 98 channel_ids[obj->pin & 0xF] = id;
mbed_official 593:78ee8643776a 99
mbed_official 593:78ee8643776a 100 // Relate the pin number to a port. If pin in is odd store in the 4 most significant bits, if pin is even store in the 4 least significant bits
mbed_official 593:78ee8643776a 101 channel_ports[(obj->pin >> 1) & 0x7] = (obj->pin & 0x1) ? (channel_ports[(obj->pin >> 1) & 0x7] & 0x0F) | (obj->pin & 0xF0) : (channel_ports[(obj->pin >> 1) & 0x7] & 0xF0) | ((obj->pin >> 4) & 0xF);
mbed_official 525:c320967f86b9 102 /* Save pointer to handler */
mbed_official 525:c320967f86b9 103 irq_handler = handler;
mbed_official 525:c320967f86b9 104
mbed_official 593:78ee8643776a 105 pin_mode(obj->pin, Input);
mbed_official 525:c320967f86b9 106 return 0;
mbed_official 525:c320967f86b9 107 }
mbed_official 525:c320967f86b9 108
mbed_official 525:c320967f86b9 109 void gpio_irq_free(gpio_irq_t *obj)
mbed_official 525:c320967f86b9 110 {
mbed_official 525:c320967f86b9 111 // Destructor
mbed_official 593:78ee8643776a 112 channel_ids[obj->pin & 0xF] = 0;
mbed_official 525:c320967f86b9 113 gpio_irq_disable(obj); // Disable interrupt channel
mbed_official 593:78ee8643776a 114 pin_mode(obj->pin, Disabled); // Disable input pin
mbed_official 525:c320967f86b9 115 }
mbed_official 525:c320967f86b9 116
mbed_official 525:c320967f86b9 117 void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable)
mbed_official 525:c320967f86b9 118 {
mbed_official 525:c320967f86b9 119 switch (event) {
mbed_official 525:c320967f86b9 120 case (IRQ_RISE):
mbed_official 525:c320967f86b9 121 obj->risingEdge = enable;
mbed_official 525:c320967f86b9 122 break;
mbed_official 525:c320967f86b9 123 case (IRQ_FALL):
mbed_official 525:c320967f86b9 124 obj->fallingEdge = enable;
mbed_official 525:c320967f86b9 125 break;
mbed_official 525:c320967f86b9 126 case (IRQ_NONE):
mbed_official 525:c320967f86b9 127 break;
mbed_official 525:c320967f86b9 128 }
mbed_official 525:c320967f86b9 129
mbed_official 525:c320967f86b9 130 /* Disable, set config and enable */
mbed_official 525:c320967f86b9 131 gpio_irq_disable(obj);
mbed_official 548:1abac31e188e 132
mbed_official 525:c320967f86b9 133 bool was_disabled = false;
mbed_official 525:c320967f86b9 134 if(GPIO->IEN == 0) was_disabled = true;
mbed_official 548:1abac31e188e 135
mbed_official 593:78ee8643776a 136 GPIO_IntConfig((GPIO_Port_TypeDef)(obj->pin >> 4 & 0xF), obj->pin &0xF, obj->risingEdge, obj->fallingEdge, obj->risingEdge || obj->fallingEdge);
mbed_official 525:c320967f86b9 137 if ((GPIO->IEN != 0) && (obj->risingEdge || obj->fallingEdge) && was_disabled) {
mbed_official 548:1abac31e188e 138 blockSleepMode(GPIO_LEAST_ACTIVE_SLEEPMODE);
mbed_official 525:c320967f86b9 139 }
mbed_official 525:c320967f86b9 140 }
mbed_official 525:c320967f86b9 141
mbed_official 525:c320967f86b9 142 inline void gpio_irq_enable(gpio_irq_t *obj)
mbed_official 525:c320967f86b9 143 {
mbed_official 548:1abac31e188e 144 if(GPIO->IEN == 0) blockSleepMode(GPIO_LEAST_ACTIVE_SLEEPMODE);
mbed_official 593:78ee8643776a 145 GPIO_IntEnable(1 << obj->pin & 0xF); // pin mask for pins to enable
mbed_official 525:c320967f86b9 146 }
mbed_official 525:c320967f86b9 147
mbed_official 525:c320967f86b9 148 inline void gpio_irq_disable(gpio_irq_t *obj)
mbed_official 525:c320967f86b9 149 {
mbed_official 593:78ee8643776a 150 GPIO_IntDisable(1 << obj->pin & 0xF); // pin mask for pins to disable
mbed_official 525:c320967f86b9 151 if(GPIO->IEN == 0) unblockSleepMode(GPIO_LEAST_ACTIVE_SLEEPMODE);
mbed_official 525:c320967f86b9 152 }
mbed_official 525:c320967f86b9 153
mbed_official 525:c320967f86b9 154 /***************************************************************************//**
mbed_official 525:c320967f86b9 155 * @brief
mbed_official 525:c320967f86b9 156 * Function calls users callback for registered pin interrupts.
mbed_official 525:c320967f86b9 157 *
mbed_official 525:c320967f86b9 158 * @details
mbed_official 525:c320967f86b9 159 * This function is called when GPIO interrupts are handled by the dispatcher.
mbed_official 525:c320967f86b9 160 * Function gets even or odd interrupt flags and calls user callback
mbed_official 525:c320967f86b9 161 * registered for that pin. Function iterates on flags starting from MSB.
mbed_official 525:c320967f86b9 162 *
mbed_official 525:c320967f86b9 163 * @param iflags
mbed_official 525:c320967f86b9 164 * Interrupt flags which shall be handled by the dispatcher.
mbed_official 525:c320967f86b9 165 *
mbed_official 525:c320967f86b9 166 ******************************************************************************/
mbed_official 525:c320967f86b9 167 static void GPIOINT_IRQDispatcher(uint32_t iflags)
mbed_official 525:c320967f86b9 168 {
mbed_official 548:1abac31e188e 169 uint32_t irqIdx;
mbed_official 525:c320967f86b9 170
mbed_official 548:1abac31e188e 171 /* check for all flags set in IF register */
mbed_official 548:1abac31e188e 172 while(iflags) {
mbed_official 548:1abac31e188e 173 irqIdx = GPIOINT_MASK2IDX(iflags);
mbed_official 525:c320967f86b9 174
mbed_official 593:78ee8643776a 175 /* clear flag */
mbed_official 548:1abac31e188e 176 iflags &= ~(1 << irqIdx);
mbed_official 525:c320967f86b9 177
mbed_official 548:1abac31e188e 178 /* call user callback */
mbed_official 548:1abac31e188e 179 handle_interrupt_in(irqIdx);
mbed_official 548:1abac31e188e 180 }
mbed_official 525:c320967f86b9 181 }
mbed_official 525:c320967f86b9 182
mbed_official 525:c320967f86b9 183 /***************************************************************************//**
mbed_official 525:c320967f86b9 184 * @brief
mbed_official 525:c320967f86b9 185 * GPIO EVEN interrupt handler. Interrupt handler clears all IF even flags and
mbed_official 525:c320967f86b9 186 * call the dispatcher passing the flags which triggered the interrupt.
mbed_official 525:c320967f86b9 187 *
mbed_official 525:c320967f86b9 188 ******************************************************************************/
mbed_official 525:c320967f86b9 189 void GPIO_EVEN_IRQHandler(void)
mbed_official 525:c320967f86b9 190 {
mbed_official 548:1abac31e188e 191 uint32_t iflags;
mbed_official 593:78ee8643776a 192 /* Get all even interrupts */
mbed_official 548:1abac31e188e 193 iflags = GPIO_IntGetEnabled() & 0x00005555;
mbed_official 525:c320967f86b9 194
mbed_official 593:78ee8643776a 195 /* Clean only even interrupts*/
mbed_official 593:78ee8643776a 196
mbed_official 548:1abac31e188e 197 GPIO_IntClear(iflags);
mbed_official 548:1abac31e188e 198 GPIOINT_IRQDispatcher(iflags);
mbed_official 525:c320967f86b9 199 }
mbed_official 525:c320967f86b9 200
mbed_official 525:c320967f86b9 201
mbed_official 525:c320967f86b9 202 /***************************************************************************//**
mbed_official 525:c320967f86b9 203 * @brief
mbed_official 525:c320967f86b9 204 * GPIO ODD interrupt handler. Interrupt handler clears all IF odd flags and
mbed_official 525:c320967f86b9 205 * call the dispatcher passing the flags which triggered the interrupt.
mbed_official 525:c320967f86b9 206 *
mbed_official 525:c320967f86b9 207 ******************************************************************************/
mbed_official 525:c320967f86b9 208 void GPIO_ODD_IRQHandler(void)
mbed_official 525:c320967f86b9 209 {
mbed_official 548:1abac31e188e 210 uint32_t iflags;
mbed_official 525:c320967f86b9 211
mbed_official 593:78ee8643776a 212 /* Get all odd interrupts */
mbed_official 548:1abac31e188e 213 iflags = GPIO_IntGetEnabled() & 0x0000AAAA;
mbed_official 525:c320967f86b9 214
mbed_official 593:78ee8643776a 215 /* Clean only even interrupts */
mbed_official 548:1abac31e188e 216 GPIO_IntClear(iflags);
mbed_official 548:1abac31e188e 217 GPIOINT_IRQDispatcher(iflags);
mbed_official 525:c320967f86b9 218 }
mbed_official 525:c320967f86b9 219
mbed_official 525:c320967f86b9 220 #endif