[SOLVED] writing to register on the STM32 (casting int value)

flyboy74
Fri Jun 15, 2018 5:06 am
I want to learn C to be able to drive the low level stuff that can’t be driven in higher level langues. So I am learning to write C (ardunio C atm). My first task simple task is I just want to turn a GPIO pin on/off using registers.

From my googling I though this code would do the job but it got a compile error

invalid conversion from ‘int’ to ‘uint32* {aka long unsigned int*}’ [-fpermissive]

void setup() {
// put your setup code here, to run once:
uint32 * GPIOA_CRL = 0x40010800;
uint32 * GPIOA_CRH = 0x40010804;
uint32 * GPIOA_IDR = 0x40010808;
uint32 * GPIOA_ODR = 0x4001080C;
uint32 * GPIOA_BSRR = 0x40010810;
uint16 * GPIOA_BRR = 0x40010814;

*GPIO_CRL = 0b01000100010001000100010001000011
}

void loop() {
// put your main code here, to run repeatedly:
*GPIO_ODR = 0b00000000000000000000000000000001
*GPIO_ODR = 0b00000000000000000000000000000000

}


Pito
Fri Jun 15, 2018 6:32 am
viewtopic.php?f=18&t=1220

flyboy74
Fri Jun 15, 2018 7:04 am
@ Pito thanks.

I got this code to work as expected but this raises a further question for me. is GPIOA->regs->CRL a standard C namingspace or is this something added to the STM32 port of Ardunio. For me reading the the datasheet on the chip it gives the physical address in memory.

void setup() {
// put your setup code here, to run once:
GPIOA->regs->CRL = 0b01000100010001000100010001000011;
}

void loop() {
// put your main code here, to run repeatedly:
GPIOA->regs->ODR = 0b00000000000000000000000000000001;
GPIOA->regs->ODR = 0b00000000000000000000000000000000;
;


Pito
Fri Jun 15, 2018 7:24 am
It comes from the definitions in the official stm32duino core

https://github.com/rogerclarkmelbourne/Arduino_STM32

gpio.h:

https://github.com/rogerclarkmelbourne/ … ies/gpio.h


flyboy74
Fri Jun 15, 2018 8:07 am
@Pito thanks again for the links. I am reading them closely now.

I have just noticed this: The BRR register is a 16 bit register but it is declared as a unit32 making for an incorrect pointer size and also an incorrect address for the following pointer LCKR

/** GPIO register map type */
typedef struct gpio_reg_map {
__IO uint32 CRL; /**< Port configuration register low */
__IO uint32 CRH; /**< Port configuration register high */
__IO uint32 IDR; /**< Port input data register */
__IO uint32 ODR; /**< Port output data register */
__IO uint32 BSRR; /**< Port bit set/reset register */
__IO uint32 BRR; /**< Port bit reset register */
__IO uint32 LCKR; /**< Port configuration lock register */
} gpio_reg_map;


edogaldo
Fri Jun 15, 2018 9:54 am
@flyboy74
BRR is not really 16bits: it’s 32bits but only the low part (lower 16 bits) is used, the high part is “reserved”.
You can see this in RM0008 where you can also see that BRR starts at offset 0x14 and LCKR starts at offset 0x18 (32 bits after)..

Edit: this is also the same for IDR and ODR.


zoomx
Fri Jun 15, 2018 10:27 am
Little correction

[flyboy74 – Fri Jun 15, 2018 7:04 am] –
void setup() {
// put your setup code here, to run once:
GPIOA->regs->CRL = 0b01000100010001000100010001000011;
}

void loop() {
// put your main code here, to run repeatedly:
GPIOA->regs->ODR = 0b00000000000000000000000000000001;
GPIOA->regs->ODR = 0b00000000000000000000000000000000;
}


flyboy74
Fri Jun 15, 2018 10:41 am
BRR is not really 16bits: it’s 32bits but only the low part (lower 16 bits) is used, the high part is “reserved”.

Ahh yes. I just read the bit at the top of GPIO registers where it says 16bit.

Ok I have been staring the the source code that was linked above trying to get mu head around it all.

this code
GPIOA->regs->ODR


fpiSTM
Fri Jun 15, 2018 10:56 am
Adress of the GPIO is defined as a structure to ease access:
https://github.com/rogerclarkmelbourne/ … gpio.h#L56

https://github.com/rogerclarkmelbourne/ … gpio.h#L51


Pito
Fri Jun 15, 2018 11:05 am
For example in ..\cores\maple\libmaple\gpioF1.c
/*
* GPIO devices
*/

gpio_dev gpioa = {
.regs = GPIOA_BASE,
.clk_id = RCC_GPIOA,
.exti_port = AFIO_EXTI_PA,
};
/** GPIO port A device. */
gpio_dev* const GPIOA = &gpioa;

gpio_dev gpiob = {
.regs = GPIOB_BASE,
.clk_id = RCC_GPIOB,
.exti_port = AFIO_EXTI_PB,
};
/** GPIO port B device. */
gpio_dev* const GPIOB = &gpiob;

gpio_dev gpioc = {
.regs = GPIOC_BASE,
.clk_id = RCC_GPIOC,
.exti_port = AFIO_EXTI_PC,
};


flyboy74
Fri Jun 15, 2018 11:36 am
Thanks it is starting to make more sense to me now.
ok I know this codes works properly because I run the code and see on my scope what I expect to see: fast on then off then little break due to running the loop.
void setup() {
// put your setup code here, to run once:
GPIOA->regs->CRL = 0b01000100010001000100010001000011;
}

void loop() {
// put your main code here, to run repeatedly:
GPIOA->regs->ODR = 0b00000000000000000000000000000001;
GPIOA->regs->ODR = 0b00000000000000000000000000000000;
}


stevestrong
Fri Jun 15, 2018 11:40 am
Try this:
GPIOA_Control_low = (uint32_t *)0x40010800; //assign start address to point to

flyboy74
Fri Jun 15, 2018 11:47 am
[stevestrong – Fri Jun 15, 2018 11:40 am] –
Try this:
GPIOA_Control_low = (uint32_t *)0x40010800; //assign start address to point to

flyboy74
Fri Jun 15, 2018 11:49 am
I will now have a play with the timers and interrupts and see if I can nut them out :)

Leave a Reply

Your email address will not be published. Required fields are marked *