|
Пишем код для отладки платы + азы, RM9200 |
|
|
|
Jan 18 2007, 03:12
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Цитата(Playnet @ Jan 17 2007, 23:59)  Какой смысл тестить рандом? Лучше всего посмотреть битовые маски в прогах типа memtest и подобных... Прямой: в противном случае вероятность обнаружения ошибок, связанных с целостностью сигналов, сильно снижается. Цитата(Playnet @ Jan 17 2007, 23:59)  Имеет смысл делать так -- заполняем всю память нулями, ждем секунду, читаем, снова ждем секунду, читаем.. так несколько раз. Потом заполняем единицами. И снова ждем-читаем. Для постоянных тестов медленно, но для разовых самое то. И что? Вы так даже закороток на шинах адреса и данных не найдете. Целью теста является не нахождение ошибок в памяти (хотя и это тоже), а проверка работоспособности интерфейса.
|
|
|
|
|
Jan 18 2007, 12:27
|
Участник

Группа: Участник
Сообщений: 71
Регистрация: 2-03-06
Из: Минск
Пользователь №: 14 879

|
Цитата(aaarrr @ Jan 18 2007, 02:12)  Цитата(Playnet @ Jan 17 2007, 23:59)  Какой смысл тестить рандом? Лучше всего посмотреть битовые маски в прогах типа memtest и подобных...
Прямой: в противном случае вероятность обнаружения ошибок, связанных с целостностью сигналов, сильно снижается. Цитата(Playnet @ Jan 17 2007, 23:59)  Имеет смысл делать так -- заполняем всю память нулями, ждем секунду, читаем, снова ждем секунду, читаем.. так несколько раз. Потом заполняем единицами. И снова ждем-читаем. Для постоянных тестов медленно, но для разовых самое то. И что? Вы так даже закороток на шинах адреса и данных не найдете. Целью теста является не нахождение ошибок в памяти (хотя и это тоже), а проверка работоспособности интерфейса. При тестировании памяти (нахождение всевозможных ошибок чтения, записи, влияния одних ячеек на других), а так же нахождение ошибок шины к памяти типа закоротко или разрыв, лучше всего использовать маршевые тесты, причем использовать для каждой из возможных ошибок свой тест.
|
|
|
|
|
Jan 18 2007, 13:01
|
Частый гость
 
Группа: Свой
Сообщений: 132
Регистрация: 10-05-06
Пользователь №: 16 930

|
Цитата(aaarrr @ Jan 18 2007, 03:12)  Цитата(Playnet @ Jan 17 2007, 23:59)  Какой смысл тестить рандом? Лучше всего посмотреть битовые маски в прогах типа memtest и подобных...
Прямой: в противном случае вероятность обнаружения ошибок, связанных с целостностью сигналов, сильно снижается. Это еще почему? Когда мы гоняем единицы, повреждение линий сразу будет заметно. Цитата Цитата(Playnet @ Jan 17 2007, 23:59)  Имеет смысл делать так -- заполняем всю память нулями, ждем секунду, читаем, снова ждем секунду, читаем.. так несколько раз. Потом заполняем единицами. И снова ждем-читаем. Для постоянных тестов медленно, но для разовых самое то.
И что? Вы так даже закороток на шинах адреса и данных не найдете. Если пропала единица, мы этого не заметим? Цитата Целью теста является не нахождение ошибок в памяти (хотя и это тоже), а проверка работоспособности интерфейса. Угу. Да, все нули или единицы может не так хороши для проверки. Тогда можно взять маски 01010101 (55) и 10101010 (АА) и гонять их. Тут видно будет все.
|
|
|
|
|
Jan 18 2007, 13:37
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Цитата(Playnet @ Jan 18 2007, 13:01)  Это еще почему? Когда мы гоняем единицы, повреждение линий сразу будет заметно. Вам термин Signal Integrity знаком? Цитата(Playnet @ Jan 18 2007, 13:01)  Если пропала единица, мы этого не заметим?  Так Вы ничего не заметите, даже если все линии адреса будут закорочены между собой (и с данными та же картина).
|
|
|
|
|
Jan 18 2007, 17:39
|

Профессионал
    
Группа: Свой
Сообщений: 1 202
Регистрация: 9-01-05
Из: Санкт-Петербург
Пользователь №: 1 861

|
Вот тут вымучил. Явно бажное. Но все мои извраты с платой отлавливает. Вроде. Кроме замыкания адресных линий - эт. сложно. Код unsigned int volatile *pSDRAM, *pSDRAM1, *pSDRAM2; unsigned int wCount; unsigned int wRead, wWrite, wError, j,jmax; unsigned char bACount, nc,nr,nb,i;
printf ("Main = %d Hz\n",AT91F_CKGR_GetMainClock(AT91C_BASE_CKGR, SLOWCLOCK)); printf ("CPU = %d Hz\n",AT91F_PMC_GetProcessorClock(AT91C_BASE_PMC, AT91C_BASE_CKGR, SLOWCLOCK));
printf ("\nSmart :) memory test (only 32 bit)\n");
#define test_packet_size (8*1024)
nc = 8 + (AT91C_BASE_SDRC->SDRC_CR & 0x03); // columns nr = 11 + ((AT91C_BASE_SDRC->SDRC_CR >> 2) & 0x03); // rows nb = 1 + ((AT91C_BASE_SDRC->SDRC_CR >> 4) & 0x01); // bancs bACount = nc + nr + nb;
if (AT91C_BASE_SDRC->SDRC_MR & AT91C_SDRC_DBW_16_BITS) { printf ("Detected %d Mb of 16 bit SDRAM (not supported)\n", 1 << (bACount - 19)); // 16 bit while (1) {} } else printf ("Detected %d Mb of 32 bit SDRAM\n", 1 << (bACount - 18)); // 32 bit
//**********ADRESS LINES TEST printf("\nAdres lines test...\n"); for (i = nc; i < bACount; i++) { if ( (1 << i) > test_packet_size) jmax = test_packet_size; else jmax = (1 << i); wError=0; srand (1); pSDRAM1 = (unsigned int *) BASE_EBI_CS1_ADDRESS; pSDRAM2 = (unsigned int *) BASE_EBI_CS1_ADDRESS + (1 << i); for (j = 0; j < jmax; j++) { *pSDRAM1 = rand(); pSDRAM1++; *pSDRAM2 = rand(); pSDRAM2++; } pSDRAM1 = (unsigned int *) BASE_EBI_CS1_ADDRESS; pSDRAM2 = (unsigned int *) BASE_EBI_CS1_ADDRESS + (1 << i); for (j = 0; j < jmax; j++) { if (*pSDRAM1 == *pSDRAM2) { wError++; } pSDRAM1++; pSDRAM2++; } if (i < nr + nc) printf ("A%d ",i-nc); else printf ("BA%d ",i-nc-nr); if (wError == 0) printf ("ok\n"); else printf ("unconnected\n"); }
//***********DATA LINE TEST***** //***********SHORT************** printf("\nData line shorts test...\n"); for (i = 0; i <= 31; i++) { wError = 0; wWrite = ~(1 << i); pSDRAM = (unsigned int *) BASE_EBI_CS1_ADDRESS; for (j = 0; j < test_packet_size; j++) { *pSDRAM = wWrite; pSDRAM++; } pSDRAM = (unsigned int *) BASE_EBI_CS1_ADDRESS; for (j = 0; j < test_packet_size; j++) { wRead = *pSDRAM; pSDRAM++; wError |= wWrite ^ wRead; } printf("D%d ",i); if (wError == 0) printf ("Ok\n"); else { printf("shorts with "); for (j = 0; j <= 31; j++) if (wError & (1 << j)) printf ("%d ",j); printf("\n"); } } //***********UNCONECT*********** printf("\nData line uncon test...\n");
wError = 0; pSDRAM = (unsigned int *) BASE_EBI_CS1_ADDRESS; for (j = 0; j < test_packet_size; j++) { *pSDRAM = 0; pSDRAM++; } pSDRAM = (unsigned int *) BASE_EBI_CS1_ADDRESS; for (j = 0; j < test_packet_size; j++) { wRead = *pSDRAM; pSDRAM++; wError |= wRead; } for (i = 0; i <= 31; i++) { printf("D%d ",i); if (wError & (1 << i)) printf("unconect\n"); else printf ("Ok\n"); }
//***********RAND TEST******** printf("\nRandom test...\n"); while (1) { printf("\n-T WR- 0x00000000\n"); srand(1); printf("First rand = 0x%8X\nStart filling\n",rand()); pSDRAM = (unsigned int *) BASE_EBI_CS1_ADDRESS; for ( wCount = 0;wCount < (1 << (bACount -2)); wCount ++) { wWrite = rand (); *pSDRAM = wWrite; pSDRAM++; } wError = 0; srand(1); printf("First rand = 0x%8X\nStart testing\n",rand()); pSDRAM = (unsigned int *) BASE_EBI_CS1_ADDRESS; for ( wCount = 0;wCount < (1 << (bACount -2)); wCount ++) { wRead = *pSDRAM; wWrite = rand(); if (wRead != wWrite ) { printf ("[0x%08X] = 0x%08X ( 0x%08X,0x%08X)\n",wCount,wRead^wWrite,wRead,wWrite ); wError++; } pSDRAM++; } printf("Done. %d errors.\n",wError); } Накосячил. Исправил.
--------------------
Если сверху смотреть, то сбоку кажется, что снизу ничего не видно.
|
|
|
|
|
Jan 20 2007, 21:35
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Цитата(Dron_Gus @ Jan 20 2007, 16:48)  Носом не ткнете? А то мне что-то не найти... Вот цитата из мануала: Код 4.18.2 Pseudo-random binary sequence generator It is often necessary to generate (pseudo-) random numbers and the most efficient algorithms are based on shift generators with exclusive-OR feedback rather like a cyclic redundancy check generator. Unfortunately the sequence of a 32 bit generator needs more than one feedback tap to be maximal length (i.e. 2^32-1 cycles before repetition), so this example uses a 33 bit register with taps at bits 33 and 20. The basic algorithm is newbit:=bit 33 eor bit 20, shift left the 33 bit number and put in newbit at the bottom; this operation is performed for all the newbits needed (i.e. 32 bits). The entire operation can be done in 5 S cycles: ; Enter with seed in Ra (32 bits), Rb (1 bit in Rb lsb), uses Rc. ; TST Rb,Rb,LSR#1; Top bit into carry MOVS Rc,Ra,RRX; 33 bit rotate right ADC Rb,Rb,Rb; carry into lsb of Rb EOR Rc,Rc,Ra,LSL#12; (involved!) EOR Ra,Rc,Rc,LSR#20; (similarly involved!) ; new seed in Ra, Rb as before И пример использования C + Asm: Код extern randtest(u_int *start_addr, u_int word_count, u_int *seed);
void ramtest(u_int address, u_int word_count) { static u_int addr; static u_int seed[0x02] = {0xdeadbeef, 0xcafedeca}; u_int pass = 0x00, fcount = 0x00;
addr = address; while(0x01) { printf("%d:%d Testing RAM...", pass, fcount); if(randtest(&addr, word_count, seed) == 0x00) { pass++; printf ("Passed.\n\r"); } else { fcount++; printf("Failed at 0x%08x, Exp: 0x%08x; Rcv: 0x%08x\n\r", addr, seed[0x00], *(volatile u_int *)addr); addr = address; } } } + Код EXPORT randtest
AREA code0, CODE, READONLY
randtest stmfd sp!, {r4-r6, lr} ldmia r2, {r4, r5} ldr r6, [r0] mov r7, r1 0 tst r5, r5, lsr #0x01 ; to bit into carry movs r12, r4, rrx ; 33-bit rotate right adc r5, r5, r5 ; carry into LSB of a2 eor r12, r12, r4, lsl #0x0c; (involved!) eor r4, r12, r12, lsr #0x14; (similarly involved!)
str r4, [r6], #0x04 subs r7, r7, #0x01 bne %B0
ldmia r2, {r4, r5} ldr r6, [r0] 1 tst r5, r5, lsr #0x01 ; to bit into carry movs r12, r4, rrx ; 33-bit rotate right adc r5, r5, r5 ; carry into LSB of a2 eor r12, r12, r4, lsl #0x0c; (involved!) eor r4, r12, r12, lsr #0x14; (similarly involved!)
ldr r12, [r6], #0x04 cmp r12, r4 bne %F2 subs r1, r1, #0x01 bne %B1 stmia r2, {r4, r5} mov r0, #0x00 ldmfd sp!, {r4-r6, pc} 2 sub r6, r6, #0x04 str r6, [r0] stmia r2, {r4, r5} mov r0, #0x01 ldmfd sp!, {r4-r6, pc}
END Только нужно учитывать, что диагностика в этом тесте может не сработать: ошибка будет зафиксирована в любом случае, но при повторном чтении *(volatile u_int *)addr может вернуть правильный результат.
|
|
|
|
|
Jan 24 2007, 00:42
|
Местный
  
Группа: Свой
Сообщений: 262
Регистрация: 18-02-05
Из: SPb
Пользователь №: 2 743

|
Извините за тупость, но Цитата на плате Rainbow v1.1, как мне кажется, это сделано правильно или я ошибаюсь? Просто тоже начал тестировать память, пробовал описанные здесь методики, но... либо все-таки что-то не правильно на плате, либо я неправильно инициализирую СДРАМ... вот инициализация, которую я подправил из 9200ЕК Цитата void AT91F_InitSDRAM() { int i; volatile int *pSDRAM = (int *)BASE_EBI_CS1_ADDRESS;
//* Configure PIOC as peripheral (D16/D31) AT91F_SDRC_CfgPIO(); //* Setup MEMC to support CS1=SDRAM AT91C_BASE_EBI->EBI_CSA |= AT91C_EBI_CS1A; AT91C_BASE_EBI->EBI_CFGR = (AT91C_EBI_DBPUC & 0x00) | (AT91C_EBI_EBSEN & 0x00);
//* Init SDRAM
//* 1. A minimum pause of 200us is provided to precede any signal toggle /* AT91C_BASE_SDRC->SDRC_CR = AT91C_SDRC_NC_9 | AT91C_SDRC_NR_12 | AT91C_SDRC_NB_4_BANKS | AT91C_SDRC_CAS_2 | 0x100 | 0x4000 | 0x8000 | 0x880000 | 0x21000000; */ AT91C_BASE_SDRC->SDRC_CR = AT91C_SDRC_NC_11 | AT91C_SDRC_NR_13 | AT91C_SDRC_NB_4_BANKS | AT91C_SDRC_CAS_2 | 0x100 | 0x4000 | 0x8000 | 0x880000 | 0x21000000;
//* 2. A Precharge All command is issued to the SDRAM AT91C_BASE_SDRC->SDRC_MR = AT91C_SDRC_MODE_PRCGALL_CMD; *pSDRAM = 0;
//* 3. Eight Auto-refresh are provided AT91C_BASE_SDRC->SDRC_MR = AT91C_SDRC_MODE_RFSH_CMD; for(i=0;i<8;i++) *pSDRAM = 0;
//* 4. A mode register cycle is issued to program the SDRAM parameters AT91C_BASE_SDRC->SDRC_MR = AT91C_SDRC_MODE_LMR_CMD; *(pSDRAM+0x80) = 0;
//* 5. Write refresh rate into SDRAMC refresh timer COUNT register AT91C_BASE_SDRC->SDRC_TR = (AT91C_SDRC_COUNT & 0x2E0); *pSDRAM = 0;
//* 6. A Normal Mode Command is provided, 3 clocks after tMRD is set AT91C_BASE_SDRC->SDRC_MR = AT91C_SDRC_MODE_NORMAL_CMD; *pSDRAM = 0; } У меня запаяно две озухи k4s641632h, по 128 мегабит каждая, Цитата // ***********RAND TEST******** printf("\n\rRandom test...\n\r"); // while (1) // { printf("\n\r-T WR- 0x00000000\n\r"); srand(1); printf("First rand = 0x%8X\n\rStart filling\n\r",rand()); pSDRAM = (unsigned int *) BASE_EBI_CS1_ADDRESS; // for ( wCount = 0;wCount < (1 << (batemp -2)); wCount ++) for ( wCount = 0;wCount < 0x80000; wCount ++) { wWrite = rand (); *pSDRAM = wWrite; pSDRAM++; } wError = 0; srand(1); printf("First rand = 0x%8X\n\rStart testing\n\r",rand()); pSDRAM = (unsigned int *) BASE_EBI_CS1_ADDRESS; // for ( wCount = 0;wCount < (1 << (batemp -2)); wCount ++) for ( wCount = 0;wCount < 0x80000; wCount ++) { wRead = *pSDRAM; wWrite = rand(); if (wRead != wWrite ) { if (wCount> 0xfffff) printf ("\n\r sting: %d \n\r", wCount); printf ("[0x%08X] = 0x%08X ( 0x%08X,0x%08X)\n\r",wCount,wRead^wWrite,wRead,wWrite ); wError++; } pSDRAM++; } printf("Done. %d errors.\n\r",wError); // } } если в этом куске wCount ставить больше, чем 0х7ffff, тоначинает запись идти на первые адреса, т.е. то, что должно быть записано в адрес 0х80000, читается в 0х0, естественно, это есть ошибка. Подскажите, что неправильно, инициализация, или все-таки надо на плате что-то переделывать и если переделывать, то что?
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|