From b2b78a871849b4781355d1f517ea5377232116b2 Mon Sep 17 00:00:00 2001 From: ZYH Date: Tue, 19 Mar 2019 11:01:15 +0800 Subject: [PATCH] [BSP][k210]Add GPIO driver --- bsp/k210/driver/SConscript | 3 + bsp/k210/driver/drv_gpio.c | 267 ++++++++++++++++++++++++++++++++ bsp/k210/driver/drv_gpio.h | 16 ++ bsp/k210/driver/drv_io_config.h | 1 + 4 files changed, 287 insertions(+) create mode 100644 bsp/k210/driver/drv_gpio.c create mode 100644 bsp/k210/driver/drv_gpio.h diff --git a/bsp/k210/driver/SConscript b/bsp/k210/driver/SConscript index 30eca625f9..4f1741e838 100644 --- a/bsp/k210/driver/SConscript +++ b/bsp/k210/driver/SConscript @@ -11,6 +11,9 @@ drv_io_config.c ''') CPPPATH = [cwd] +if GetDepend('RT_USING_PIN'): + src += ['drv_gpio.c'] + if GetDepend('BSP_USING_LCD'): src += ['drv_lcd.c'] diff --git a/bsp/k210/driver/drv_gpio.c b/bsp/k210/driver/drv_gpio.c new file mode 100644 index 0000000000..376fa3e1b1 --- /dev/null +++ b/bsp/k210/driver/drv_gpio.c @@ -0,0 +1,267 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-03-19 ZYH first version + */ + +#include +#include +#include +#include +#include "drv_gpio.h" +#include "drv_io_config.h" +#include +#include +#include +#include + +#define DBG_ENABLE +#define DBG_SECTION_NAME "PIN" +#define DBG_LEVEL DBG_WARNING +#define DBG_COLOR +#include + +#define FUNC_GPIOHS(n) (FUNC_GPIOHS0 + n) + +static int pin_alloc_table[FPIOA_NUM_IO]; +static uint32_t free_pin = 0; + +static int alloc_pin_channel(rt_base_t pin_index) +{ + if(free_pin == 31) + { + LOG_E("no free gpiohs channel to alloc"); + return -1; + } + + if(pin_alloc_table[pin_index] != -1) + { + LOG_W("already alloc gpiohs channel for pin %d", pin_index); + return pin_alloc_table[pin_index]; + } + + pin_alloc_table[pin_index] = free_pin; + free_pin++; + + fpioa_set_function(pin_index, FUNC_GPIOHS(pin_alloc_table[pin_index])); + return pin_alloc_table[pin_index]; +} + +static int get_pin_channel(rt_base_t pin_index) +{ + return pin_alloc_table[pin_index]; +} + +static void free_pin_channel(rt_base_t pin_index) +{ + if(pin_alloc_table[pin_index] == -1) + { + LOG_W("free error:not alloc gpiohs channel for pin %d", pin_index); + return; + } + pin_alloc_table[pin_index] = -1; + free_pin--; +} + + +static void drv_pin_mode(struct rt_device *device, rt_base_t pin, rt_base_t mode) +{ + int pin_channel = get_pin_channel(pin); + if(pin_channel == -1) + { + pin_channel = alloc_pin_channel(pin); + if(pin_channel == -1) + { + return; + } + } + + switch (mode) + { + case PIN_MODE_OUTPUT: + gpiohs_set_drive_mode(pin_channel, GPIO_DM_OUTPUT); + break; + case PIN_MODE_INPUT: + gpiohs_set_drive_mode(pin_channel, GPIO_DM_INPUT); + break; + case PIN_MODE_INPUT_PULLUP: + gpiohs_set_drive_mode(pin_channel, GPIO_DM_INPUT_PULL_UP); + break; + case PIN_MODE_INPUT_PULLDOWN: + gpiohs_set_drive_mode(pin_channel, GPIO_DM_INPUT_PULL_DOWN); + break; + default: + LOG_E("Not support mode %d", mode); + break; + } +} + +static void drv_pin_write(struct rt_device *device, rt_base_t pin, rt_base_t value) +{ + int pin_channel = get_pin_channel(pin); + if(pin_channel == -1) + { + LOG_E("pin %d not set mode", pin); + return; + } + gpiohs_set_pin(pin_channel, value == PIN_HIGH ? GPIO_PV_HIGH : GPIO_PV_LOW); +} + +static int drv_pin_read(struct rt_device *device, rt_base_t pin) +{ + int pin_channel = get_pin_channel(pin); + if(pin_channel == -1) + { + LOG_E("pin %d not set mode", pin); + return -1; + } + return gpiohs_get_pin(pin_channel) == GPIO_PV_HIGH ? PIN_HIGH : PIN_LOW; +} + +static struct +{ + void (*hdr)(void *args); + void *args; + gpio_pin_edge_t edge; +} irq_table[32]; + +static void pin_irq(int vector, void *param) +{ + int pin_channel = vector - IRQN_GPIOHS0_INTERRUPT; + if(irq_table[pin_channel].edge & GPIO_PE_FALLING) + { + set_gpio_bit(gpiohs->fall_ie.u32, pin_channel, 0); + set_gpio_bit(gpiohs->fall_ip.u32, pin_channel, 1); + set_gpio_bit(gpiohs->fall_ie.u32, pin_channel, 1); + } + + if(irq_table[pin_channel 2019-03-18 ZYH first version].edge & GPIO_PE_RISING) + { + set_gpio_bit(gpiohs->rise_ie.u32, pin_channel, 0); + set_gpio_bit(gpiohs->rise_ip.u32, pin_channel, 1); + set_gpio_bit(gpiohs->rise_ie.u32, pin_channel, 1); + } + + if(irq_table[pin_channel].edge & GPIO_PE_LOW) + { + set_gpio_bit(gpiohs->low_ie.u32, pin_channel, 0); + set_gpio_bit(gpiohs->low_ip.u32, pin_channel, 1); + set_gpio_bit(gpiohs->low_ie.u32, pin_channel, 1); + } + + if(irq_table[pin_channel].edge & GPIO_PE_HIGH) + { + set_gpio_bit(gpiohs->high_ie.u32, pin_channel, 0); + set_gpio_bit(gpiohs->high_ip.u32, pin_channel, 1); + set_gpio_bit(gpiohs->high_ie.u32, pin_channel, 1); + } + if(irq_table[pin_channel].hdr) + { + irq_table[pin_channel].hdr(irq_table[pin_channel].args); + } +} + +static rt_err_t drv_pin_attach_irq(struct rt_device *device, rt_int32_t pin, + rt_uint32_t mode, void (*hdr)(void *args), void *args) +{ + int pin_channel = get_pin_channel(pin); + char irq_name[10]; + if(pin_channel == -1) + { + LOG_E("pin %d not set mode", pin); + return -RT_ERROR; + } + irq_table[pin_channel].hdr = hdr; + irq_table[pin_channel].args = args; + switch (mode) + { + case PIN_IRQ_MODE_RISING: + irq_table[pin_channel].edge = GPIO_PE_FALLING; + break; + case PIN_IRQ_MODE_FALLING: + irq_table[pin_channel].edge = GPIO_PE_RISING; + break; + case PIN_IRQ_MODE_RISING_FALLING: + irq_table[pin_channel].edge = GPIO_PE_BOTH; + break; + case PIN_IRQ_MODE_HIGH_LEVEL: + irq_table[pin_channel].edge = GPIO_PE_LOW; + break; + case PIN_IRQ_MODE_LOW_LEVEL: + irq_table[pin_channel].edge = GPIO_PE_HIGH; + break; + default: + break; + } + gpiohs_set_pin_edge(pin_channel, irq_table[pin_channel].edge); + rt_snprintf(irq_name, sizeof irq_name, "pin%d", pin); + rt_hw_interrupt_install(IRQN_GPIOHS0_INTERRUPT + pin_channel, pin_irq, RT_NULL, irq_name); + + return RT_EOK; +} + +static rt_err_t drv_pin_detach_irq(struct rt_device *device, rt_int32_t pin) +{ + rt_err_t ret = RT_EOK; + + int pin_channel = get_pin_channel(pin); + if(pin_channel == -1) + { + LOG_E("pin %d not set mode", pin); + return -RT_ERROR; + } + + irq_table[pin_channel].hdr = RT_NULL; + irq_table[pin_channel].args = RT_NULL; + + return ret; +} + +static rt_err_t drv_pin_irq_enable(struct rt_device *device, rt_base_t pin, rt_uint32_t enabled) +{ + int pin_channel = get_pin_channel(pin); + + if(pin_channel == -1) + { + LOG_E("pin %d not set mode", pin); + return -RT_ERROR; + } + + if(enabled) + { + rt_hw_interrupt_umask(IRQN_GPIOHS0_INTERRUPT + pin_channel); + } + else + { + rt_hw_interrupt_mask(IRQN_GPIOHS0_INTERRUPT + pin_channel); + } + + return RT_EOK; +} + +const static struct rt_pin_ops drv_pin_ops = +{ + drv_pin_mode, + drv_pin_write, + drv_pin_read, + + drv_pin_attach_irq, + drv_pin_detach_irq, + drv_pin_irq_enable +}; + +int rt_hw_pin_init(void) +{ + rt_err_t ret = RT_EOK; + memset(pin_alloc_table, 0, sizeof pin_alloc_table); + free_pin = GPIO_ALLOC_START; + ret = rt_device_pin_register("pin", &drv_pin_ops, RT_NULL); + + return ret; +} +INIT_BOARD_EXPORT(rt_hw_pin_init); + diff --git a/bsp/k210/driver/drv_gpio.h b/bsp/k210/driver/drv_gpio.h new file mode 100644 index 0000000000..1b4cf4e21a --- /dev/null +++ b/bsp/k210/driver/drv_gpio.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-03-19 ZYH first version + */ + +#ifndef DRV_GPIO_H__ +#define DRV_GPIO_H__ + +int rt_hw_pin_init(void); + +#endif \ No newline at end of file diff --git a/bsp/k210/driver/drv_io_config.h b/bsp/k210/driver/drv_io_config.h index c5c00161fe..52bb8c6e52 100644 --- a/bsp/k210/driver/drv_io_config.h +++ b/bsp/k210/driver/drv_io_config.h @@ -18,6 +18,7 @@ enum HS_GPIO_CONFIG #ifdef BSP_SPI1_USING_SS3 SPI1_CS3_PIN, #endif + GPIO_ALLOC_START /* index of gpio driver start */ }; extern int io_config_init(void); -- GitLab