mbed library sources. Supersedes mbed-src.

Dependents:   Hobbyking_Cheetah_Compact Hobbyking_Cheetah_Compact_DRV8323_14bit Hobbyking_Cheetah_Compact_DRV8323_V51_201907 HKC_MiniCheetah ... more

Fork of mbed-dev by mbed official

Committer:
benkatz
Date:
Mon Jul 30 20:31:44 2018 +0000
Revision:
181:36facd806e4a
Parent:
149:156823d33999
going on the robot.  fixed a dumb bug in float_to_uint

Who changed what in which revision?

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