mbed library sources

Dependents:   frdm_kl05z_gpio_test

Fork of mbed-src by mbed official

Committer:
mbed_official
Date:
Tue Mar 25 09:30:07 2014 +0000
Revision:
134:4fb64af58963
Parent:
113:65a335a675de
Child:
158:3121b9889f7b
Synchronized with git revision d4c04e866e041b272b75d9ee61ff446dc5efebfd

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

Create a platform specific file to override WEAK Handlers and pre-main hook mbed_sdk_init

I thought about a better solution for this problem, but I couldn't find one, so this is fine. Just one comment: I wouldn't name that file 'platform_init.c'. First, it might contain other code than just initialization code (for example, mbed_die is also declared as a weak function and we'll need to override it for NRF51822). Second, it doesn't realy send the "this file is special and should be treated as such" message. I'd call it something like 'mbed_overrides.c'. But I'll make this change later. Thanks for the pull request!

Who changed what in which revision?

UserRevisionLine numberNew contents of line
emilmont 10:3bc89ef62ce7 1 /* mbed Microcontroller Library
emilmont 10:3bc89ef62ce7 2 * Copyright (c) 2006-2013 ARM Limited
emilmont 10:3bc89ef62ce7 3 *
emilmont 10:3bc89ef62ce7 4 * Licensed under the Apache License, Version 2.0 (the "License");
emilmont 10:3bc89ef62ce7 5 * you may not use this file except in compliance with the License.
emilmont 10:3bc89ef62ce7 6 * You may obtain a copy of the License at
emilmont 10:3bc89ef62ce7 7 *
emilmont 10:3bc89ef62ce7 8 * http://www.apache.org/licenses/LICENSE-2.0
emilmont 10:3bc89ef62ce7 9 *
emilmont 10:3bc89ef62ce7 10 * Unless required by applicable law or agreed to in writing, software
emilmont 10:3bc89ef62ce7 11 * distributed under the License is distributed on an "AS IS" BASIS,
emilmont 10:3bc89ef62ce7 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
emilmont 10:3bc89ef62ce7 13 * See the License for the specific language governing permissions and
emilmont 10:3bc89ef62ce7 14 * limitations under the License.
emilmont 10:3bc89ef62ce7 15 */
emilmont 10:3bc89ef62ce7 16 #include <stddef.h>
emilmont 10:3bc89ef62ce7 17 #include "cmsis.h"
emilmont 10:3bc89ef62ce7 18
emilmont 10:3bc89ef62ce7 19 #include "gpio_irq_api.h"
mbed_official 113:65a335a675de 20 #include "gpio_api.h"
emilmont 10:3bc89ef62ce7 21 #include "error.h"
emilmont 10:3bc89ef62ce7 22
emilmont 10:3bc89ef62ce7 23 #define CHANNEL_NUM 64
emilmont 10:3bc89ef62ce7 24
emilmont 10:3bc89ef62ce7 25 static uint32_t channel_ids[CHANNEL_NUM] = {0};
emilmont 10:3bc89ef62ce7 26 static gpio_irq_handler irq_handler;
emilmont 10:3bc89ef62ce7 27
emilmont 10:3bc89ef62ce7 28 #define IRQ_DISABLED (0)
emilmont 10:3bc89ef62ce7 29 #define IRQ_RAISING_EDGE PORT_PCR_IRQC(9)
emilmont 10:3bc89ef62ce7 30 #define IRQ_FALLING_EDGE PORT_PCR_IRQC(10)
emilmont 10:3bc89ef62ce7 31 #define IRQ_EITHER_EDGE PORT_PCR_IRQC(11)
emilmont 10:3bc89ef62ce7 32
emilmont 10:3bc89ef62ce7 33 static void handle_interrupt_in(PORT_Type *port, int ch_base) {
emilmont 10:3bc89ef62ce7 34 uint32_t mask = 0, i;
emilmont 10:3bc89ef62ce7 35
emilmont 10:3bc89ef62ce7 36 for (i = 0; i < 32; i++) {
emilmont 10:3bc89ef62ce7 37 uint32_t pmask = (1 << i);
emilmont 10:3bc89ef62ce7 38 if (port->ISFR & pmask) {
emilmont 10:3bc89ef62ce7 39 mask |= pmask;
emilmont 10:3bc89ef62ce7 40 uint32_t id = channel_ids[ch_base + i];
mbed_official 86:26fc69fd3b6c 41 if (id == 0) {
mbed_official 86:26fc69fd3b6c 42 continue;
mbed_official 86:26fc69fd3b6c 43 }
emilmont 10:3bc89ef62ce7 44
emilmont 10:3bc89ef62ce7 45 FGPIO_Type *gpio;
emilmont 10:3bc89ef62ce7 46 gpio_irq_event event = IRQ_NONE;
emilmont 10:3bc89ef62ce7 47 switch (port->PCR[i] & PORT_PCR_IRQC_MASK) {
emilmont 10:3bc89ef62ce7 48 case IRQ_RAISING_EDGE:
emilmont 10:3bc89ef62ce7 49 event = IRQ_RISE;
emilmont 10:3bc89ef62ce7 50 break;
emilmont 10:3bc89ef62ce7 51
emilmont 10:3bc89ef62ce7 52 case IRQ_FALLING_EDGE:
emilmont 10:3bc89ef62ce7 53 event = IRQ_FALL;
emilmont 10:3bc89ef62ce7 54 break;
emilmont 10:3bc89ef62ce7 55
emilmont 10:3bc89ef62ce7 56 case IRQ_EITHER_EDGE:
emilmont 10:3bc89ef62ce7 57 gpio = (port == PORTA) ? (FPTA) : (FPTD);
emilmont 10:3bc89ef62ce7 58 event = (gpio->PDIR & pmask) ? (IRQ_RISE) : (IRQ_FALL);
emilmont 10:3bc89ef62ce7 59 break;
emilmont 10:3bc89ef62ce7 60 }
mbed_official 86:26fc69fd3b6c 61 if (event != IRQ_NONE) {
emilmont 10:3bc89ef62ce7 62 irq_handler(id, event);
mbed_official 86:26fc69fd3b6c 63 }
emilmont 10:3bc89ef62ce7 64 }
emilmont 10:3bc89ef62ce7 65 }
emilmont 10:3bc89ef62ce7 66 port->ISFR = mask;
emilmont 10:3bc89ef62ce7 67 }
emilmont 10:3bc89ef62ce7 68
emilmont 10:3bc89ef62ce7 69 void gpio_irqA(void) {handle_interrupt_in(PORTA, 0);}
emilmont 10:3bc89ef62ce7 70 void gpio_irqD(void) {handle_interrupt_in(PORTD, 32);}
emilmont 10:3bc89ef62ce7 71
emilmont 10:3bc89ef62ce7 72 int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id) {
emilmont 10:3bc89ef62ce7 73 if (pin == NC) return -1;
emilmont 10:3bc89ef62ce7 74
emilmont 10:3bc89ef62ce7 75 irq_handler = handler;
emilmont 10:3bc89ef62ce7 76
emilmont 10:3bc89ef62ce7 77 obj->port = pin >> PORT_SHIFT;
emilmont 10:3bc89ef62ce7 78 obj->pin = (pin & 0x7F) >> 2;
emilmont 10:3bc89ef62ce7 79
emilmont 10:3bc89ef62ce7 80 uint32_t ch_base, vector;
emilmont 10:3bc89ef62ce7 81 IRQn_Type irq_n;
emilmont 10:3bc89ef62ce7 82 switch (obj->port) {
emilmont 10:3bc89ef62ce7 83 case PortA:
emilmont 10:3bc89ef62ce7 84 ch_base = 0; irq_n = PORTA_IRQn; vector = (uint32_t)gpio_irqA;
emilmont 10:3bc89ef62ce7 85 break;
emilmont 10:3bc89ef62ce7 86
emilmont 10:3bc89ef62ce7 87 case PortD:
emilmont 10:3bc89ef62ce7 88 ch_base = 32; irq_n = PORTD_IRQn; vector = (uint32_t)gpio_irqD;
emilmont 10:3bc89ef62ce7 89 break;
emilmont 10:3bc89ef62ce7 90
emilmont 10:3bc89ef62ce7 91 default:
emilmont 10:3bc89ef62ce7 92 error("gpio_irq only supported on port A and D\n");
emilmont 10:3bc89ef62ce7 93 break;
emilmont 10:3bc89ef62ce7 94 }
emilmont 10:3bc89ef62ce7 95 NVIC_SetVector(irq_n, vector);
emilmont 10:3bc89ef62ce7 96 NVIC_EnableIRQ(irq_n);
emilmont 10:3bc89ef62ce7 97
emilmont 10:3bc89ef62ce7 98 obj->ch = ch_base + obj->pin;
emilmont 10:3bc89ef62ce7 99 channel_ids[obj->ch] = id;
emilmont 10:3bc89ef62ce7 100
emilmont 10:3bc89ef62ce7 101 return 0;
emilmont 10:3bc89ef62ce7 102 }
emilmont 10:3bc89ef62ce7 103
emilmont 10:3bc89ef62ce7 104 void gpio_irq_free(gpio_irq_t *obj) {
emilmont 10:3bc89ef62ce7 105 channel_ids[obj->ch] = 0;
emilmont 10:3bc89ef62ce7 106 }
emilmont 10:3bc89ef62ce7 107
emilmont 10:3bc89ef62ce7 108 void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable) {
emilmont 10:3bc89ef62ce7 109 PORT_Type *port = (PORT_Type *)(PORTA_BASE + 0x1000 * obj->port);
emilmont 10:3bc89ef62ce7 110
emilmont 10:3bc89ef62ce7 111 uint32_t irq_settings = IRQ_DISABLED;
emilmont 10:3bc89ef62ce7 112
emilmont 10:3bc89ef62ce7 113 switch (port->PCR[obj->pin] & PORT_PCR_IRQC_MASK) {
emilmont 10:3bc89ef62ce7 114 case IRQ_DISABLED:
emilmont 10:3bc89ef62ce7 115 if (enable) {
emilmont 10:3bc89ef62ce7 116 irq_settings = (event == IRQ_RISE) ? (IRQ_RAISING_EDGE) : (IRQ_FALLING_EDGE);
emilmont 10:3bc89ef62ce7 117 }
emilmont 10:3bc89ef62ce7 118 break;
emilmont 10:3bc89ef62ce7 119
emilmont 10:3bc89ef62ce7 120 case IRQ_RAISING_EDGE:
emilmont 10:3bc89ef62ce7 121 if (enable) {
emilmont 10:3bc89ef62ce7 122 irq_settings = (event == IRQ_RISE) ? (IRQ_RAISING_EDGE) : (IRQ_EITHER_EDGE);
emilmont 10:3bc89ef62ce7 123 } else {
emilmont 10:3bc89ef62ce7 124 if (event == IRQ_FALL)
emilmont 10:3bc89ef62ce7 125 irq_settings = IRQ_RAISING_EDGE;
emilmont 10:3bc89ef62ce7 126 }
emilmont 10:3bc89ef62ce7 127 break;
emilmont 10:3bc89ef62ce7 128
emilmont 10:3bc89ef62ce7 129 case IRQ_FALLING_EDGE:
emilmont 10:3bc89ef62ce7 130 if (enable) {
emilmont 10:3bc89ef62ce7 131 irq_settings = (event == IRQ_FALL) ? (IRQ_FALLING_EDGE) : (IRQ_EITHER_EDGE);
emilmont 10:3bc89ef62ce7 132 } else {
emilmont 10:3bc89ef62ce7 133 if (event == IRQ_RISE)
emilmont 10:3bc89ef62ce7 134 irq_settings = IRQ_FALLING_EDGE;
emilmont 10:3bc89ef62ce7 135 }
emilmont 10:3bc89ef62ce7 136 break;
emilmont 10:3bc89ef62ce7 137
emilmont 10:3bc89ef62ce7 138 case IRQ_EITHER_EDGE:
emilmont 10:3bc89ef62ce7 139 if (enable) {
emilmont 10:3bc89ef62ce7 140 irq_settings = IRQ_EITHER_EDGE;
emilmont 10:3bc89ef62ce7 141 } else {
emilmont 10:3bc89ef62ce7 142 irq_settings = (event == IRQ_RISE) ? (IRQ_FALLING_EDGE) : (IRQ_RAISING_EDGE);
emilmont 10:3bc89ef62ce7 143 }
emilmont 10:3bc89ef62ce7 144 break;
emilmont 10:3bc89ef62ce7 145 }
emilmont 10:3bc89ef62ce7 146
emilmont 10:3bc89ef62ce7 147 // Interrupt configuration and clear interrupt
emilmont 10:3bc89ef62ce7 148 port->PCR[obj->pin] = (port->PCR[obj->pin] & ~PORT_PCR_IRQC_MASK) | irq_settings | PORT_PCR_ISF_MASK;
emilmont 10:3bc89ef62ce7 149 }
mbed_official 35:371630885ad6 150
mbed_official 35:371630885ad6 151 void gpio_irq_enable(gpio_irq_t *obj) {
mbed_official 35:371630885ad6 152 if (obj->port == PortA) {
mbed_official 35:371630885ad6 153 NVIC_EnableIRQ(PORTA_IRQn);
mbed_official 35:371630885ad6 154 } else if (obj->port == PortD) {
mbed_official 35:371630885ad6 155 NVIC_EnableIRQ(PORTD_IRQn);
mbed_official 35:371630885ad6 156 }
mbed_official 35:371630885ad6 157 }
mbed_official 35:371630885ad6 158
mbed_official 35:371630885ad6 159 void gpio_irq_disable(gpio_irq_t *obj) {
mbed_official 35:371630885ad6 160 if (obj->port == PortA) {
mbed_official 35:371630885ad6 161 NVIC_DisableIRQ(PORTA_IRQn);
mbed_official 35:371630885ad6 162 } else if (obj->port == PortD) {
mbed_official 35:371630885ad6 163 NVIC_DisableIRQ(PORTD_IRQn);
mbed_official 35:371630885ad6 164 }
mbed_official 35:371630885ad6 165 }