Skip to main content
Starman
Associate III
Apr 10, 2021 1:09 PM UTC
Solved

Why can I only use 2 GPIO pins?

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.
waclawek.jan
waclawek.janBest answer
Super User
Apr 12, 2021 10:55 AM UTC

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
Apr 10, 2021 3:51 PM UTC

Try:

volatile uint32_t a = 0;

JW

Starman
StarmanAuthor
Associate III
Apr 10, 2021 9:15 PM UTC

gave that a go, but it made no difference

Tesla DeLorean
Guru
Apr 10, 2021 6:14 PM UTC

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
Apr 10, 2021 9:17 PM UTC

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
Apr 10, 2021 10:34 PM UTC

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
Apr 10, 2021 11:54 PM UTC

PG0: 3.30V

PG1: 3.30V

PG2: 0.43V

waclawek.jan
Super User
Apr 11, 2021 2:12 AM UTC

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

Starman
StarmanAuthor
Associate III
Apr 11, 2021 10:18 AM UTC

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
Apr 11, 2021 10:34 AM UTC

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
Apr 11, 2021 5:30 PM UTC

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

JW

Starman
StarmanAuthor
Associate III
Apr 11, 2021 5:37 PM UTC

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
Apr 11, 2021 9:01 PM UTC

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
Apr 11, 2021 11:51 PM UTC

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
Apr 12, 2021 10:55 AM UTC

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
Apr 13, 2021 10:07 AM UTC

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
Apr 13, 2021 11:16 AM UTC

> 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
Apr 13, 2021 11:34 AM UTC

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
Apr 13, 2021 1:24 PM UTC

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
Apr 13, 2021 1:55 PM UTC

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?