[U-Boot-Users] get_ram_size() returns wrong value

Hiya folks,
Somehow I've missed this before, but just today noticed that u-boot is reporting DRAM: 64 MB (BTW, machine is running with 128MB)
So, again, I had peaked inside the u-boot, and after doing some printf statements, I can get it to detect 128MB but I cant seem to get to the root of the problem. This is orginal code with my printf.
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- for (cnt = 1; cnt < maxsize / sizeof (long); cnt <<= 1) { printf("*addr(%x)\n",*(addr=base + 0x1000000)); addr = base + cnt; /* pointer arith! */ val = *addr; *addr = save[--i]; if (val != ~cnt) { size = cnt * sizeof (long); /* Restore the original data before leaving the function. */ for (cnt <<= 1; cnt < maxsize / sizeof (long); cnt <<= 1) { addr = base + cnt; *addr = save[--i]; } return (size); } } =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
I can see what the code does. It tries to write ~cnt value (first backingup) then read it in to see if it had written it successfully.
But problem lies at (base + 0x1000000). If u-boot detects val != ~cnt, then it will finish the loop right there and return size 64MB. If it succeeds, returns 128MB (which is what I have).
So, natually, I wanted to see what exactly does it change it to, and when, hence the printf. But guess WHAT? It reads back perfectly correct and return 128MB.
Do you guys think its timing issue ? Having printf natually adds delay factor to the code. Could this be HW problem ? (I can just throw it back to the HW people to get it fixed if so :) )
If I get desperate, I might just leave the dummy printf or hardcode the size, but for now, I wouldnt mind diving at it.

In message 9b7ca65705040603187af7aa9c@mail.gmail.com you wrote:
Somehow I've missed this before, but just today noticed that u-boot is reporting DRAM: 64 MB (BTW, machine is running with 128MB)
...
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- for (cnt = 1; cnt < maxsize / sizeof (long); cnt <<= 1) { printf("*addr(%x)\n",*(addr=base + 0x1000000));
How is maxsize defined in your configuration?
How is your memory controller configured (address masks) ?
Best regards,
Wolfgang Denk

On Apr 6, 2005 7:42 PM, Wolfgang Denk wd@denx.de wrote:
Thanks for the hint. You are right I left out configuring memory controller. Okay, now I've configured it, but it's still playing up on me.
How is maxsize defined in your configuration?
maxsize is configured as, #define CFG_MAX_RAM_SIZE 0x08000000 /* 0 .. 128 MB of (S)DRAM */
How is your memory controller configured (address masks) ?
#define CFG_BANK0_START 0x00000000 #define CFG_BANK0_END (CFG_MAX_RAM_SIZE/2 - 1) #define CFG_BANK0_ENABLE 1 #define CFG_BANK1_START (CFG_MAX_RAM_SIZE/2) #define CFG_BANK1_END (CFG_MAX_RAM_SIZE - 1) #define CFG_BANK1_ENABLE 1
Rest is all disabled.
It gets to DRAM: 128MB, but soon after that, it wants to access 0x7FDEEB0, where there's no data. Looks like its configuration issue. Guess I should look into it.
BTW, is it right by simply halving the MAX value ? I sort of guessed this part. Looked at schemetics and they used 2 chip selects. So, I figured halving it. Is it cool ?

In message 9b7ca65705040605525c3317b5@mail.gmail.com you wrote:
How is maxsize defined in your configuration?
maxsize is configured as, #define CFG_MAX_RAM_SIZE 0x08000000 /* 0 .. 128 MB of (S)DRAM */
Try doubling it ;-)
How is your memory controller configured (address masks) ?
#define CFG_BANK0_START 0x00000000 #define CFG_BANK0_END (CFG_MAX_RAM_SIZE/2 - 1) #define CFG_BANK0_ENABLE 1 #define CFG_BANK1_START (CFG_MAX_RAM_SIZE/2) #define CFG_BANK1_END (CFG_MAX_RAM_SIZE - 1) #define CFG_BANK1_ENABLE 1
Umm.. this seems bogus to me. If the actual size is != MAX_RAM_SIZE thenyou will have a hole in your mapping; this is not what you want to do. See the README how to handle such a situation.
BTW, is it right by simply halving the MAX value ? I sort of guessed
No, this is ... bogus.
this part. Looked at schemetics and they used 2 chip selects. So, I figured halving it. Is it cool ?
Definitely not.
Best regards,
Wolfgang Denk

On Apr 6, 2005 10:20 PM, Wolfgang Denk wd@denx.de wrote:
Umm.. this seems bogus to me. If the actual size is != MAX_RAM_SIZE thenyou will have a hole in your mapping; this is not what you want to do. See the README how to handle such a situation.
Okay this sounds rather dumb, but I cant seem to find it anywhere in READMEs. Any hint ?
It looks like values that are defined by CFG_BANKx_START are used way before initdram is called. And initdram only configures the end address using the size it got back from get_ram_size. My question is, looking at board/a3000/a3000.c, is it correct to configure ending address of bank0 only ?

In message 9b7ca6570504062133713b09d2@mail.gmail.com you wrote:
On Apr 6, 2005 10:20 PM, Wolfgang Denk wd@denx.de wrote:
Umm.. this seems bogus to me. If the actual size is != MAX_RAM_SIZE thenyou will have a hole in your mapping; this is not what you want to do. See the README how to handle such a situation.
Okay this sounds rather dumb, but I cant seem to find it anywhere in READMEs. Any hint ?
Read here:
[System Initialization:] ... Next, all (potentially) available memory banks are mapped using a preliminary mapping. For example, we put them on 512 MB boundaries ...
Best regards,
Wolfgang Denk

Daniel Ann wrote:
Hiya folks,
Somehow I've missed this before, but just today noticed that u-boot is reporting DRAM: 64 MB (BTW, machine is running with 128MB)
So, again, I had peaked inside the u-boot, and after doing some printf statements, I can get it to detect 128MB but I cant seem to get to the root of the problem. This is orginal code with my printf.
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- for (cnt = 1; cnt < maxsize / sizeof (long); cnt <<= 1) { printf("*addr(%x)\n",*(addr=base + 0x1000000)); addr = base + cnt; /* pointer arith! */ val = *addr; *addr = save[--i]; if (val != ~cnt) { size = cnt * sizeof (long); /* Restore the original data before leaving the function. */ for (cnt <<= 1; cnt < maxsize / sizeof (long); cnt <<= 1) { addr = base + cnt; *addr = save[--i]; } return (size); } } =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
I can see what the code does. It tries to write ~cnt value (first backingup) then read it in to see if it had written it successfully.
But problem lies at (base + 0x1000000). If u-boot detects val != ~cnt, then it will finish the loop right there and return size 64MB. If it succeeds, returns 128MB (which is what I have).
So, natually, I wanted to see what exactly does it change it to, and when, hence the printf. But guess WHAT? It reads back perfectly correct and return 128MB.
Do you guys think its timing issue ? Having printf natually adds delay factor to the code. Could this be HW problem ? (I can just throw it back to the HW people to get it fixed if so :) )
If I get desperate, I might just leave the dummy printf or hardcode the size, but for now, I wouldnt mind diving at it.
Its a memory problem. Ultimately yes, it is a timing problem. The question is where... * Is it your SDRAM initialization? * Is it a hardware/layout problem? * Are the address line lengths close to the same length? * Are the data line lengths close to the same length? * Is it a termination resistor problem (missing/wrong value)? * Is it the SDRAM itself?
Note that, with your printf(), you are repeatedly reading the memory at your boundary case address as well as changing the timing. You are also doing a side-effect assignment to "addr" which gets discarded on the next line.
For identifying and debugging memory problems, those are bad practices. Quite often a memory failure will show up on the first read, but be fine after that (which is apparently what you are seeing). By doing multiple reads, you are throwing away any information you would have otherwise gleaned from the print statement (which may not be much, but hey, don't throw it away, it's all you have!).
My suggestion:
for (cnt = 1; cnt < maxsize / sizeof (long); cnt <<= 1) { addr = base + cnt; /* pointer arith! */ val = *addr; *addr = save[--i]; if (val != ~cnt) { printf("*addr %08X => %04X != %04X\n",addr,val,~cnt); size = cnt * sizeof (long); /* Restore the original data before leaving the function. */ for (cnt <<= 1; cnt < maxsize / sizeof (long); cnt <<= 1) { addr = base + cnt; *addr = save[--i]; } return (size); } }
gvb

On Apr 6, 2005 9:27 PM, Jerry Van Baren <gerald.vanbaren@smiths-
Its a memory problem. Ultimately yes, it is a timing problem. The question is where...
- Is it your SDRAM initialization?
Yeah looks alot like it. Previously I left bank 1 disabled. See below, #define CFG_BANK1_ENABLE 0
I believe SDRAM is on 64bit mode, and schematics shows two chip selects. I've sort of wrote about this prior to this email.
- Is it a hardware/layout problem?
- Are the address line lengths close to the same length?
- Are the data line lengths close to the same length?
- Is it a termination resistor problem (missing/wrong value)?
- Is it the SDRAM itself?
Bit hard to confirm at this stage. I guess I have to do everything I can on the software side first. Hardware people are little reluctant about looking up on these things.. :P
Note that, with your printf(), you are repeatedly reading the memory at your boundary case address as well as changing the timing. You are also doing a side-effect assignment to "addr" which gets discarded on the next line. For identifying and debugging memory problems, those are bad practices.
Thanks. I knew I was doing wrong :) Just didnt know what and why. Didnt think my printf was a magic one :)
My suggestion:
for (cnt = 1; cnt < maxsize / sizeof (long); cnt <<= 1) { addr = base + cnt; /* pointer arith! */ val = *addr; *addr = save[--i]; if (val != ~cnt) {
printf("*addr %08X => %04X != %04X\n",addr,val,~cnt); size = cnt * sizeof (long); /* Restore the original data before leaving the function. */ for (cnt <<= 1; cnt < maxsize / sizeof (long); cnt <<= 1) { addr = base + cnt; *addr = save[--i]; } return (size); } }
Thanks for your input. As for now, since the mistake came from misconfiguration, I'm going to dig up on that first.
participants (3)
-
Daniel Ann
-
Jerry Van Baren
-
Wolfgang Denk