diff --git a/bsp/stm32f10x/drivers/gpio.c b/bsp/stm32f10x/drivers/gpio.c index 7bcff4602f..5010481a15 100755 --- a/bsp/stm32f10x/drivers/gpio.c +++ b/bsp/stm32f10x/drivers/gpio.c @@ -17,6 +17,7 @@ #include #include #include +#include #ifdef RT_USING_PIN @@ -408,6 +409,50 @@ static const struct pin_index pins[] = #endif }; +struct pin_irq_map +{ + rt_uint16_t pinbit; + rt_uint32_t irqbit; + enum IRQn irqno; +}; +static const struct pin_irq_map pin_irq_map[] = +{ + {GPIO_Pin_0, EXTI_Line0, EXTI0_IRQn }, + {GPIO_Pin_1, EXTI_Line1, EXTI1_IRQn }, + {GPIO_Pin_2, EXTI_Line2, EXTI2_IRQn }, + {GPIO_Pin_3, EXTI_Line3, EXTI3_IRQn }, + {GPIO_Pin_4, EXTI_Line4, EXTI4_IRQn }, + {GPIO_Pin_5, EXTI_Line5, EXTI9_5_IRQn }, + {GPIO_Pin_6, EXTI_Line6, EXTI9_5_IRQn }, + {GPIO_Pin_7, EXTI_Line7, EXTI9_5_IRQn }, + {GPIO_Pin_8, EXTI_Line8, EXTI9_5_IRQn }, + {GPIO_Pin_9, EXTI_Line9, EXTI9_5_IRQn }, + {GPIO_Pin_10, EXTI_Line10, EXTI15_10_IRQn}, + {GPIO_Pin_11, EXTI_Line11, EXTI15_10_IRQn}, + {GPIO_Pin_12, EXTI_Line12, EXTI15_10_IRQn}, + {GPIO_Pin_13, EXTI_Line13, EXTI15_10_IRQn}, + {GPIO_Pin_14, EXTI_Line14, EXTI15_10_IRQn}, + {GPIO_Pin_15, EXTI_Line15, EXTI15_10_IRQn}, +}; +struct rt_pin_irq_hdr pin_irq_hdr_tab[] = +{ + {-1, 0, RT_NULL, RT_NULL}, + {-1, 0, RT_NULL, RT_NULL}, + {-1, 0, RT_NULL, RT_NULL}, + {-1, 0, RT_NULL, RT_NULL}, + {-1, 0, RT_NULL, RT_NULL}, + {-1, 0, RT_NULL, RT_NULL}, + {-1, 0, RT_NULL, RT_NULL}, + {-1, 0, RT_NULL, RT_NULL}, + {-1, 0, RT_NULL, RT_NULL}, + {-1, 0, RT_NULL, RT_NULL}, + {-1, 0, RT_NULL, RT_NULL}, + {-1, 0, RT_NULL, RT_NULL}, + {-1, 0, RT_NULL, RT_NULL}, + {-1, 0, RT_NULL, RT_NULL}, + {-1, 0, RT_NULL, RT_NULL}, + {-1, 0, RT_NULL, RT_NULL}, +}; #define ITEM_NUM(items) sizeof(items)/sizeof(items[0]) const struct pin_index *get_pin(uint8_t pin) @@ -515,11 +560,193 @@ void stm32_pin_mode(rt_device_t dev, rt_base_t pin, rt_base_t mode) GPIO_Init(index->gpio, &GPIO_InitStructure); } +rt_inline rt_int32_t bit2bitno(rt_uint32_t bit) +{ + int i; + for(i = 0; i < 32; i++) + { + if((0x01 << i) == bit) + { + return i; + } + } + return -1; +} +rt_inline const struct pin_irq_map *get_pin_irq_map(uint32_t pinbit) +{ + rt_int32_t mapindex = bit2bitno(pinbit); + if(mapindex < 0 || mapindex >= ITEM_NUM(pin_irq_map)) + { + return RT_NULL; + } + return &pin_irq_map[mapindex]; +}; +rt_err_t stm32_pin_attach_irq(struct rt_device *device, rt_int32_t pin, + rt_uint32_t mode, void (*hdr)(void *args), void *args) +{ + const struct pin_index *index; + rt_base_t level; + rt_int32_t irqindex = -1; + + index = get_pin(pin); + if (index == RT_NULL) + { + return RT_ENOSYS; + } + irqindex = bit2bitno(index->pin); + if(irqindex < 0 || irqindex >= ITEM_NUM(pin_irq_map)) + { + return RT_ENOSYS; + } + + level = rt_hw_interrupt_disable(); + if(pin_irq_hdr_tab[irqindex].pin == pin && + pin_irq_hdr_tab[irqindex].hdr == hdr && + pin_irq_hdr_tab[irqindex].mode == mode && + pin_irq_hdr_tab[irqindex].args == args + ) + { + rt_hw_interrupt_enable(level); + return RT_EOK; + } + if(pin_irq_hdr_tab[irqindex].pin != -1) + { + rt_hw_interrupt_enable(level); + return RT_EBUSY; + } + pin_irq_hdr_tab[irqindex].pin = pin; + pin_irq_hdr_tab[irqindex].hdr = hdr; + pin_irq_hdr_tab[irqindex].mode = mode; + pin_irq_hdr_tab[irqindex].args = args; + rt_hw_interrupt_enable(level); + + return RT_EOK; +} +rt_err_t stm32_pin_dettach_irq(struct rt_device *device, rt_int32_t pin) +{ + const struct pin_index *index; + rt_base_t level; + rt_int32_t irqindex = -1; + + index = get_pin(pin); + if (index == RT_NULL) + { + return RT_ENOSYS; + } + irqindex = bit2bitno(index->pin); + if(irqindex < 0 || irqindex >= ITEM_NUM(pin_irq_map)) + { + return RT_ENOSYS; + } + + level = rt_hw_interrupt_disable(); + if(pin_irq_hdr_tab[irqindex].pin == -1) + { + rt_hw_interrupt_enable(level); + return RT_EOK; + } + pin_irq_hdr_tab[irqindex].pin = -1; + pin_irq_hdr_tab[irqindex].hdr = RT_NULL; + pin_irq_hdr_tab[irqindex].mode = 0; + pin_irq_hdr_tab[irqindex].args = RT_NULL; + rt_hw_interrupt_enable(level); + + return RT_EOK; +} +rt_err_t stm32_pin_irq_enable(struct rt_device *device, rt_base_t pin) +{ + const struct pin_index *index; + const struct pin_irq_map *irqmap; + rt_base_t level; + rt_int32_t irqindex = -1; + GPIO_InitTypeDef GPIO_InitStructure; + NVIC_InitTypeDef NVIC_InitStructure; + EXTI_InitTypeDef EXTI_InitStructure; + + index = get_pin(pin); + if (index == RT_NULL) + { + return RT_ENOSYS; + } + irqindex = bit2bitno(index->pin); + if(irqindex < 0 || irqindex >= ITEM_NUM(pin_irq_map)) + { + return RT_ENOSYS; + } + + level = rt_hw_interrupt_disable(); + if(pin_irq_hdr_tab[irqindex].pin == -1) + { + rt_hw_interrupt_enable(level); + return RT_ENOSYS; + } + irqmap = &pin_irq_map[irqindex]; + /* GPIO Periph clock enable */ + RCC_APB2PeriphClockCmd(index->rcc, ENABLE); + /* Configure GPIO_InitStructure */ + GPIO_InitStructure.GPIO_Pin = index->pin; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_Init(index->gpio, &GPIO_InitStructure); + + NVIC_InitStructure.NVIC_IRQChannel= irqmap->irqno; + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority= 2; + NVIC_InitStructure.NVIC_IRQChannelSubPriority= 2; + NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE; + NVIC_Init(&NVIC_InitStructure); + + EXTI_InitStructure.EXTI_Line = irqmap->irqbit; + EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; + switch(pin_irq_hdr_tab[irqindex].mode) + { + case PIN_IRQ_MODE_RISING: + EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; + break; + case PIN_IRQ_MODE_FALLING: + EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; + break; + case PIN_IRQ_MODE_RISING_FALLING: + EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling; + break; + } + EXTI_InitStructure.EXTI_LineCmd = ENABLE; + EXTI_Init(&EXTI_InitStructure); + rt_hw_interrupt_enable(level); + + return RT_EOK; +} +rt_err_t stm32_pin_irq_disable(struct rt_device *device, rt_base_t pin) +{ + const struct pin_index *index; + const struct pin_irq_map *irqmap; + EXTI_InitTypeDef EXTI_InitStructure; + + index = get_pin(pin); + if (index == RT_NULL) + { + return RT_ENOSYS; + } + irqmap = get_pin_irq_map(index->pin); + if(irqmap == RT_NULL) + { + return RT_ENOSYS; + } + EXTI_InitStructure.EXTI_Line = irqmap->irqbit; + EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; + EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; + EXTI_InitStructure.EXTI_LineCmd = DISABLE; + EXTI_Init(&EXTI_InitStructure); + return RT_EOK; +} const static struct rt_pin_ops _stm32_pin_ops = { stm32_pin_mode, stm32_pin_write, stm32_pin_read, + stm32_pin_attach_irq, + stm32_pin_dettach_irq, + stm32_pin_irq_enable, + stm32_pin_irq_disable }; int stm32_hw_pin_init(void) @@ -531,4 +758,111 @@ int stm32_hw_pin_init(void) } INIT_BOARD_EXPORT(stm32_hw_pin_init); +rt_inline void pin_irq_hdr(int irqno) +{ + EXTI_ClearITPendingBit(pin_irq_map[irqno].irqno); + if(pin_irq_hdr_tab[irqno].hdr) + { + pin_irq_hdr_tab[irqno].hdr(pin_irq_hdr_tab[irqno].args); + } +} +void EXTI0_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + pin_irq_hdr(0); + /* leave interrupt */ + rt_interrupt_leave(); +} +void EXTI1_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + pin_irq_hdr(1); + /* leave interrupt */ + rt_interrupt_leave(); +} +void EXTI2_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + pin_irq_hdr(2); + /* leave interrupt */ + rt_interrupt_leave(); +} +void EXTI3_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + pin_irq_hdr(3); + /* leave interrupt */ + rt_interrupt_leave(); +} +void EXTI4_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + pin_irq_hdr(4); + /* leave interrupt */ + rt_interrupt_leave(); +} +void EXTI9_5_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + if(EXTI_GetITStatus(EXTI_Line5) != RESET) + { + pin_irq_hdr(5); + } + if(EXTI_GetITStatus(EXTI_Line6) != RESET) + { + pin_irq_hdr(6); + } + if(EXTI_GetITStatus(EXTI_Line7) != RESET) + { + pin_irq_hdr(7); + } + if(EXTI_GetITStatus(EXTI_Line8) != RESET) + { + pin_irq_hdr(8); + } + if(EXTI_GetITStatus(EXTI_Line9) != RESET) + { + pin_irq_hdr(9); + } + /* leave interrupt */ + rt_interrupt_leave(); +} +void EXTI15_10_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + if(EXTI_GetITStatus(EXTI_Line10) != RESET) + { + pin_irq_hdr(10); + } + if(EXTI_GetITStatus(EXTI_Line11) != RESET) + { + pin_irq_hdr(11); + } + if(EXTI_GetITStatus(EXTI_Line12) != RESET) + { + pin_irq_hdr(12); + } + if(EXTI_GetITStatus(EXTI_Line13) != RESET) + { + pin_irq_hdr(13); + } + if(EXTI_GetITStatus(EXTI_Line14) != RESET) + { + pin_irq_hdr(14); + } + if(EXTI_GetITStatus(EXTI_Line15) != RESET) + { + pin_irq_hdr(15); + } + /* leave interrupt */ + rt_interrupt_leave(); +} + #endif diff --git a/components/drivers/include/drivers/pin.h b/components/drivers/include/drivers/pin.h index 704114cf99..ac35ed3baa 100644 --- a/components/drivers/include/drivers/pin.h +++ b/components/drivers/include/drivers/pin.h @@ -46,6 +46,12 @@ struct rt_device_pin #define PIN_MODE_INPUT 0x01 #define PIN_MODE_INPUT_PULLUP 0x02 +#define PIN_IRQ_MODE_RISING 0x00 +#define PIN_IRQ_MODE_FALLING 0x01 +#define PIN_IRQ_MODE_RISING_FALLING 0x02 + +#define PIN_IRQ_PIN_NONE -1 + struct rt_device_pin_mode { rt_uint16_t pin; @@ -56,7 +62,13 @@ struct rt_device_pin_status rt_uint16_t pin; rt_uint16_t status; }; - +struct rt_pin_irq_hdr +{ + rt_int32_t pin; + rt_uint32_t mode; + void (*hdr)(void *args); + void *args; +}; struct rt_pin_ops { void (*pin_mode)(struct rt_device *device, rt_base_t pin, rt_base_t mode); @@ -64,6 +76,11 @@ struct rt_pin_ops int (*pin_read)(struct rt_device *device, rt_base_t pin); /* TODO: add GPIO interrupt */ + rt_err_t (*pin_attach_irq)(struct rt_device *device, rt_int32_t pin, + rt_uint32_t mode, void (*hdr)(void *args), void *args); + rt_err_t (*pin_dettach_irq)(struct rt_device *device, rt_int32_t pin); + rt_err_t (*pin_irq_enable)(struct rt_device *device, rt_base_t pin); + rt_err_t (*pin_irq_disable)(struct rt_device *device, rt_base_t pin); }; int rt_device_pin_register(const char *name, const struct rt_pin_ops *ops, void *user_data); @@ -71,7 +88,14 @@ int rt_device_pin_register(const char *name, const struct rt_pin_ops *ops, void void rt_pin_mode(rt_base_t pin, rt_base_t mode); void rt_pin_write(rt_base_t pin, rt_base_t value); int rt_pin_read(rt_base_t pin); +rt_err_t rt_pin_attach_irq(rt_int32_t pin, rt_uint32_t mode, + void (*hdr)(void *args), void *args); +rt_err_t rt_pin_dettach_irq(rt_int32_t pin); +rt_err_t pin_irq_enable(rt_base_t pin); +rt_err_t pin_irq_disable(rt_base_t pin); +int rt_device_pin_irq_register(const char *name, const struct rt_pin_ops *ops, + void *user_data); #ifdef __cplusplus } #endif diff --git a/components/drivers/misc/pin.c b/components/drivers/misc/pin.c index 0a200af5aa..a3232b8e03 100644 --- a/components/drivers/misc/pin.c +++ b/components/drivers/misc/pin.c @@ -98,24 +98,61 @@ int rt_device_pin_register(const char *name, const struct rt_pin_ops *ops, void return 0; } +rt_err_t rt_pin_attach_irq(rt_int32_t pin, rt_uint32_t mode, + void (*hdr)(void *args), void *args) +{ + RT_ASSERT(_hw_pin.ops != RT_NULL); + if(_hw_pin.ops->pin_attach_irq) + { + return _hw_pin.ops->pin_attach_irq(&_hw_pin.parent, pin, mode, hdr, args); + } + return RT_ENOSYS; +} +rt_err_t rt_pin_dettach_irq(rt_int32_t pin) +{ + RT_ASSERT(_hw_pin.ops != RT_NULL); + if(_hw_pin.ops->pin_dettach_irq) + { + return _hw_pin.ops->pin_dettach_irq(&_hw_pin.parent, pin); + } + return RT_ENOSYS; +} +rt_err_t pin_irq_enable(rt_base_t pin) +{ + RT_ASSERT(_hw_pin.ops != RT_NULL); + if(_hw_pin.ops->pin_irq_enable) + { + return _hw_pin.ops->pin_irq_enable(&_hw_pin.parent, pin); + } + return RT_ENOSYS; +} +rt_err_t pin_irq_disable(rt_base_t pin) +{ + RT_ASSERT(_hw_pin.ops != RT_NULL); + if(_hw_pin.ops->pin_irq_disable) + { + return _hw_pin.ops->pin_irq_disable(&_hw_pin.parent, pin); + } + return RT_ENOSYS; +} /* RT-Thread Hardware PIN APIs */ void rt_pin_mode(rt_base_t pin, rt_base_t mode) { - RT_ASSERT(_hw_pin.ops != RT_NULL); + RT_ASSERT(_hw_pin.ops != RT_NULL); _hw_pin.ops->pin_mode(&_hw_pin.parent, pin, mode); } FINSH_FUNCTION_EXPORT_ALIAS(rt_pin_mode, pinMode, set hardware pin mode); void rt_pin_write(rt_base_t pin, rt_base_t value) { - RT_ASSERT(_hw_pin.ops != RT_NULL); + RT_ASSERT(_hw_pin.ops != RT_NULL); _hw_pin.ops->pin_write(&_hw_pin.parent, pin, value); } FINSH_FUNCTION_EXPORT_ALIAS(rt_pin_write, pinWrite, write value to hardware pin); int rt_pin_read(rt_base_t pin) { - RT_ASSERT(_hw_pin.ops != RT_NULL); + RT_ASSERT(_hw_pin.ops != RT_NULL); return _hw_pin.ops->pin_read(&_hw_pin.parent, pin); } FINSH_FUNCTION_EXPORT_ALIAS(rt_pin_read, pinRead, read status from hardware pin);