Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
20 years ago

running sw in SDRAM

Hello,

I want to use SDRAM for a small set of functions, toghether with big chunks of data. The rest of the software runs from SRAM.

I verfied the correct working of the SDRAM, the instruction bus is connected to SDRAM.

I tried with a small function placed in SDRAM, but the system restarts when I call the function. The test function contained just a printf to see it is called.

Then I tried with a function that just increments a global variable, nothing happens, the variable is not incremeted. When I place that same function in SRAM, the value gets incremented everytime I call the function.

Is there something I miss here for running sw in SDRAM??

Thanks,

Stefaan.

9 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I use SDRAM for most of my projects and have never had a problem. Looks like normal memory.

    A few things to check: Maybe you have a screw-up with the stack or something.

    * Compile a program to run only from SDRAM. If that works then you might have screw-up pointers.

    * How have you compiled the code? Most of time the functions are not relocatable. Have you compiled the code for that specific location in SDRAM or just copied it there?

    *Where are the local variables stored?

    *When the function returns where does it return to?

    VictorS
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    originally posted by victors@Jan 3 2006, 01:57 PM

    i use sdram for most of my projects and have never had a problem. looks like normal memory.

    a few things to check: maybe you have a screw-up with the stack or something.

    * compile a program to run only from sdram. if that works then you might have screw-up pointers.

    --- Quote End ---

    I tried also a small program running only from SDRAM, no luck.

    <div class='quotetop'>QUOTE </div>

    --- Quote Start ---

    * How have you compiled the code? Most of time the functions are not relocatable. Have you compiled the code for that specific location in SDRAM or just copied it there?[/b]

    --- Quote End ---

    I added a section in the linkerscript and then used the __attribute((.section(".sdram"))) on the function. I verified in on object dump, and it seems to be ok.

    <div class='quotetop'>QUOTE </div>

    --- Quote Start ---

    *Where are the local variables stored?[/b]

    --- Quote End ---

    in SRAM, only one global integer to test.

    <div class='quotetop'>QUOTE </div>

    --- Quote Start ---

    *When the function returns where does it return to?[/b]

    --- Quote End ---

    I hope to the place where it was called from.

    Here&#39;s the small test function :

    volatile int ga = 0;
    void TestSDRam() __attribute__ ((section (".sdram")));
    void TestSDRam()
    {
        __asm__("NOP");
        __asm__("NOP");
        __asm__("NOP");
        __asm__("NOP");
        ga++;
    }

    This function gets compiled to :

    Disassembly of section .sdram:
    01000000 <_Z9TestSDRamv>:
     1000000:    0001883a  nop
     1000004:    0001883a  nop
     1000008:    0001883a  nop
     100000c:    0001883a  nop
     1000010:    00c00534  movhi    r3,20
     1000014:    18c6d404  addi    r3,r3,6992
     1000018:    18800037  ldwio    r2,0(r3)
     100001c:    10800044  addi    r2,r2,1
     1000020:    18800035  stwio    r2,0(r3)
     1000024:    f800283a  ret

    This function is called from somewhere else in the sw, and I print out the memory contents before the call, so I can verify the code is still there :

    void foo()
    {
      volatile int* a = (int*) na_SDRAM;
              
      for (int k = 0; k < 40; k++)
      {
          printf("%08x : %08x \r", a, *a);
          a++; 
      }
      TestSDRam();
      printf("ga : %d\r", ga);
    }

    The result :

    01000000 : 0001883a
    01000004 : 0001883a
    01000008 : 0001883a
    0100000c : 0001883a
    01000010 : 00c00534
    01000014 : 18c6d404
    01000018 : 18800037
    0100001c : 10800044
    01000020 : 18800035
    01000024 : f800283a
    01000028 : 32463032
    0100002c : 31303343
    01000030 : 32423030
    01000034 : 31303443
    01000038 : 34303030
    0100003c : 46464245
    01000040 : 41374544
    01000044 : 31333033
    01000048 : 36423030
    0100004c : 33530a0d
    01000050 : 30303531
    01000054 : 30343030
    01000058 : 34303033
    0100005c : 46374646
    01000060 : 35314645
    01000064 : 30343130
    01000068 : 35314644
    0100006c : 30303030
    01000070 : 35314544
    01000074 : 30384630
    01000078 : 35363844
    0100007c : 33530a0d
    01000080 : 30303531  
    ** START BOOTLOADER **

    The processor starts again at its reset address.

    Yesterday, I tried the same, and the processor didn&#39;t restart, the only change was that I didn&#39;t use the -G0 compiler option to get rid of the global pointer. Still the integer &#39;ga&#39; was nopt modified.

    With the use of the global pointer, I have this disassembled code :

    01000000 <_Z9TestSDRamv>:
     1000000:    0001883a  nop
     1000004:    0001883a  nop
     1000008:    0001883a  nop
     100000c:    0001883a  nop
     1000010:    d0a00337  ldwio    r2,-32756(gp)
     1000014:    10800044  addi    r2,r2,1
     1000018:    d0a00335  stwio    r2,-32756(gp)
     100001c:    f800283a  ret

    The only difference here seems to be the use of register r3. I can not understand why this changes the effect on calling the function.

    Stefaan
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Does it still crash if you take the ga++ out, i.e. only NOPs?

    I had a &#39;thing&#39; about 2 years ago. NIOS1 design. All went well by checking memory with GERMS. BUT as soon as I ran code from it the software crashed. First of all the PCB was crappy. Had to design the entire thing on double sided PCB which caused my tracks to be too long (budget constraint :-( Then I tried to lower the CPU speed but the same thing occured. Hmmm. Eventually I tracked it down. No matter what the speed was the problem originated from the rise times. It seemed that when I had repeated hits on the datalines the data would get corrupted. I could fix the errors by soldering 1pF caps between data and ground but eventually decided to redo the boards using multilayered PCBs- problem solved.

    It looks like the code should run. It does not jump (relocation error possibility) and when it hits RET the stack should have the right return address.

    Options:

    1) Check with an empty function, e.g. 1 NOP and RET. This should work, surely!

    2) Lower the clock speed

    3) I don&#39;t know what track lengths you have, going to the SDRAM, but try to increase the delay from the PLL (You are using a PLL ?)

    4) Write some SRAM code to hammer the SDRAM with a pseudo random stream of data and verify it back. Don&#39;t use the same value. The more chaotic the better. If there are errors then the interface doesn&#39;t work.

    VMS
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Being able of writing-then-reading a bunch of bytes from the SDRAM is not the final probe that timing is OK. Between one access and the next (as pointer handling code should be executed) there could be a "too long" time that could mask the timing problems, as the use of a data cache would also do.

    Create a new project targeted to run in your SDRAM. Compile and try to run. If you have an invalid timing issue it will show-up here, the JTAG debug module and the instruction cache put much more stress on the SDRAM avalon slave interface than your code.

    Try with several delay values (compensation) in your SDRAM clock PLL.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    ....or use the memtest example software template, running out of SRAM or onchip memory, to really slam the SDRAM. It will even make use of a DMA (which is latency aware), if you have one in your system.

    Cheers,

    - slacker
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Indeed, indeed, The PLL tuning.

    The delay was on -4ns.

    In a small test project, it turned out that -3ns untill +1ns works for both instruction fetching and data access.

    Mean time I found the document sdram controller (http://www.altera.com/literature/hb/nios2/n2cpu_nii51005.pdf) and used the calculations to estimate the timing, it turns that the shift should be -2ns average.

    I decided to use -1.5ns, and the SDRAM works fine also in the real project.

    Thanks for the hint.

    Stefaan