2020-03-20 05:33 PM
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
Solved! Go to Solution.
2020-03-21 05:42 AM
> which pin and port are connected the user led and switch?
Yes the Nucleo UM is not the example of well-executed document,. but generally the schematics for the STM32 devboards are quite well usable. (Maybe that's why ST does put them into the new devboards' UMs...)
JW
2020-03-20 09:32 PM
This is not recommended practice. Specifying register addresses manually is very prone to errors, and makes it harder for the compiler to optimize code.
If you still want to do it, search for "register boundary addresses" in the reference manual for the base address of each peripheral, and the "register map" section at the end of each chapter for the register offsets from the base address.
2020-03-20 09:32 PM
Generally a combination of Data Sheet and Reference Manual. Can also dig out from the include files, or printf of pointer addresses.
2020-03-21 04:15 AM
hi,
first of all, thanks for your answer.
IMHO if you want to work with different fabricant boards, which is not good practice is to use CubeMX, because:
Anyway, I still need to know the port and pin where onboard switch and led are connected. The sheet included in the package is not very informative, and the info in STM, again, is not easy-to-find.
2020-03-21 04:50 AM
The reference manual and the datasheet cover the microcontroller only. You can find the register addresses, pinouts, but whatever the board makes has put on the board is outside the scope of these documents.
Boards made by ST have a product page on the website, where you can access the board user manual under resources / technical documentation, and there should be a board schematics either included in the user manual, or provided as separate document on the same page.
Boards made by third parties might or might not come with schematics, contact the distributor or the manufacturer if you can't find it.
2020-03-21 05:20 AM
hi, yes, I agree, as a general rule, it doesn't matter the fabricant or the model there are manuals and info should be there. Even if you buy a microwave oven or a FM radio. But now I am interested in my specific case, not the general receipt. I cannot find the info. This is my board, which is official https://www.st.com/en/evaluation-tools/nucleo-l476rg.html#
but the documentation is a mesh of specific parts related to my precise model as well as general info, and so far, I was unable to find this simple info: in which pin and port are connected the user led and switch?
2020-03-21 05:42 AM
> which pin and port are connected the user led and switch?
Yes the Nucleo UM is not the example of well-executed document,. but generally the schematics for the STM32 devboards are quite well usable. (Maybe that's why ST does put them into the new devboards' UMs...)
JW
2020-03-21 10:40 AM
Hi,
finally I succeed thanks to this nice page with addresses for different microcontrollers http://libopencm3.org/docs/latest/stm32l4/html/modules.html
The difference of my board (STM32L476RG) with the other board (STM32F446RE) is that clock activation is with RCC_AHB2ENR and not with RCC_AHB1ENR
this is my code with direct register definition (more definitions than required for future extensions)
/* 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
*/
/* --- STM32 specific peripheral definitions ------------------------------- */
/* Memory map for all busses */
#define PERIPH_BASE (0x40000000U)
#define FMC1_BANK_BASE (0x60000000U)
#define FMC3_BANK_BASE (0x80000000U)
#define QUADSPI_BANK_BASE (0x90000000U)
#define FMC_QUADSPI_BASE (0xA0000000U)
#define INFO_BASE (0x1fff0000U)
#define PERIPH_BASE_APB1 (PERIPH_BASE + 0x00000)
#define PERIPH_BASE_APB2 (PERIPH_BASE + 0x10000)
#define PERIPH_BASE_AHB1 (PERIPH_BASE + 0x20000)
#define PERIPH_BASE_AHB2 (0x48000000U)
/* AHB2 */
#define GPIO_PORT_A_BASE (PERIPH_BASE_AHB2 + 0x0000)
#define GPIO_PORT_B_BASE (PERIPH_BASE_AHB2 + 0x0400)
#define GPIO_PORT_C_BASE (PERIPH_BASE_AHB2 + 0x0800)
#define GPIO_PORT_D_BASE (PERIPH_BASE_AHB2 + 0x0c00)
#define GPIO_PORT_E_BASE (PERIPH_BASE_AHB2 + 0x1000)
#define GPIO_PORT_F_BASE (PERIPH_BASE_AHB2 + 0x1400)
#define GPIO_PORT_G_BASE (PERIPH_BASE_AHB2 + 0x1800)
#define GPIO_PORT_H_BASE (PERIPH_BASE_AHB2 + 0x1c00)
#define GPIOA GPIO_PORT_A_BASE
#define GPIOB GPIO_PORT_B_BASE
#define GPIOC GPIO_PORT_C_BASE
#define GPIOD GPIO_PORT_D_BASE
#define GPIOE GPIO_PORT_E_BASE
#define GPIOF GPIO_PORT_F_BASE
#define MMIO32(addr) (*(volatile unsigned int*)(addr))
#define RCC_AHB1ENR_OFFSET 0x48
#define RCC_AHB2ENR_OFFSET 0x4C
#define RCC_BASE (PERIPH_BASE_AHB1 + 0x1000)
#define RCC_AHB1ENR MMIO32(RCC_BASE + RCC_AHB1ENR_OFFSET)
#define RCC_AHB2ENR MMIO32(RCC_BASE + RCC_AHB2ENR_OFFSET)
/* --- GPIO registers for STM32F2, STM32F3 and STM32F4 --------------------- */
/* Port mode register (GPIOx_MODER) */
#define GPIO_MODER(port) MMIO32((port) + 0x00)
#define GPIOA_MODER GPIO_MODER(GPIOA)
#define GPIOB_MODER GPIO_MODER(GPIOB)
#define GPIOC_MODER GPIO_MODER(GPIOC)
#define GPIOD_MODER GPIO_MODER(GPIOD)
#define GPIOE_MODER GPIO_MODER(GPIOE)
#define GPIOF_MODER GPIO_MODER(GPIOF)
/* Port output type register (GPIOx_OTYPER) */
#define GPIO_OTYPER(port) MMIO32((port) + 0x04)
#define GPIOA_OTYPER GPIO_OTYPER(GPIOA)
#define GPIOB_OTYPER GPIO_OTYPER(GPIOB)
#define GPIOC_OTYPER GPIO_OTYPER(GPIOC)
#define GPIOD_OTYPER GPIO_OTYPER(GPIOD)
#define GPIOE_OTYPER GPIO_OTYPER(GPIOE)
#define GPIOF_OTYPER GPIO_OTYPER(GPIOF)
/* Port output speed register (GPIOx_OSPEEDR) */
#define GPIO_OSPEEDR(port) MMIO32((port) + 0x08)
#define GPIOA_OSPEEDR GPIO_OSPEEDR(GPIOA)
#define GPIOB_OSPEEDR GPIO_OSPEEDR(GPIOB)
#define GPIOC_OSPEEDR GPIO_OSPEEDR(GPIOC)
#define GPIOD_OSPEEDR GPIO_OSPEEDR(GPIOD)
#define GPIOE_OSPEEDR GPIO_OSPEEDR(GPIOE)
#define GPIOF_OSPEEDR GPIO_OSPEEDR(GPIOF)
/* Port pull-up/pull-down register (GPIOx_PUPDR) */
#define GPIO_PUPDR(port) MMIO32((port) + 0x0c)
#define GPIOA_PUPDR GPIO_PUPDR(GPIOA)
#define GPIOB_PUPDR GPIO_PUPDR(GPIOB)
#define GPIOC_PUPDR GPIO_PUPDR(GPIOC)
#define GPIOD_PUPDR GPIO_PUPDR(GPIOD)
#define GPIOE_PUPDR GPIO_PUPDR(GPIOE)
#define GPIOF_PUPDR GPIO_PUPDR(GPIOF)
/* Port input data register (GPIOx_IDR) */
#define GPIO_IDR(port) MMIO32((port) + 0x10)
#define GPIOA_IDR GPIO_IDR(GPIOA)
#define GPIOB_IDR GPIO_IDR(GPIOB)
#define GPIOC_IDR GPIO_IDR(GPIOC)
#define GPIOD_IDR GPIO_IDR(GPIOD)
#define GPIOE_IDR GPIO_IDR(GPIOE)
#define GPIOF_IDR GPIO_IDR(GPIOF)
/* Port output data register (GPIOx_ODR) */
#define GPIO_ODR(port) MMIO32((port) + 0x14)
#define GPIOA_ODR GPIO_ODR(GPIOA)
#define GPIOB_ODR GPIO_ODR(GPIOB)
#define GPIOC_ODR GPIO_ODR(GPIOC)
#define GPIOD_ODR GPIO_ODR(GPIOD)
#define GPIOE_ODR GPIO_ODR(GPIOE)
#define GPIOF_ODR GPIO_ODR(GPIOF)
/* Port bit set/reset register (GPIOx_BSRR) */
#define GPIO_BSRR(port) MMIO32((port) + 0x18)
#define GPIOA_BSRR GPIO_BSRR(GPIOA)
#define GPIOB_BSRR GPIO_BSRR(GPIOB)
#define GPIOC_BSRR GPIO_BSRR(GPIOC)
#define GPIOD_BSRR GPIO_BSRR(GPIOD)
#define GPIOE_BSRR GPIO_BSRR(GPIOE)
#define GPIOF_BSRR GPIO_BSRR(GPIOF)
/* Port configuration lock register (GPIOx_LCKR) */
#define GPIO_LCKR(port) MMIO32((port) + 0x1c)
#define GPIOA_LCKR GPIO_LCKR(GPIOA)
#define GPIOB_LCKR GPIO_LCKR(GPIOB)
#define GPIOC_LCKR GPIO_LCKR(GPIOC)
#define GPIOD_LCKR GPIO_LCKR(GPIOD)
#define GPIOE_LCKR GPIO_LCKR(GPIOE)
#define GPIOF_LCKR GPIO_LCKR(GPIOF)
/* Alternate function low register (GPIOx_AFRL) */
#define GPIO_AFRL(port) MMIO32((port) + 0x20)
#define GPIOA_AFRL GPIO_AFRL(GPIOA)
#define GPIOB_AFRL GPIO_AFRL(GPIOB)
#define GPIOC_AFRL GPIO_AFRL(GPIOC)
#define GPIOD_AFRL GPIO_AFRL(GPIOD)
#define GPIOE_AFRL GPIO_AFRL(GPIOE)
#define GPIOF_AFRL GPIO_AFRL(GPIOF)
/* Alternate function high register (GPIOx_AFRH) */
#define GPIO_AFRH(port) MMIO32((port) + 0x24)
#define GPIOA_AFRH GPIO_AFRH(GPIOA)
#define GPIOB_AFRH GPIO_AFRH(GPIOB)
#define GPIOC_AFRH GPIO_AFRH(GPIOC)
#define GPIOD_AFRH GPIO_AFRH(GPIOD)
#define GPIOE_AFRH GPIO_AFRH(GPIOE)
#define GPIOF_AFRH GPIO_AFRH(GPIOF)
void delayMs(int n);
int main(void) {
//RCC_AHB1ENR |= 1; /* enable GPIOA clock */
RCC_AHB2ENR |= 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++) ;
}
2020-03-21 10:16 PM
> clock activation is with RCC_AHB2ENR and not with RCC_AHB1ENR
Oh, did I mention that it is very prone to errors?
Using CMSIS definitions from the MCU header, it would have been immediately apparent at compile time that RCC_AHB1ENR_GPIOAEN is not defined, but RCC_AHB2ENR_GPIOAEN is.
2020-03-22 03:55 AM
I have an empty CMSIS section. Which option do you suggest?