//! \file stm32f4_gpio.c //! \author tkl //! \date Mai 8, 2012 //! \brief Source file of the stm32f4 architecture dependent gpio driver. #include #include #include #include "stm32f4xx.h" #include "gpio.h" #include "stm32f4_gpio.h" //! \brief Contains data for a callback for an external interrupt. typedef struct { gpio_ext_it_cb_t callback; //!< The call back to be executed. void *param; //!< Parameter for the callback }exti_cb_list_t; //! \brief Contains call back data for all 16 exti lines. static struct { exti_cb_list_t callback_list[16]; //!< Call back data list for the exti lines. }gpio_obj; static uint8_t gpio_bin2dec(uint16_t bin) { uint8_t ret = 0; switch(bin) { case 0x0001: ret = 0; break; case 0x0002: ret = 1; break; case 0x0004: ret = 2; break; case 0x0008: ret = 3; break; case 0x0010: ret = 4; break; case 0x0020: ret = 5; break; case 0x0040: ret = 6; break; case 0x0080: ret = 7; break; case 0x0100: ret = 8; break; case 0x0200: ret = 9; break; case 0x0400: ret = 10; break; case 0x0800: ret = 11; break; case 0x1000: ret = 12; break; case 0x2000: ret = 13; break; case 0x4000: ret = 14; break; case 0x8000: ret = 15; break; } return ret; } static void gpio_init(const struct stm32f4_gpio *gpio) { uint8_t m_port = 0; uint8_t m_pin = 0; uint32_t clock = 0; if(gpio == NULL) return; if(gpio->port == GPIOA) { clock = RCC_AHB1Periph_GPIOA; m_port = EXTI_PortSourceGPIOA; } else if(gpio->port == GPIOB) { clock = RCC_AHB1Periph_GPIOB; m_port = EXTI_PortSourceGPIOB; } else if(gpio->port == GPIOC) { clock = RCC_AHB1Periph_GPIOC; m_port = EXTI_PortSourceGPIOC; } else if(gpio->port == GPIOD) { clock = RCC_AHB1Periph_GPIOD; m_port = EXTI_PortSourceGPIOD; } else if(gpio->port == GPIOE) { clock = RCC_AHB1Periph_GPIOE; m_port = EXTI_PortSourceGPIOE; } else if(gpio->port == GPIOF) { clock = RCC_AHB1Periph_GPIOF; m_port = EXTI_PortSourceGPIOF; } else if(gpio->port == GPIOG) { clock = RCC_AHB1Periph_GPIOG; m_port = EXTI_PortSourceGPIOG; } else if(gpio->port == GPIOH) { clock = RCC_AHB1Periph_GPIOH; m_port = EXTI_PortSourceGPIOH; } else if(gpio->port == GPIOI) { clock = RCC_AHB1Periph_GPIOI; m_port = EXTI_PortSourceGPIOI; } RCC_AHB1PeriphClockCmd(clock, ENABLE); m_pin = gpio_bin2dec(gpio->pin->GPIO_Pin); SYSCFG_EXTILineConfig(m_port, m_pin); } int stm32f4_gpio_open(const void *gpio) { struct stm32f4_gpio *this; uint8_t m_pin = 0; if(gpio == NULL) return -1; this = (struct stm32f4_gpio *)gpio; gpio_init(this); m_pin = gpio_bin2dec(this->pin->GPIO_Pin); GPIO_Init(this->port, (GPIO_InitTypeDef*)this->pin); if(this->ext_it_cb != NULL) { gpio_obj.callback_list[m_pin].callback = this->ext_it_cb; gpio_obj.callback_list[m_pin].param = this->param; } if((this->exti != NULL) && (this->nvic != NULL)) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); EXTI_Init((EXTI_InitTypeDef*)this->exti); NVIC_Init((NVIC_InitTypeDef*)this->nvic); } return 0; } int stm32f4_gpio_close(const void *gpio) { if(gpio == NULL) return -1; // TODO: deinit exti, nvic & gpio return 0; } char stm32f4_gpio_read(const void *gpio) { struct stm32f4_gpio *this; if(gpio == NULL) return 0; this = (struct stm32f4_gpio *)gpio; return GPIO_ReadOutputDataBit(this->port, this->pin->GPIO_Pin); } void stm32f4_gpio_write(const void *gpio, char byte) { struct stm32f4_gpio *this; if(gpio == NULL) return; this = (struct stm32f4_gpio *)gpio; GPIO_WriteBit(this->port, this->pin->GPIO_Pin, (BitAction)byte); } void stm32f4_gpio_toggle(const void *gpio) { struct stm32f4_gpio *this; if(gpio == NULL) return; this = (struct stm32f4_gpio *)gpio; BitAction act = Bit_SET; if(GPIO_ReadOutputDataBit(this->port, this->pin->GPIO_Pin)) act = Bit_RESET; GPIO_WriteBit(this->port, this->pin->GPIO_Pin, act); } int stm32f4_gpio_set_exti_callback(const void *gpio, const void *callback, const void *param) { struct stm32f4_gpio *this; uint8_t pin; if((gpio == NULL) || (callback == NULL)) return -1; this = (struct stm32f4_gpio *)gpio; pin = gpio_bin2dec(this->exti->EXTI_Line); gpio_obj.callback_list[pin].callback = (gpio_ext_it_cb_t)callback; gpio_obj.callback_list[pin].param = (void*)param; return 0; } //! \brief The ISR for the EXTI0_IRQn interrupt. void EXTI0_IRQHandler(void) { if(gpio_obj.callback_list[0].callback != NULL) { gpio_ext_it_cb_t cb = gpio_obj.callback_list[0].callback; void *param = gpio_obj.callback_list[0].param; cb(param); } EXTI_ClearITPendingBit(EXTI_Line0); } //! \brief The ISR for the EXTI1_IRQn interrupt. void EXTI1_IRQHandler(void) { if(gpio_obj.callback_list[1].callback != NULL) { gpio_ext_it_cb_t cb = gpio_obj.callback_list[1].callback; void *param = gpio_obj.callback_list[1].param; cb(param); } EXTI_ClearITPendingBit(EXTI_Line1); } //! \brief The ISR for the EXTI2_IRQn interrupt. void EXTI2_IRQHandler(void) { if(gpio_obj.callback_list[2].callback != NULL) { gpio_ext_it_cb_t cb = gpio_obj.callback_list[2].callback; void *param = gpio_obj.callback_list[2].param; cb(param); } EXTI_ClearITPendingBit(EXTI_Line2); } //! \brief The ISR for the EXTI3_IRQn interrupt. void EXTI3_IRQHandler(void) { if(gpio_obj.callback_list[3].callback != NULL) { gpio_ext_it_cb_t cb = gpio_obj.callback_list[3].callback; void *param = gpio_obj.callback_list[3].param; cb(param); } EXTI_ClearITPendingBit(EXTI_Line3); } //! \brief The ISR for the EXTI4_IRQn interrupt. void EXTI4_IRQHandler(void) { if(gpio_obj.callback_list[4].callback != NULL) { gpio_ext_it_cb_t cb = gpio_obj.callback_list[4].callback; void *param = gpio_obj.callback_list[4].param; cb(param); } EXTI_ClearITPendingBit(EXTI_Line4); } //! \brief The ISR for the EXTI9_5_IRQn interrupt. void EXTI9_5_IRQHandler(void) { uint32_t exti = 0; uint8_t pin; if(EXTI_GetITStatus(EXTI_Line6)) exti = EXTI_Line6; pin = gpio_bin2dec(exti); if(gpio_obj.callback_list[pin].callback != NULL) { gpio_ext_it_cb_t cb = gpio_obj.callback_list[pin].callback; void *param = gpio_obj.callback_list[pin].param; cb(param); } EXTI_ClearITPendingBit(exti); } //! \brief The ISR for the EXTI15_10_IRQn interrupt. void EXTI15_10_IRQHandler(void) { // TODO: detect & clear pending bit }