UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Visitor vbmazter
Visitor
7,643 Views
Registered: ‎04-18-2012

DDR3 memory access goes wrong: axi_v6_ddrx broken?

Hi,

 

I'm experiencing very strange behavior on Microblaze when accessing heap memory, which looks like the V6 memory controller is doing the wrong thing. It occasionally writes to the wrong place, when the program is located in DDR memory (heap+stack+text+data). Simple pointer operations on heap go wrong, overwriting the stack finally (in my case; if the code is different then the unwanted write could happen to any address). Note that the heap is definitely *not* meeting the stack, as you will see in a while.

 

My memory map is:

 

.heap           0xc0003208  0x848f8c0
                0xc0003208                . = ALIGN (0x8)
                0xc0003208                _heap = .
                0xc0003208                _heap_start = .
                0xc8492ac8                . = (. + _HEAP_SIZE)
 *fill*         0xc0003208  0x848f8c0 00
 *fill*         0xc8492ac8        0x0 00
 *fill*         0xc8492ac8        0x0 00
 *fill*         0xc8492ac8        0x0 00
                0xc8492ac8                _heap_end = .

.stack          0xc8492ac8      0x400
                0xc8492ac8                _stack_end = .
                0xc8492ec8                . = (. + _STACK_SIZE)
 *fill*         0xc8492ac8      0x400 00
 *fill*         0xc8492ec8        0x0 00
 *fill*         0xc8492ec8        0x0 00
 *fill*         0xc8492ec8        0x0 00
                0xc8492ec8                . = ALIGN (0x8)
                0xc8492ec8                _stack = .
                0xc8492ec8                __stack = _stack
                0xc8492ec8                _end = .

I.e. the heap is ca. 132MB large. I am allocating 10 MB using malloc, and then filling it with a test pattern. During that, at a certain point the data is written to the wrong place in RAM - into the stack, instead of into the heap!

 

I used the memory test application to provoke the error:

 

/*
 * Copyright (c) 2009 Xilinx, Inc.  All rights reserved.
 *
 * Xilinx, Inc.
 * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
 * COURTESY TO YOU.  BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
 * ONE POSSIBLE   IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
 * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
 * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
 * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION
 * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
 * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
 * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
 * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#include <stdio.h>
#include "xparameters.h"
#include "xil_types.h"
#include "xstatus.h"
#include "xil_testmem.h"

#include "platform.h"
#include "memory_config.h"

void putnum(unsigned int num);
void print(char *ptr);

void test_memory_range(struct memory_range_s *range) {
    XStatus status;

    /* This application uses print statements instead of xil_printf/printf
     * to reduce the text size.
     *
     * The default linker script generated for this application does not have
     * heap memory allocated. This implies that this program cannot use any
     * routines that allocate memory on heap (printf is one such function).
     * If you'd like to add such functions, then please generate a linker script
     * that does allocate sufficient heap memory.
     */

    print("Testing memory region: "); print(range->name);  print("\n\r");
    print("    Memory Controller: "); print(range->ip);  print("\n\r");
    print("         Base Address: 0x"); putnum(range->base); print("\n\r");
    print("                 Size: 0x"); putnum(range->size); print (" bytes \n\r");

    // heap alloc addr test
#define MYMEMSIZE (10*1024*1024) /* 10 MB */
    Xuint32*myheap = (Xuint32*)malloc(MYMEMSIZE*sizeof(char));
    print("heap addr="); putnum((int)myheap); print("\r\n");
    unsigned int k=0;
    unsigned int MBs = 0;
    for (k=0; k<MYMEMSIZE/4; k++) {
        myheap[k] = (Xuint32)(k);
        if ((k%250000) == 0) { // each MB
            putnum(MBs); print(" MByte written.\r\n");
            MBs++;
        }
    }
    print("my area was written\r\n");

    status = Xil_TestMem32((u32*)range->base, 1024000, 0xAAAA5555, XIL_TESTMEM_ALLMEMTESTS);
    print("          32-bit test: "); print(status == XST_SUCCESS? "PASSED!":"FAILED!"); print("\n\r");

    status = Xil_TestMem16((u16*)range->base, 2048000, 0xAA55, XIL_TESTMEM_ALLMEMTESTS);
    print("          16-bit test: "); print(status == XST_SUCCESS? "PASSED!":"FAILED!"); print("\n\r");

    status = Xil_TestMem8((u8*)range->base, 4096000, 0xA5, XIL_TESTMEM_ALLMEMTESTS);
    print("           8-bit test: "); print(status == XST_SUCCESS? "PASSED!":"FAILED!"); print("\n\r");

}

int main()
{
    int i;

    init_platform();

    print("--Starting Memory Test Application--\n\r");
    print("addr of stack around "); putnum((int)&i); print("\r\n");
    print("NOTE: This application runs with D-Cache disabled.");
    print("As a result, cacheline requests will not be generated\n\r");

    for (i = 0; i < n_memory_ranges; i++) {
        test_memory_range(&memory_ranges[i]);
    }

    print("--Memory Test Application Complete--\n\r");

    cleanup_platform();

    return 0;
}

Try to run this with everything located in RAM and you will get output like this:

 

--Starting Memory Test Application--
addr of stack around c8492e9c
NOTE: This application runs with D-Cache disabled.As a result, cacheline requests will not be generated
Testing memory region: DDR3_SDRAM
    Memory Controller: axi_v6_ddrx
         Base Address: 0xc0003208
                 Size: 0x10000000 bytes
heap addr=c0003210
00000000 MByte written.
00000001 MByte written.
00000002 MByte written.
00091f8a MByte written.
00091f8b MByte written.
00091f8c MByte written.
00091f8d MByte written.
00091f8e MByte written.
00091f8f MByte written.
00091f90 MByte written.
00091f91 MByte written.
my area was written
          32-bit test: PASSED!
          16-bit test: PASSED!
           8-bit test: PASSED!
--Memory Test Application Complete--

 

The value "00091f8a" which shows up unexpectedly in "MBs" is actually the value of the current "k" stack variable, i.e. the test pattern which should have been written to heap, was written to the stack, although the pointer was correct! All this can be seen more clearly in the attached screenshot, showing the exact moment in the debugger, where I added some code to catch this problem.

 

I just don't understand what's going on here. Is it maybe, that the frequency for my DDR3 memory is too high? Used the BSB wizard, Microblaze is running at 100MHz and the clock wizard is showing 400MHz for clk_mem - the DIMM is a PC3-8500.

Otherwise there might be a bug when the whole application is located to DDR memory.

 

Regards,

martin

 

EDK 13.4.

counter-error.png
0 Kudos
8 Replies
Visitor vbmazter
Visitor
7,634 Views
Registered: ‎04-18-2012

Re: DDR3 memory access goes wrong: axi_v6_ddrx broken?

Meanwhile I tried the following things, without substantial success:

  • ran memory test included in ML605 CF card: all test passed; DIMM seems fine.
  • tried various cache on/off configurations: same effects
  • xilkernel instead of standalone: same effects
  • rebuilding the system with 50MHz instead of 100MHz: seems stable for allocation sizes of up to 32MB. 64 already fails

Summary: problem is still there.

0 Kudos
Visitor vbmazter
Visitor
7,630 Views
Registered: ‎04-18-2012

Re: DDR3 memory access goes wrong: axi_v6_ddrx broken?

Further findings: it is deterministic! Happens always at the very same address: 0xC4005E64 in my case (DDR starts at 0xC0000000 and the address range I'm trying to write at 0xC000A058). That means it happens after 64MB every time.

 

The registers of the Microblaze are calculating the correct addresses, so it is not a software issue. I suppose now, that is really the memory controller is to blame. I'm going to try to debug that thing later... Any suggestions which sigals would be interesting

0 Kudos
Visitor vbmazter
Visitor
7,624 Views
Registered: ‎04-18-2012

Re: DDR3 memory access goes wrong: axi_v6_ddrx broken?

Found out something interesting, maybe this is the solution: It seems that the memory controller is configured for 64M...just changing the dropdown value in the address table in EDK to 512M or something does not help...obviously. The MIG log is showing, that it was configured for MT41J64M16XX-15E, i.e. a 64MB DIMM (although I selected ML605 in the BSB). Also the synthesis report shows trimming of the lines 31 downto 26 for the address signals to the controller, which also indicates a 64M address range.

 

So it looks like, that the axi_v6_ddrx, as it was added from the BSB, is fixed to that 64M DDR memory, and that all addresses after 64M are wrapping back into the beginning of the RAM - where my text segment is located. If this is true, then EDK should warn the user that the memory controller must be reconfigured, when the address range size is changed. Otherwise this always leads to an inconsistent system with a hidden memory time bomb.

 

I'm trying to work with MIG now to get a controller configuration for 512M...let's see whether that helps.

0 Kudos
Visitor brabin
Visitor
7,576 Views
Registered: ‎05-25-2012

Re: DDR3 memory access goes wrong: axi_v6_ddrx broken?

Have you had any success in getting the full 512M working?

0 Kudos
Visitor vbmazter
Visitor
7,567 Views
Registered: ‎04-18-2012

Re: DDR3 memory access goes wrong: axi_v6_ddrx broken?

Sorry, I didn't do it eventually. Specifically for ML605 there is a presentation available (XPT047: http%3a//www.xilinx.com/support/documentation/boards_and_kits/xtp047.pdf), which goes step by step through MIG setup. Maybe you try to follow that. I didn't have the time. Best, martin
0 Kudos
Visitor brabin
Visitor
7,554 Views
Registered: ‎05-25-2012

Re: DDR3 memory access goes wrong: axi_v6_ddrx broken?

Yes, I've gone through that document a whole bunch of times already.  My design works fine with 64M, but not with anything greater.

0 Kudos
Explorer
Explorer
7,467 Views
Registered: ‎05-30-2008

Re: DDR3 memory access goes wrong: axi_v6_ddrx broken?

Xilinx, any word on why BSB is doing this?

Thanks,

Josh

0 Kudos
Visitor tcornall
Visitor
7,305 Views
Registered: ‎09-29-2011

Re: DDR3 memory access goes wrong: axi_v6_ddrx broken?

Hey, I just noticed that something silly is happening when I create a Microblaze using the ML605 BSB too. That board is supposed to have 512M SDRAM on it, but it only puts 64M into the Microblaze!

Any comments from Xilinx on this one?

0 Kudos