From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from gandalf.k-7.ch (96-100-31-185.ftth.cust.kwaoo.net [185.31.100.96]) by sourceware.org (Postfix) with ESMTPS id 0129A385B83E for ; Thu, 2 Dec 2021 12:39:48 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 0129A385B83E Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=k-7.ch Authentication-Results: sourceware.org; spf=fail smtp.mailfrom=k-7.ch Received: from van (alfred.lan [192.168.1.1]) (Authenticated sender: seb) by gandalf.k-7.ch (Postfix) with ESMTPSA id E3886E2B05 for ; Thu, 2 Dec 2021 13:39:46 +0100 (CET) User-agent: mu4e 1.6.6; emacs 27.2 From: =?utf-8?Q?S=C3=A9bastien?= Gendre To: gcc-help@gcc.gnu.org Subject: Wrong assembly code generated from C code (ARM =?utf-8?Q?Cortex-m?= =?utf-8?Q?3=29=C2=A0=3F?= Date: Thu, 02 Dec 2021 13:38:55 +0100 Message-ID: <87wnkngozy.fsf@k-7.ch> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Spam-Status: No, score=-0.5 required=5.0 tests=BAYES_00, KAM_DMARC_STATUS, KHOP_HELO_FCRDNS, PDS_RDNS_DYNAMIC_FP, RDNS_DYNAMIC, SPF_HELO_NONE, T_SPF_PERMERROR autolearn=no autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: gcc-help@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-help mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 02 Dec 2021 12:39:50 -0000 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:=20 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 =3D (unsigned int *)0x4002C044; // Register to define GPIO direction of pins P0.0 to P0.31 unsigned int *FIO0DIR =3D (unsigned int *)0x2009C000; // Register to define GPIO value of pins P0.0 to P0.31 unsigned int *FIO0SET =3D (unsigned int *)0x2009C018; // Config the GPIO to drive a LED // Enable P0.22 pin to put the line to ground *PINMODE1 =3D 0x00003000; // Set P0.22 as GPIO output *FIO0DIR =3D 0x400000; // To the eternity while (1) { // Wait for (int i =3D 0; i < 500000; ++i); // Toggle the LED via P0.22 *FIO0SET ^=3D (0b1<<22); } =20=20 } ``` The problem is at the line `*PINMODE1 =3D 0x00003000;`. This is the assembly code generated by GCC and view from GDB: ``` assembly =3D> 0x0000001a <+18>: ldr r3, [r7, #8] 0x0000001c <+20>: strb r6, [r0, #28] 0x0000001e <+22>: ; 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=C2=A0? Why not simply copy the value `0x00003000` to the adress stored in `r3` register=C2=A0? Why this undefined instruction `0xf590601a`=C2=A0? This third asm code, the "undefied" `0xf590601a` is the instruction that make the CPU reset.=20 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:=20 11.1.0 (Fedora 11.1.0-2.fc35) Version of GDB:=20 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 =3D (unsigned int *)0x4002C044; // Register to define GPIO direction of pins P0.0 to P0.31 unsigned int *FIO0DIR =3D (unsigned int *)0x2009C000; // Register to define GPIO value of pins P0.0 to P0.31 unsigned int *FIO0SET =3D (unsigned int *)0x2009C018; =20=20 // Config the GPIO to drive a LED // Enable P0.22 pin to put the line to ground /* *PINMODE1 |=3D (0x1<<12); */ /* *PINMODE1 |=3D (0x1<<13); */ *PINMODE1 =3D 0x00003000; // Set P0.22 as GPIO output /* *FIO0DIR |=3D (0x1<<22); */ *FIO0DIR =3D 0x400000; // To the eternity while (1) { // Wait for (int i =3D 0; i < 500000; ++i); // Toggle the LED via P0.22 *FIO0SET ^=3D (0b1<<22); } =20=20 } int STACK[256]; const void *vectors[] __attribute__ ((section (".vectors"))) =3D { STACK + sizeof(STACK) / sizeof(*STACK), reset }; ``` This is my link script: ``` MEMORY { flash (RX) : ORIGIN =3D 0x00000000, LENGTH =3D 512K sram (RW!X) : ORIGIN =3D 0x10000000, LENGTH =3D 32K } SECTIONS { .vectors : { *(.vectors) } >flash .text : { *(.text) } >flash .rodata : { *(.rodata) } >flash .bss : { *(.bss) } >sram } ``` This is my Makefile: ``` CFLAGS =3D -g -O0 -Wall CFLAGS +=3D -mthumb -mcpu=3Dcortex-m3=20 CC =3D arm-none-eabi-gcc LD =3D arm-none-eabi-ld OBJCPY =3D 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=3Dmi -x gdbconfig blink.elf ```