/* * Copyright (c) 2006-2020, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2021-02-11 supperthomas first version * */ #include "drv_gpio.h" #include #include "gpio.h" #ifdef RT_USING_PIN #define DBG_LEVEL DBG_LOG #include #define LOG_TAG "drv.gpio" #define PIN_PORT_OFFSET 4 #define PIN_NUM(port, no) ((((((port) & 0xFu) << PIN_PORT_OFFSET) | ((no) & 0xFu))) #define PIN_PORT(pin) ((uint8_t)(((pin) >> PIN_PORT_OFFSET) & 0xFu)) #define PIN_NO(pin) ((uint8_t)((pin) & 0xFu)) #define PIN_MCU_PORT(pin) PIN_PORT(pin) #define PIN_MCU_PIN(pin) ((uint32_t)(1u << PIN_NO(pin))) static void mcu_pin_write(rt_device_t dev, rt_base_t pin, rt_base_t value) { gpio_cfg_t tmp_gpio_cfg; tmp_gpio_cfg.port = PIN_PORT(pin); tmp_gpio_cfg.mask = PIN_MCU_PIN(pin); if (value) { GPIO_OutSet(&tmp_gpio_cfg); } else { GPIO_OutClr(&tmp_gpio_cfg); } } static int mcu_pin_read(rt_device_t dev, rt_base_t pin) { int value; gpio_cfg_t tmp_gpio_cfg; tmp_gpio_cfg.port = PIN_PORT(pin); tmp_gpio_cfg.mask = PIN_MCU_PIN(pin); if (GPIO_InGet(&tmp_gpio_cfg)) { value = 1; } else { value = 0; } return value; } static void mcu_pin_mode(rt_device_t dev, rt_base_t pin, rt_base_t mode) { gpio_cfg_t tmp_gpio_cfg; int ret = 0; tmp_gpio_cfg.port = PIN_PORT(pin); tmp_gpio_cfg.mask = PIN_MCU_PIN(pin); switch (mode) { case PIN_MODE_OUTPUT: tmp_gpio_cfg.func = GPIO_FUNC_OUT; tmp_gpio_cfg.pad = GPIO_PAD_NONE; break; case PIN_MODE_INPUT: tmp_gpio_cfg.func = GPIO_FUNC_IN; tmp_gpio_cfg.pad = GPIO_PAD_NONE; break; case PIN_MODE_INPUT_PULLUP: tmp_gpio_cfg.func = GPIO_FUNC_IN; tmp_gpio_cfg.pad = GPIO_PAD_PULL_UP; break; case PIN_MODE_INPUT_PULLDOWN: tmp_gpio_cfg.func = GPIO_FUNC_IN; tmp_gpio_cfg.pad = GPIO_PAD_PULL_DOWN; break; case PIN_MODE_OUTPUT_OD: //not support LOG_E("NOT SUPPORT"); break; } ret = GPIO_Config(&tmp_gpio_cfg); if (E_NO_ERROR != ret) { LOG_E("GPIO_Config error :%d", ret); } } static rt_err_t mcu_pin_attach_irq(struct rt_device *device, rt_int32_t pin, rt_uint32_t irq_mode, void (*hdr)(void *args), void *args) { gpio_cfg_t tmp_gpio_cfg; tmp_gpio_cfg.port = PIN_MCU_PORT(pin); tmp_gpio_cfg.mask = PIN_MCU_PIN(pin); tmp_gpio_cfg.pad = GPIO_PAD_PULL_UP; tmp_gpio_cfg.func = GPIO_FUNC_IN; GPIO_Config(&tmp_gpio_cfg); GPIO_RegisterCallback(&tmp_gpio_cfg, hdr, args); gpio_int_mode_t mcu_mode; gpio_int_pol_t mcu_pol; switch (irq_mode) { case PIN_IRQ_MODE_RISING: mcu_mode = GPIO_INT_EDGE; mcu_pol = GPIO_INT_RISING; break; case PIN_IRQ_MODE_FALLING: mcu_mode = GPIO_INT_EDGE; mcu_pol = GPIO_INT_FALLING; break; case PIN_IRQ_MODE_RISING_FALLING: mcu_mode = GPIO_INT_EDGE; mcu_pol = GPIO_INT_BOTH; break; case PIN_IRQ_MODE_HIGH_LEVEL: mcu_mode = GPIO_INT_LEVEL; mcu_pol = GPIO_INT_HIGH; break; case PIN_IRQ_MODE_LOW_LEVEL: mcu_mode = GPIO_INT_LEVEL; mcu_pol = GPIO_INT_LOW; break; } GPIO_IntConfig(&tmp_gpio_cfg, mcu_mode, mcu_pol); return RT_EOK; } static rt_err_t mcu_pin_dettach_irq(struct rt_device *device, rt_int32_t pin) { gpio_cfg_t tmp_gpio_cfg; tmp_gpio_cfg.port = PIN_MCU_PORT(pin); tmp_gpio_cfg.mask = PIN_MCU_PIN(pin); tmp_gpio_cfg.pad = GPIO_PAD_PULL_UP; tmp_gpio_cfg.func = GPIO_FUNC_IN; GPIO_Config(&tmp_gpio_cfg); GPIO_IntDisable(&tmp_gpio_cfg); GPIO_RegisterCallback(&tmp_gpio_cfg, NULL, NULL); return RT_EOK; } static rt_err_t mcu_pin_irq_enable(struct rt_device *device, rt_base_t pin, rt_uint32_t enabled) { gpio_cfg_t tmp_gpio_cfg; tmp_gpio_cfg.port = PIN_MCU_PORT(pin); tmp_gpio_cfg.mask = PIN_MCU_PIN(pin); if (enabled) { GPIO_IntEnable(&tmp_gpio_cfg); NVIC_EnableIRQ((IRQn_Type)MXC_GPIO_GET_IRQ(PIN_MCU_PORT(pin))); } else { GPIO_IntDisable(&tmp_gpio_cfg); NVIC_DisableIRQ((IRQn_Type)MXC_GPIO_GET_IRQ(PIN_MCU_PORT(pin))); } return RT_EOK; } const static struct rt_pin_ops _mcu_pin_ops = { mcu_pin_mode, mcu_pin_write, mcu_pin_read, mcu_pin_attach_irq, mcu_pin_dettach_irq, mcu_pin_irq_enable, NULL, }; int rt_hw_pin_init(void) { GPIO_Init(); return rt_device_pin_register("pin", &_mcu_pin_ops, RT_NULL); } INIT_BOARD_EXPORT(rt_hw_pin_init); void GPIO0_IRQHandler(void) { GPIO_Handler(PORT_0); } #endif /* RT_USING_PIN */