123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202 |
- #include <board.h>
- #include "drv_gpio.h"
- #include "rtdevice.h"
- #include "rthw.h"
- #include "xparameters.h"
- #include "xgpiops.h"
- #define GPIOPS_ID XPAR_XGPIOPS_0_DEVICE_ID
- #define GPIO_INTERRUPT_ID XPAR_XGPIOPS_0_INTR
- struct hw_intr_node {
- rt_slist_t node;
- rt_uint32_t id;
- void (*hdr)(void *args);
- void *args;
- };
- static XGpioPs gpio;
- static rt_slist_t intr_list;
- rt_inline struct hw_intr_node *_find_intr_node(rt_uint32_t id)
- {
- struct hw_intr_node *p;
- rt_slist_for_each_entry(p, &intr_list, node)
- {
- if (p->id == id)
- {
- return p;
- }
- }
- return RT_NULL;
- }
- static void intr_handler(int vector, void *param)
- {
- struct hw_intr_node *p;
- rt_slist_for_each_entry(p, &intr_list, node)
- {
- if (!XGpioPs_IntrGetStatusPin(&gpio, p->id))
- continue;
- XGpioPs_IntrDisablePin(&gpio, p->id);
- if (p->hdr)
- p->hdr(p->args);
- XGpioPs_IntrClearPin(&gpio, p->id);
- XGpioPs_IntrEnablePin(&gpio, p->id);
- }
- }
- static rt_base_t zynq_pin_get(const char *name)
- {
- rt_set_errno(-RT_ENOSYS);
- return -1;
- }
- static void zynq_pin_write(rt_device_t dev, rt_base_t pin, rt_uint8_t value)
- {
- if (pin >= XGPIOPS_DEVICE_MAX_PIN_NUM)
- {
- rt_set_errno(-RT_ENOSYS);
- return;
- }
- XGpioPs_WritePin(&gpio, pin, value);
- }
- static rt_int8_t zynq_pin_read(rt_device_t dev, rt_base_t pin)
- {
- if (pin >= XGPIOPS_DEVICE_MAX_PIN_NUM)
- {
- rt_set_errno(-RT_ENOSYS);
- return -1;
- }
- return XGpioPs_ReadPin(&gpio, pin);
- }
- static void zynq_pin_mode(rt_device_t dev, rt_base_t pin, rt_uint8_t mode)
- {
- rt_uint8_t isOutput = (mode == PIN_MODE_OUTPUT) || (mode == PIN_MODE_OUTPUT_OD);
- XGpioPs_SetDirectionPin(&gpio, pin, isOutput);
- XGpioPs_SetOutputEnablePin(&gpio, pin, isOutput);
- }
- static rt_err_t zynq_pin_attach_irq(struct rt_device *device, rt_int32_t pin,
- rt_uint8_t mode, void (*hdr)(void *args), void *args)
- {
- u8 irq_type;
- switch (mode)
- {
- case PIN_IRQ_MODE_RISING:
- irq_type = XGPIOPS_IRQ_TYPE_EDGE_RISING;
- break;
- case PIN_IRQ_MODE_FALLING:
- irq_type = XGPIOPS_IRQ_TYPE_EDGE_FALLING;
- break;
- case PIN_IRQ_MODE_RISING_FALLING:
- irq_type = XGPIOPS_IRQ_TYPE_EDGE_BOTH;
- break;
- case PIN_IRQ_MODE_HIGH_LEVEL:
- irq_type = XGPIOPS_IRQ_TYPE_LEVEL_HIGH;
- break;
- case PIN_IRQ_MODE_LOW_LEVEL:
- irq_type = XGPIOPS_IRQ_TYPE_LEVEL_LOW;
- break;
- default:
- return -RT_ENOSYS;
- }
- struct hw_intr_node *node = _find_intr_node(pin);
- if (node != RT_NULL)
- {
- return -RT_EBUSY;
- }
- node = rt_malloc(sizeof(struct hw_intr_node));
- if (node == RT_NULL)
- {
- return -RT_ENOMEM;
- }
- XGpioPs_SetIntrTypePin(&gpio, pin, irq_type);
- node->id = pin;
- node->hdr = hdr;
- node->args = args;
- rt_slist_append(&intr_list, &node->node);
- return RT_EOK;
- }
- static rt_err_t zynq_pin_dettach_irq(struct rt_device *device, rt_base_t pin)
- {
- struct hw_intr_node *node;
- rt_enter_critical();
- node = _find_intr_node(pin);
- if (node != RT_NULL)
- {
- rt_exit_critical();
- return -RT_ERROR;
- }
- rt_slist_remove(&intr_list, &node->node);
- rt_exit_critical();
- rt_free(node);
- return RT_EOK;
- }
- static rt_err_t zynq_pin_irq_enable(struct rt_device *device, rt_base_t pin,
- rt_uint8_t enabled)
- {
- if (enabled)
- {
- XGpioPs_IntrEnablePin(&gpio, pin);
- }
- else
- {
- XGpioPs_IntrDisablePin(&gpio, pin);
- }
- return RT_EOK;
- }
- const static struct rt_pin_ops _zynq_pin_ops =
- {
- zynq_pin_mode,
- zynq_pin_write,
- zynq_pin_read,
- zynq_pin_attach_irq,
- zynq_pin_dettach_irq,
- zynq_pin_irq_enable,
- zynq_pin_get,
- };
- int rt_hw_pin_init(void)
- {
- XGpioPs_Config *gpiops_cfg_ptr;
- gpiops_cfg_ptr = XGpioPs_LookupConfig(GPIOPS_ID);
- RT_ASSERT(gpiops_cfg_ptr);
- RT_ASSERT(
- XGpioPs_CfgInitialize(&gpio, gpiops_cfg_ptr, gpiops_cfg_ptr->BaseAddr)
- == 0
- )
- rt_slist_init(&intr_list);
- rt_hw_interrupt_install(GPIO_INTERRUPT_ID, intr_handler, RT_NULL, "pin");
- rt_hw_interrupt_umask(GPIO_INTERRUPT_ID);
- return rt_device_pin_register("pin", &_zynq_pin_ops, RT_NULL);
- }
|