cancel
Showing results for 
Search instead for 
Did you mean: 

where can I find the register addresses for STM32L476RG?

MFaun.1
Associate II

Hi,

I have a STM32L476RG board and I try to execute the following program, obtained from this web http://www.microdigitaled.com/ARM/STM_ARM/Code/Ver1/Chapter02/Program2-1.txt which is for a different Nucleo 64 board (STM32F446RE)

/* p2_5.c Toggle Green LED (LD2) on STM32F446RE Nucleo64 board at 1 Hz
 *
 * This program toggles LD2 for 0.5 second ON and 0.5 second OFF.
 * It is identical to Program 2-2 but was written without using
 * the header file. The registers are defined locally in the file.
 *
 * This program was tested with Keil uVision v5.24a with DFP v2.11.0
 */
 
#define RCC_AHB1ENR (*((volatile unsigned int*)0x40023830))
#define GPIOA_MODER (*((volatile unsigned int*)0x40020000))
#define GPIOA_BSRR  (*((volatile unsigned int*)0x40020018))
 
void delayMs(int n);
 
int main(void) {
    RCC_AHB1ENR |=  1;              /* enable GPIOA clock */
    
    GPIOA_MODER &= ~0x00000C00;     /* clear pin mode */
    GPIOA_MODER |=  0x00000400;     /* set pin to output mode */
    
    while(1) {
        GPIOA_BSRR = 0x00000020;    /* turn on LED */
        delayMs(500);
        GPIOA_BSRR = 0x00200000;    /* turn off LED */
        delayMs(500);
    }
}
 
/* 16 MHz SYSCLK */
void delayMs(int n) {
    int i;
    for (; n > 0; n--)
        for (i = 0; i < 3195; i++) ;
}

I can compile and load the file to the board but it does not turn on green led, and it doesn't matter if I press the switch,

I guess that the problem is that both boards have different memory sizes and adddresses for registers (lines 10-12) or maybe led and switch is connected to different port and pin in my board, but: I do not know where to find the addresses and pins where onboard led and switch are connected

Where can I find this info?

thanks in advance

Marcos

14 REPLIES 14

No idea. I am not willing to use a development environment that makes it unnecessarily hard to add include directories to a project.

CMSIS headers are distributed with the STM32CubeL4 library. Extract the Drivers/CMSIS subdirectory, and add the Drivers/CMSIS/Include and Drivers/CMSIS/Device/ST/STM32L0xx/Include directories to the project.

OK, I was thinking you were suggesting to activate some more cells.

This definition is in stm32l74xxx.h file generated by keil. To be more precisely below this line (11.147)

/********************  Bit definition for RCC_AHB2ENR register  ***************/
#define RCC_AHB2ENR_GPIOAEN_Pos              (0U)
#define RCC_AHB2ENR_GPIOAEN_Msk              (0x1UL << RCC_AHB2ENR_GPIOAEN_Pos) /*!< 0x00000001 */
#define RCC_AHB2ENR_GPIOAEN                  RCC_AHB2ENR_GPIOAEN_Msk
#define RCC_AHB2ENR_GPIOBEN_Pos              (1U)
#define RCC_AHB2ENR_GPIOBEN_Msk              (0x1UL << RCC_AHB2ENR_GPIOBEN_Pos) /*!< 0x00000002 */
#define RCC_AHB2ENR_GPIOBEN                  RCC_AHB2ENR_GPIOBEN_Msk
#define RCC_AHB2ENR_GPIOCEN_Pos              (2U)
#define RCC_AHB2ENR_GPIOCEN_Msk              (0x1UL << RCC_AHB2ENR_GPIOCEN_Pos) /*!< 0x00000004 */
#define RCC_AHB2ENR_GPIOCEN                  RCC_AHB2ENR_GPIOCEN_Msk
#define RCC_AHB2ENR_GPIODEN_Pos              (3U)
#define RCC_AHB2ENR_GPIODEN_Msk              (0x1UL << RCC_AHB2ENR_GPIODEN_Pos) /*!< 0x00000008 */
#define RCC_AHB2ENR_GPIODEN                  RCC_AHB2ENR_GPIODEN_Msk
#define RCC_AHB2ENR_GPIOEEN_Pos              (4U)
#define RCC_AHB2ENR_GPIOEEN_Msk              (0x1UL << RCC_AHB2ENR_GPIOEEN_Pos) /*!< 0x00000010 */
#define RCC_AHB2ENR_GPIOEEN                  RCC_AHB2ENR_GPIOEEN_Msk
#define RCC_AHB2ENR_GPIOFEN_Pos              (5U)
#define RCC_AHB2ENR_GPIOFEN_Msk              (0x1UL << RCC_AHB2ENR_GPIOFEN_Pos) /*!< 0x00000020 */
#define RCC_AHB2ENR_GPIOFEN                  RCC_AHB2ENR_GPIOFEN_Msk
#define RCC_AHB2ENR_GPIOGEN_Pos              (6U)
#define RCC_AHB2ENR_GPIOGEN_Msk              (0x1UL << RCC_AHB2ENR_GPIOGEN_Pos) /*!< 0x00000040 */
#define RCC_AHB2ENR_GPIOGEN                  RCC_AHB2ENR_GPIOGEN_Msk
#define RCC_AHB2ENR_GPIOHEN_Pos              (7U)
#define RCC_AHB2ENR_GPIOHEN_Msk              (0x1UL << RCC_AHB2ENR_GPIOHEN_Pos) /*!< 0x00000080 */
#define RCC_AHB2ENR_GPIOHEN                  RCC_AHB2ENR_GPIOHEN_Msk
#define RCC_AHB2ENR_OTGFSEN_Pos              (12U)
#define RCC_AHB2ENR_OTGFSEN_Msk              (0x1UL << RCC_AHB2ENR_OTGFSEN_Pos) /*!< 0x00001000 */
#define RCC_AHB2ENR_OTGFSEN                  RCC_AHB2ENR_OTGFSEN_Msk
#define RCC_AHB2ENR_ADCEN_Pos                (13U)
#define RCC_AHB2ENR_ADCEN_Msk                (0x1UL << RCC_AHB2ENR_ADCEN_Pos)  /*!< 0x00002000 */
#define RCC_AHB2ENR_ADCEN                    RCC_AHB2ENR_ADCEN_Msk
#define RCC_AHB2ENR_RNGEN_Pos                (18U)
#define RCC_AHB2ENR_RNGEN_Msk                (0x1UL << RCC_AHB2ENR_RNGEN_Pos)  /*!< 0x00040000 */
#define RCC_AHB2ENR_RNGEN                    RCC_AHB2ENR_RNGEN_Msk

it's easy to find when you know the name. What is unclear is the link between "my program is not working" and "there is a "RCC_AHB2ENR_GPIOAEN" definition hidden in a file with 18.488 lines. Even worse when you are not aware about the purpose of this defined value.

I think it's more straightforward and general my procedure: look at the manual.

Look at the manual, and use the mnemonics to avoid having to look at the manual the next time.

It does not matter at the time of writing the code, but at the time someone else comes along and tries to do something with it. You have just demonstrated my point in this thread.

You have looked at the code from someone else, and took the line

RCC_AHB1ENR |=  1;              /* enable GPIOA clock */

You have missed what is wrong with it the first time, and I have missed it too.

If the original author had written

RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;

and you tried to use it on a STM32L4, you'd immediately be greeted with a compiler error

../Core/Src/main.c: In function 'main':
../Core/Src/main.c:42:18: error: 'RCC_AHB1ENR_GPIOAEN' undeclared (first use in this function); did you mean 'RCC_AHB2ENR_GPIOAEN'?

Moreover, anyone who is a bit more familiar with STM32 would immediately recognize what

RCC->AHB2ENR |= RCC_AHB2ENR_GPIOAEN;

does, i.e. enables GPIOA, there is no need to even look at the manual.

This works in the other way round too, you want to start timer 3, and figure out from the reference manual that you have to set the CEN (counter enable) bit of CR1 to do that. So you can just write

TIM3->CR1 |= TIM_CR1_CEN;

without looking any further.

Just note the general pattern,

AAA->BBB |= AAA_BBB_CCC;

sets the CCC bit in the BBB register of the AAA peripheral. If there are more bits in the bitfield, there are _0, _1 etc suffixes for the individual bits, and the _Pos and _Msk macros for setting numerical values in bitfields.

In a commercial setting, this saves work hours, and makes spotting bugs easier, possibly affecting revenue. In a non-commercial setting like this user forum, it affects my decision between trying to look into your problem or just skipping it.

great. Many thanks. This really looks like very good practice.

Kind regards

Piranha
Chief II

Just define STM32L476xx in project settings and include <stm32l4xx.h> in code.

https://community.st.com/s/question/0D53W00000379BESAY/header-files-required-for-programming-stm32f446-mcu-in-c