From: "Sébastien Gendre" <seb@k-7.ch>
To: gcc-help@gcc.gnu.org
Subject: Wrong assembly code generated from C code (ARM Cortex-m3) ?
Date: Thu, 02 Dec 2021 13:38:55 +0100 [thread overview]
Message-ID: <87wnkngozy.fsf@k-7.ch> (raw)
Hello,
I got a problem with an assembly code generated by GCC from a C code.
A little bit of context:
I try to write a minimal firmware for a micro-controller, the LPC1769.
It use ARM Cortex-M3 CPU. My firmware is simple:
* Run a function named "reset()" at CPU reset
* In this function, I declare 3 locals variables: 3 pointers to 3
differents registers, initialized with their address
* Then, I write a value in each register
The problem:
The CPU reset after the first value I write in a register
This is the code of the function "reset()":
``` c
void reset() {
// Define some registers
// Register to define mode of the pins P0.16 to P0.26
unsigned int *PINMODE1 = (unsigned int *)0x4002C044;
// Register to define GPIO direction of pins P0.0 to P0.31
unsigned int *FIO0DIR = (unsigned int *)0x2009C000;
// Register to define GPIO value of pins P0.0 to P0.31
unsigned int *FIO0SET = (unsigned int *)0x2009C018;
// Config the GPIO to drive a LED
// Enable P0.22 pin to put the line to ground
*PINMODE1 = 0x00003000;
// Set P0.22 as GPIO output
*FIO0DIR = 0x400000;
// To the eternity
while (1) {
// Wait
for (int i = 0; i < 500000; ++i);
// Toggle the LED via P0.22
*FIO0SET ^= (0b1<<22);
}
}
```
The problem is at the line `*PINMODE1 = 0x00003000;`. This is the
assembly code generated by GCC and view from GDB:
``` assembly
=> 0x0000001a <+18>: ldr r3, [r7, #8]
0x0000001c <+20>: strb r6, [r0, #28]
0x0000001e <+22>: ; <UNDEFINED> instruction: 0xf590601a
0x00000022 <+26>: ldr r3, [r7, #4]
```
The first assembly code, ldr, load the address `0x4002C044` into the
register `r3`. But the second asm code, `strb`, is it store the value
from the register `r6` to the address made frome the value of register
`r0` plus a shift of 28 ? Why not simply copy the value `0x00003000`
to the adress stored in `r3` register ? Why this undefined instruction
`0xf590601a` ? This third asm code, the "undefied" `0xf590601a` is the
instruction that make the CPU reset.
I'm not an expert in assemply and I don't know if it's me that don't
understand it of if the assembly code generated by GCC is wrong. Any
help is welcome. ;)
Thank you. :)
This is the version of arm-none-eabi-gcc I use:
11.1.0 (Fedora 11.1.0-2.fc35)
Version of GDB:
11.1 (Fedora 11.1-2.fc35)
Version of OpenOCD:
0.11.0 (from Fedora repo)
This is the full C code:
``` c
/* reset
Function run right after the reset of the CPU
*/
void reset() {
// Define some registers
// Register to define mode of the pins P0.16 to P0.26
unsigned int *PINMODE1 = (unsigned int *)0x4002C044;
// Register to define GPIO direction of pins P0.0 to P0.31
unsigned int *FIO0DIR = (unsigned int *)0x2009C000;
// Register to define GPIO value of pins P0.0 to P0.31
unsigned int *FIO0SET = (unsigned int *)0x2009C018;
// Config the GPIO to drive a LED
// Enable P0.22 pin to put the line to ground
/* *PINMODE1 |= (0x1<<12); */
/* *PINMODE1 |= (0x1<<13); */
*PINMODE1 = 0x00003000;
// Set P0.22 as GPIO output
/* *FIO0DIR |= (0x1<<22); */
*FIO0DIR = 0x400000;
// To the eternity
while (1) {
// Wait
for (int i = 0; i < 500000; ++i);
// Toggle the LED via P0.22
*FIO0SET ^= (0b1<<22);
}
}
int STACK[256];
const void *vectors[] __attribute__ ((section (".vectors"))) = {
STACK + sizeof(STACK) / sizeof(*STACK),
reset
};
```
This is my link script:
```
MEMORY {
flash (RX) : ORIGIN = 0x00000000, LENGTH = 512K
sram (RW!X) : ORIGIN = 0x10000000, LENGTH = 32K
}
SECTIONS {
.vectors : { *(.vectors) } >flash
.text : { *(.text) } >flash
.rodata : { *(.rodata) } >flash
.bss : { *(.bss) } >sram
}
```
This is my Makefile:
```
CFLAGS = -g -O0 -Wall
CFLAGS += -mthumb -mcpu=cortex-m3
CC = arm-none-eabi-gcc
LD = arm-none-eabi-ld
OBJCPY = arm-none-eabi-objcopy
all: blink.bin
blink.bin: blink.elf
@echo "Make the binary"
$(OBJCPY) -O binary blink.elf blink.bin
blink.elf: blink.o
@echo "Linkage"
$(LD) -T blink.ld -o blink.elf blink.o
blink.o: blink.c
@echo "Compile the code"
$(CC) -c $(CFLAGS) -o blink.o blink.c
clean:
@echo "Clean the working dir"
rm blink.o blink.elf blink.bin
debug: blink.elf
gdb -x gdbconfig blink.elf
debug-mi: blink.elf
gdb -i=mi -x gdbconfig blink.elf
```
next reply other threads:[~2021-12-02 12:39 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-12-02 12:38 Sébastien Gendre [this message]
2021-12-02 15:44 ` David Brown
2021-12-02 16:06 ` Sébastien Gendre
2021-12-02 19:26 ` Stefan Ring
2021-12-02 19:35 ` Stefan Ring
2021-12-02 21:58 ` David Brown
2021-12-08 5:51 ` Sébastien Gendre
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87wnkngozy.fsf@k-7.ch \
--to=seb@k-7.ch \
--cc=gcc-help@gcc.gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).