Перейти к содержанию
    

Какую максимальную частоту можно считать с портов контроллера?

Накатал кодик:

 

__ramfunc unsigned int GetScanLineTest(BYTE *dest, unsigned long volatile *port)
{
  unsigned int v;
  BYTE *d = dest;
  while(!((*port) & HSYNC_MASK)); //Ждем начала строки
  do
  {
    v = *port;
    if((v & PCLK_MASK))
    {
      __no_operation();
      //__no_operation();
      while((v & HSYNC_MASK))
      {
        *d++ = v;
        v = *port;
        /*__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();*/
         __no_operation();
        __no_operation();
        __no_operation();
        __no_operation();
        __no_operation();
        __no_operation();
        __no_operation();

      }  
    }
  }
  while((v & HSYNC_MASK));
  return d - dest; 
}

 

Оцените, пожалуйста.

2,25MHz считал, но всё равно этот медот мне ужасно не нравится. Прям душа не лежит.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Оцените, пожалуйста.

 

Ересь какая-то. У Вас чем камера тактируется? Процессором? Или совершенно отдельной частотой?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ересь какая-то. У Вас чем камера тактируется? Процессором? Или совершенно отдельной частотой?

 

Отдельно. А что нельзя, в начале один раз затактировать, а дальше задержками считать всю строку?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А что нельзя, в начале один раз затактировать, а дальше задержками считать всю строку?

 

Нельзя, если генератор отдельный. Нужен ФАПЧ. Посмотрите внимательно на последний код, который я Вам написал - там это реализовано.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Нельзя, если генератор отдельный. Нужен ФАПЧ. Посмотрите внимательно на последний код, который я Вам написал - там это реализовано.

 

Это должно быть так!?

 

__ramfunc unsigned int GetScanLine(unsigned char *dest, unsigned long volatile *port)
{
   unsigned int v;
   unsigned char *d=dest;
   while(!((*port) & HSYNC_MASK)); 
   do
   {
     v = *port;
     if (!(v & PCLK_MASK)) 
     {
       __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();
       v = *port;
     }
     *d++ = v;
     __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;
}

 

Я не знаком с I2S.

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

Мне кто-то его уже советовал.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Это должно быть так!?

 

Уберите вот эти __no_operation, которые отмечены комментарием "пол периода". Там только это

 if (!(v & PCLK_MASK))    v = *port;

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

 

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

 

Это некое подобие SPI. Почитайте usermanual на процессор, там же все написано.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Уберите вот эти __no_operation, которые отмечены комментарием "пол периода". Там только это

 if (!(v & PCLK_MASK))    v = *port;

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

Это некое подобие SPI. Почитайте usermanual на процессор, там же все написано.

 

 

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

Что нет так?

 

Я это понял, что подобие SPI.

The I2S bus specification defines a 3-wire serial bus

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Что нет так?

 

Ну надо точно засинхронизироваться с началом PCLK, видимо как-то так:

   while(!((*port) & HSYNC_MASK)); 
   while (!((*port) & PCLK_MASK));
   do
   {
     v = *port;
...

 

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

 

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

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну надо точно засинхронизироваться с началом PCLK, видимо как-то так:

 

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

 

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

 

Вот результат моего творчества:

__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; каманда исполняется за разное число тактов.

Проверил точно предложенным Вами способом.

В чём проблема. Может как-то не так настроена внешняя память??? Из - за этого сбивается вся синхронизация и поэтому получается такой своего рода случайный процесс. )))

Помогите пожалуйста и как правильно объявлять массив во внешней памяти?

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1,125 MHz Поднимает на ура и железно.

 

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

 

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

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Это еще не предел. В пределе - 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);


}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

Вы бы определились, а? А то все началось с этого:

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

 

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

 

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

 

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

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вы бы определились, а? А то все началось с этого:

 

 

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

 

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

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

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

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

 

Вы имеете ввиду вот эти вод регистры?

PCLKSEL0 =0x55595555;

PCLKSEL1 =0x55555555;

Тут всё по максимому, кроме RTC.

 

Прилогаю usermanual:

 

user.manual.lpc24xx.pdf

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

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

 

        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МГц.

 

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

 

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

 

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

 

Ну уже хуже.

 

Прилогаю usermanual:

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

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

 

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

 

Ну уже хуже.

 

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

 

Понятно, буду выжимать мксимум, но я ещё дождусь другой контроллер с готовым интерфейсом.

Тоесть его писать самому? Его нет в библиотеках, как на билдере?

Если честно, то я на армах всего 3-ю неделю пишу, но разжёвывать не надо, я его на всякий случай выложил, раз вы сказали его нет под рукой.

Никогда ничего не покупал, всё сам, так что лучше вариант второй, с мозгом который)))

За помощь спасибо.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...