mbed

Fork of mbed-dev by mbed official

Committer:
AnnaBridge
Date:
Fri Feb 16 16:09:33 2018 +0000
Revision:
182:57724642e740
Parent:
179:79309dc6340a
mbed-dev library. Release version 159.

Who changed what in which revision?

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