Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Пишем код для отладки платы + азы
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Отладочные платы
Ken@t
Вот сидел, читал форумы - at91, електроникс, йаха, телесиськи... . все спрашивают "а КАК".
Отвечаем (иар подразумеваю, для других компилеров товарищи добавят описание)
1. Ставим процессор +обвязку+питание и по Жтагу заливаем минимальный код для проверки работоспособности ...
2. Ставим СДРАМ и минимальным кодом проверем работоспособность памяти.
Код
unsigned int volatile *pSDRAM;
  unsigned int  wCount;
  unsigned int  wRead,
                wWrite;
  
  printf ("CPU %d MHz\n",GetCPUFrequencyMhz() );
  printf ("PCK %d MHz\n",GetPCKFrequencyMhz() );

  while (1){
    printf("-T WR- 0x00000000\n");
   pSDRAM = (unsigned int *) BASE_EBI_CS1_ADDRESS;
   for ( wCount = 0,wWrite=0x0;wCount < 0x800000;wCount ++  ){
     *pSDRAM = wWrite;
     wRead = *pSDRAM;
     if (wWrite != wRead )
       printf ("[0x%08X] = 0x%08X ( 0x%08X,0x%08X)\n",wCount,wRead^wWrite,wRead,wWrite );
     pSDRAM++;
   }
}

Здесь c помощью простого осцилографа можно определить - залипания и не пропай по линиям, конечно же, ставим сначала одну микросхему, потом другую, что бы проще отлаживать было.

далее отладили ... теперь очень хочется залить что-нибудь в SDRAM и выполнить оттуда. НО
1. Контроллер SDRAM не инициализирован
2. Частоты ПЛЛ не выставлены.
Вот здесь на помощь нам приходит инструмент Жлинка , а именно его mac файл

привожу его
Код
//---- Инициализация PLLA = 200 MHz , PLLB = 48 MHz , PCK = 100MHz
init_PLL()
{
__var     tmp,
        var;

__message("Init Clock");
__writeMemory32(0x0000FF01,0xFFFFFC20,"Memory"); // PMC_MOR: MOSCEN = 1, enable main clock
while( (( var =__readMemory32(0xFFFFFC24,"Memory")) & (0x1 << 16))  == 0 ) { };  // wait time out

// AT91C_BASE_CKGR->CKGR_PLLAR = PLLAR_Register;
__writeMemory32(0x2030BF04,0xFFFFFC28,"Memory");
tmp = 0;
while( !(( var=__readMemory32(0xFFFFFC68,"Memory")) & ( 0x1 <<  1)) && (tmp++ < 100) ) {};

var = __readMemory32(0xFFFFFC28,"Memory");
__message "PLLAR=",var;

//AT91C_BASE_CKGR->CKGR_PLLBR = PLLBR_Register;
  __writeMemory32(0x10533F0E,0xFFFFFC2C,"Memory");
  tmp = 0;
  while( !((var = __readMemory32(0xFFFFFC68,"Memory")) & ( 0x1 <<  2)) && (tmp++ < 100) ) {};


  __writeMemory32( 0x1 ,0xFFFFFC30,"Memory");

  tmp = 0;
  while( !((var = __readMemory32(0xFFFFFC68,"Memory")) & (0x1 << 3)) && (tmp++ < 100) ) {};


//  AT91C_BASE_PMC->PMC_MCKR = MCKR_Register;
  __writeMemory32(0x00000102,0xFFFFFC30,"Memory");

  tmp = 0;
  while( !((var = __readMemory32(0xFFFFFC68,"Memory")) & (0x1 << 3)) && (tmp++ < 100) ) {};


}

//----------- Инициализация SDRAM 2х8х16 (2х MT48LC8M16A2-75)
init_SDRAM ()
{
__var i;
__message("Init SDRAM");

  __writeMemory32(0xFFFF0000,0xFFFFF800 +0x0070,"Memory");
  __writeMemory32(0x0,0xFFFFF800 +0x0074,"Memory");
  __writeMemory32(0xFFFF0000,0xFFFFF804,"Memory");      
  i = __readMemory32(0xFFFFFF60,"Memory");
  __writeMemory32(i|(0x1 << 1),0xFFFFFF60,"Memory");
  __writeMemory32( 0x0 ,0xFFFFFF64,"Memory");


__writeMemory32( 0x2A99C255,0xFFFFFF98,"Memory");

__writeMemory32(0x02,0xFFFFFF90,"Memory");
__writeMemory32(0x0,0x20000000,"Memory");
__writeMemory32(0x04,0xFFFFFF90,"Memory");

for(i=0;i<8;i++)
  __writeMemory32(0x0,0x20000000,"Memory");
__writeMemory32(0x3,0xFFFFFF90,"Memory");
__writeMemory32(0x0,0x20000000,"Memory");

__writeMemory32(0x610,0xFFFFFF94,"Memory");
__writeMemory32(0x00,0x20000000,"Memory");
__writeMemory32(0x0,0xFFFFFF90,"Memory");
__writeMemory32(0x0,0x20000000,"Memory");
}


execUserPreload()
{

init_PLL();
__writeMemory32(0xAAAAAAAA,0x00000000,"Memory");
  if(__readMemory32(0x00000000,"Memory") != 0xAAAAAAAA)
  {
    __writeMemory32(0x01,0xFFFFFF00,"Memory");    // MC_RCR: toggle remap bit
  }
init_SDRAM ();
  __message("Target init macro complete");
}


теперь можите компилить код с загрузкой в сдрам и выполнять его отуда.
Замечу , что с адреса 0х0 распологается SRAM и в стартап коде надо перенести в область 0х0 - 0х38
вектора прерывания.
пример стартапа at91_cstartup.s79
Код
        MODULE    ?RESET
;        COMMON    INTVEC:CODE:NOROOT(2); Я убрал, линкер подразумевает эту секцию с 0 , но её мы будем копировать в SRAM
            RSEG    ICODE:CODE:NOROOT(2)
                PUBLIC  __program_start
        EXTERN    ?cstartup
;        EXTERN    undef_handler, swi_handler, prefetch_handler
;        EXTERN    data_handler, irq_handler, fiq_handler
        CODE32; Always ARM mode after reset    
ADRSTART:
        org    0x00+ADRSTART
__program_start
        ldr    pc,=?cstartup; Absolute jump
        org    0x04+ADRSTART
undef_handler:
        ldr    pc,=undef_handler
        org    0x08+ADRSTART
swi_handler:
        ldr    pc,=swi_handler
        org    0x0c+ADRSTART
prefetch_handler:
        ldr    pc,=prefetch_handler
        org    0x10+ADRSTART
data_handler:
        ldr    pc,=data_handler
        org    0x18+ADRSTART
    ldr pc, [pc,#-0xF20]  ; IRQ : read the AIC
        org    0x1c+ADRSTART
fiq_handler:
        ldr    pc,=fiq_handler

; Constant table entries (for ldr pc) will be placed at 0x20
        org    0x20+ADRSTART
        LTORG
;        ENDMOD    __program_start
                ENDMOD


;---------------------------------------------------------------
; ?CSTARTUP
;---------------------------------------------------------------
        MODULE    ?CSTARTUP

        RSEG    IRQ_STACK:DATA(2)
        RSEG    SVC_STACK:DATA:NOROOT(2)
        RSEG    CSTACK:DATA(2)
        RSEG    ICODE:CODE:NOROOT(2)
        PUBLIC    ?cstartup
        EXTERN    ?main

; Execution starts here.
; After a reset, the mode is ARM, Supervisor, interrupts disabled.


        CODE32
?cstartup

; Add initialization nedded before setup of stackpointers here


; Initialize the stack pointers.
; The pattern below can be used for any of the exception stacks:
; FIQ, IRQ, SVC, ABT, UND, SYS.
; The USR mode uses the same stack as SYS.
; The stack segments must be defined in the linker command file,
; and be declared above.
                mrs     r0,cpsr                        ; Original PSR value
                bic     r0,r0,#MODE_BITS                  ; Clear the mode bits

.... дальше как было


понятно , что в lowlevelinit пишите перемещение области памяти 0х2000000 - 0х20000038 на 0 адрес
или прямо в стартапном коде перемещение делаете.
хотя можно и использовать TTB для ремпаирования, но это вы дальше будете делать...
Ruslan1
Спасибо! Интересно почитать. Ты рассказал как раз о том, что я уже прошел только что. Процарапался. smile.gif

Если бы еще кто привел пример программы, которую возможно загрузить из скажем DataFlash. Ну там, валидный стартап, например.
Что-то я затормозился с этим. sad.gif
Ken@t
О , добрался до Москвы. здесь холодно и не уютно... Решил побаловать губителей АРМов... Загрузчиком во флэш стартапного кода.
И так прикладываю два проекта IAR fLoader записывает бинарный образ во флэш. применён механизм линковки бинарного файла ( см закладку Extra Options в линкере)
и сам проект первичного загрузчика , который инициализирует sdram, pll пытается считать из флэша заголовок образа, если заголовок правильный , то загружает, иначе активно моргает светодиодом.
вторичный лодырь
Сначала компилите fBoot , смотрите JTAG как идёт процесс. Затем собираете релиз. Бинарник релиза в дальнейшем будет записан во флэш.

В fBoot файл at91_cstartup.s79
FlashInfo DC32 ((1056 << 17) | ( 13 << 13 ) | 6) ;
1056 - размер страницы флэша
13 - 2^13 = 8096 количество страниц в флэше
6 - 6 * 512 = 3072 байт грузится в RAM, что немного больше самого кода 2696 байт
это придётся ручками для ленивых прописать или макросами в автомате. Кстати в fLoader нужно указать размерчик ручками или создать именованный сегмент в xcl.

а так в планах ... BSP CE50 ...
LeonY
Если мы пишим программы, так же как и сообщения, то фиг оно заработает :-) Ребята - имейте совесть, это же читать невозможно.
Ruslan1
Цитата(Ken@t @ Sep 13 2006, 20:04) *
О , добрался до Москвы. здесь холодно и не уютно... Решил побаловать губителей АРМов... Загрузчиком во флэш стартапного кода.


О!
Я как раз вчера вернулся к этому вопросу. Сегодня таки хочу добить. Или допинать. smile.gif
Спасибочки! smile.gif

Кстати, что-то на фоне юкоса не хотят встроенные сервисы работать как нужно (наверное проблема в прерываниях, не успел еще разобраться). Да и не понравилась еррата про снятие CS, если не успею данные подсунуть. Хотя как это ПДП может не успеть- отдельный вопрос, это очень тормозную память наверное нужно (Меня интересует доступ не только для загрузки, но и потом тоже).



Цитата(LeonY @ Sep 13 2006, 21:52) *
Если мы пишим программы, так же как и сообщения, то фиг оно заработает :-) Ребята - имейте совесть, это же читать невозможно.

Опечатки возможны у всех.
Вот можно ли подкорректировать название темы, я не уверен. Понятно, что Администрация все может. smile.gif
Ruslan1
Цитата(Ken@t @ Sep 13 2006, 20:04) *
О , добрался до Москвы. здесь холодно и не уютно... Решил побаловать губителей АРМов...

сам проект первичного загрузчика , который инициализирует sdram, pll пытается считать из флэша заголовок образа, если заголовок правильный , то загружает, иначе активно моргает светодиодом.


Вот нашел недоработку в загрузчике, связанную с ограничениями ПДП. В связи с тем, что контроллеру ПДП нельзя указывать длину пакетов более 65535 байт, при более длинных прошивках нужно грузить частями. Вот измененный кусочек :


[/code]
{
unsigned int tmpLoadAddr = hOSImage.LoadAddr;
unsigned int tmpLoadBytes = hOSImage.LoadBytes;
unsigned int tmpFlashAdr = 0x4020; //Это мой адрес начала расположения прошивки в DataFlash
do {
if (tmpLoadBytes > 0xffff){
AT91F_DataFlashArrayRead(&DataFlash,tmpFlashAdr,(unsigned char *)tmpLoadAddr, 0xffff );
tmpFlashAdr = tmpFlashAdr + 0xffff;
tmpLoadAddr = tmpLoadAddr + 0xffff;
tmpLoadBytes = tmpLoadBytes - 0xffff;
}
else{
AT91F_DataFlashArrayRead(&DataFlash,tmpFlashAdr,(unsigned char *)tmpLoadAddr, tmpLoadBytes );
tmpLoadBytes = 0;
}
AT91F_DataFlashWaitReady(DataFlash.pDataFlashDesc,AT91C_DATAFLASH_TIMEOUT);
}while (tmpLoadBytes != 0);
}
[code]

Как понимаете, вылазит только в случае загрузки длинных программ. Актуально для таких как я, которые грузят напрямую код, а не вторичный загрузчик. Вот сегодня подключил пару bmp-шек к микроГуе и сразу ощутил эту границу smile.gif
Playnet
Цитата(Ken@t @ Aug 22 2006, 17:58) *
printf ("CPU %d MHz\n",GetCPUFrequencyMhz() );
printf ("PCK %d MHz\n",GetPCKFrequencyMhz() );

У меня ругается, что не знает таких функций...
AlexMad
Цитата
Вот сидел, читал форумы - at91, електроникс, йаха, телесиськи... . все спрашивают "а КАК".
Отвечаем (иар подразумеваю, для других компилеров товарищи добавят описание)
1. Ставим процессор +обвязку+питание и по Жтагу заливаем минимальный код для проверки работоспособности ...
2. Ставим СДРАМ и минимальным кодом проверем работоспособность памяти.

....

Здесь c помощью простого осцилографа можно определить - залипания и не пропай по линиям, конечно же, ставим сначала одну микросхему, потом другую, что бы проще отлаживать было.


Вот сидел, ждал, когда же кто нибудь вопросы задаст... видать, кроме меня все разобрались sad.gif
А теперь мне приперло разбираться с АРМами, потому, наверно, в ближайшее время буду сыпать дурные вопросы.
По этому коду ситуация такая - заливается, "работает", залипаний на ногах нет, но и соответствия нет тоже.

Цитата
wRead = *pSDRAM;
if (wWrite != wRead )
printf ("[0x%08X] = 0x%08X ( 0x%08X,0x%08X)\n",wCount,wRead^wWrite,wRead,wWrite );


Вопрос чисто дурацкий, где копать, житагом смотрю переменную wRead, она всегда равна нулю, хотя я пробовал туда писать различные значения, константы, пробовал инкрементировать... Вобщем, непонятно, на этой стадии должно ли это работать, или без инициализации ПЛЛ и СДРАМ и не надо туда смотреть?

И еще вопрос
Цитата
и сам проект первичного загрузчика , который инициализирует sdram, pll пытается считать из флэша заголовок образа, если заголовок правильный , то загружает, иначе активно моргает светодиодом.
вторичный лодырь
Сначала компилите fBoot , смотрите JTAG как идёт процесс. Затем собираете релиз. Бинарник релиза в дальнейшем будет записан во флэш.

Я так понимаю, что в дебагере этот код тоже должен работать. У меня же он с ошибкой вылетает
Цитата
do {
AT91F_DataFlashGetStatus(pDataFlashDesc);
timeout--;
// dummy waiting time
for(i=0;i<10;i++);
} while( ((pDataFlashDesc->DataFlash_state & 0x80) != 0x80) && (timeout>0) );

pDataFlashDesc->DataFlash_state у меня равно 0x27, при чем осциллографом я не вижу НИКАКОЙ активности на выводах SPI.

Ну, на сегодня пока дурацких вопросов хватит smile.gif, буду пока сам копаться, потом еще вопросов наберу.
Dron_Gus
Цитата
Вопрос чисто дурацкий, где копать, житагом смотрю переменную wRead, она всегда равна нулю, хотя я пробовал туда писать различные значения, константы, пробовал инкрементировать... Вобщем, непонятно, на этой стадии должно ли это работать, или без инициализации ПЛЛ и СДРАМ и не надо туда смотреть?

Как минимум СДРАМ надо проинициализировать. Смотрите файл init.c, например из проекта fBoot. Только настройки памяти поменяйте под себя. И кварца, если у Вас другие.
AlexMad
Цитата(Ken@t @ Sep 13 2006, 17:04) *
Сначала компилите fBoot , смотрите JTAG как идёт процесс. Затем собираете релиз. Бинарник релиза в дальнейшем будет записан во флэш.


Кем и как он будет записан во флеш? его надо залить самому или это сделает fLoader ?
AlexMad
И ещё дурацкий вопрос: как, имея МТ-линк залить в камень код релиза? при дебаге из ИАРа все понятно. Чего делать, когда есть откомпиленный код?
В конфигурациях релизов дебагер, понятно ругается, что не знает как дебажить, если нет отладочной информации, но меня интересует, хотябы, как в камень должен попасть готовый код?
Dron_Gus
Предлагаю пообщаться на предмет проверки памяти. smile.gif
Как я уже где-то писал, код, предложенный Ken@t при некотором стечении обстоятельств не реагирует на сбои. Во всяком случае у меня при нескольких непропаях на шине данных.
Собственно интересует почему и как быть. smile.gif Возможно ли такое при включенном кэше? Как я понимаю кэш - это "фича" ядра и читать про него надо в описании ядра?
aaarrr
Цитата(Dron_Gus @ Jan 16 2007, 20:55) *
Возможно ли такое при включенном кэше?

Для теста памяти кэш нужно выключить, иначе можно в результате получить тест кэша smile.gif
Исходя из личного опыта могу сказать, что самая надежная проверка - заполнение всей памяти псевдослучайной последовательностью с последующей проверкой. Тест нужно крутить несколько суток, и желательно в жестких условиях - только тогда можно говорить о достаточно надежной работе памяти.
Dron_Gus
Почитал описание ядра - все кэши отключены после сброса. Наверное я что-то еще не учел.
Про полное заполнение - тоже об этом подумал. По идее и на кэш тогда наплевать, т.к. ему все равно придется "сбрасываться" в память. Осталось найти генератор псевдослучайной последовательности.
Dron_Gus
Да. И зачем что-то изобретать. smile.gif rand() + srand()
Dron_Gus
Эм... А rand() дает ту же последовательность, если его заново инициализировать (srand) тем же числом?
makc
Цитата(Dron_Gus @ Jan 16 2007, 22:19) *
Эм... А rand() дает ту же последовательность, если его заново инициализировать (srand) тем же числом?


Конечно ту же. Он же псевдослучайный.
aaarrr
Цитата(Dron_Gus @ Jan 16 2007, 22:19) *
Эм... А rand() дает ту же последовательность, если его заново инициализировать (srand) тем же числом?

Да, но rand лучше не использовать - медленно. В TRM на ARM7TDMI есть пример генератора псевдослучайной последовательности с использованием barrel shifter'а.
Playnet
Какой смысл тестить рандом? Лучше всего посмотреть битовые маски в прогах типа memtest и подобных... И потом, если есть ошибки из-за косячного рефреша, записал-прочитал будет нормально.
Имеет смысл делать так -- заполняем всю память нулями, ждем секунду, читаем, снова ждем секунду, читаем.. так несколько раз. Потом заполняем единицами. И снова ждем-читаем.
Для постоянных тестов медленно, но для разовых самое то.
aaarrr
Цитата(Playnet @ Jan 17 2007, 23:59) *
Какой смысл тестить рандом? Лучше всего посмотреть битовые маски в прогах типа memtest и подобных...

Прямой: в противном случае вероятность обнаружения ошибок, связанных с целостностью сигналов, сильно снижается.

Цитата(Playnet @ Jan 17 2007, 23:59) *
Имеет смысл делать так -- заполняем всю память нулями, ждем секунду, читаем, снова ждем секунду, читаем.. так несколько раз. Потом заполняем единицами. И снова ждем-читаем.
Для постоянных тестов медленно, но для разовых самое то.

И что? Вы так даже закороток на шинах адреса и данных не найдете.

Целью теста является не нахождение ошибок в памяти (хотя и это тоже), а проверка работоспособности интерфейса.
Newegor
Цитата(aaarrr @ Jan 18 2007, 02:12) *
Цитата(Playnet @ Jan 17 2007, 23:59) *

Какой смысл тестить рандом? Лучше всего посмотреть битовые маски в прогах типа memtest и подобных...

Прямой: в противном случае вероятность обнаружения ошибок, связанных с целостностью сигналов, сильно снижается.

Цитата(Playnet @ Jan 17 2007, 23:59) *
Имеет смысл делать так -- заполняем всю память нулями, ждем секунду, читаем, снова ждем секунду, читаем.. так несколько раз. Потом заполняем единицами. И снова ждем-читаем.
Для постоянных тестов медленно, но для разовых самое то.

И что? Вы так даже закороток на шинах адреса и данных не найдете.

Целью теста является не нахождение ошибок в памяти (хотя и это тоже), а проверка работоспособности интерфейса.


При тестировании памяти (нахождение всевозможных ошибок чтения, записи, влияния одних ячеек на других), а так же нахождение ошибок шины к памяти типа закоротко или разрыв, лучше всего использовать маршевые тесты, причем использовать для каждой из возможных ошибок свой тест.
Playnet
Цитата(aaarrr @ Jan 18 2007, 03:12) *
Цитата(Playnet @ Jan 17 2007, 23:59) *

Какой смысл тестить рандом? Лучше всего посмотреть битовые маски в прогах типа memtest и подобных...

Прямой: в противном случае вероятность обнаружения ошибок, связанных с целостностью сигналов, сильно снижается.

Это еще почему? Когда мы гоняем единицы, повреждение линий сразу будет заметно.

Цитата
Цитата(Playnet @ Jan 17 2007, 23:59) *

Имеет смысл делать так -- заполняем всю память нулями, ждем секунду, читаем, снова ждем секунду, читаем.. так несколько раз. Потом заполняем единицами. И снова ждем-читаем.
Для постоянных тестов медленно, но для разовых самое то.

И что? Вы так даже закороток на шинах адреса и данных не найдете.

Если пропала единица, мы этого не заметим? ohmy.gif

Цитата
Целью теста является не нахождение ошибок в памяти (хотя и это тоже), а проверка работоспособности интерфейса.

Угу.

Да, все нули или единицы может не так хороши для проверки. Тогда можно взять маски 01010101 (55) и 10101010 (АА) и гонять их. Тут видно будет все.
aaarrr
Цитата(Playnet @ Jan 18 2007, 13:01) *
Это еще почему? Когда мы гоняем единицы, повреждение линий сразу будет заметно.

Вам термин Signal Integrity знаком?

Цитата(Playnet @ Jan 18 2007, 13:01) *
Если пропала единица, мы этого не заметим? ohmy.gif

Так Вы ничего не заметите, даже если все линии адреса будут закорочены между собой (и с данными та же картина).
Dron_Gus
Вот тут вымучил. Явно бажное. Но все мои извраты с платой отлавливает. Вроде. Кроме замыкания адресных линий - эт. сложно. smile.gif



Код
  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);
  }


Накосячил. Исправил. smile.gif
Dron_Gus
Цитата(aaarrr @ Jan 16 2007, 22:28) *
В TRM на ARM7TDMI есть пример генератора псевдослучайной последовательности с использованием barrel shifter'а.


Носом не ткнете? А то мне что-то не найти...
aaarrr
Цитата(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 может вернуть правильный результат.
AlexMad
Извините за тупость, но
Цитата

на плате 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, естественно, это есть ошибка.
Подскажите, что неправильно, инициализация, или все-таки надо на плате что-то переделывать и если переделывать, то что?
Dron_Gus
А вы перекинули А12 и А14? У Вас же память с 13 битами адресации столбцов. Соответственно, реально доступна только половина, если Вы еще не перепаивали.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.