EmbDev.net

Forum: ARM programming with GCC/GNU tools GCC weirdness (I think)


von jm (Guest)


Rate this post
useful
not useful
I'm using a recently downloaded install of MinGW and Eclipse to test 
some functions by using the debugger...so anyway, I have defined a 
struct and instantiated one as a global by doing something like this:

struct foo_t
{
    signed int num;
};

struct foo_t foo;

This statement is outside of main(), and outside of all functions.

The real struct contains mostly signed ints.

In main(), I do something like this:

int main(void)
{
foo.num = 300;
afunc();
}


Now for the weird part: when I step past where it sets it to 300, I can 
see that struct member is 300.  As soon as I enter afunc(), foo.num is 
zero!  I don't even modify foo in afunc().  Once it exits afunc(), the 
value of 300 is restored.

I've done lots of C programming, so either I'm having a brain fart or 
come across some bug.

von Norbert (Guest)


Rate this post
useful
not useful
Hmmm, don't know which version you're using but it compiles and runs 
fine here.


GNU C (Debian 4.4.5-8) version 4.4.5 (x86_64-linux-gnu)
  compiled by GNU C version 4.4.5, GMP version 4.3.2, MPFR version 
3.0.0-p3.
1
#include <stdio.h>
2
3
struct foo_t
4
{
5
    signed int num;
6
};
7
8
struct foo_t foo;
9
10
void afunc(void)
11
{
12
    printf("%d\n", foo.num);
13
}
14
15
int main(void)
16
{
17
    foo.num = 300;
18
    printf("%d\n", foo.num);
19
    afunc();
20
    printf("%d\n", foo.num);
21
    return 0;
22
}


Result:
300
300
300

von Alexander F. (alexf91)


Rate this post
useful
not useful
It compiles and runs fine at my system too.

gcc (Debian 4.7.2-5) 4.7.2 and
GNU gdb (GDB) 7.6-debian

von jm (Guest)


Rate this post
useful
not useful
Definite brain fart.  I had the struct defined in main() AND globally. 
I had to start stripping large sections of code out to see it.

I guess I'll never stop making dumb mistakes.

von Clarence R. (croopnarine)


Rate this post
useful
not useful
Hi, I’ve tried to compile a drivre for a UART on the TMS470R1B1M part of 
the driver ( the write function is shown below):

static int uart_write( struct _file_descriptor* fd, const void* 
write_buf, int num_bytes )
{
       volatile int bytes_written = -1;
       volatile SCI_TypeDef* SCIx;
       if( ( is_valid_handle( fd ) ) &&
           ( write_buf != NULL )     &&
           ( num_bytes > 0 ) )
       {
             SCIx = ( ( SCI_TypeDef* )( fd->fd_priv_data ) );
             if( ( fd->mode & O_RDONLY ) != O_RDONLY )
             {
                    bytes_written = 0;
                    while( bytes_written < num_bytes )
                    {
                       /* Determine if the transmitter is ready to
                          transmit a byte */
                           while( ( SCIx->CTL2 & SCI_TXRDY ) != 0 )
                               asm("nop;");
                           SCIx->TXBUF =
                              ( ( char* )( write_buf ) 
)[bytes_written++];
                    }
             }
       }
       return bytes_written;
}

When complied with gcc arm-elf 4.2.0 I’ve got the following output:

static int uart_write( struct _file_descriptor* fd,
                       const void* write_buf,
                       int num_bytes )
{
    uart_wri:mov     r12,r13
    stmdb   r13!,{r11-r12,r14,pc}
    sub     r11,r12,#0x4
    sub     r13,r13,#0x14
    str     r0,[r11,#-0x18]
    str     r1,[r11,#-0x1C]
    str     r2,[r11,#-0x20]
    volatile int bytes_written = -1;
    mvn     r3,#0x0
    str     r3,[r11,#-0x14]
    volatile SCI_TypeDef* SCIx;
    if( ( is_valid_handle( fd ) ) &&
        ( write_buf != NULL )     &&
        ( num_bytes > 0 ) )
    ldr     r0,[r11,#-0x18]
    bl      0x11180          ; is_valid_handle
    mov     r3,r0
    cmp     r3,#0x0
    beq     0x11540
    ldr     r3,[r11,#-0x1C]
    cmp     r3,#0x0
    beq     0x11540
    ldr     r3,[r11,#-0x20]
    cmp     r3,#0x0
    ble     0x11540
{
    SCIx = ( ( SCI_TypeDef* )( fd->fd_priv_data ) );
    ldr     r3,[r11,#-0x18]
    ldr     r3,[r3,#0x1C]
    str     r3,[r11,#-0x10]

    while( bytes_written < num_bytes )
    {
        /* Determine if the transmitter is ready to transmit a byte */
        while( ( SCIx->CTL2 & SCI_TXRDY ) != 0 ) asm("nop;");
        SCIx->TXBUF = ( ( char* )( write_buf ) )[bytes_written++];
     }

}
    return bytes_written;
    ldr     r3,[r11,#-0x14]
    mov     r0,r3
    sub     r13,r11,#0x0C
    ldmia   r13,{r11,r13,pc}
}

As can be seen no assembly code is generated for the while loop. These 
are the flags used for gcc

CFLAGS += -mbig-endian  -mcpu=arm7tdmi -mapcs-frame -gdwarf-2 
-I$(PROJECTROOT)

AFLAGS = -mcpu=arm7tdmi  --warn -EB -mfpu=softfpa -mapcs-32 --gdwarf2

LDFLAGS = --script=$(TMS470R1B1MDIR)ldscript -EB 
-Map=$(OUTPUTDIR)/main.map --cref --gc-sections

ODFLAGS = --wide --source --all-headers --reloc --syms --disassemble -t

LDFLAGS += -L /cygdrive/c/GNUARM/arm-elf/lib/be/

LIBS = $(SYSTEMLIBSDIR)libgcc.a
LIBS += /cygdrive/c/GNUARM/arm-elf/lib/be/libc.a
LIBS += /cygdrive/c/GNUARM/arm-elf/lib/be/libg.a
LIBS += /cygdrive/c/GNUARM/arm-elf/lib/be/libm.a


Any suggestion I can try to get the complier to generate the assembly 
code for the while loop?

Thanks

Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
No account? Register here.