cancel
Showing results for 
Search instead for 
Did you mean: 

[stm32F411RE] Turning on LD2 through C, not working!

aeaefbay
Associate

Hi ST Community!

 

Warning, this is about to be a long one 🙂

 

I have tried following the LED on step by step, but for my board. In this instance, the LED I am flashing is LD2 on my board which is connected to pin D13, based on the schematic below (which I obtained from https://www.st.com/en/evaluation-tools/nucleo-f411re.html#cad-resources)

 

aeaefbay_7-1712811987963.png

 

I have used the AHB1 clock channel peripherals as dictated by the architecture in the datasheet of my boards chip.

 

aeaefbay_8-1712811999985.png

 

System architecture up close

 

aeaefbay_9-1712812009327.png

 

Full View

 

Now, onto its reference manual (RM0383) I use the following Addresses

 

aeaefbay_10-1712812020895.png

 

 

Boundary addresses used for RCC and GPIOD

 

 

aeaefbay_11-1712812029680.png

 

 

Based on this data, my clock enable register has been set as 0x4002 3800 + 0x30 ==> 4002 3830

To enable the peripheral for Port D the value 0x08 was written through an OR shift (see final code)

 

aeaefbay_12-1712812039877.png

 

With this data, my register of initialising port D is 0x4002 0C00 + 0x0 ==> 0x40020C00. Pin 13 was highlighted

To clear the register for the 26th and 27th position the value 0xF3FFFFFF was calculated to AND shift, and then set up with calculated hex value of 0x04000000 with the OR shift (see final code)

 

aeaefbay_13-1712812049533.png

 

 

The output register determined to be was 0x4002 0C00 + 0x14 ==> 0x4002 0C14

The final output value 0x2000 based on Pin 13 was masked on the output register with an OR operation (see final code)

The final code I used was this

 

 

 

#include <stdint.h>

 

#if !defined(__SOFT_FP__) && defined(__ARM_FP)

#warning "FPU is not initialized, but the project is compiling for an FPU. Please initialize the FPU before use."

#endif

 

int main(void)

{

 

/* Loop forever */

 

// Create the pointer variables for the addresses

uint32_t *pClkctrlreg = (uint32_t*)0x40023830; // It will store as a pointer not a number

uint32_t *pPortDModeReg = (uint32_t*)0x40020C00; // It will store as a pointer not a number

uint32_t *pPortDOutReg = (uint32_t*)0x40020C14; // It will store as a pointer not a number

 

// Enable the clock for the relevant register (AHB1)

// uint32_t temp = *pClkctrlreg; // read

// temp = temp | 0x08; //modify

// *pClkctrlreg = temp; //write

*pClkctrlreg |= 0x08;

 

// clear the 26th and 27th bit positions to reset it initially

*pPortDModeReg &= 0xF3FFFFFF;

 

// Set the 26th bit as general purpose output mode

*pPortDModeReg |= 0x04000000;

 

// Output register

*pPortDOutReg |= 0x2000;

 

while (1);

 

}

 

 

No lights! and I can confirm my LED wasnt busted, as I used an old default LED dimming code which works

 

I went to debug to monitor the registers to make sure it was working too, and bridged the CN5 to see if it helped but no avail!

aeaefbay_14-1712812153967.png

aeaefbay_15-1712812160342.png

aeaefbay_16-1712812175539.png

 

 

1 ACCEPTED SOLUTION

Accepted Solutions

I've pulled a Nucleo411 from the stash of STM32 boards I have, copypasted your code, compiled, loaded, no LED.

But, observing registers, GPIOD_MODER register is zero. What gives?

I always compile with optimization, and your definitions don't define registers as volatile, so the compiler felt free - and rightly so - to reorganize the code and also omit some of the writes. This, together with poor readability, highlight the fact that not using symbols from the CMSIS-mandated device header is a bad idea.

Regardless, the root problem is elsewhere, and it is, surprisingly, in Arduino... the LED is *not* on pin PD13, but on the pin which is in Arduino world (hence the Arduino header used on Nucleo) called as D13, i.e. 13th Digital pin.

It is PA5.

waclawekjan_0-1712818538641.png

 

Here is Nucleo411 blinky:

#include "stm32f4xx.h"  // must be before common.h, where the OR macro is defined
#include "stm32f4xx_augment.h"

// 'F411 NUCLEO
// LED  PA5
#define LED_PORT     GPIOA
#define LED_PIN      5

// BUTTON     PC13, switches to GND
#define BUTTON_PORT      GPIOC
#define BUTTON_PIN       13




// default HSI 16MHz clock
#define CLOCK_MHZ  16



// -------- utils/frameworks
// trivial loopdelay
static void LoopDelay(volatile uint32_t n) {
	while(n > 0) n--;
}

#define DELAY_CONSTANT 1000000



// ---------------------------- MAIN ------------------------------
int main(void) {

  RCC->AHB1ENR |= 0
    | RCC_AHB1ENR_GPIOAEN   
    | RCC_AHB1ENR_GPIOCEN
  ;

  GPIOA->MODER = (GPIOA->MODER  // assuming reset value
  ) | (0
    | (GPIO_Mode_Out  * GPIO_MODER_MODER5_0)   // LED
  );

// GPIOC - button is on PC13 - GPIO In is the default value, and there's an external pullup, so we don't need to set up here anything


  while(1) {
    PIN_SET(LED);
    LoopDelay(DELAY_CONSTANT);
    if (PIN_GET(BUTTON)) {
      LoopDelay(3 * DELAY_CONSTANT);
    }
    PIN_CLR(LED);
    LoopDelay(DELAY_CONSTANT);
  }
}
  // GPIOx_MODER - 2 bits per pin
#define GPIO_Mode_In                         0x00  // GPIO Input Mode
#define GPIO_Mode_Out                        0x01  // GPIO Output Mode
#define GPIO_Mode_AlternateFunction          0x02  // GPIO Alternate function Mode
#define GPIO_Mode_AF                         GPIO_Mode_AlternateFunction
#define GPIO_Mode_Analog                     0x03  // GPIO Analog Mode

  #define PIN_SET(pin)   pin##_PORT->BSRR = (1 << (pin##_PIN + 0))
  #define PIN_CLR(pin)   pin##_PORT->BSRR = (1 << (pin##_PIN + 16))
  #define PIN_GET(pin)   ((pin##_PORT->IDR & (1 << pin##_PIN)) ? 1 : 0)

 

JW

View solution in original post

3 REPLIES 3

I've pulled a Nucleo411 from the stash of STM32 boards I have, copypasted your code, compiled, loaded, no LED.

But, observing registers, GPIOD_MODER register is zero. What gives?

I always compile with optimization, and your definitions don't define registers as volatile, so the compiler felt free - and rightly so - to reorganize the code and also omit some of the writes. This, together with poor readability, highlight the fact that not using symbols from the CMSIS-mandated device header is a bad idea.

Regardless, the root problem is elsewhere, and it is, surprisingly, in Arduino... the LED is *not* on pin PD13, but on the pin which is in Arduino world (hence the Arduino header used on Nucleo) called as D13, i.e. 13th Digital pin.

It is PA5.

waclawekjan_0-1712818538641.png

 

Here is Nucleo411 blinky:

#include "stm32f4xx.h"  // must be before common.h, where the OR macro is defined
#include "stm32f4xx_augment.h"

// 'F411 NUCLEO
// LED  PA5
#define LED_PORT     GPIOA
#define LED_PIN      5

// BUTTON     PC13, switches to GND
#define BUTTON_PORT      GPIOC
#define BUTTON_PIN       13




// default HSI 16MHz clock
#define CLOCK_MHZ  16



// -------- utils/frameworks
// trivial loopdelay
static void LoopDelay(volatile uint32_t n) {
	while(n > 0) n--;
}

#define DELAY_CONSTANT 1000000



// ---------------------------- MAIN ------------------------------
int main(void) {

  RCC->AHB1ENR |= 0
    | RCC_AHB1ENR_GPIOAEN   
    | RCC_AHB1ENR_GPIOCEN
  ;

  GPIOA->MODER = (GPIOA->MODER  // assuming reset value
  ) | (0
    | (GPIO_Mode_Out  * GPIO_MODER_MODER5_0)   // LED
  );

// GPIOC - button is on PC13 - GPIO In is the default value, and there's an external pullup, so we don't need to set up here anything


  while(1) {
    PIN_SET(LED);
    LoopDelay(DELAY_CONSTANT);
    if (PIN_GET(BUTTON)) {
      LoopDelay(3 * DELAY_CONSTANT);
    }
    PIN_CLR(LED);
    LoopDelay(DELAY_CONSTANT);
  }
}
  // GPIOx_MODER - 2 bits per pin
#define GPIO_Mode_In                         0x00  // GPIO Input Mode
#define GPIO_Mode_Out                        0x01  // GPIO Output Mode
#define GPIO_Mode_AlternateFunction          0x02  // GPIO Alternate function Mode
#define GPIO_Mode_AF                         GPIO_Mode_AlternateFunction
#define GPIO_Mode_Analog                     0x03  // GPIO Analog Mode

  #define PIN_SET(pin)   pin##_PORT->BSRR = (1 << (pin##_PIN + 0))
  #define PIN_CLR(pin)   pin##_PORT->BSRR = (1 << (pin##_PIN + 16))
  #define PIN_GET(pin)   ((pin##_PORT->IDR & (1 << pin##_PIN)) ? 1 : 0)

 

JW

Thanks Jan! Yes turns out it was the wrong pin😂 its a very bare metal C programming (so no ST libraries), just standard C ones 🙂 shouldve mentioned that.

The CMSIS-mandated device header is IMO a good least common denominator, which should be used even if you want to avoid using ST libraries.

IMO there's no benefit from not using it and also negligible risk in using it.

JW