Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Какую максимальную частоту можно считать с портов контроллера?
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Страницы: 1, 2
Rst7
QUOTE
Это должно быть так!?


Уберите вот эти __no_operation, которые отмечены комментарием "пол периода". Там только это
CODE
if (!(v & PCLK_MASK))    v = *port;

должно остаться. Сей код будет занимать по времени или 1 или три такта, в зависимости от попадания на фронт сигнала. И будет держать фазу (и, как следствие, компенсировать разбег частот) в общем зачете.

QUOTE
Как он может мне помочь?


Это некое подобие SPI. Почитайте usermanual на процессор, там же все написано.
Prinz
Цитата(Rst7 @ Apr 21 2011, 17:53) *
Уберите вот эти __no_operation, которые отмечены комментарием "пол периода". Там только это
Код
if (!(v & PCLK_MASK))    v = *port;

должно остаться. Сей код будет занимать по времени или 1 или три такта, в зависимости от попадания на фронт сигнала. И будет держать фазу (и, как следствие, компенсировать разбег частот) в общем зачете.
Это некое подобие SPI. Почитайте usermanual на процессор, там же все написано.



Убрал всё лишнее, только почему-то колличество считанных пикселей всегда нестабильное. Оно вроде как кружиться у нужного числа, так сказть маткматического ожидания, с какой-то дисперсией.
Что нет так?

Я это понял, что подобие SPI.
The I2S bus specification defines a 3-wire serial bus
Тут вроде как написано, что это трёх проводная последовательная шмна. Как она должна мне помочь? Просветите пожалуйста.
Rst7
QUOTE
Что нет так?


Ну надо точно засинхронизироваться с началом PCLK, видимо как-то так:
CODE
   while(!((*port) & HSYNC_MASK));
   while (!((*port) & PCLK_MASK));
   do
   {
     v = *port;
...


Рекомендую вместо __no_operation() добавить дергание какой-либо ножкой порта и посмотреть, в какие моменты времени происходит считывание. Благо, сейчас там у Вас очень много nop'ов.

QUOTE
Тут вроде как написано, что это трёх проводная последовательная шмна. Как она должна мне помочь? Просветите пожалуйста.


Черт... Пардон... У Вас же шина параллельная. Да, конечно, не поможет, это я загнался sad.gif
Prinz
Цитата(Rst7 @ Apr 22 2011, 12:44) *
Ну надо точно засинхронизироваться с началом PCLK, видимо как-то так:

Рекомендую вместо __no_operation() добавить дергание какой-либо ножкой порта и посмотреть, в какие моменты времени происходит считывание. Благо, сейчас там у Вас очень много nop'ов.

Черт... Пардон... У Вас же шина параллельная. Да, конечно, не поможет, это я загнался sad.gif


Вот результат моего творчества:
Код
__ramfunc unsigned int GetScanLine(unsigned char *dest, unsigned long volatile *port)
{
   unsigned int v;
   unsigned char *d = dest;
   while(!((*port) & HSYNC_MASK));
   while(!((*port) & PCLK_MASK));
   do
   {
     v = *port;
     *d++ = v;
     if (!(v & PCLK_MASK))
     {
       v = *port;
     }
     FIO2SET |= 1 << 10;
     __no_operation();
     __no_operation();
     FIO2CLR |= 1 << 10;
     __no_operation();
     __no_operation();
     __no_operation();
     __no_operation();
     __no_operation();
     __no_operation();
     __no_operation();
     __no_operation();
     __no_operation();
     __no_operation();
     __no_operation();
     __no_operation();
     __no_operation();
     __no_operation();
     __no_operation();
     __no_operation();
     __no_operation();
     __no_operation();
     __no_operation();
     __no_operation();
     __no_operation();
     __no_operation();
     __no_operation();
     __no_operation();
     __no_operation();
     __no_operation();
     __no_operation();
    }
    while((v & HSYNC_MASK));
    return d - dest;
}


1,125 MHz Поднимает на ура и железно.
Возникла другая проблема вот в этом месте: *d++ = v;

Когда в функцию передаёшь указатель на внутреннею память, тоесть просто создаёшь BYTE buff[500];
Всё нормально, *d++ = v эта команда выполняется с постоянное число тактов.
А когда передаёшь на внешнюю память, то вот это *d++ = v; каманда исполняется за разное число тактов.
Проверил точно предложенным Вами способом.
В чём проблема. Может как-то не так настроена внешняя память??? Из - за этого сбивается вся синхронизация и поэтому получается такой своего рода случайный процесс. )))
Помогите пожалуйста и как правильно объявлять массив во внешней памяти?
Rst7
QUOTE
1,125 MHz Поднимает на ура и железно.


Это еще не предел. В пределе - 6МГц (ибо 12 тактов минимум)

QUOTE
Возникла другая проблема


Немудрено. Внешняя память наверняка работает на более низкой частоте чем ядро и посему процессор должен ждать начала нового цикла внешней памяти.
Prinz
Цитата(Rst7 @ Apr 22 2011, 14:50) *
Это еще не предел. В пределе - 6МГц (ибо 12 тактов минимум)



Немудрено. Внешняя память наверняка работает на более низкой частоте чем ядро и посему процессор должен ждать начала нового цикла внешней памяти.


6 всё равно маловато, надо 9 )
А что делать? Ведь одна строка занимает 400 байт, при этом их 150. Это самый худшиф вариант,а надо 3200 байт, на 1200 строк.
Ну или ходя бы 1600 байт на 600 строк.Тоесть однозначно около 1 MB.

Можно построчно запихивать, а потом капировать, но это как-то не выход. Что подскажите. может что понастраивать надо?

Вот мой кусочек настройки внешней памяти:

Код
//#define USE_32_BIT_DATABUS
#define SDRAM_BASE_ADDR 0xA0000000
void initEMC(void)
{
  volatile unsigned int i, dummy = dummy;
  //  SCS     &= ~0x00000002;
  //  SCS     |= 0x00000002;
  EMCCONTROL = 0x00000001;
  PCONP   |= 0x00000800;        /* Turn on EMC PCLK */  
  FIO2DIR &= ~(1 << 12);    /* make P2.12 pin as input */
  FIO2MASK &= ~(1 << 12);  
  PINSEL4  = 0x50000000;
#ifdef USE_32_BIT_DATABUS
  PINSEL5  = 0x55010115;
  PINSEL7  = 0x55555555;
  
#else         //  x
  PINSEL5  = 0x05000555;
#endif
  PINSEL6  = 0x55555555;
  PINSEL8  = 0x55555555;
  PINSEL9  = 0x50555555;

  //all registers...
#ifdef USE_32_BIT_DATABUS
  EMCDYNAMICRP     = 1;
EMCDYNAMICRAS    = 3;
  EMCDYNAMICSREX   = 5;
  EMCDYNAMICAPR    = 1;
  EMCDYNAMICDAL    = 5;
  EMCDYNAMICWR     = 1;
  EMCDYNAMICRC     = 5;
  EMCDYNAMICRFC   = 5;
  EMCDYNAMICXSR    = 5;
EMCDYNAMICRRD    = 1;
  EMCDYNAMICMRD    = 1;
  EMCDINAMICRDCFG = 1;
    
  //
  EMCDYNAMICRASCAS0 = 0x00000202;

  //
  EMCDYNAMICCFG0 = 0x00005480;
#else
   EMCDYNAMICRP     = 2;
  EMCDYNAMICRAS    = 3;
  EMCDYNAMICSREX   = 7;
  EMCDYNAMICAPR    = 2;
  EMCDYNAMICDAL    = 5;
  EMCDYNAMICWR     = 1;
  EMCDYNAMICRC     = 5;
  EMCDYNAMICRFC    = 5;
  EMCDYNAMICXSR    = 7;
  EMCDYNAMICRRD    = 1;
  EMCDYNAMICMRD    = 2;
  EMCDINAMICRDCFG = 1;
    
  //
  EMCDYNAMICRASCAS0 = 0x00000303;
    
  //
  EMCDYNAMICCFG0 = 0x00000680;
#endif
    
  //wait 100mS
  delay(100000);

  //Send command: NOP
  EMCDINAMICCTRL = 0x00000183;
    
  //wait 200mS
  delay(200000);
    
  //Send command: PRECHARGE-ALL, shortest possible refresh period
  EMCDINAMICCTRL = 0x00000103;
  EMCDINAMICRFR = 0x00000002;
    
  //wait 128 ABH clock cycles
  for(i=0; i<0x40; i++)
    asm ("nop");
    
  //Set correct refresh period
  EMCDINAMICRFR = 28;
    
  //Send command: MODE
  EMCDINAMICCTRL = 0x00000083;
    
  //Set mode register in SDRAM
#ifdef USE_32_BIT_DATABUS
  dummy = *((volatile unsigned int*)(SDRAM_BASE_ADDR | (0x22 << 11)));
#else
  dummy = *((volatile unsigned int*)(SDRAM_BASE_ADDR | (0x33 << 12)));
#endif

  //Send command: NORMAL
  EMCDINAMICCTRL = 0x00000000;

  //Enable buffer
  EMCDYNAMICCFG0 |= 0x00080000;

  //initial system delay
  delay(1000);

  EMCSTATICWAITWEN0  = 0x2;
  EMCSTATICWAITOEN0  = 0x2;
  EMCSTATICWAITRD0   = 0x1f;
  EMCSTATICWAITPG0 = 0x1f;
  EMCSTATICWAITWR0   = 0x1f;
  EMCSTATICWAITTURN0 = 0xf;
  EMCSTATICCNFG0      = 0x00000081;
    delay(2000);
    /* for NAND FLASH */
  EMCSTATICCNFG1      = 0x00000080;
  EMCSTATICWAITWEN1  = 0x2;
  EMCSTATICWAITOEN1  = 0x2;
  EMCSTATICWAITRD1   = 0x1F;
  EMCSTATICWAITPG1 = 0x1F;
  EMCSTATICWAITWR1   = 0x1F;
  EMCSTATICWAITTURN1 = 0xF;
  delay(2000);


}
Rst7
QUOTE
6 всё равно маловато, надо 9 )


Вы бы определились, а? А то все началось с этого:
QUOTE
Самый быстрый строб, ко которому надо записывать эти 8bit меняется с частотой 4,5 МегаГерца.


QUOTE
Можно построчно запихивать, а потом капировать, но это как-то не выход.


Это, кстати, хороший и правильный выход. Надо оценить, успеет или нет за время обратного хода. Ну, грубо говоря, практически чуть больше, чем пол-такта на байт скорость правильного memcpy (это если внешняя память без задержек, 32 бита и SDRAM-контроллер поддерживает burst-запись), тогда 400*0.5 примерно равно 200 тактов, это, грубо говоря, 3мкс. Походу вполне, насколько я понимаю.

QUOTE
Что подскажите. может что понастраивать надо?


Ничего Вы там особо не понастраиваете. SDRAM довольно хитрозадая вещь. У меня под рукой нет мануала на Ваш проц, гляньте разве что, какая скорость CLK на SDRAM установленна.
Prinz
Цитата(Rst7 @ Apr 22 2011, 15:11) *
Вы бы определились, а? А то все началось с этого:


Это, кстати, хороший и правильный выход. Надо оценить, успеет или нет за время обратного хода. Ну, грубо говоря, практически чуть больше, чем пол-такта на байт скорость правильного memcpy (это если внешняя память без задержек, 32 бита и SDRAM-контроллер поддерживает burst-запись), тогда 400*0.5 примерно равно 200 тактов, это, грубо говоря, 3мкс. Походу вполне, насколько я понимаю.

Ничего Вы там особо не понастраиваете. SDRAM довольно хитрозадая вещь. У меня под рукой нет мануала на Ваш проц, гляньте разве что, какая скорость CLK на SDRAM установленна.

4.5 это нормальный результат. В идеале надо 9.
У меня память подключена по 16 бит.
А правильный memcpy это какой???

Вы имеете ввиду вот эти вод регистры?
PCLKSEL0 =0x55595555;
PCLKSEL1 =0x55555555;
Тут всё по максимому, кроме RTC.

Прилогаю usermanual:

Rst7
QUOTE
4.5 это нормальный результат. В идеале надо 9.


Можно и 9. На асме и с считыванием кратно 3м байтам.

CODE
        SECTION `.textrw`:CODE:NOROOT(2)
        SECTION_TYPE SHT_PROGBITS, SHF_WRITE | SHF_EXECINSTR
        ARM
//  189 __ramfunc unsigned int GetScanLine(unsigned char *dest, unsigned long volatile *port)
//  190 {
//  191   unsigned int v;
//  192   unsigned char *d=dest;
GetScanLine:
        MOV      R2,R0
//  193   while(!((*port) & 0x400000));
??GetScanLine_0:
        LDR      R3,[R1, #+0]
        TST      R3,#0x400000
        BEQ      ??GetScanLine_0
//  194   while(!((*port) & 0x800000));
??GetScanLine_1:
        LDR      R3,[R1, #+0]
        TST      R3,#0x800000
        BEQ      ??GetScanLine_1
//  195   do
//  196   {
//  197     v=*port;
??GetScanLine_2:
        LDR      R3,[R1, #+0]
//  198     *d++=v;
        STRB     R3,[R2], #+1
//  199     if (!(v&0x800000)) {v=*port;}
        TST      R3,#0x800000
        LDREQ    R3,[R1, #+0]
//  200     v=*port;
        LDR      R3,[R1, #+0]
//  201     *d++=v;
        STRB     R3,[R2], #+1
        TST      R3,#0x400000
//  203     __no_operation();
        Nop      
//  204     __no_operation();
        Nop      
//  205     v=*port;
        LDR      R3,[R1, #+0]
//  206     *d++=v;
        STRB     R3,[R2], #+1
//  207   }
//  208   while(v & 0x400000);
        BNE      ??GetScanLine_2
//  209   return d-dest;
        SUB      R0,R2,R0
        BX       LR              ;; return
//  210 }


Смысл в том, что в одном цикле считывается три байта и доп. действия распределены так - на первом байте - ФАПЧ, на втором - проверка конца строки, на третьем - собственно цикл. Обратите внимание, что собственно чтение с порта выполняется всегда на точке, кратной 8ми тактам, т.е. 72/8=9МГц.

QUOTE
А правильный memcpy это какой???


Который не по байту копирует, а пачками слов через LDM/STM.

QUOTE
У меня память подключена по 16 бит.


Ну уже хуже.

QUOTE
Прилогаю usermanual:


Ну и? Вам еще и начальные настройки разжевывать? Учить азам ремесла? Уж извините, молодой человек, но Вам уже все на блюдечке принесли. Дальше - за деньги, или включайте собственный мозг, учите матчасть.
Prinz
Цитата(Rst7 @ Apr 22 2011, 15:53) *
Можно и 9. На асме и с считыванием кратно 3м байтам.

Смысл в том, что в одном цикле считывается три байта и доп. действия распределены так - на первом байте - ФАПЧ, на втором - проверка конца строки, на третьем - собственно цикл. Обратите внимание, что собственно чтение с порта выполняется всегда на точке, кратной 8ми тактам, т.е. 72/8=9МГц.

Который не по байту копирует, а пачками слов через LDM/STM.

Ну уже хуже.

Ну и? Вам еще и начальные настройки разжевывать? Учить азам ремесла? Уж извините, молодой человек, но Вам уже все на блюдечке принесли. Дальше - за деньги, или включайте собственный мозг, учите матчасть.


Понятно, буду выжимать мксимум, но я ещё дождусь другой контроллер с готовым интерфейсом.
Тоесть его писать самому? Его нет в библиотеках, как на билдере?
Если честно, то я на армах всего 3-ю неделю пишу, но разжёвывать не надо, я его на всякий случай выложил, раз вы сказали его нет под рукой.
Никогда ничего не покупал, всё сам, так что лучше вариант второй, с мозгом который)))
За помощь спасибо.
Rst7
QUOTE
Тоесть его писать самому? Его нет в библиотеках, как на билдере?


Посмотрите в дизассемблере, в IAR'овских библиотеках вроде раньше был банальный побайтный memcpy, но вроде в новых версиях заменили.

Щас глянул - в библиотеке от EWARM 5.30.1 хороший годный memcpy. Так что и новее версии явно не хуже.

Главное - чтобы источник и приемник были с круглого (в смысле - кратного 32хбитному слову) адреса.
Prinz
Цитата(Rst7 @ Apr 22 2011, 16:26) *
Посмотрите в дизассемблере, в IAR'овских библиотеках вроде раньше был банальный побайтный memcpy, но вроде в новых версиях заменили.

Щас глянул - в библиотеке от EWARM 5.30.1 хороший годный memcpy. Так что и новее версии явно не хуже.

Главное - чтобы источник и приемник были с круглого (в смысле - кратного 32хбитному слову) адреса.


Большое спасибо за помощь. Пойду выкуривать касяки.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.