mbed-os/targets/TARGET_TOSHIBA/TARGET_TMPM066/gpio_irq_api.c

235 lines
7.2 KiB
C
Raw Normal View History

2017-08-01 05:56:58 +00:00
/* mbed Microcontroller Library
* (C)Copyright TOSHIBA ELECTRONIC DEVICES & STORAGE CORPORATION 2017 All rights reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "gpio_irq_api.h"
#include "mbed_error.h"
#include "PeripheralNames.h"
#include "pinmap.h"
#include "mbed_critical.h"
2017-08-01 05:56:58 +00:00
#define CHANNEL_NUM 6
const PinMap PinMap_GPIO_IRQ[] = {
{PD5, GPIO_IRQ_0, PIN_DATA(0, 0)},
{PA5, GPIO_IRQ_1, PIN_DATA(0, 0)},
{PA6, GPIO_IRQ_2, PIN_DATA(0, 0)},
{PF1, GPIO_IRQ_3, PIN_DATA(0, 0)},
{PC5, GPIO_IRQ_4, PIN_DATA(0, 0)},
{PF0, GPIO_IRQ_5, PIN_DATA(0, 0)},
{NC, NC, 0}
};
static uint32_t channel_ids[CHANNEL_NUM] = {0};
static gpio_irq_handler hal_irq_handler[CHANNEL_NUM] = {NULL};
static void INT_IRQHandler(PinName pin, GPIO_IRQName irq_id, uint32_t index)
{
uint32_t val;
GPIO_Port port;
uint32_t mask;
INTIFAO_INTActiveState ActiveState;
port = (GPIO_Port)(pin >> 3);
mask = 0x01 << (pin & 0x07);
// Clear interrupt request
INTIFAO_ClearINTReq((INTIFAO_INTSrc)(INTIFAO_INT_SRC_0 + index));
// Clear gpio pending interrupt
NVIC_ClearPendingIRQ((IRQn_Type)irq_id);
ActiveState = INTIFAO_GetSTBYReleaseINTState((INTIFAO_INTSrc)(INTIFAO_INT_SRC_0 + index));
INTIFAO_SetSTBYReleaseINTSrc((INTIFAO_INTSrc)(INTIFAO_INT_SRC_0 + index),
ActiveState, DISABLE);
// Get pin value
val = GPIO_ReadDataBit(port, mask);
switch (val) {
// Falling edge detection
case 0:
hal_irq_handler[index](channel_ids[index], IRQ_FALL);
break;
// Rising edge detection
case 1:
hal_irq_handler[index](channel_ids[index], IRQ_RISE);
break;
default:
break;
}
// Enable interrupt request
INTIFAO_SetSTBYReleaseINTSrc((INTIFAO_INTSrc)(INTIFAO_INT_SRC_0 + index),
ActiveState, ENABLE);
}
void INT0_IRQHandler(void)
{
INT_IRQHandler(PD5, GPIO_IRQ_0, 0);
}
void INT1_IRQHandler(void)
{
INT_IRQHandler(PA5, GPIO_IRQ_1, 1);
}
void INT2_IRQHandler(void)
{
INT_IRQHandler(PA6, GPIO_IRQ_2, 2);
}
void INT3_IRQHandler(void)
{
INT_IRQHandler(PF1, GPIO_IRQ_3, 3);
}
void INT4_IRQHandler(void)
{
INT_IRQHandler(PC5, GPIO_IRQ_4, 4);
}
void INT5_IRQHandler(void)
{
INT_IRQHandler(PF0, GPIO_IRQ_5, 5);
}
int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id)
{
// Get gpio interrupt ID
obj->irq_id = pinmap_peripheral(pin, PinMap_GPIO_IRQ);
core_util_critical_section_enter();
2017-08-01 05:56:58 +00:00
// Get pin mask
obj->mask = (uint32_t)(1 << (pin & 0x07));
// Get GPIO port
obj->port = (GPIO_Port)(pin >> 3);
// Set pin level as LOW
GPIO_WriteDataBit(obj->port, obj->mask, 0);
// Enable gpio interrupt function
pinmap_pinout(pin, PinMap_GPIO_IRQ);
// Get GPIO irq source
switch (obj->irq_id) {
case GPIO_IRQ_0:
obj->irq_src = INTIFAO_INT_SRC_0;
break;
case GPIO_IRQ_1:
obj->irq_src = INTIFAO_INT_SRC_1;
break;
case GPIO_IRQ_2:
obj->irq_src = INTIFAO_INT_SRC_2;
break;
case GPIO_IRQ_3:
obj->irq_src = INTIFAO_INT_SRC_3;
break;
case GPIO_IRQ_4:
obj->irq_src = INTIFAO_INT_SRC_4;
break;
case GPIO_IRQ_5:
obj->irq_src = INTIFAO_INT_SRC_5;
break;
default:
break;
}
// Save irq handler
hal_irq_handler[obj->irq_src] = handler;
// Save irq id
channel_ids[obj->irq_src] = id;
// Initialize interrupt event as both edges detection
obj->event = INTIFAO_INT_ACTIVE_STATE_INVALID;
// Set interrupt event and enable INTx clear
INTIFAO_SetSTBYReleaseINTSrc(obj->irq_src, (INTIFAO_INTActiveState)obj->event, ENABLE);
// Clear gpio pending interrupt
NVIC_ClearPendingIRQ((IRQn_Type)obj->irq_id);
core_util_critical_section_exit();;
2017-08-01 05:56:58 +00:00
return 0;
}
void gpio_irq_free(gpio_irq_t *obj)
{
// Clear gpio_irq
NVIC_ClearPendingIRQ((IRQn_Type)obj->irq_id);
// Reset interrupt handler
hal_irq_handler[obj->irq_src] = NULL;
// Reset interrupt id
channel_ids[obj->irq_src] = 0;
}
void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable)
{
//Disable GPIO interrupt on obj
gpio_irq_disable(obj);
if (enable) {
// Get gpio interrupt event
if (event == IRQ_RISE) {
if ((obj->event == INTIFAO_INT_ACTIVE_STATE_FALLING) ||
(obj->event == INTIFAO_INT_ACTIVE_STATE_BOTH_EDGES)) {
obj->event = INTIFAO_INT_ACTIVE_STATE_BOTH_EDGES;
} else {
obj->event = INTIFAO_INT_ACTIVE_STATE_RISING;
}
} else if (event == IRQ_FALL) {
if ((obj->event == INTIFAO_INT_ACTIVE_STATE_RISING) ||
(obj->event == INTIFAO_INT_ACTIVE_STATE_BOTH_EDGES)) {
obj->event = INTIFAO_INT_ACTIVE_STATE_BOTH_EDGES;
} else {
obj->event = INTIFAO_INT_ACTIVE_STATE_FALLING;
}
} else {
error("Not supported event\n");
}
} else {
// Get gpio interrupt event
if (event == IRQ_RISE) {
if ((obj->event == INTIFAO_INT_ACTIVE_STATE_RISING) ||
(obj->event == INTIFAO_INT_ACTIVE_STATE_INVALID)) {
obj->event = INTIFAO_INT_ACTIVE_STATE_INVALID;
} else {
obj->event = INTIFAO_INT_ACTIVE_STATE_FALLING;
}
} else if (event == IRQ_FALL) {
if ((obj->event == INTIFAO_INT_ACTIVE_STATE_FALLING) ||
(obj->event == INTIFAO_INT_ACTIVE_STATE_INVALID)) {
obj->event = INTIFAO_INT_ACTIVE_STATE_INVALID;
} else {
obj->event = INTIFAO_INT_ACTIVE_STATE_RISING;
}
} else {
error("Not supported event\n");
}
}
if (obj->event != INTIFAO_INT_ACTIVE_STATE_INVALID) {
2017-08-01 05:56:58 +00:00
// Set interrupt event and enable INTx clear
INTIFAO_SetSTBYReleaseINTSrc(obj->irq_src, (INTIFAO_INTActiveState)obj->event, ENABLE);
GPIO_SetOutputEnableReg(obj->port, obj->mask, DISABLE);
} else {
GPIO_SetOutputEnableReg(obj->port, obj->mask, ENABLE);
}
// Clear interrupt request
INTIFAO_ClearINTReq(obj->irq_src);
// Enable GPIO interrupt on obj
gpio_irq_enable(obj);
}
void gpio_irq_enable(gpio_irq_t *obj)
{
// Clear and Enable gpio_irq object
NVIC_ClearPendingIRQ((IRQn_Type)obj->irq_id);
NVIC_EnableIRQ((IRQn_Type)obj->irq_id);
}
void gpio_irq_disable(gpio_irq_t *obj)
{
// Disable gpio_irq object
NVIC_DisableIRQ((IRQn_Type)obj->irq_id);
}