cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F7: why some specific GPIO pins don't work?

Wowa
Associate III

Hello everyone,

I'm using USART3 on F746, but only RX/TX pins which are mapped to pins PD8/PD9.

Besides that, I want to configure general output to pins PD10/PD11 (to control LEDs), but they don't work when I try to control them. I looked up the AF mapping for the chip and can see that these pins fall into "USART pin domain" (PD10 = USART3_CK, PD11 = USART3_CTS). Can this prevent me from using them as GPIO_MODE_OUTPUT_PP? Is this documented in any paper? Because I didn't find any such limitations in reference/datasheet and thought that I might program those independently.

Thanks!

Vladimir

This discussion is locked. Please start a new topic to ask your question.
1 ACCEPTED SOLUTION

Accepted Solutions
waclawek.jan
Super User

Couldn't confirm.

Tried on a 'F746 DISCO. Enabled GPIOD in RCC, set MODER to 0x1a0000 (i.e. PD10 to Out, PD9 and PD8 to AF), set AFR[1] to 0x777 (i.e. all three pins to USART3). Enabled USART3 in RCC, set CR2.CLKEN and CR1.TE/RE/UE. As expected, wiggling bit 10 of GPIOD.ODR was reflected by bit 10 of GPIOD.IDR (PD10 is not exposed on the Disco, unfortunately), regardless of the AFR[1] setting.

Please post the readout of GPIOD registers with the modification; try to revert the modification, make sure that reproduces the problem and post then that readout of GPIOD registers, too.

@Mike_ST,

can you please clarify your comment.​ 

Thanks,

JW

View solution in original post

9 REPLIES 9
Mike_ST
ST Employee

>> Can this prevent me from using them as GPIO_MODE_OUTPUT_PP?

No, just make sure to enable clock on GPIOD and set alternate value to 0 for PD10/PD11.

waclawek.jan
Super User

@Mike_ST​ ,

> set alternate value to 0

What is "alternate value" and why would it have to be 0?

JW

waclawek.jan
Super User

Wowa,

read out and check content of relevant GPIO registers.

Is this your own board? Are *all* VDD and VSS/GND connected? If this is some of the devboards (Nucleo, Disco, Eval), are all jumpers/solder bridges to these pins disconnected?

JW

UPD: I found a bug in my code later, so it turned out that there is no need in any modifications in HAL_GPIO_Init() function. Explained this in the other post below.

---------------------------------------------------------------

Thank you, that was it!

For those who might get into this too: the matter is that HAL_GPIO_Init() function sets AFR registers only if GPIO_Init->Mode == GPIO_MODE_AF_... . But it does not reset them if you ask it to set up non-AF mode!

So, I just added to this part of HAL_GPIO_Init():

/*--------------------- GPIO Mode Configuration ------------------------*/
      /* In case of Alternate function mode selection */
      if((GPIO_Init->Mode == GPIO_MODE_AF_PP) || (GPIO_Init->Mode == GPIO_MODE_AF_OD))
      {
        /* Check the Alternate function parameter */
        assert_param(IS_GPIO_AF(GPIO_Init->Alternate));
        
        /* Configure Alternate function mapped with the current IO */
        temp = GPIOx->AFR[position >> 3];
        temp &= ~((uint32_t)0xF << ((uint32_t)(position & (uint32_t)0x07) * 4)) ;
        temp |= ((uint32_t)(GPIO_Init->Alternate) << (((uint32_t)position & (uint32_t)0x07) * 4));
        GPIOx->AFR[position >> 3] = temp;
      }

an 'else' section to make it:

/*--------------------- GPIO Mode Configuration ------------------------*/
      /* In case of Alternate function mode selection */
      if((GPIO_Init->Mode == GPIO_MODE_AF_PP) || (GPIO_Init->Mode == GPIO_MODE_AF_OD))
      {
        /* Check the Alternate function parameter */
        assert_param(IS_GPIO_AF(GPIO_Init->Alternate));
        
        /* Configure Alternate function mapped with the current IO */
        temp = GPIOx->AFR[position >> 3];
        temp &= ~((uint32_t)0xF << ((uint32_t)(position & (uint32_t)0x07) * 4)) ;
        temp |= ((uint32_t)(GPIO_Init->Alternate) << (((uint32_t)position & (uint32_t)0x07) * 4));
        GPIOx->AFR[position >> 3] = temp;
      } else {
        /* !!! No AF required - set Alternate function for current IO to 0 !!! */
        temp = GPIOx->AFR[position >> 3];
        temp &= ~((uint32_t)0xF << ((uint32_t)(position & (uint32_t)0x07) * 4)) ;
        GPIOx->AFR[position >> 3] = temp;
      }

I got it solved, at least the LED is now on.

Yes, it's our self-developed board, all those are connected, seems that the reason was really in AFR regs, see my post above. Thank you for your reply!

This does not make sense - as long as the respective MODER bits are set to Out, the AF ought to be ignored.

If this is not the case, it's a hardware bug.

Can you please read out the GPIOD registers before the modification and after it?

Thanks,

JW

Wowa
Associate III

I just gave out the board to a colleague, but will try this tomorrow. Still, the LED is working. I checked errata on this chip today, there are no GPIO issues there. Interestingly...

waclawek.jan
Super User

Couldn't confirm.

Tried on a 'F746 DISCO. Enabled GPIOD in RCC, set MODER to 0x1a0000 (i.e. PD10 to Out, PD9 and PD8 to AF), set AFR[1] to 0x777 (i.e. all three pins to USART3). Enabled USART3 in RCC, set CR2.CLKEN and CR1.TE/RE/UE. As expected, wiggling bit 10 of GPIOD.ODR was reflected by bit 10 of GPIOD.IDR (PD10 is not exposed on the Disco, unfortunately), regardless of the AFR[1] setting.

Please post the readout of GPIOD registers with the modification; try to revert the modification, make sure that reproduces the problem and post then that readout of GPIOD registers, too.

@Mike_ST,

can you please clarify your comment.​ 

Thanks,

JW

Thank you for your efforts to help me with this! Today I tried to reproduce it, but didn't succeed as well. You were right, it works without modification either. I rolled back to the code that didn't work and finally found out the real reason for that failure. It happened so that besides my modification to HAL_GPIO_Init() there was another code change made at the same moment. And the glitch that caused problem was trivial misuse of logical OR (||) instead of binary one (|) trying to set two bits of one port at once (like this:  GPIO_InitStruct.Pin = nLedD_Pin || nLedR_Pin;). So it was totally my fault from the very beginning, sorry for bothering!