Strange results on memtest...

Gianluca gianlucarenzi at eptar.com
Mon May 14 14:11:30 CEST 2007


Hello list,
I know this is not the right place to ask such stuff, but I need a little help to
understand better what is going on inside u-boot on s3c2440 architecture.

I got a s3c2442 eval board from Meritech with 64MiB SDRAM, 128MiB NAND (all in one SoC).

I got strange behaviour on running mtest from u-boot running, or running a custom memory tester
and running the same linux kernel from u-boot or from the custom made bootloader.

here is the scenario:
I am used to boot from a custom bootloader that configures the UPLL/MPLL of s3c2442 running
at 300Mhz (CPU), 100Mhz (SDRAM), 50Mhz (Peripherals) (1_2_4 clock ratio)
A simple memory tester I wrote:

#define MB(a)           ( a * 1024 * 1024L )
#define SDRAM_MEMSIZE   MB(63)
#define TEST_MEMSIZE    (SDRAM_MEMSIZE)
#define _RAM_STARTADDRESS 0x30000000

#define WriteMemory(a,b)        ( *( volatile unsigned int * )(a) = b )
#define ReadMemory(a)           ( *( volatile unsigned int * )(a) )

void main(void)
{
        MMU_EnableICache();
        InitS3C2442(); /* Initialize SDRAM Controller, Serial Port, UPLL/MPLL @300Mhz,100Mhz,50Mhz and other stuff... */ 
        uart_print("Starting MEMTEST...\n");
        if ( my_mem_test( _RAM_STARTADDRESS, TEST_MEMSIZE/4) == 0 ) {
                uart_print(" write/read System RAM passed\r\n\n");
        }
        else
        {
                uart_print(" write/read System RAM Failed!!!!\r\n\n");
        }

        while( 1 ) ;;
}

int my_mem_test( unsigned int addr, unsigned int n_words)
{
        int Index;
        int errors;
        int k;
        unsigned int Mem32Value, val;

        errors = 0;
        {
                int errflag;

                uart_print("Inverse address...(W)\r\n");
                errflag = 0;
                for ( Index = 0; Index < n_words; Index++ )
                {
                        val = ~(addr+4*Index);
                        WriteMemory(addr+4*Index, val);
                }
                uart_print("\r\nInverse address (R)\r");
                for ( Index = 0; Index < n_words; Index++ )
                {
                        val = ~(addr+4*Index);
                        Mem32Value = ReadMemory(addr+4*Index);
                        if ( Mem32Value != val )
                        {
                                uart_print("0x%08X - 0x%08X - %d\n", addr+4*Index, Mem32Value, val);
                                errors++;
                                errflag = 1;
                                break;
                        }
                }
                if (errflag)
                        uart_print("Inverse address FAILED\r\n");
                else
                        uart_print("Inverse address SUCCESS\r\n");

                uart_print("Fixed pattern...(W)\r\n");
                errflag = 0;
                for ( Index = 0; Index < n_words; Index++ )
                {
                        val = 0xDEADBEEF;
                        WriteMemory(addr+4*Index, val);
                }
                uart_print("\r\nFixed pattern (R)\r");
                for ( Index = 0; Index < n_words; Index++ )
                {
                        val = 0xDEADBEEF;
                        Mem32Value = ReadMemory(addr+4*Index);
                        if ( Mem32Value != val )
                        {
                                uart_print("0x%08X - 0x%08X - %d\n", addr+4*Index, Mem32Value, val);
                                errors++;
                                errflag = 1;
                                break;
                        }
                }
                if (errflag)
                        uart_print("Fixed pattern FAILED\r\n");
                else
                        uart_print("Fixed pattern SUCCESS\r\n");

                print("Walk ones\r");
                errflag = 0;
                for (k = 0; k < 32 && !errflag; k++)
                {
                        for ( Index = 0; Index < n_words; Index++ )
                        {
                                val = 1 << k;
                                WriteMemory(addr+4*Index, val);
                        }
                        for ( Index = 0; Index < n_words; Index++ )
                        {
                                val = 1 << k;
                                Mem32Value = ReadMemory(addr+4*Index);
                                if ( Mem32Value != val )
                                {
                                        uart_print("0x%08X - 0x%08X - %d\n", addr+4*Index, Mem32Value, val);
                                        errors++;
                                        errflag = 1;
                                        break;
                                }
                        }
                }
                if (errflag)
                        uart_print("Walk ones FAILED\r\n");
                else
                        uart_print("Walk ones SUCCESS\r\n");

                uart_print("Walk zeroes\r");
                errflag = 0;
                for (k = 0; k < 32 && !errflag; k++)
                {
                        for ( Index = 0; Index < n_words; Index++ )
                        {
                                val = ~(1 << k);
                                WriteMemory(addr+4*Index, val);
                        }
                        for ( Index = 0; Index < n_words; Index++ )
                        {
                                val = ~(1 << k);
                                Mem32Value = ReadMemory(addr+4*Index);
                                if ( Mem32Value != val )
                                {
                                        uart_print("0x%08X - 0x%08X - %d\n", addr+4*Index, Mem32Value, val);
                                        errors++;
                                        errflag = 1;
                                        break;
                                }
                        }
                }
                if (errflag)
                        uart_print("Walk zeroes FAILED\r\n");
                else
                        uart_print("Walk zeroes SUCCESS\r\n");
        
                uart_print("Increment\r");
                errflag = 0;
                for (k = 0; k < 1024 && !errflag; k++)
                {
                        for ( Index = 0; Index < n_words; Index++ )
                        {
                                val = k+1;
                                WriteMemory(addr+4*Index, val);
                        }
                        for ( Index = 0; Index < n_words; Index++ )
                        {
                                val = k+1;
                                Mem32Value = ReadMemory(addr+4*Index);
                                if ( Mem32Value != val )
                                {
                                        uart_print("0x%08X - 0x%08X - %d\n", addr+4*Index, Mem32Value, val);
                                        errors++;
                                        errflag = 1;
                                        break;
                                }
                        }
                }
                if (errflag)
                        uart_print("Increment FAILED\r\n");
                else
                        uart_print("Increment SUCCESS\r\n");
        }

        return errors;
}

It gives me an error at inverse_address test reading at 0x30000000.
If I load linux kernel with that configuration of UPLL/MPLL stuff, usually it hangs with a kernel oops,
with a corrupted page request while reaching the end of the physical memory available. (SDRAM Failed?)

So I changed the bootloader to u-boot configured as smdk2440_config.
Then I try to run mtest from command line interface. Here is the log:

U-Boot 1.2.0-gabca9018-dirty-moko8 (May 14 2007 - 13:12:21)

DRAM:  64 MB
Flash:  1 MB
NAND:  128 MiB
*** Warning - bad CRC or NAND, using default environment

USB:   S3C2410 USB Deviced
mtdparts variable not set, see 'help mtdparts'
mtdparts variable not set, see 'help mtdparts'
mtdparts variable not set, see 'help mtdparts'
mtdparts variable not set, see 'help mtdparts'
mtdparts variable not set, see 'help mtdparts'
In:    serial
Out:   serial
Err:   serial
Hit any key to stop autoboot:  0
SMDK2440 # s3c2410 speed get
FCLK = 399 MHz, HCLK = 133 MHz, PCLK = 66 MHz
SMDK2440 # mtest
Pattern 00000000  Writing...  Reading...
Mem error @ 0x33D5CB34: found 00000001, expected 00F572CD
Mem error @ 0x33D5CB38: found 00F572CD, expected 00F572CE
Pattern FFFFFFFF  Writing...

Then it resets itself and reboot.

But if I jump directly to linux without checking the SDRAM chips,
with the UPLL/MPLL configured from u-boot at 400Mhz,133Mhz,66Mhz the kernel no-more hangs,
and everything is working as expected, and it runs for ages without any hassle.

What the hell is happening? Why uboot's mtest gives me that errors and the kernel runs good,
and _WHY_ running at 300Mhz it gives me error at 0x30000000 and linux kernel hangs??

Can I slow down the speed of s3c2440 from 400Mhz to 300Mhz and see if this behaviour happens again,
from inside uboot itself? How? I just tried: "s3c2410 speed set 266" but it hangs...

Awaiting your reply,
Best regards,
-- 
Gianluca Renzi


More information about the openmoko-uboot mailing list