mirror of https://github.com/ARMmbed/mbed-os.git
155 lines
4.2 KiB
C
155 lines
4.2 KiB
C
/****************************************************************************
|
|
*
|
|
* Copyright 2020 Samsung Electronics All Rights Reserved.
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* 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.
|
|
*
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Included Files
|
|
****************************************************************************/
|
|
|
|
#include <stddef.h>
|
|
#include "cmsis.h"
|
|
#include "gpio_irq_api.h"
|
|
#include "mbed_error.h"
|
|
|
|
/****************************************************************************
|
|
* Pre-processor definitions
|
|
****************************************************************************/
|
|
#define CHANNEL_NUM 48
|
|
#define MAX_PIN_PER_PORT 16
|
|
static gpio_irq_handler irq_handler;
|
|
static uint32_t channel_ids[CHANNEL_NUM];
|
|
static gpio_irq_event pins_event[CHANNEL_NUM];
|
|
|
|
static inline void handle_gpio_irq(uint32_t port)
|
|
{
|
|
int i;
|
|
uint32_t pin_name = port << 4;
|
|
|
|
BP_GPIO_TypeDef *gpio_base = (BP_GPIO_TypeDef *)GPIO_PORT_BASE(port);
|
|
|
|
for (i = 0; i < MAX_PIN_PER_PORT; i++) {
|
|
if (gpio_base->INTSTAT & (1u << i)) {
|
|
pin_name += i;
|
|
NVIC_ClearPendingIRQ(PORT0_0_IRQn + port * 16 + i);
|
|
gpio_base->INTCLR = 1u << i;
|
|
irq_handler(channel_ids[pin_name], pins_event[pin_name]);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void gpio0_irq(void)
|
|
{
|
|
handle_gpio_irq(0);
|
|
NVIC_ClearPendingIRQ(PORT0_ALL_IRQn);
|
|
}
|
|
void gpio1_irq(void)
|
|
{
|
|
handle_gpio_irq(1);
|
|
NVIC_ClearPendingIRQ(PORT1_ALL_IRQn);
|
|
}
|
|
void gpio2_irq(void)
|
|
{
|
|
handle_gpio_irq(2);
|
|
NVIC_ClearPendingIRQ(PORT2_ALL_IRQn);
|
|
}
|
|
|
|
int gpio_irq_init(gpio_irq_t *obj, PinName pin,
|
|
gpio_irq_handler handler, uint32_t id)
|
|
{
|
|
if (pin == (PinName)NC) {
|
|
return -1;
|
|
}
|
|
|
|
obj->pin = pin;
|
|
irq_handler = handler;
|
|
channel_ids[pin] = id;
|
|
|
|
bp6a_gpio_set_dir(BP6A_PORT_IDX(obj->pin), BP6A_PIN_IDX(obj->pin), true);
|
|
return 0;
|
|
}
|
|
|
|
void gpio_irq_free(gpio_irq_t *obj)
|
|
{
|
|
channel_ids[obj->pin] = 0;
|
|
gpio_irq_disable(obj);
|
|
}
|
|
|
|
void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable)
|
|
{
|
|
pins_event[obj->pin] = event;
|
|
|
|
if (event == IRQ_NONE) {
|
|
return;
|
|
}
|
|
|
|
if (event == IRQ_RISE) {
|
|
bp6a_gpio_set_int_type(BP6A_PORT_IDX(obj->pin), BP6A_PIN_IDX(obj->pin),
|
|
true, true);
|
|
} else {
|
|
bp6a_gpio_set_int_type(BP6A_PORT_IDX(obj->pin), BP6A_PIN_IDX(obj->pin),
|
|
false, true);
|
|
}
|
|
if (enable) {
|
|
gpio_irq_enable(obj);
|
|
} else {
|
|
gpio_irq_disable(obj);
|
|
}
|
|
}
|
|
|
|
void gpio_irq_enable(gpio_irq_t *obj)
|
|
{
|
|
uint32_t port = BP6A_PORT_IDX(obj->pin);
|
|
|
|
bp6a_gpio_set_int(port, BP6A_PIN_IDX(obj->pin), true);
|
|
|
|
void (*port_irq)(void) = NULL;
|
|
|
|
switch (port) {
|
|
case 0:
|
|
port_irq = &gpio0_irq;
|
|
break;
|
|
case 1:
|
|
port_irq = &gpio1_irq;
|
|
break;
|
|
case 2:
|
|
port_irq = &gpio2_irq;
|
|
break;
|
|
}
|
|
|
|
NVIC_SetVector((IRQn_Type)(PORT0_0_IRQn + port * 16 + BP6A_PIN_IDX(obj->pin)), (uint32_t)port_irq);
|
|
|
|
#if defined (__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U)
|
|
SCB_InvalidateICache();
|
|
#endif
|
|
|
|
NVIC_EnableIRQ((IRQn_Type)(PORT0_0_IRQn + port * 16 + BP6A_PIN_IDX(obj->pin)));
|
|
}
|
|
|
|
void gpio_irq_disable(gpio_irq_t *obj)
|
|
{
|
|
uint32_t port_n = BP6A_PORT_IDX(obj->pin);
|
|
uint32_t pin_n = BP6A_PIN_IDX(obj->pin);
|
|
|
|
NVIC_ClearPendingIRQ((IRQn_Type)(PORT0_ALL_IRQn + port_n));
|
|
bp6a_gpio_clear_pend(port_n, pin_n);
|
|
|
|
NVIC_DisableIRQ((IRQn_Type)(PORT0_ALL_IRQn + port_n));
|
|
bp6a_gpio_set_int(port_n, pin_n, false);
|
|
}
|