You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

409 lines
12 KiB

#include "zgpio.hpp"
#define TAG "GPIO"
namespace iflytop {
/*******************************************************************************
* LISTENER *
*******************************************************************************/
static ZGPIO *s_irqGPIO[20];
int s_irqGPIO_num = 0;
extern "C" {
/**
* @brief This function handles EXTI line3 interrupt.
*/
void EXTI0_IRQHandler() { HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0); }
void EXTI1_IRQHandler() { HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_1); }
void EXTI2_IRQHandler() { HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_2); }
void EXTI3_IRQHandler() { HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_3); }
void EXTI4_IRQHandler() { HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_4); }
void EXTI9_5_IRQHandler(void) {
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_5);
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_6);
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_7);
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_8);
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_9);
}
void EXTI15_10_IRQHandler(void) {
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_10);
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_11);
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_12);
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_13);
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_14);
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_15);
}
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
for (int i = 0; i < s_irqGPIO_num; i++) {
s_irqGPIO[i]->tryTriggerIRQ(GPIO_Pin);
}
}
}
void ZGPIO::regListener(onirq_t listener) { m_onirq = listener; }
/*******************************************************************************
* GPIOIMPL *
*******************************************************************************/
/*******************************************************************************
* BASE_FUNC *
*******************************************************************************/
bool ZGPIO::enableClock(GPIO_TypeDef *port) {
#ifdef GPIOA
if (port == GPIOA) {
__HAL_RCC_GPIOA_CLK_ENABLE();
return true;
}
#endif
#ifdef GPIOB
if (port == GPIOB) {
__HAL_RCC_GPIOB_CLK_ENABLE();
return true;
}
#endif
#ifdef GPIOC
if (port == GPIOC) {
__HAL_RCC_GPIOC_CLK_ENABLE();
return true;
}
#endif
#ifdef GPIOD
if (port == GPIOD) {
__HAL_RCC_GPIOD_CLK_ENABLE();
return true;
}
#endif
#ifdef GPIOE
if (port == GPIOE) {
__HAL_RCC_GPIOE_CLK_ENABLE();
return true;
}
#endif
#ifdef GPIOF
if (port == GPIOF) {
__HAL_RCC_GPIOF_CLK_ENABLE();
return true;
}
#endif
#ifdef GPIOG
if (port == GPIOG) {
__HAL_RCC_GPIOG_CLK_ENABLE();
return true;
}
#endif
#ifdef GPIOH
if (port == GPIOH) {
__HAL_RCC_GPIOH_CLK_ENABLE();
return true;
}
#endif
#ifdef GPIOI
if (port == GPIOI) {
__HAL_RCC_GPIOI_CLK_ENABLE();
return true;
}
#endif
#ifdef GPIOJ
if (port == GPIOJ) {
__HAL_RCC_GPIOJ_CLK_ENABLE();
return true;
}
#endif
#ifdef GPIOK
if (port == GPIOK) {
__HAL_RCC_GPIOK_CLK_ENABLE();
return true;
}
#endif
return false;
}
bool ZGPIO::enableClock() { return enableClock(m_gpio); }
void regIRQGPIO(ZGPIO *gpio) {
for (int i = 0; i < s_irqGPIO_num; i++) {
if (s_irqGPIO[i] == gpio) {
return;
}
}
EARLY_ASSERT((s_irqGPIO_num + 1) < (int)ZARRAY_SIZE(s_irqGPIO));
s_irqGPIO[s_irqGPIO_num] = gpio;
s_irqGPIO_num++;
}
bool ZGPIO::isMirror() { return m_mirror; }
void ZGPIO::initAsInput(Pin_t pin, GPIOMode_t mode, GPIOIrqType_t irqtype, bool mirror) {
if (pin == PinNull) return;
m_mirror = mirror;
m_mode = mode;
m_irqtype = irqtype;
m_gpiotype = kType_Input;
m_pin = pin;
m_gpio = chip_get_gpio(pin);
m_pinoff = chip_get_pinoff(pin);
uint32_t pulluptype = 0;
if (mode == kMode_nopull) {
pulluptype = GPIO_NOPULL;
} else if (mode == kMode_pullup) {
pulluptype = GPIO_PULLUP;
} else if (mode == kMode_pulldown) {
pulluptype = GPIO_PULLDOWN;
}
enableClock();
GPIO_InitTypeDef m_GPIO_InitStruct = {0};
if (m_irqtype == kIRQ_noIrq) {
m_GPIO_InitStruct.Pin = m_pinoff;
m_GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
m_GPIO_InitStruct.Pull = pulluptype;
m_GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
} else if (m_irqtype == kIRQ_risingIrq) {
m_GPIO_InitStruct.Pin = m_pinoff;
m_GPIO_InitStruct.Mode = m_mirror ? GPIO_MODE_IT_FALLING : GPIO_MODE_IT_RISING;
m_GPIO_InitStruct.Pull = pulluptype;
m_GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
} else if (m_irqtype == kIRQ_fallingIrq) {
m_GPIO_InitStruct.Pin = m_pinoff;
m_GPIO_InitStruct.Mode = !m_mirror ? GPIO_MODE_IT_FALLING : GPIO_MODE_IT_RISING;
m_GPIO_InitStruct.Pull = pulluptype;
m_GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
} else if (m_irqtype == kIRQ_risingAndFallingIrq) {
m_GPIO_InitStruct.Pin = m_pinoff;
m_GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING;
m_GPIO_InitStruct.Pull = pulluptype;
m_GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
}
HAL_GPIO_Init(m_gpio, &m_GPIO_InitStruct);
if (m_irqtype != kIRQ_noIrq) {
regIRQGPIO(this);
lastLevel = getState();
HAL_NVIC_SetPriority(getEXTIIRQn(), PC_IRQ_PREEMPTPRIORITY_DEFAULT, 0);
HAL_NVIC_EnableIRQ(getEXTIIRQn());
}
m_initflag = true;
return;
}
void ZGPIO::initAsOutputStatic(Pin_t pin, GPIOMode_t mode, bool mirror, bool initLevel) {
if (pin == PinNull) return;
GPIO_TypeDef *m_gpio = chip_get_gpio(pin);
uint16_t m_pinoff = chip_get_pinoff(pin);
enableClock(m_gpio);
GPIO_InitTypeDef m_GPIO_InitStruct = {0};
initLevel = mirror ? !initLevel : initLevel;
GPIO_PinState pinState = initLevel ? GPIO_PIN_SET : GPIO_PIN_RESET;
HAL_GPIO_WritePin(m_gpio, m_pinoff, pinState);
if (mode == kMode_nopull) {
m_GPIO_InitStruct.Pin = m_pinoff;
m_GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
m_GPIO_InitStruct.Pull = GPIO_NOPULL;
m_GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
} else if (mode == kMode_pullup) {
m_GPIO_InitStruct.Pin = m_pinoff;
m_GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
m_GPIO_InitStruct.Pull = GPIO_PULLUP;
m_GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
} else if (mode == kMode_pulldown) {
m_GPIO_InitStruct.Pin = m_pinoff;
m_GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
m_GPIO_InitStruct.Pull = GPIO_PULLDOWN;
m_GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
} else if (mode == kMode_od) {
m_GPIO_InitStruct.Pin = m_pinoff;
m_GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
m_GPIO_InitStruct.Pull = 0;
m_GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
}
HAL_GPIO_Init(m_gpio, &m_GPIO_InitStruct);
return;
}
void ZGPIO::initAsOutput(Pin_t pin, GPIOMode_t mode, bool mirror, bool initLevel) {
if (pin == PinNull) return;
m_mirror = mirror;
m_mode = mode;
m_irqtype = kIRQ_noIrq;
m_gpiotype = kType_Output;
m_pin = pin;
m_gpio = chip_get_gpio(pin);
m_pinoff = chip_get_pinoff(pin);
enableClock();
GPIO_InitTypeDef m_GPIO_InitStruct = {0};
initLevel = m_mirror ? !initLevel : initLevel;
GPIO_PinState pinState = initLevel ? GPIO_PIN_SET : GPIO_PIN_RESET;
HAL_GPIO_WritePin(m_gpio, m_pinoff, pinState);
if (m_mode == kMode_nopull) {
m_GPIO_InitStruct.Pin = m_pinoff;
m_GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
m_GPIO_InitStruct.Pull = GPIO_NOPULL;
m_GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
} else if (m_mode == kMode_pullup) {
m_GPIO_InitStruct.Pin = m_pinoff;
m_GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
m_GPIO_InitStruct.Pull = GPIO_PULLUP;
m_GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
} else if (m_mode == kMode_pulldown) {
m_GPIO_InitStruct.Pin = m_pinoff;
m_GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
m_GPIO_InitStruct.Pull = GPIO_PULLDOWN;
m_GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
} else if (m_mode == kMode_od) {
m_GPIO_InitStruct.Pin = m_pinoff;
m_GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
m_GPIO_InitStruct.Pull = 0;
m_GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
}
HAL_GPIO_Init(m_gpio, &m_GPIO_InitStruct);
m_initflag = true;
return;
}
bool ZGPIO::isItRisingEXITGPIO() { return m_irqtype == kIRQ_risingIrq; }
bool ZGPIO::isItFallingEXITGPIO() { return m_irqtype == kIRQ_fallingIrq; }
bool ZGPIO::isItRisingAndItFallingEXITGPIO() { return m_irqtype == kIRQ_risingAndFallingIrq; }
/*******************************************************************************
* EXT FUNC *
*******************************************************************************/
/**
* @brief 判断当前是否是这个引脚产生的中断
*
* @param checkloop
* @param GPIO_Pin
* @return true
* @return false
*
* 由于STM32的GPIO中断线是共用的,所以需要根据GPIO的即时状态判断是否是这个引脚产生的中??
*
* 判断逻辑??:
* 先判断所有中断模式是 GPIO_MODE_IT_RISING ?? GPIO_MODE_IT_FALLING 的引脚,采样当前电平判断是否是这个引脚产生的中断
* 再判断中断模式是 GPIO_MODE_IT_RISING_FALLING 的引脚,直接返回true
*/
bool ZGPIO::tryTriggerIRQ(uint16_t GPIO_Pin) {
bool ret = false;
bool nostate = false;
if (GPIO_Pin != m_pinoff) return false;
if (!(isItRisingEXITGPIO() || isItFallingEXITGPIO() || isItRisingAndItFallingEXITGPIO())) {
return false;
}
nostate = getState();
if (isItRisingEXITGPIO()) {
if (nostate) {
ret = true;
if (m_onirq) {
m_onirq(this, kRisingIrqEvent);
}
}
} else if (isItFallingEXITGPIO()) {
if (!nostate) {
ret = true;
if (m_onirq) {
m_onirq(this, kFallingIrqEvent);
}
}
} else {
if (lastLevel != nostate) {
ret = true;
if (m_onirq) {
if (lastLevel)
m_onirq(this, kRisingIrqEvent);
else
m_onirq(this, kFallingIrqEvent);
}
}
}
lastLevel = nostate;
return ret;
}
void ZGPIO::toggleState() { HAL_GPIO_TogglePin(m_gpio, m_pinoff); }
uint32_t ZGPIO::getStateUint32() {
if (getState())
return 1;
else
return 0;
}
bool ZGPIO::getState() {
if (m_pin == PinNull) return false;
bool ret = false;
if (HAL_GPIO_ReadPin(m_gpio, m_pinoff) == GPIO_PIN_SET) {
ret = true;
} else {
ret = false;
}
if (m_mirror) ret = !ret;
return ret;
}
bool ZGPIO::setState(bool state) {
if (m_pin == PinNull) return true;
if (m_mirror) state = !state;
if (m_log_when_setstate) ZEARLY_LOGI(TAG, "%s%s set %d", chip_gpio_group_get_name(m_gpio), chip_pinoff_get_name(m_pinoff), state);
if (state) {
HAL_GPIO_WritePin(m_gpio, m_pinoff, GPIO_PIN_SET);
} else {
HAL_GPIO_WritePin(m_gpio, m_pinoff, GPIO_PIN_RESET);
}
return true;
}
IRQn_Type ZGPIO::getEXTIIRQn() {
switch (m_pinoff) {
case GPIO_PIN_0:
return EXTI0_IRQn;
case GPIO_PIN_1:
return EXTI1_IRQn;
case GPIO_PIN_2:
return EXTI2_IRQn;
case GPIO_PIN_3:
return EXTI3_IRQn;
case GPIO_PIN_4:
return EXTI4_IRQn;
case GPIO_PIN_5:
case GPIO_PIN_6:
case GPIO_PIN_7:
case GPIO_PIN_8:
case GPIO_PIN_9:
return EXTI9_5_IRQn;
case GPIO_PIN_10:
case GPIO_PIN_11:
case GPIO_PIN_12:
case GPIO_PIN_13:
case GPIO_PIN_14:
case GPIO_PIN_15:
return EXTI15_10_IRQn;
default:
ZEARLY_ASSERT(0);
}
return EXTI0_IRQn;
}
/**
* @brief 初始化GPIO为中断模??
*
* @param pull GPIO_NOPULL, GPIO_PULLUP, GPIO_PULLDOWN
* @param mode GPIO_MODE_IT_RISING, GPIO_MODE_IT_FALLING, GPIO_MODE_IT_RISING_FALLING
* @return true
* @return false
*/
} // namespace iflytop