mbed library sources. Supersedes mbed-src.

Dependents:   Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more

Committer:
AnnaBridge
Date:
Wed Feb 20 22:31:08 2019 +0000
Revision:
189:f392fc9709a3
Parent:
187:0387e8f68319
mbed library release version 165

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Anna Bridge 186:707f6e361f3e 1 /* mbed Microcontroller Library
Anna Bridge 186:707f6e361f3e 2 * Copyright (c) 2006-2013 ARM Limited
Anna Bridge 186:707f6e361f3e 3 *
Anna Bridge 186:707f6e361f3e 4 * Licensed under the Apache License, Version 2.0 (the "License");
Anna Bridge 186:707f6e361f3e 5 * you may not use this file except in compliance with the License.
Anna Bridge 186:707f6e361f3e 6 * You may obtain a copy of the License at
Anna Bridge 186:707f6e361f3e 7 *
Anna Bridge 186:707f6e361f3e 8 * http://www.apache.org/licenses/LICENSE-2.0
Anna Bridge 186:707f6e361f3e 9 *
Anna Bridge 186:707f6e361f3e 10 * Unless required by applicable law or agreed to in writing, software
Anna Bridge 186:707f6e361f3e 11 * distributed under the License is distributed on an "AS IS" BASIS,
Anna Bridge 186:707f6e361f3e 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Anna Bridge 186:707f6e361f3e 13 * See the License for the specific language governing permissions and
Anna Bridge 186:707f6e361f3e 14 * limitations under the License.
Anna Bridge 186:707f6e361f3e 15 */
Anna Bridge 186:707f6e361f3e 16 #include "mbed_assert.h"
Anna Bridge 186:707f6e361f3e 17 #include "gpio_api.h"
Anna Bridge 186:707f6e361f3e 18 #include "gpio_irq_api.h"
Anna Bridge 186:707f6e361f3e 19 #include "pinmap.h"
Anna Bridge 186:707f6e361f3e 20 #include "nrf_drv_gpiote.h"
Anna Bridge 186:707f6e361f3e 21
Anna Bridge 186:707f6e361f3e 22
Anna Bridge 186:707f6e361f3e 23 #if defined(TARGET_MCU_NRF51822)
AnnaBridge 187:0387e8f68319 24 #define GPIO_PIN_COUNT 31
Anna Bridge 186:707f6e361f3e 25 #elif defined(TARGET_MCU_NRF52832)
AnnaBridge 187:0387e8f68319 26 #define GPIO_PIN_COUNT 32
Anna Bridge 186:707f6e361f3e 27 #elif defined(TARGET_MCU_NRF52840)
AnnaBridge 187:0387e8f68319 28 #define GPIO_PIN_COUNT 48
Anna Bridge 186:707f6e361f3e 29 #else
AnnaBridge 187:0387e8f68319 30 #error not recognized gpio count for mcu
Anna Bridge 186:707f6e361f3e 31 #endif
Anna Bridge 186:707f6e361f3e 32
Anna Bridge 186:707f6e361f3e 33 typedef struct {
Anna Bridge 186:707f6e361f3e 34 bool used_as_gpio : 1;
Anna Bridge 186:707f6e361f3e 35 PinDirection direction : 1;
Anna Bridge 186:707f6e361f3e 36 PinMode pull : 2;
Anna Bridge 186:707f6e361f3e 37 bool used_as_irq : 1;
Anna Bridge 186:707f6e361f3e 38 bool irq_fall : 1;
Anna Bridge 186:707f6e361f3e 39 bool irq_rise : 1;
Anna Bridge 186:707f6e361f3e 40 } gpio_cfg_t;
Anna Bridge 186:707f6e361f3e 41
Anna Bridge 186:707f6e361f3e 42 #if GPIO_PIN_COUNT > 32
AnnaBridge 187:0387e8f68319 43 typedef uint64_t gpio_mask_t;
Anna Bridge 186:707f6e361f3e 44 #else
AnnaBridge 187:0387e8f68319 45 typedef uint32_t gpio_mask_t;
Anna Bridge 186:707f6e361f3e 46 #endif
Anna Bridge 186:707f6e361f3e 47
Anna Bridge 186:707f6e361f3e 48 static gpio_mask_t m_gpio_initialized;
Anna Bridge 186:707f6e361f3e 49 static gpio_cfg_t m_gpio_cfg[GPIO_PIN_COUNT];
Anna Bridge 186:707f6e361f3e 50
Anna Bridge 186:707f6e361f3e 51
Anna Bridge 186:707f6e361f3e 52 /***********
Anna Bridge 186:707f6e361f3e 53 GPIO IRQ
Anna Bridge 186:707f6e361f3e 54 ***********/
Anna Bridge 186:707f6e361f3e 55
Anna Bridge 186:707f6e361f3e 56 static gpio_irq_handler m_irq_handler;
Anna Bridge 186:707f6e361f3e 57 static uint32_t m_channel_ids[GPIO_PIN_COUNT] = {0};
Anna Bridge 186:707f6e361f3e 58 static gpio_mask_t m_gpio_irq_enabled;
Anna Bridge 186:707f6e361f3e 59
Anna Bridge 186:707f6e361f3e 60
Anna Bridge 186:707f6e361f3e 61 static void gpiote_irq_handler(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
Anna Bridge 186:707f6e361f3e 62 {
Anna Bridge 186:707f6e361f3e 63 nrf_gpio_pin_sense_t sense = nrf_gpio_pin_sense_get(pin);
Anna Bridge 186:707f6e361f3e 64 gpio_irq_event event = (sense == NRF_GPIO_PIN_SENSE_LOW) ? IRQ_RISE : IRQ_FALL;
AnnaBridge 187:0387e8f68319 65
Anna Bridge 186:707f6e361f3e 66 if (m_gpio_irq_enabled & ((gpio_mask_t)1 << pin)) {
Anna Bridge 186:707f6e361f3e 67 if (((event == IRQ_RISE) && m_gpio_cfg[pin].irq_rise)
AnnaBridge 187:0387e8f68319 68 || ((event == IRQ_FALL) && m_gpio_cfg[pin].irq_fall)) {
AnnaBridge 187:0387e8f68319 69 m_irq_handler(m_channel_ids[pin], event);
AnnaBridge 187:0387e8f68319 70 }
Anna Bridge 186:707f6e361f3e 71 }
Anna Bridge 186:707f6e361f3e 72 }
Anna Bridge 186:707f6e361f3e 73
Anna Bridge 186:707f6e361f3e 74 void GPIOTE_IRQHandler(void);// exported from nrf_drv_gpiote.c
Anna Bridge 186:707f6e361f3e 75
Anna Bridge 186:707f6e361f3e 76 void gpio_init(gpio_t *obj, PinName pin)
Anna Bridge 186:707f6e361f3e 77 {
Anna Bridge 186:707f6e361f3e 78 obj->pin = pin;
Anna Bridge 186:707f6e361f3e 79 if (pin == (PinName)NC) {
Anna Bridge 186:707f6e361f3e 80 return;
Anna Bridge 186:707f6e361f3e 81 }
Anna Bridge 186:707f6e361f3e 82 MBED_ASSERT((uint32_t)pin < GPIO_PIN_COUNT);
AnnaBridge 187:0387e8f68319 83
Anna Bridge 186:707f6e361f3e 84 NVIC_SetVector(GPIOTE_IRQn, (uint32_t) GPIOTE_IRQHandler);
AnnaBridge 187:0387e8f68319 85
Anna Bridge 186:707f6e361f3e 86 (void) nrf_drv_gpiote_init();
Anna Bridge 186:707f6e361f3e 87
Anna Bridge 186:707f6e361f3e 88 m_gpio_cfg[obj->pin].used_as_gpio = true;
Anna Bridge 186:707f6e361f3e 89 }
Anna Bridge 186:707f6e361f3e 90
Anna Bridge 186:707f6e361f3e 91 #ifdef TARGET_SDK_11
Anna Bridge 186:707f6e361f3e 92 // implement polyfill of gpio hal for the nRF5 SDK v11
Anna Bridge 186:707f6e361f3e 93 __STATIC_INLINE uint32_t nrf_gpio_pin_out_read(uint32_t pin)
Anna Bridge 186:707f6e361f3e 94 {
Anna Bridge 186:707f6e361f3e 95 return (NRF_GPIO->OUTSET & (1UL << (pin)));
Anna Bridge 186:707f6e361f3e 96 }
Anna Bridge 186:707f6e361f3e 97 #endif
Anna Bridge 186:707f6e361f3e 98
Anna Bridge 186:707f6e361f3e 99 int gpio_read(gpio_t *obj)
Anna Bridge 186:707f6e361f3e 100 {
Anna Bridge 186:707f6e361f3e 101 MBED_ASSERT(obj->pin != (PinName)NC);
Anna Bridge 186:707f6e361f3e 102 if (m_gpio_cfg[obj->pin].direction == PIN_OUTPUT) {
Anna Bridge 186:707f6e361f3e 103 return (nrf_gpio_pin_out_read(obj->pin) ? 1 : 0);
Anna Bridge 186:707f6e361f3e 104 } else {
Anna Bridge 186:707f6e361f3e 105 return nrf_gpio_pin_read(obj->pin);
Anna Bridge 186:707f6e361f3e 106 }
Anna Bridge 186:707f6e361f3e 107 }
Anna Bridge 186:707f6e361f3e 108
Anna Bridge 186:707f6e361f3e 109 static void gpiote_pin_uninit(uint8_t pin)
Anna Bridge 186:707f6e361f3e 110 {
Anna Bridge 186:707f6e361f3e 111 if (m_gpio_initialized & ((gpio_mask_t)1UL << pin)) {
Anna Bridge 186:707f6e361f3e 112 if ((m_gpio_cfg[pin].direction == PIN_OUTPUT) && (!m_gpio_cfg[pin].used_as_irq)) {
Anna Bridge 186:707f6e361f3e 113 nrf_drv_gpiote_out_uninit(pin);
AnnaBridge 187:0387e8f68319 114 } else if (m_gpio_cfg[pin].used_as_irq) {
Anna Bridge 186:707f6e361f3e 115 nrf_drv_gpiote_in_uninit(pin);
Anna Bridge 186:707f6e361f3e 116 }
Anna Bridge 186:707f6e361f3e 117 }
Anna Bridge 186:707f6e361f3e 118 }
Anna Bridge 186:707f6e361f3e 119
Anna Bridge 186:707f6e361f3e 120 static void gpio_apply_config(uint8_t pin)
Anna Bridge 186:707f6e361f3e 121 {
Anna Bridge 186:707f6e361f3e 122 if (m_gpio_cfg[pin].used_as_gpio || m_gpio_cfg[pin].used_as_irq) {
Anna Bridge 186:707f6e361f3e 123 if ((m_gpio_cfg[pin].direction == PIN_INPUT)
AnnaBridge 187:0387e8f68319 124 || (m_gpio_cfg[pin].used_as_irq)) {
Anna Bridge 186:707f6e361f3e 125 //Configure as input.
Anna Bridge 186:707f6e361f3e 126 nrf_drv_gpiote_in_config_t cfg;
Anna Bridge 186:707f6e361f3e 127
Anna Bridge 186:707f6e361f3e 128 cfg.hi_accuracy = false;
Anna Bridge 186:707f6e361f3e 129 cfg.is_watcher = false;
Anna Bridge 186:707f6e361f3e 130 cfg.sense = NRF_GPIOTE_POLARITY_TOGGLE;
AnnaBridge 187:0387e8f68319 131 switch (m_gpio_cfg[pin].pull) {
AnnaBridge 187:0387e8f68319 132 case PullUp:
AnnaBridge 187:0387e8f68319 133 cfg.pull = NRF_GPIO_PIN_PULLUP;
AnnaBridge 187:0387e8f68319 134 break;
AnnaBridge 187:0387e8f68319 135 case PullDown:
AnnaBridge 187:0387e8f68319 136 cfg.pull = NRF_GPIO_PIN_PULLDOWN;
AnnaBridge 187:0387e8f68319 137 break;
AnnaBridge 187:0387e8f68319 138 default:
AnnaBridge 187:0387e8f68319 139 cfg.pull = NRF_GPIO_PIN_NOPULL;
AnnaBridge 187:0387e8f68319 140 break;
AnnaBridge 187:0387e8f68319 141 }
Anna Bridge 186:707f6e361f3e 142 if (m_gpio_cfg[pin].used_as_irq) {
Anna Bridge 186:707f6e361f3e 143 nrf_drv_gpiote_in_init(pin, &cfg, gpiote_irq_handler);
Anna Bridge 186:707f6e361f3e 144 if ((m_gpio_irq_enabled & ((gpio_mask_t)1 << pin))
AnnaBridge 187:0387e8f68319 145 && (m_gpio_cfg[pin].irq_rise || m_gpio_cfg[pin].irq_fall)) {
Anna Bridge 186:707f6e361f3e 146 nrf_drv_gpiote_in_event_enable(pin, true);
Anna Bridge 186:707f6e361f3e 147 }
AnnaBridge 187:0387e8f68319 148 } else {
AnnaBridge 187:0387e8f68319 149 nrf_gpio_cfg_input(pin, cfg.pull);
Anna Bridge 186:707f6e361f3e 150 }
AnnaBridge 187:0387e8f68319 151 } else {
Anna Bridge 186:707f6e361f3e 152 // Configure as output.
Anna Bridge 186:707f6e361f3e 153 nrf_drv_gpiote_out_config_t cfg = GPIOTE_CONFIG_OUT_SIMPLE(nrf_gpio_pin_out_read(pin));
Anna Bridge 186:707f6e361f3e 154 nrf_drv_gpiote_out_init(pin, &cfg);
Anna Bridge 186:707f6e361f3e 155 }
Anna Bridge 186:707f6e361f3e 156 m_gpio_initialized |= ((gpio_mask_t)1UL << pin);
AnnaBridge 187:0387e8f68319 157 } else {
Anna Bridge 186:707f6e361f3e 158 m_gpio_initialized &= ~((gpio_mask_t)1UL << pin);
Anna Bridge 186:707f6e361f3e 159 }
Anna Bridge 186:707f6e361f3e 160 }
Anna Bridge 186:707f6e361f3e 161
Anna Bridge 186:707f6e361f3e 162
Anna Bridge 186:707f6e361f3e 163 void gpio_mode(gpio_t *obj, PinMode mode)
Anna Bridge 186:707f6e361f3e 164 {
Anna Bridge 186:707f6e361f3e 165 MBED_ASSERT(obj->pin != (PinName)NC);
AnnaBridge 187:0387e8f68319 166
Anna Bridge 186:707f6e361f3e 167 gpiote_pin_uninit(obj->pin); // try to uninitialize gpio before a change.
AnnaBridge 187:0387e8f68319 168
Anna Bridge 186:707f6e361f3e 169 m_gpio_cfg[obj->pin].pull = mode;
Anna Bridge 186:707f6e361f3e 170 gpio_apply_config(obj->pin);
Anna Bridge 186:707f6e361f3e 171 }
Anna Bridge 186:707f6e361f3e 172
Anna Bridge 186:707f6e361f3e 173
Anna Bridge 186:707f6e361f3e 174 void gpio_dir(gpio_t *obj, PinDirection direction)
Anna Bridge 186:707f6e361f3e 175 {
Anna Bridge 186:707f6e361f3e 176 MBED_ASSERT(obj->pin != (PinName)NC);
AnnaBridge 187:0387e8f68319 177
Anna Bridge 186:707f6e361f3e 178 gpiote_pin_uninit(obj->pin); // try to uninitialize gpio before a change.
AnnaBridge 187:0387e8f68319 179
Anna Bridge 186:707f6e361f3e 180 m_gpio_cfg[obj->pin].direction = direction;
Anna Bridge 186:707f6e361f3e 181 gpio_apply_config(obj->pin);
Anna Bridge 186:707f6e361f3e 182 }
Anna Bridge 186:707f6e361f3e 183
Anna Bridge 186:707f6e361f3e 184
Anna Bridge 186:707f6e361f3e 185 /***********
Anna Bridge 186:707f6e361f3e 186 GPIO IRQ
Anna Bridge 186:707f6e361f3e 187 ***********/
Anna Bridge 186:707f6e361f3e 188
Anna Bridge 186:707f6e361f3e 189 int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id)
Anna Bridge 186:707f6e361f3e 190 {
Anna Bridge 186:707f6e361f3e 191 if (pin == NC) {
Anna Bridge 186:707f6e361f3e 192 return -1;
Anna Bridge 186:707f6e361f3e 193 }
Anna Bridge 186:707f6e361f3e 194 MBED_ASSERT((uint32_t)pin < GPIO_PIN_COUNT);
Anna Bridge 186:707f6e361f3e 195 (void) nrf_drv_gpiote_init();
Anna Bridge 186:707f6e361f3e 196
Anna Bridge 186:707f6e361f3e 197 gpiote_pin_uninit(pin); // try to uninitialize gpio before a change.
AnnaBridge 187:0387e8f68319 198
Anna Bridge 186:707f6e361f3e 199 m_gpio_cfg[pin].used_as_irq = true;
AnnaBridge 187:0387e8f68319 200 m_gpio_cfg[pin].pull = PullNone;
Anna Bridge 186:707f6e361f3e 201 m_channel_ids[pin] = id;
Anna Bridge 186:707f6e361f3e 202 obj->ch = pin;
Anna Bridge 186:707f6e361f3e 203 m_irq_handler = handler;
Anna Bridge 186:707f6e361f3e 204 m_channel_ids[pin] = id;
Anna Bridge 186:707f6e361f3e 205
Anna Bridge 186:707f6e361f3e 206 gpio_apply_config(pin);
Anna Bridge 186:707f6e361f3e 207 return 1;
Anna Bridge 186:707f6e361f3e 208 }
Anna Bridge 186:707f6e361f3e 209
Anna Bridge 186:707f6e361f3e 210
Anna Bridge 186:707f6e361f3e 211 void gpio_irq_free(gpio_irq_t *obj)
Anna Bridge 186:707f6e361f3e 212 {
Anna Bridge 186:707f6e361f3e 213 nrf_drv_gpiote_in_uninit(obj->ch);
Anna Bridge 186:707f6e361f3e 214 m_gpio_cfg[obj->ch].used_as_irq = false;
Anna Bridge 186:707f6e361f3e 215 m_channel_ids[obj->ch] = 0;
Anna Bridge 186:707f6e361f3e 216
Anna Bridge 186:707f6e361f3e 217 gpio_apply_config(obj->ch);
Anna Bridge 186:707f6e361f3e 218 }
Anna Bridge 186:707f6e361f3e 219
Anna Bridge 186:707f6e361f3e 220
Anna Bridge 186:707f6e361f3e 221 void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable)
Anna Bridge 186:707f6e361f3e 222 {
AnnaBridge 187:0387e8f68319 223 gpio_cfg_t *cfg = &m_gpio_cfg[obj->ch];
Anna Bridge 186:707f6e361f3e 224 bool irq_enabled_before =
Anna Bridge 186:707f6e361f3e 225 (m_gpio_irq_enabled & ((gpio_mask_t)1 << obj->ch)) &&
Anna Bridge 186:707f6e361f3e 226 (cfg->irq_rise || cfg->irq_fall);
Anna Bridge 186:707f6e361f3e 227
Anna Bridge 186:707f6e361f3e 228 if (event == IRQ_RISE) {
Anna Bridge 186:707f6e361f3e 229 cfg->irq_rise = enable ? true : false;
AnnaBridge 187:0387e8f68319 230 } else if (event == IRQ_FALL) {
Anna Bridge 186:707f6e361f3e 231 cfg->irq_fall = enable ? true : false;
Anna Bridge 186:707f6e361f3e 232 }
Anna Bridge 186:707f6e361f3e 233
Anna Bridge 186:707f6e361f3e 234 bool irq_enabled_after = cfg->irq_rise || cfg->irq_fall;
Anna Bridge 186:707f6e361f3e 235
Anna Bridge 186:707f6e361f3e 236 if (irq_enabled_before != irq_enabled_after) {
Anna Bridge 186:707f6e361f3e 237 if (irq_enabled_after) {
Anna Bridge 186:707f6e361f3e 238 gpio_irq_enable(obj);
Anna Bridge 186:707f6e361f3e 239 } else {
Anna Bridge 186:707f6e361f3e 240 gpio_irq_disable(obj);
Anna Bridge 186:707f6e361f3e 241 }
Anna Bridge 186:707f6e361f3e 242 }
Anna Bridge 186:707f6e361f3e 243 }
Anna Bridge 186:707f6e361f3e 244
Anna Bridge 186:707f6e361f3e 245
Anna Bridge 186:707f6e361f3e 246 void gpio_irq_enable(gpio_irq_t *obj)
Anna Bridge 186:707f6e361f3e 247 {
Anna Bridge 186:707f6e361f3e 248 m_gpio_irq_enabled |= ((gpio_mask_t)1 << obj->ch);
Anna Bridge 186:707f6e361f3e 249 if (m_gpio_cfg[obj->ch].irq_rise || m_gpio_cfg[obj->ch].irq_fall) {
Anna Bridge 186:707f6e361f3e 250 nrf_drv_gpiote_in_event_enable(obj->ch, true);
Anna Bridge 186:707f6e361f3e 251 }
Anna Bridge 186:707f6e361f3e 252 }
Anna Bridge 186:707f6e361f3e 253
Anna Bridge 186:707f6e361f3e 254
Anna Bridge 186:707f6e361f3e 255 void gpio_irq_disable(gpio_irq_t *obj)
Anna Bridge 186:707f6e361f3e 256 {
Anna Bridge 186:707f6e361f3e 257 m_gpio_irq_enabled &= ~((gpio_mask_t)1 << obj->ch);
Anna Bridge 186:707f6e361f3e 258 nrf_drv_gpiote_in_event_disable(obj->ch);
Anna Bridge 186:707f6e361f3e 259 }