This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Code compiled with GNU gives memory problem

Hi,

Setup:
- Keil MCB2103 Evaluation Kit
- Keilmdk303j.exe installed
- gccARM331.exe installed

I did a little software with I2C, Timer, WD, etc. It compiled with the Keil compiler. I tried the software on flash and ram and worked as expected.

Then, I tried to compile with GNU (Cygnus). I had some issues, but did succeed.

Because I am new with GNU, I used the LinkerScript.ld from C:\Keil\ARM\GNU. I changed the size to:

  CODE (rx) : ORIGIN = 0x00000000, LENGTH = 0x00004000
  DATA (rw) : ORIGIN = 0x40000000, LENGTH = 0x00004000


In the /Options for Target/Linker I have:

Text Start: 0x00000000
Data Start: 0x40000000


I took the Startup.s file from C:\Keil\ARM\GNU\Boards\Keil\MCB2100\Blinky

Once the debugger is started, the first line that is pointed is

   119: Vectors:        LDR     PC, Reset_Addr
0x00000000  E59F4034  LDR       R4,[PC,#0x0034]

Then, I step by step in the code until I reached the swp line:

   120:                 LDR     PC, Undef_Addr
0x00000004  E3A05002  MOV       R5,#0x00000002
   121:                 LDR     PC, SWI_Addr
0x00000008  E5845000  STR       R5,[R4]
   122:                 LDR     PC, PAbt_Addr
0x0000000C  E3A05003  MOV       R5,#0x00000003
   123:                 LDR     PC, DAbt_Addr
0x00000010  E5845004  STR       R5,[R4,#0x0004]
   124:                 NOP                            /* Reserved Vector */
0x00000014  E59F201C  LDR       R2,[PC,#0x001C]
   125:                 LDR     PC, IRQ_Addr
0x00000018  E3A03000  MOV       R3,#0x00000000
   126:                 LDR     PC, FIQ_Addr
   127:
   128: Reset_Addr:     .word   Reset_Handler
   129: Undef_Addr:     .word   Undef_Handler
   130: SWI_Addr:       .word   SWI_Handler
   131: PAbt_Addr:      .word   PAbt_Handler
   132: DAbt_Addr:      .word   DAbt_Handler
   133:                 .word   0                      /* Reserved Address */
   134: IRQ_Addr:       .word   IRQ_Handler
   135: FIQ_Addr:       .word   FIQ_Handler
   136:
0x0000001C  E1020093  SWP       R0,R3,[R2]
0x00000020  E2822028  ADD       R2,R2,#0x00000028
0x00000024  E1021093  SWP       R1,R3,[R2]


What happened after that line is the code points to:

0xFFFFFFF3  FFFF      (???)     PC, Reset_Addr


Not good at all!

Anybody has a clue why I have this behavior. It looks like I did not configure my memory correctly, but I am not sure.

I tried the C:\Keil\ARM\GNU\Boards\Keil\MCB2100\Blinky. After the debugger is started, it points to:

    50: int main (void) {
    51:   unsigned int n;
    52:
0x00000310  E1A0C00D  MOV       R12,R13


After couple of lines, it goes to

   123:                 LDR     PC, DAbt_Addr
0x00000010  E59FF018  LDR       PC,[PC,#0x0018]

Not really good either.

Thanks in advance for your help

Parents
  • I changed the size in LinkerScript.ld for

      CODE (rx) : ORIGIN = 0x00000000, LENGTH = 0x00008000
      DATA (rw) : ORIGIN = 0x40000000, LENGTH = 0x00002000
    

    I also checked the Run to main() in the Options for Target/Debug

    I started the debugger again and instead to start from Vectors line it started into my main().

        69: {
    0x00000828  E1A0C00D  MOV       R12,R13
    0x0000082C  E92DD870  STMDB     R13!,{R4-R6,R11-R12,R14-PC}
    0x00000830  E24CB004  SUB       R11,R12,#0x00000004
        70:         u32 i = 0;
        71: //      u32 j = 0;
    

    But once the line STMDB is executed, it goes directly to:

       123:                 LDR     PC, DAbt_Addr
    0x00000010  E59FF018  LDR       PC,[PC,#0x0018]
    

    Any clue?

Reply
  • I changed the size in LinkerScript.ld for

      CODE (rx) : ORIGIN = 0x00000000, LENGTH = 0x00008000
      DATA (rw) : ORIGIN = 0x40000000, LENGTH = 0x00002000
    

    I also checked the Run to main() in the Options for Target/Debug

    I started the debugger again and instead to start from Vectors line it started into my main().

        69: {
    0x00000828  E1A0C00D  MOV       R12,R13
    0x0000082C  E92DD870  STMDB     R13!,{R4-R6,R11-R12,R14-PC}
    0x00000830  E24CB004  SUB       R11,R12,#0x00000004
        70:         u32 i = 0;
        71: //      u32 j = 0;
    

    But once the line STMDB is executed, it goes directly to:

       123:                 LDR     PC, DAbt_Addr
    0x00000010  E59FF018  LDR       PC,[PC,#0x0018]
    

    Any clue?

Children
  • Is the C runtime startup somehow failing to initialize R13 for use as the stack pointer?

  • GNU version

    At the beginning, R13 = 0x40003F70
    Once the abort occurs, R13 = 0x40003FFC

    Keil version

    At the beginning, R13 = 0x400004A8

    I am a new with this kind of stuff, but should the stack pointer initialize itself?

  • I wrote a little dummy program and had the same problem (R13 was set at 0x40003FFC:

    void test();
    
    int main()
    {
        int i = 0;
        int j = 1;
    
        i = i + 1;
        j = i;
    
        if (j == 1)
        {
            i = 1;
            test();
        }
    }
    
    void test()
    {
        int i = 1;
        if (i == 1)
        {
            i++;
        }
    }
    

  • When I said that I used the Keil compiler I was in error. I am using the Realview one.

  • "I am a new with this kind of stuff, but should the stack pointer initialize itself?"

    No, setting the initial SP usually occurs during post-reset initialization or in the C runtime startup code.

    Anyway, looking up your eval board, then looking the CPU used on the board (LPC2103), I see that it only has 8K of internal SRAM, yet your linker file has it set for 16K. That might be the problem.

  • "... your linker file has it set for 16K. That might be the problem."

    I see your subsequent .ld file edit, yet the R13 value at the abort suggests that 16K is still being used for some reason.

  • Any clue what it could write at that address? Even the basic program that I did (see other post) has the same behavior and there is nothing special in that code.

    How the Realview result is working and not the GNU one? Ok, they do not compile the same way, but still it is the same code.

  • "Any clue what it could write at that address?"

    I believe that the intent of the STMDB you mentioned above is to set up a stack frame, but it must be within existing memory, hence the data abort exception.

    "How the Realview result is working and not the GNU one?"

    You showed us above that the GNU version's R13 = 0x40003F70 is beyond the 8K SRAM space, whereas the other version's R13 = 0x400004A8 is within the valid address range. The GNU version must have the notion that the data space is bigger than it is and is initializing SP up too high.

  • Hi Dan,

    Guess what?

    I re-scan for the X times the Startup.s and I saw that:

        .equ    Top_Stack,      0x40004000
    

    I changed it for 0x40002000. No more "Data Abort" exception error!

    Now, I need to know why my interrupts are not working now. You have some knowledge about interrupt with GNU?

    By the way, thanks for all the help that you gave me.

  • "Now, I need to know why my interrupts are not working now."

    What kind of trouble are you having?

    "You have some knowledge about interrupt with GNU?"

    Enough to know that GCC provides special extension syntax for the interrupt function attribute.

    There should be interrupt examples in your directory tree somewhere.

    Also see:

    www.hitex.co.uk/.../index.html

  • Ok, here is the situation.

    I set an interrupt TIMER0 and I2C0.

    // Initialise VIC for I2C use
    VICIntSelect = 0x0;
    VICVectAddr0 = (u32) i2cISR;
    VICVectCntl0 = 0x20 | 9;// use it for I2C Interrupt
    VICIntEnable = 0x200;   // Enabling I2C Channel (9)
    
    // Initialise VIC for TIMER0 use
    VICIntSelect = 0x0;
    VICVectAddr1 = (u32)timerInt;
    VICVectCntl1 = 0x20 | 4;  // use it for Timer 0
    VICIntEnable = 0x10;      // Enable Timer0 Interrupt
    

    Of course, there is other code around that

    When I run the program, I never receive any I2C interrupt.

    I tried to take out the TIMER0 interrupt, and nothing happened on I2C.

    I tried to take out the I2C module and confirmed that the timer works.

    So, why the I2C module does not work? Are those definition are ok?

    void timerInt(void) __attribute__ ((interrupt));
    void i2cISR(void) __attribute__ ((interrupt));
    

    By the way, what is the difference between:

    void timerInt(void) __attribute__ ((interrupt));
    and
    void timerInt(void) __attribute__ ((interrupt("IRQ")));
    

    Regards

  • Looks like with:

    void timerInt(void) __attribute__ ((interrupt("IRQ")));
    void i2cISR(void) __attribute__ ((interrupt("IRQ")));
    

    it is working.

    But I still want to know what is the difference between the two syntax

  • "But I still want to know what is the difference between the two syntax"

    Isn't it that "IRQ" is implicit with ((interrupt)) compared to the explicit ((interrupt("IRQ"))) and that ((interrupt("???"))) supports others like FIQ?

  • I think you are right

    Thanks for all the tips!