cancel
Showing results for 
Search instead for 
Did you mean: 

Pin as an Open Drain output and EXTI at the same time. STM32F030

ABaba.12
Associate

Hello I have an application where it would be usefull to have a pin configured as an open drain output but at the same time to detect a falling edge on that pin usirn EXTI.

In the refference manual RM0091 there in Figure 18 (Output configuration) I have seen the mentioning that even if the pin is configured as output, there is also a signal going to EXTI. Theoretically I could configure the pin as both Output OD and EXTI but I can't mannage that.

When I try to do so, it behaves as an exti and does not work as an output. When I update the ODR using debugger, I see that IDR also changes however EXTI interrupt is not generated and actual output voltage drops only by 20mV.

Do you think it would be possible to configure pin as EXTI and Output?

Thank you.

9 REPLIES 9

Don't rely on CubeMX to configure the pin, it does not support this mode of operation.

JW

I did not rely on automatic configuration but I found the problem. It was the fact that I was not carefull and confgured the Gpio mode register to 10 instead of 01 os it was connected to Alternative function.

If I set it manually to Open drain output and enable EXTI - it works as expected. I can toggle the pin and I get an interrupt at every flling edge.

Hi I had similar situation, can you share the code on how you manage to make open drain and exti work together, thanks.

Yevgeni Tunik
Senior

I had similar demand using STM32F427. After some trying, I shorted pin EXTI with some free pin. This previously free pin I configured as output open drain.

Pin is set to output in GPIO_MODER and to open drain in GPIO_OTYPER.

The same pin is set to trigger EXTI by selecting the proper port for given pin in SYSCFG_EXTICRx, and then select required edge in EXTI_RTSR/EXTI_FTSR, enable interrupt in EXTI_IMR, and then enable interrupt in NVIC using the standard NVIC_EnableIRQ() call. Of course, there must be an ISR written with the appropriate name.

These two things are mutually independent and are simple to set after reading the GPIO and EXTI chapters in the RM.

If you depend on Cube/CubeMX, I know folks were able to pull similar out (setting pin to AF and EXTI) by setting the pin as Input/EXTI in CubeMX and then writing manually a call to set the pin to AF, which did not change the EXTI setting. Search in this forum.

Unless there's some other reason to do the external connection, just to trigger EXTI from a pin set to output (does not matter if open-drain or push-pull) does not require external connection and the extra pin.

JW

Sorry for missing significant detail: instead of open drain output, my project used SPI MISO.

My project used AD7793 that has the same output pin DOUT/nRDY as SPI MISO and as "new sample is ready". Function DOUT of this pin demands configuring related microcontroller pin as SPI MOSI, and function nRDY of this pin demands configuring related microcontroller pin as EXTI.

Hi JW, thanks your excellent explaination.

I used your suggestion, and copied part of void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init), come up with a pin initialization function, but I can't get external interrupt, I tried by using CubeMX set Pin 10 to external interrupt, it works, following is the function I did, please help find out what's missing.

static void EXTI_IRQHandler_Config2(EXTI_InitTypeDef *EXTI_InitStruct)
{
  uint32_t position = EXTI_InitStruct->Position; //10
  uint32_t iocurrent;
  uint32_t temp;
  uint32_t index;
  GPIO_TypeDef *GPIOx = EXTI_InitStruct->PORT;
 
  /* Get current io position */
  iocurrent = (EXTI_InitStruct->GPIO_Pin); //1024
 
  temp = GPIOx->OSPEEDR;
  temp &= ~(GPIO_OSPEEDER_OSPEEDR0 << (position * 2u));
  temp |= (GPIO_SPEED_FREQ_HIGH << (position * 2u));
  GPIOx->OSPEEDR = temp;
 
  /* Configure the IO Output Type */
  temp = GPIOx->OTYPER;
  temp &= ~(GPIO_OTYPER_OT_0 << position);
  temp |= (((GPIO_MODE_OUTPUT_OD & OUTPUT_TYPE) >> OUTPUT_TYPE_Pos) << position);
  GPIOx->OTYPER = temp;
 
  /* Activate the Pull-up or Pull down resistor for the current IO */
  temp = GPIOx->PUPDR;
  temp &= ~(GPIO_PUPDR_PUPDR0 << (position * 2u));
  temp |= ((GPIO_NOPULL) << (position * 2u)); //GPIO_PULLUP, GPIO_NOPULL
  GPIOx->PUPDR = temp;
 
  //if (EXTI_InitStruct->EXTI_Mode == EXTI_MODE_NONE)
  { /* Configure IO Direction mode (Input, Output, Alternate or Analog) */
    temp = GPIOx->MODER;
    temp &= ~(GPIO_MODER_MODER0 << (position * 2u));
    index = GPIO_MODE_OUTPUT_OD & GPIO_MODE;
    temp |= ((index) << (position * 2u));
    GPIOx->MODER = temp;
  }
  //else
  {
    //temp = GPIOx->MODER;
    //temp &= ~(GPIO_MODER_MODER0 << (position * 2u));
    //temp |= ((GPIO_MODE_INPUT & GPIO_MODE) << (position * 2u));
    //GPIOx->MODER = temp;
  }
  __HAL_RCC_SYSCFG_CLK_ENABLE();
 
  index = position >> 2u; //2
  temp = SYSCFG->EXTICR[index];
  temp &= ~(0x0FuL << (4u * (position & 0x03u)));
  temp |= (GPIO_GET_INDEX(GPIOx) << (4u * (position & 0x03u)));
  SYSCFG->EXTICR[index] = temp; //PB10, PB11
 
  temp = EXTI->IMR;
  temp &= ~(iocurrent);
  if ((EXTI_InitStruct->EXTI_Mode & EXTI_MODE_INTERRUPT) != 0x00u)
  {
    temp |= iocurrent; //1024
  }
  EXTI->IMR = temp;
 
  temp = EXTI->EMR;
  temp &= ~(iocurrent);
  if ((EXTI_InitStruct->EXTI_Mode & EXTI_MODE_EVENT) != 0x00u)
  {
    temp |= iocurrent;
  }
  EXTI->EMR = temp; //0
 
  /* Clear Rising Falling edge configuration */
  temp = EXTI->RTSR;
  temp &= ~(iocurrent);
  if ((EXTI_InitStruct->EXTI_Trigger & EXTI_TRIGGER_RISING) != 0x00u)
  {
    temp |= iocurrent;
  }
  EXTI->RTSR = temp;
 
  temp = EXTI->FTSR;
  temp &= ~(iocurrent);
  if ((EXTI_InitStruct->EXTI_Trigger & EXTI_TRIGGER_FALLING) != 0x00u)
  {
    temp |= iocurrent; //1024
  }
  EXTI->FTSR = temp;
}

Forgot to mention, I am using NucleoF446, master is I2C1, slave is using I2C3's pins PA8(SCL), PC9(SDA), I direct connect I2C1's SCL to PA8, I2C1's SDA to PC9.

Tried with built in I2C3, I2C1 can talk to I2C3 each other, but when I try to implement soft i2c, seem SCL and SDA lines stay at logic 0.

Read out and check/compare to working case content of EXTI and relevant GPIO registers.

JW