mbed library sources: Modified to operate FRDM-KL25Z at 48MHz from internal 32kHz oscillator (nothing else changed).
Fork of mbed-src by
The only file that changed is: mbed-src-FLL48/targets/cmsis/TARGET_Freescale/TARGET_KL25Z/system_MKL25Z4.h
targets/hal/TARGET_Freescale/TARGET_KL05Z/gpio_irq_api.c@20:4263a77256ae, 2013-09-10 (annotated)
- Committer:
- bogdanm
- Date:
- Tue Sep 10 15:14:19 2013 +0300
- Revision:
- 20:4263a77256ae
Sync with git revision 171dda705c947bf910926a0b73d6a4797802554d
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
bogdanm | 20:4263a77256ae | 1 | /* mbed Microcontroller Library |
bogdanm | 20:4263a77256ae | 2 | * Copyright (c) 2006-2013 ARM Limited |
bogdanm | 20:4263a77256ae | 3 | * |
bogdanm | 20:4263a77256ae | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
bogdanm | 20:4263a77256ae | 5 | * you may not use this file except in compliance with the License. |
bogdanm | 20:4263a77256ae | 6 | * You may obtain a copy of the License at |
bogdanm | 20:4263a77256ae | 7 | * |
bogdanm | 20:4263a77256ae | 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
bogdanm | 20:4263a77256ae | 9 | * |
bogdanm | 20:4263a77256ae | 10 | * Unless required by applicable law or agreed to in writing, software |
bogdanm | 20:4263a77256ae | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
bogdanm | 20:4263a77256ae | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
bogdanm | 20:4263a77256ae | 13 | * See the License for the specific language governing permissions and |
bogdanm | 20:4263a77256ae | 14 | * limitations under the License. |
bogdanm | 20:4263a77256ae | 15 | */ |
bogdanm | 20:4263a77256ae | 16 | #include <stddef.h> |
bogdanm | 20:4263a77256ae | 17 | #include "cmsis.h" |
bogdanm | 20:4263a77256ae | 18 | |
bogdanm | 20:4263a77256ae | 19 | #include "gpio_irq_api.h" |
bogdanm | 20:4263a77256ae | 20 | #include "error.h" |
bogdanm | 20:4263a77256ae | 21 | |
bogdanm | 20:4263a77256ae | 22 | #define CHANNEL_NUM 64 // 31 pins on 2 ports |
bogdanm | 20:4263a77256ae | 23 | |
bogdanm | 20:4263a77256ae | 24 | static uint32_t channel_ids[CHANNEL_NUM] = {0}; |
bogdanm | 20:4263a77256ae | 25 | static gpio_irq_handler irq_handler; |
bogdanm | 20:4263a77256ae | 26 | |
bogdanm | 20:4263a77256ae | 27 | #define IRQ_DISABLED (0) |
bogdanm | 20:4263a77256ae | 28 | #define IRQ_RAISING_EDGE PORT_PCR_IRQC(9) |
bogdanm | 20:4263a77256ae | 29 | #define IRQ_FALLING_EDGE PORT_PCR_IRQC(10) |
bogdanm | 20:4263a77256ae | 30 | #define IRQ_EITHER_EDGE PORT_PCR_IRQC(11) |
bogdanm | 20:4263a77256ae | 31 | |
bogdanm | 20:4263a77256ae | 32 | static void handle_interrupt_in(PORT_Type *port, int ch_base) { |
bogdanm | 20:4263a77256ae | 33 | uint32_t mask = 0, i; |
bogdanm | 20:4263a77256ae | 34 | |
bogdanm | 20:4263a77256ae | 35 | for (i = 0; i < 32; i++) { |
bogdanm | 20:4263a77256ae | 36 | uint32_t pmask = (1 << i); |
bogdanm | 20:4263a77256ae | 37 | if (port->ISFR & pmask) { |
bogdanm | 20:4263a77256ae | 38 | mask |= pmask; |
bogdanm | 20:4263a77256ae | 39 | uint32_t id = channel_ids[ch_base + i]; |
bogdanm | 20:4263a77256ae | 40 | if (id == 0) continue; |
bogdanm | 20:4263a77256ae | 41 | |
bogdanm | 20:4263a77256ae | 42 | FGPIO_Type *gpio; |
bogdanm | 20:4263a77256ae | 43 | gpio_irq_event event = IRQ_NONE; |
bogdanm | 20:4263a77256ae | 44 | switch (port->PCR[i] & PORT_PCR_IRQC_MASK) { |
bogdanm | 20:4263a77256ae | 45 | case IRQ_RAISING_EDGE: |
bogdanm | 20:4263a77256ae | 46 | event = IRQ_RISE; |
bogdanm | 20:4263a77256ae | 47 | break; |
bogdanm | 20:4263a77256ae | 48 | |
bogdanm | 20:4263a77256ae | 49 | case IRQ_FALLING_EDGE: |
bogdanm | 20:4263a77256ae | 50 | event = IRQ_FALL; |
bogdanm | 20:4263a77256ae | 51 | break; |
bogdanm | 20:4263a77256ae | 52 | |
bogdanm | 20:4263a77256ae | 53 | case IRQ_EITHER_EDGE: |
bogdanm | 20:4263a77256ae | 54 | gpio = (port == PORTA) ? (FPTA) : (FPTB); |
bogdanm | 20:4263a77256ae | 55 | event = (gpio->PDIR & pmask) ? (IRQ_RISE) : (IRQ_FALL); |
bogdanm | 20:4263a77256ae | 56 | break; |
bogdanm | 20:4263a77256ae | 57 | } |
bogdanm | 20:4263a77256ae | 58 | if (event != IRQ_NONE) { |
bogdanm | 20:4263a77256ae | 59 | irq_handler(id, event); |
bogdanm | 20:4263a77256ae | 60 | } |
bogdanm | 20:4263a77256ae | 61 | } |
bogdanm | 20:4263a77256ae | 62 | } |
bogdanm | 20:4263a77256ae | 63 | port->ISFR = mask; |
bogdanm | 20:4263a77256ae | 64 | } |
bogdanm | 20:4263a77256ae | 65 | |
bogdanm | 20:4263a77256ae | 66 | /* IRQ only on PORTA and PORTB */ |
bogdanm | 20:4263a77256ae | 67 | void gpio_irqA(void) { |
bogdanm | 20:4263a77256ae | 68 | handle_interrupt_in(PORTA, 0); |
bogdanm | 20:4263a77256ae | 69 | } |
bogdanm | 20:4263a77256ae | 70 | |
bogdanm | 20:4263a77256ae | 71 | void gpio_irqB(void) { |
bogdanm | 20:4263a77256ae | 72 | handle_interrupt_in(PORTB, 32); |
bogdanm | 20:4263a77256ae | 73 | } |
bogdanm | 20:4263a77256ae | 74 | |
bogdanm | 20:4263a77256ae | 75 | int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id) { |
bogdanm | 20:4263a77256ae | 76 | if (pin == NC) return -1; |
bogdanm | 20:4263a77256ae | 77 | |
bogdanm | 20:4263a77256ae | 78 | irq_handler = handler; |
bogdanm | 20:4263a77256ae | 79 | |
bogdanm | 20:4263a77256ae | 80 | obj->port = pin >> PORT_SHIFT; |
bogdanm | 20:4263a77256ae | 81 | obj->pin = (pin & 0x7F) >> 2; |
bogdanm | 20:4263a77256ae | 82 | |
bogdanm | 20:4263a77256ae | 83 | uint32_t ch_base, vector; |
bogdanm | 20:4263a77256ae | 84 | IRQn_Type irq_n; |
bogdanm | 20:4263a77256ae | 85 | switch (obj->port) { |
bogdanm | 20:4263a77256ae | 86 | case PortA: |
bogdanm | 20:4263a77256ae | 87 | ch_base = 0; |
bogdanm | 20:4263a77256ae | 88 | irq_n = PORTA_IRQn; |
bogdanm | 20:4263a77256ae | 89 | vector = (uint32_t)gpio_irqA; |
bogdanm | 20:4263a77256ae | 90 | break; |
bogdanm | 20:4263a77256ae | 91 | |
bogdanm | 20:4263a77256ae | 92 | case PortB: |
bogdanm | 20:4263a77256ae | 93 | ch_base = 32; |
bogdanm | 20:4263a77256ae | 94 | irq_n = PORTB_IRQn; |
bogdanm | 20:4263a77256ae | 95 | vector = (uint32_t)gpio_irqB; |
bogdanm | 20:4263a77256ae | 96 | break; |
bogdanm | 20:4263a77256ae | 97 | |
bogdanm | 20:4263a77256ae | 98 | default: |
bogdanm | 20:4263a77256ae | 99 | error("gpio_irq only supported on Port A and B\n"); |
bogdanm | 20:4263a77256ae | 100 | break; |
bogdanm | 20:4263a77256ae | 101 | } |
bogdanm | 20:4263a77256ae | 102 | NVIC_SetVector(irq_n, vector); |
bogdanm | 20:4263a77256ae | 103 | NVIC_EnableIRQ(irq_n); |
bogdanm | 20:4263a77256ae | 104 | |
bogdanm | 20:4263a77256ae | 105 | obj->ch = ch_base + obj->pin; |
bogdanm | 20:4263a77256ae | 106 | channel_ids[obj->ch] = id; |
bogdanm | 20:4263a77256ae | 107 | |
bogdanm | 20:4263a77256ae | 108 | return 0; |
bogdanm | 20:4263a77256ae | 109 | } |
bogdanm | 20:4263a77256ae | 110 | |
bogdanm | 20:4263a77256ae | 111 | void gpio_irq_free(gpio_irq_t *obj) { |
bogdanm | 20:4263a77256ae | 112 | channel_ids[obj->ch] = 0; |
bogdanm | 20:4263a77256ae | 113 | } |
bogdanm | 20:4263a77256ae | 114 | |
bogdanm | 20:4263a77256ae | 115 | void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable) { |
bogdanm | 20:4263a77256ae | 116 | PORT_Type *port = (PORT_Type *)(PORTA_BASE + 0x1000 * obj->port); |
bogdanm | 20:4263a77256ae | 117 | |
bogdanm | 20:4263a77256ae | 118 | uint32_t irq_settings = IRQ_DISABLED; |
bogdanm | 20:4263a77256ae | 119 | |
bogdanm | 20:4263a77256ae | 120 | switch (port->PCR[obj->pin] & PORT_PCR_IRQC_MASK) { |
bogdanm | 20:4263a77256ae | 121 | case IRQ_DISABLED: |
bogdanm | 20:4263a77256ae | 122 | if (enable) { |
bogdanm | 20:4263a77256ae | 123 | irq_settings = (event == IRQ_RISE) ? (IRQ_RAISING_EDGE) : (IRQ_FALLING_EDGE); |
bogdanm | 20:4263a77256ae | 124 | } |
bogdanm | 20:4263a77256ae | 125 | break; |
bogdanm | 20:4263a77256ae | 126 | |
bogdanm | 20:4263a77256ae | 127 | case IRQ_RAISING_EDGE: |
bogdanm | 20:4263a77256ae | 128 | if (enable) { |
bogdanm | 20:4263a77256ae | 129 | irq_settings = (event == IRQ_RISE) ? (IRQ_RAISING_EDGE) : (IRQ_EITHER_EDGE); |
bogdanm | 20:4263a77256ae | 130 | } else { |
bogdanm | 20:4263a77256ae | 131 | if (event == IRQ_FALL) |
bogdanm | 20:4263a77256ae | 132 | irq_settings = IRQ_RAISING_EDGE; |
bogdanm | 20:4263a77256ae | 133 | } |
bogdanm | 20:4263a77256ae | 134 | break; |
bogdanm | 20:4263a77256ae | 135 | |
bogdanm | 20:4263a77256ae | 136 | case IRQ_FALLING_EDGE: |
bogdanm | 20:4263a77256ae | 137 | if (enable) { |
bogdanm | 20:4263a77256ae | 138 | irq_settings = (event == IRQ_FALL) ? (IRQ_FALLING_EDGE) : (IRQ_EITHER_EDGE); |
bogdanm | 20:4263a77256ae | 139 | } else { |
bogdanm | 20:4263a77256ae | 140 | if (event == IRQ_RISE) |
bogdanm | 20:4263a77256ae | 141 | irq_settings = IRQ_FALLING_EDGE; |
bogdanm | 20:4263a77256ae | 142 | } |
bogdanm | 20:4263a77256ae | 143 | break; |
bogdanm | 20:4263a77256ae | 144 | |
bogdanm | 20:4263a77256ae | 145 | case IRQ_EITHER_EDGE: |
bogdanm | 20:4263a77256ae | 146 | if (enable) { |
bogdanm | 20:4263a77256ae | 147 | irq_settings = IRQ_EITHER_EDGE; |
bogdanm | 20:4263a77256ae | 148 | } else { |
bogdanm | 20:4263a77256ae | 149 | irq_settings = (event == IRQ_RISE) ? (IRQ_FALLING_EDGE) : (IRQ_RAISING_EDGE); |
bogdanm | 20:4263a77256ae | 150 | } |
bogdanm | 20:4263a77256ae | 151 | break; |
bogdanm | 20:4263a77256ae | 152 | } |
bogdanm | 20:4263a77256ae | 153 | |
bogdanm | 20:4263a77256ae | 154 | // Interrupt configuration and clear interrupt |
bogdanm | 20:4263a77256ae | 155 | port->PCR[obj->pin] = (port->PCR[obj->pin] & ~PORT_PCR_IRQC_MASK) | irq_settings | PORT_PCR_ISF_MASK; |
bogdanm | 20:4263a77256ae | 156 | } |