added prescaler for 16 bit pwm in LPC1347 target

Fork of mbed-dev by mbed official

Committer:
JojoS
Date:
Sat Sep 10 15:32:04 2016 +0000
Revision:
147:ba84b7dc41a7
Parent:
144:ef7eb2e8f9f7
added prescaler for 16 bit timers (solution as in LPC11xx), default prescaler 31 for max 28 ms period time

Who changed what in which revision?

UserRevisionLine numberNew contents of line
<> 144:ef7eb2e8f9f7 1 /* mbed Microcontroller Library
<> 144:ef7eb2e8f9f7 2 * Copyright (c) 2006-2015 ARM Limited
<> 144:ef7eb2e8f9f7 3 *
<> 144:ef7eb2e8f9f7 4 * Licensed under the Apache License, Version 2.0 (the "License");
<> 144:ef7eb2e8f9f7 5 * you may not use this file except in compliance with the License.
<> 144:ef7eb2e8f9f7 6 * You may obtain a copy of the License at
<> 144:ef7eb2e8f9f7 7 *
<> 144:ef7eb2e8f9f7 8 * http://www.apache.org/licenses/LICENSE-2.0
<> 144:ef7eb2e8f9f7 9 *
<> 144:ef7eb2e8f9f7 10 * Unless required by applicable law or agreed to in writing, software
<> 144:ef7eb2e8f9f7 11 * distributed under the License is distributed on an "AS IS" BASIS,
<> 144:ef7eb2e8f9f7 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<> 144:ef7eb2e8f9f7 13 * See the License for the specific language governing permissions and
<> 144:ef7eb2e8f9f7 14 * limitations under the License.
<> 144:ef7eb2e8f9f7 15 */
<> 144:ef7eb2e8f9f7 16 #include <stddef.h>
<> 144:ef7eb2e8f9f7 17 #include "cmsis.h"
<> 144:ef7eb2e8f9f7 18
<> 144:ef7eb2e8f9f7 19 #include "gpio_irq_api.h"
<> 144:ef7eb2e8f9f7 20 #include "mbed_error.h"
<> 144:ef7eb2e8f9f7 21
<> 144:ef7eb2e8f9f7 22 #define CHANNEL_NUM 160
<> 144:ef7eb2e8f9f7 23
<> 144:ef7eb2e8f9f7 24 static uint32_t channel_ids[CHANNEL_NUM] = {0};
<> 144:ef7eb2e8f9f7 25 static gpio_irq_handler irq_handler;
<> 144:ef7eb2e8f9f7 26
<> 144:ef7eb2e8f9f7 27 #define IRQ_DISABLED (0)
<> 144:ef7eb2e8f9f7 28 #define IRQ_RAISING_EDGE PORT_PCR_IRQC(9)
<> 144:ef7eb2e8f9f7 29 #define IRQ_FALLING_EDGE PORT_PCR_IRQC(10)
<> 144:ef7eb2e8f9f7 30 #define IRQ_EITHER_EDGE PORT_PCR_IRQC(11)
<> 144:ef7eb2e8f9f7 31
<> 144:ef7eb2e8f9f7 32 static void handle_interrupt_in(PORT_Type *port, int ch_base) {
<> 144:ef7eb2e8f9f7 33 uint32_t isfr;
<> 144:ef7eb2e8f9f7 34 uint32_t pin;
<> 144:ef7eb2e8f9f7 35
<> 144:ef7eb2e8f9f7 36 while ((isfr = port->ISFR) != 0) {
<> 144:ef7eb2e8f9f7 37 pin = 31 - __CLZ(isfr);
<> 144:ef7eb2e8f9f7 38 uint32_t id = channel_ids[ch_base + pin];
<> 144:ef7eb2e8f9f7 39 if (id == 0) {
<> 144:ef7eb2e8f9f7 40 continue;
<> 144:ef7eb2e8f9f7 41 }
<> 144:ef7eb2e8f9f7 42
<> 144:ef7eb2e8f9f7 43 GPIO_Type *gpio = PTA;
<> 144:ef7eb2e8f9f7 44 gpio_irq_event event = IRQ_NONE;
<> 144:ef7eb2e8f9f7 45 uint32_t port_num = (port - PORTA) >> 12;
<> 144:ef7eb2e8f9f7 46
<> 144:ef7eb2e8f9f7 47 switch (port->PCR[pin] & PORT_PCR_IRQC_MASK) {
<> 144:ef7eb2e8f9f7 48 case IRQ_RAISING_EDGE:
<> 144:ef7eb2e8f9f7 49 event = IRQ_RISE;
<> 144:ef7eb2e8f9f7 50 break;
<> 144:ef7eb2e8f9f7 51 case IRQ_FALLING_EDGE:
<> 144:ef7eb2e8f9f7 52 event = IRQ_FALL;
<> 144:ef7eb2e8f9f7 53 break;
<> 144:ef7eb2e8f9f7 54 case IRQ_EITHER_EDGE:
<> 144:ef7eb2e8f9f7 55 gpio += (port_num * 0x40);
<> 144:ef7eb2e8f9f7 56 event = (gpio->PDIR & (1 << pin)) ? (IRQ_RISE) : (IRQ_FALL);
<> 144:ef7eb2e8f9f7 57 break;
<> 144:ef7eb2e8f9f7 58 }
<> 144:ef7eb2e8f9f7 59 if (event != IRQ_NONE) {
<> 144:ef7eb2e8f9f7 60 irq_handler(id, event);
<> 144:ef7eb2e8f9f7 61 }
<> 144:ef7eb2e8f9f7 62 port->ISFR = 1 << pin;
<> 144:ef7eb2e8f9f7 63 }
<> 144:ef7eb2e8f9f7 64 }
<> 144:ef7eb2e8f9f7 65
<> 144:ef7eb2e8f9f7 66 void gpio_irqA(void) {
<> 144:ef7eb2e8f9f7 67 handle_interrupt_in(PORTA, 0);
<> 144:ef7eb2e8f9f7 68 }
<> 144:ef7eb2e8f9f7 69
<> 144:ef7eb2e8f9f7 70 void gpio_irqB(void)
<> 144:ef7eb2e8f9f7 71 {
<> 144:ef7eb2e8f9f7 72 handle_interrupt_in(PORTB, 32);
<> 144:ef7eb2e8f9f7 73 }
<> 144:ef7eb2e8f9f7 74
<> 144:ef7eb2e8f9f7 75 void gpio_irqC(void)
<> 144:ef7eb2e8f9f7 76 {
<> 144:ef7eb2e8f9f7 77 handle_interrupt_in(PORTC, 64);
<> 144:ef7eb2e8f9f7 78 }
<> 144:ef7eb2e8f9f7 79
<> 144:ef7eb2e8f9f7 80 void gpio_irqD(void)
<> 144:ef7eb2e8f9f7 81 {
<> 144:ef7eb2e8f9f7 82 handle_interrupt_in(PORTD, 96);
<> 144:ef7eb2e8f9f7 83 }
<> 144:ef7eb2e8f9f7 84
<> 144:ef7eb2e8f9f7 85 void gpio_irqE(void)
<> 144:ef7eb2e8f9f7 86 {
<> 144:ef7eb2e8f9f7 87 handle_interrupt_in(PORTE, 128);
<> 144:ef7eb2e8f9f7 88 }
<> 144:ef7eb2e8f9f7 89
<> 144:ef7eb2e8f9f7 90
<> 144:ef7eb2e8f9f7 91 int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id) {
<> 144:ef7eb2e8f9f7 92 if (pin == NC)
<> 144:ef7eb2e8f9f7 93 return -1;
<> 144:ef7eb2e8f9f7 94
<> 144:ef7eb2e8f9f7 95 irq_handler = handler;
<> 144:ef7eb2e8f9f7 96
<> 144:ef7eb2e8f9f7 97 obj->port = pin >> PORT_SHIFT;
<> 144:ef7eb2e8f9f7 98 obj->pin = (pin & 0x7F) >> 2;
<> 144:ef7eb2e8f9f7 99
<> 144:ef7eb2e8f9f7 100 uint32_t ch_base, vector;
<> 144:ef7eb2e8f9f7 101 IRQn_Type irq_n;
<> 144:ef7eb2e8f9f7 102 switch (obj->port) {
<> 144:ef7eb2e8f9f7 103 case PortA:
<> 144:ef7eb2e8f9f7 104 ch_base = 0;
<> 144:ef7eb2e8f9f7 105 irq_n = PORTA_IRQn;
<> 144:ef7eb2e8f9f7 106 vector = (uint32_t)gpio_irqA;
<> 144:ef7eb2e8f9f7 107 break;
<> 144:ef7eb2e8f9f7 108 case PortB:
<> 144:ef7eb2e8f9f7 109 ch_base = 32;
<> 144:ef7eb2e8f9f7 110 irq_n = PORTB_IRQn;
<> 144:ef7eb2e8f9f7 111 vector = (uint32_t)gpio_irqB;
<> 144:ef7eb2e8f9f7 112 break;
<> 144:ef7eb2e8f9f7 113 case PortC:
<> 144:ef7eb2e8f9f7 114 ch_base = 64;
<> 144:ef7eb2e8f9f7 115 irq_n = PORTC_IRQn;
<> 144:ef7eb2e8f9f7 116 vector = (uint32_t)gpio_irqC;
<> 144:ef7eb2e8f9f7 117 break;
<> 144:ef7eb2e8f9f7 118 case PortD:
<> 144:ef7eb2e8f9f7 119 ch_base = 96;
<> 144:ef7eb2e8f9f7 120 irq_n = PORTD_IRQn; vector = (uint32_t)gpio_irqD;
<> 144:ef7eb2e8f9f7 121 break;
<> 144:ef7eb2e8f9f7 122 case PortE:
<> 144:ef7eb2e8f9f7 123 ch_base = 128;
<> 144:ef7eb2e8f9f7 124 irq_n = PORTE_IRQn;
<> 144:ef7eb2e8f9f7 125 vector = (uint32_t)gpio_irqE;
<> 144:ef7eb2e8f9f7 126 break;
<> 144:ef7eb2e8f9f7 127
<> 144:ef7eb2e8f9f7 128 default:
<> 144:ef7eb2e8f9f7 129 error("gpio_irq only supported on port A-E.");
<> 144:ef7eb2e8f9f7 130 break;
<> 144:ef7eb2e8f9f7 131 }
<> 144:ef7eb2e8f9f7 132 NVIC_SetVector(irq_n, vector);
<> 144:ef7eb2e8f9f7 133 NVIC_EnableIRQ(irq_n);
<> 144:ef7eb2e8f9f7 134
<> 144:ef7eb2e8f9f7 135 obj->ch = ch_base + obj->pin;
<> 144:ef7eb2e8f9f7 136 channel_ids[obj->ch] = id;
<> 144:ef7eb2e8f9f7 137
<> 144:ef7eb2e8f9f7 138 return 0;
<> 144:ef7eb2e8f9f7 139 }
<> 144:ef7eb2e8f9f7 140
<> 144:ef7eb2e8f9f7 141 void gpio_irq_free(gpio_irq_t *obj) {
<> 144:ef7eb2e8f9f7 142 channel_ids[obj->ch] = 0;
<> 144:ef7eb2e8f9f7 143 }
<> 144:ef7eb2e8f9f7 144
<> 144:ef7eb2e8f9f7 145 void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable) {
<> 144:ef7eb2e8f9f7 146 PORT_Type *port = (PORT_Type *)(PORTA_BASE + 0x1000 * obj->port);
<> 144:ef7eb2e8f9f7 147
<> 144:ef7eb2e8f9f7 148 uint32_t irq_settings = IRQ_DISABLED;
<> 144:ef7eb2e8f9f7 149
<> 144:ef7eb2e8f9f7 150 switch (port->PCR[obj->pin] & PORT_PCR_IRQC_MASK) {
<> 144:ef7eb2e8f9f7 151 case IRQ_DISABLED:
<> 144:ef7eb2e8f9f7 152 if (enable)
<> 144:ef7eb2e8f9f7 153 irq_settings = (event == IRQ_RISE) ? (IRQ_RAISING_EDGE) : (IRQ_FALLING_EDGE);
<> 144:ef7eb2e8f9f7 154 break;
<> 144:ef7eb2e8f9f7 155
<> 144:ef7eb2e8f9f7 156 case IRQ_RAISING_EDGE:
<> 144:ef7eb2e8f9f7 157 if (enable) {
<> 144:ef7eb2e8f9f7 158 irq_settings = (event == IRQ_RISE) ? (IRQ_RAISING_EDGE) : (IRQ_EITHER_EDGE);
<> 144:ef7eb2e8f9f7 159 } else {
<> 144:ef7eb2e8f9f7 160 if (event == IRQ_FALL)
<> 144:ef7eb2e8f9f7 161 irq_settings = IRQ_RAISING_EDGE;
<> 144:ef7eb2e8f9f7 162 }
<> 144:ef7eb2e8f9f7 163 break;
<> 144:ef7eb2e8f9f7 164
<> 144:ef7eb2e8f9f7 165 case IRQ_FALLING_EDGE:
<> 144:ef7eb2e8f9f7 166 if (enable) {
<> 144:ef7eb2e8f9f7 167 irq_settings = (event == IRQ_FALL) ? (IRQ_FALLING_EDGE) : (IRQ_EITHER_EDGE);
<> 144:ef7eb2e8f9f7 168 } else {
<> 144:ef7eb2e8f9f7 169 if (event == IRQ_RISE)
<> 144:ef7eb2e8f9f7 170 irq_settings = IRQ_FALLING_EDGE;
<> 144:ef7eb2e8f9f7 171 }
<> 144:ef7eb2e8f9f7 172 break;
<> 144:ef7eb2e8f9f7 173
<> 144:ef7eb2e8f9f7 174 case IRQ_EITHER_EDGE:
<> 144:ef7eb2e8f9f7 175 if (enable) {
<> 144:ef7eb2e8f9f7 176 irq_settings = IRQ_EITHER_EDGE;
<> 144:ef7eb2e8f9f7 177 } else {
<> 144:ef7eb2e8f9f7 178 irq_settings = (event == IRQ_RISE) ? (IRQ_FALLING_EDGE) : (IRQ_RAISING_EDGE);
<> 144:ef7eb2e8f9f7 179 }
<> 144:ef7eb2e8f9f7 180 break;
<> 144:ef7eb2e8f9f7 181 }
<> 144:ef7eb2e8f9f7 182
<> 144:ef7eb2e8f9f7 183 // Interrupt configuration and clear interrupt
<> 144:ef7eb2e8f9f7 184 port->PCR[obj->pin] = (port->PCR[obj->pin] & ~PORT_PCR_IRQC_MASK) | irq_settings | PORT_PCR_ISF_MASK;
<> 144:ef7eb2e8f9f7 185 }
<> 144:ef7eb2e8f9f7 186
<> 144:ef7eb2e8f9f7 187 void gpio_irq_enable(gpio_irq_t *obj) {
<> 144:ef7eb2e8f9f7 188 switch (obj->port) {
<> 144:ef7eb2e8f9f7 189 case PortA:
<> 144:ef7eb2e8f9f7 190 NVIC_EnableIRQ(PORTA_IRQn);
<> 144:ef7eb2e8f9f7 191 break;
<> 144:ef7eb2e8f9f7 192 case PortB:
<> 144:ef7eb2e8f9f7 193 NVIC_EnableIRQ(PORTB_IRQn);
<> 144:ef7eb2e8f9f7 194 break;
<> 144:ef7eb2e8f9f7 195 case PortC:
<> 144:ef7eb2e8f9f7 196 NVIC_EnableIRQ(PORTC_IRQn);
<> 144:ef7eb2e8f9f7 197 break;
<> 144:ef7eb2e8f9f7 198 case PortD:
<> 144:ef7eb2e8f9f7 199 NVIC_EnableIRQ(PORTD_IRQn);
<> 144:ef7eb2e8f9f7 200 break;
<> 144:ef7eb2e8f9f7 201 case PortE:
<> 144:ef7eb2e8f9f7 202 NVIC_EnableIRQ(PORTE_IRQn);
<> 144:ef7eb2e8f9f7 203 break;
<> 144:ef7eb2e8f9f7 204 }
<> 144:ef7eb2e8f9f7 205 }
<> 144:ef7eb2e8f9f7 206
<> 144:ef7eb2e8f9f7 207 void gpio_irq_disable(gpio_irq_t *obj) {
<> 144:ef7eb2e8f9f7 208 switch (obj->port) {
<> 144:ef7eb2e8f9f7 209 case PortA:
<> 144:ef7eb2e8f9f7 210 NVIC_DisableIRQ(PORTA_IRQn);
<> 144:ef7eb2e8f9f7 211 break;
<> 144:ef7eb2e8f9f7 212 case PortB:
<> 144:ef7eb2e8f9f7 213 NVIC_DisableIRQ(PORTB_IRQn);
<> 144:ef7eb2e8f9f7 214 break;
<> 144:ef7eb2e8f9f7 215 case PortC:
<> 144:ef7eb2e8f9f7 216 NVIC_DisableIRQ(PORTC_IRQn);
<> 144:ef7eb2e8f9f7 217 break;
<> 144:ef7eb2e8f9f7 218 case PortD:
<> 144:ef7eb2e8f9f7 219 NVIC_DisableIRQ(PORTD_IRQn);
<> 144:ef7eb2e8f9f7 220 break;
<> 144:ef7eb2e8f9f7 221 case PortE:
<> 144:ef7eb2e8f9f7 222 NVIC_DisableIRQ(PORTE_IRQn);
<> 144:ef7eb2e8f9f7 223 break;
<> 144:ef7eb2e8f9f7 224 }
<> 144:ef7eb2e8f9f7 225 }