CKiamy
CKiamy

Reputation: 41

Built-in led won't turn on STM32F303RE Nucleo board

I am trying to turn the led (LD2 in schematic) inside the nucleo board on using only registers with the STM32CubeIDE.

Schematic for the STM32F303RE board.

The user manual states the following addresses for the clock, mode and data registers:

Led pin: PA5

Address of the Clock control register: RCC_AHBENR
[base address] + [offset] ===> [Result]
  0x4002 1000  +   0x14   ===> 0x40021014

Address of the GPIOA mode register
0x4800 0000 + 0x00 ===> 0x48000000

Address of the GPIOA output data register
0x4800 0000 + 0x14 ===> 0x48000014

I am using the following code to set/clear the registers in the board:

#include <stdint.h>

int main(void)
{
    uint32_t *pClkCtrlReg = (uint32_t*)0x40021014;
    uint32_t *pPortAModeReg = (uint32_t*)0x48000000;
    uint32_t *pPortAOutReg = (uint32_t*)0x48000014;

    //1. enable the clock for GPIOA peripheral in the AHBENR
    *pClkCtrlReg |= 0x00020000;

    //2. configure the mode of the IO pin as output
    //a. clear the 24th and 25th bit positions
    *pPortAModeReg &= 0xFCFFFFFF;
    //b set 24th bit position as 1
    *pPortAModeReg |= 0x01000000;

    //3. SET 12th bit of the output data register to make I/O pin-12 as HIGH
    *pPortAOutReg |= 0x20;



    while(1);
}

Using the register viewer from the IDE, I can see that the PA5 is set as output, but physically, my led is not turning on.

Position 6 is the bit that is turned on

I do not know what I am doing wrong. I am suspecting that the pin PA5 is wrong, but i tried PA12 too and it does not work. Can someone please help me out here?

Upvotes: 3

Views: 1886

Answers (3)

Hobojo
Hobojo

Reputation: 66

A few comments on your code:

  • Get in the habit of always using the volatile keyword when accessing peripheral registers. Otherwise the compiler may end up optimizing out your code. I usually make a typedef for something like a reg32_t type in order not to forget.
  • As the OP pointed out, use code of the form (1 << b) to make it obvious which bit(s) you are referencing. Your compiler will optimize this, so the end result in the compiled code will be the same. You could even consider making this into a couple of macros or inline functions.
  • When you make several changes to a peripheral register, it's a good idea to copy it; make the changes to the copy; then store the copy back to the register. This way, you don't temporarily put the register in an unwanted state.

Here's your code with these changes:

#include <stdint.h>

typedef volatile uint32_t reg32_t;

int main(void)
{
    reg32_t *pClkCtrlReg = (reg32_t*)0x40021014;
    reg32_t *pPortAModeReg = (reg32_t*)0x48000000;
    reg32_t *pPortABsrReg = (reg32_t*)0x48000018;

    //1. enable the clock for GPIOA peripheral in the AHBENR
    *pClkCtrlReg |= (1<<17);

    //2. configure the mode of the IO pin as output
    uint32_t modereg = *pPortAModeReg & ~(3<<(2*5));
    modereg |= (1<<(2*5));
    *pPortAModeReg = modereg;

    //3. SET 5th bit of the bit set/reset register to make I/O pin 5 HIGH
    *pPortABsrReg = (1<<5);

    // If you want to turn the LED back off at a later time, do this:
    // *pPortABsrReg = (1<<(5+16));

    for (;;) ;
}

Good luck with your blinky!

Upvotes: 3

Ilya
Ilya

Reputation: 1525

I ran through your code with reference manual in hand. RM0316 STM32F303 Reference manual.

You activate clock to GPIO Port A correctly (also, GPIOA registers would also read all 0x00 is it hadn't been activated).

Then you set GPIO mode as, quoting you:

//2. configure the mode of the IO pin as output
//a. clear the 24th and 25th bit positions
*pPortAModeReg &= 0xFCFFFFFF;
//b set 24th bit position as 1
*pPortAModeReg |= 0x01000000;

You work with bits 24 and 25. Which are these:

enter image description here

So you set the mode for pin A12, not A5. For GPIOA Pin 5 you need to manipulate bits 10 and 11.

//clear pin5 bits
*pPortAModeReg &= ~(0x03 << 10); //take 0b11, shift it to position 10, flip all bits, AND with original state of register

And follow it with setting those bits to "General purpose output mode" 01, which you also do for wrong bits:

//b set 10th bit position as 1
*pPortAModeReg |= (0x01 << 10);

I checked all the registers GPIO has, there shouldn't be anything else you need to set. If things still don't work, please post the contents of all GPIOA registers.

EDIT: also, try using bit set/reset registers. Note that they are read only, so no "|=" for them, only "=". Writing 0 to them doesn't do anything. So you need to write only (0x01<<5) straight to the GPIOA BSRR register.

GPIOA->BSRR = (1U<<5); //or however you want to address that register

Upvotes: 3

ThongDT
ThongDT

Reputation: 189

//3. SET 12th bit of the output data register to make I/O pin-12 as HIGH
*pPortAOutReg |= 0x20;

for PIN 12, the value should be *pPortAOutReg |= 0x1000;

Or you could do as following:*pPortAOutReg |= (1 << 12); With this you don't need to know excactly value.

Upvotes: 0

Related Questions