Skip to main content
Starman
Associate III
April 10, 2021
Solved

Why can I only use 2 GPIO pins?

  • April 10, 2021
  • 23 replies
  • 3287 views

I am only able to use 2 GPIO pins with an STM32F767ZI on a Nucleo-144 board. The issue doesn't appear to be with any specific pins, it's just that only 2 pins seem to output any voltage at all.

Take this code for example:

main.c

#include "./headers/stm32f767xx.h"
#include <stdint.h>
 
int main(void)
{
 initMotor(0);
 initMotor(1);
 initMotor(2);
 uint32_t a = 0;
 while (1)
 {
 if (a >= 25000)
 {
 stepMotor(0);
 stepMotor(1);
 stepMotor(2);
 a = 0;
 }
 a++;
 }
}

./drivers/motor.c

#include "../headers/stm32f767xx.h"
 
void initMotor(int step_pin)
{
 RCC->AHB1ENR |= RCC_AHB1ENR_GPIOGEN;
 GPIOG->MODER |= (0b01 << (step_pin * 2));
 GPIOG->OTYPER &= ~(0b1 << step_pin);
 GPIOG->ODR &= ~(0b1 << step_pin);
}
 
void stepMotor(int step_pin)
{
 GPIOG->ODR ^= (0b1 << step_pin);
}

Using this code, only 2 of the 3 GPIO ports give out a voltage as I would expect them to. If main.c is modified to remove any of the three motors/pins, the other two will work (they give out a voltage which changes from HIGH to LOW every time period).

This issue extends even when adding LEDs which are already on the board.

Only a maximum of 2 GPIO pins (regardless of whether it is GPIOA, GPIOB, etc.) ever seem to work.

I am very unsure of the cause of this, and would appreciate any direction that people can point me in.

This topic has been closed for replies.
Best answer by waclawek.jan

Try to remove

RCC->AHB1ENR |= RCC_AHB1ENR_GPIOGEN;

from initMotor(), and place it at the beginning of main(). Also try to add a readback of RCC->AHB1ENR after that.

JW

23 replies

waclawek.jan
Super User
April 10, 2021

Try:

volatile uint32_t a = 0;

JW

Starman
StarmanAuthor
Associate III
April 10, 2021

gave that a go, but it made no difference

Tesla DeLorean
Guru
April 10, 2021

What kind of loads are you trying to drive?

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
Starman
StarmanAuthor
Associate III
April 10, 2021

i am using a separate driver, rather than directly powering the motor from the STM32. this driver requires a single pulse to step the motor by one step

waclawek.jan
Super User
April 10, 2021

With 3 pins, make one "step", stop, measure output voltages, and read out and check/post the corresponding GPIO registers values.

You can manipulate the GPIOs in debugger.

JW

Starman
StarmanAuthor
Associate III
April 10, 2021

PG0: 3.30V

PG1: 3.30V

PG2: 0.43V

waclawek.jan
Super User
April 11, 2021

and read out and check/post the corresponding GPIO registers values.

Starman
StarmanAuthor
Associate III
April 11, 2021

0x40021800 (G_MODER)

0x5 - 0000000000000101

0x40021804 (G_TYPER)

0x0 - 0000000000000000

0x40021814 (G_ODR)

0x7 - 0000000000000111

very strange, seems the MODE register isn't setting pin 2 to output

Starman
StarmanAuthor
Associate III
April 11, 2021

and when an additional motor is connected up (so four in total now), the motors connected to GP0 and GP2 spin/step rather than GP0 and GP1, like previously

the voltage output by GP0 and GP2 is 3.30V, whereas GP1 and GP3 output 0V

(yes, the code has been modified to rotate/step this additional motor by adding "initMotor(3);" and "stepMotor(3);")

and once again, the registers reflect this:

0x40021800 (G_MODER)

0x11 - 0000000000010001

0x40021804 (G_TYPER)

0x0 - 0000000000000000

0x40021814 (G_ODR)

0xf - 0000000000001111

i have no clue why the MODE register isn't being set properly

waclawek.jan
Super User
April 11, 2021

Post your code, complete, as is, don't edit it.

JW

Starman
StarmanAuthor
Associate III
April 11, 2021

https://github.com/Starman3787/motor-driver-test (it is a little big to post here)

the 'main' branch contains the fully updated code that i am using currently

waclawek.jan
Super User
April 11, 2021

I see nothing suspicious there.

From where I sit, the only option now is that you step through the code in debugger and observe, what happens with GPIOG_MODER in each step.

Alternatively, you can go through the disasm, if you are comfortable with that. Or post it, it's a fairly simple program so it shouldn't be that long.

JW

Starman
StarmanAuthor
Associate III
April 11, 2021

thanks for looking into this and the suggestion.

i added a breakpoint at the end of the motor initialisation function. each time the program stopped, i examined the MODE register, and it seemed to have the correct values. when it reached the loop, all motors spun correctly!

my best guess from this is that perhaps the MODE register was being set too quickly? the delay from having breakpoints between each call to the initMotor() function seemed to solve the issue of the MODE register not being set properly.

i'll try looking into this a little more and will update you if i find anything dramatic

waclawek.jan
waclawek.janBest answer
Super User
April 12, 2021

Try to remove

RCC->AHB1ENR |= RCC_AHB1ENR_GPIOGEN;

from initMotor(), and place it at the beginning of main(). Also try to add a readback of RCC->AHB1ENR after that.

JW

Starman
StarmanAuthor
Associate III
April 13, 2021

gave that a go and it completely fixed the issue, without the use of breakpoints between each initialisation function

do you know why it behaved like this? surely if the clock register has already been set for that GPIO, OR'ing it any further shouldnt change anything?

waclawek.jan
Super User
April 13, 2021

> do you know why it behaved like this?

No, it's a mystery to me.

Can you please contact ST through the web support form, giving link to this thread and to that github repo? Maybe we'll hear some explanation.

JW

Starman
StarmanAuthor
Associate III
April 13, 2021

will do, thanks so much for the assistance, i really appreciate it.

i will let you know here if i hear anything from ST about this

Piranha
Principal III
April 13, 2021

The RM0410 section 5.2.12 explains this. After enabling any peripheral clock, there is a general requirement to wait at least 2 peripheral clock cycles. And take a note - it's peripheral, not core or some other clock cycles.

Starman
StarmanAuthor
Associate III
April 13, 2021

the peripheral clock had already been enabled though, would OR'ing the register (as if enabling it again, but essentially a useless operation) really make a difference?