Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Производительность ARM
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Dato
Начал пробовать ARM LPC2294(Плата Olimex LPC-L2294).
Получаю, на мой взгляд, очень странный резултат.
кварц на плате 14 MHz, PLL Множитель = 3. Компилирую - IAR EWARM v5.50, Prcessor mode - Arm, Optimisation - High(speed).

так инициализирую PLL
Код
void LPC2294PLLInit(void)
{
  PLLCFG_bit.MSEL = 2;
  PLLCFG_bit.PSEL = 1;
  
  PLLCON_bit.PLLE = 1;
  PLLCON_bit.PLLC = 1;
  
  PLLFEED_bit.FEED = 0xAA;
  PLLFEED_bit.FEED = 0x55;
}

и выполняется код
Код
unsigned char a_buf[255];
for(unsigned char i=0; i<100; i++)
{
a_buf[i]=i;
}

На выполнение этого кода, процессору требуется примерно 100us, что мне кажется очень много.
После разрешения прерываний по таймеру(прерывание каждый 15us, обработчик выполняется 7us), это время становится 800us и это уже катастрофически много. я ожидал увеличения примерно в два раза.
Не понятно что не так делаю, не могу поверить что, LPC2294 не может работать быстрее
Канечно по такому описанию проблемы, трудно посоветовать, smile.gif но если кто проходил через это, буду рад любой подсказке. smile.gif
SasaVitebsk
Jlink-ом вы можете напрямую измерить скорость процессора командой testcspeed.

Также можно измерить это косвенно, выведя частоту на какую-нибудь ножку. Либо аппаратно, либо программно накрайняк.
Dato
Цитата
Также можно измерить это косвенно, выведя частоту на какую-нибудь ножку. Либо аппаратно, либо программно накрайняк.


Да именно так я измеряю время выполнения кода(Осцилографом).
попробую Jlink-ом тоже. спасибо smile.gif

Я плохо разбираюсь в деталях тактирования и циклов ARM, но должен работать на много быстрее да? или я ошибаюсь и не надо ожидать большей производительности?
Но такую произвадительност обеспечивает например ATmega16 на 8MHz, с компиляцией без оптимизаций wink.gif

при пустом цикле
Код
unsigned char a_buf[255];
for(unsigned char i=0; i<100; i++)
{
     //a_buf[i]=i;
}

время выполнения 5us.
Запись в рам требует столько времени?
a_buf будет расположена в внутреннем RAM, так?
sonycman
Убедитесь, что PLL точно залочен и используется в качестве тактового сигнала системы.
После конфигурирования PLL прочитайте и проанализируйте регистр PLLSTAT.

Вы всегда таким образом настраиваете PLL?
Вообще то подсоединять его нужно только после того, как он запустится и настроится на частоту - после установки бита PLOCK.
Dato
Цитата
Вообще то подсоединять его нужно только после того, как он запустится и настроится на частоту - после установки бита PLOCK


так?
Код
PLLCON_bit.PLLE = 1;
while(!PLLSTAT_bit.PLOCK);
PLLCON_bit.PLLC = 1;




Да, проверил PLLSTAT
PLLE=1, PLLC=1, PLOCK=1
sonycman
Цитата(Dato @ Aug 24 2010, 16:26) *
так?
Код
PLLCON_bit.PLLE = 1;
while(!PLLSTAT_bit.PLOCK);
PLLCON_bit.PLLC = 1;

Да.
Только не забудьте каждый раз после записи в PLLCON про feed sequence в PLLFEED.

Можете привести ассемблерный листинг функции?
demiurg_spb
Цитата(Dato @ Aug 24 2010, 14:15) *
Начал пробовать ARM
...
и выполняется код
Код
unsigned char a_buf[255];
for(unsigned char i=0; i<100; i++)
{
  a_buf[i]=i;
}
Нативнм типом для ARM является int а не unsigned char...
Dato
Цитата
Можете привести ассемблерный листинг функции?


Код
void LPC2294PLLInit(void)
     76          {
     77            PLLCFG_bit.MSEL = 3;
   \                     LPC2294PLLInit:
   \   00000000   ........           LDR      R0,??DataTable9_2 ;; 0xe01fc080
   \   00000004   041090E5           LDR      R1,[R0, #+4]
   \   00000008   1F10C1E3           BIC      R1,R1,#0x1F
   \   0000000C   031081E3           ORR      R1,R1,#0x3
   \   00000010   041080E5           STR      R1,[R0, #+4]
     78            PLLCFG_bit.PSEL = 1;
   \   00000014   041090E5           LDR      R1,[R0, #+4]
   \   00000018   6010C1E3           BIC      R1,R1,#0x60
   \   0000001C   201081E3           ORR      R1,R1,#0x20
   \   00000020   041080E5           STR      R1,[R0, #+4]
     79            
     80            
     81            
     82            
     83            PLLCON_bit.PLLE = 1;
   \   00000024   001090E5           LDR      R1,[R0, #+0]
   \   00000028   011081E3           ORR      R1,R1,#0x1
   \   0000002C   001080E5           STR      R1,[R0, #+0]
     84            PLLCON_bit.PLLC = 1;
   \   00000030   001090E5           LDR      R1,[R0, #+0]
   \   00000034   021081E3           ORR      R1,R1,#0x2
   \   00000038   001080E5           STR      R1,[R0, #+0]
     85            
     86            __disable_interrupt();
   \   0000003C   00100FE1           MRS      R1,CPSR
   \   00000040   C01081E3           ORR      R1,R1,#0xC0
   \   00000044   01F021E1           MSR      CPSR_c,R1
     87            PLLFEED_bit.FEED = 0xAA;
   \   00000048   0C1090E5           LDR      R1,[R0, #+12]
   \   0000004C   FF10C1E3           BIC      R1,R1,#0xFF
   \   00000050   AA1081E3           ORR      R1,R1,#0xAA
   \   00000054   0C1080E5           STR      R1,[R0, #+12]
     88            PLLFEED_bit.FEED = 0x55;
   \   00000058   0C1090E5           LDR      R1,[R0, #+12]
   \   0000005C   FF10C1E3           BIC      R1,R1,#0xFF
   \   00000060   551081E3           ORR      R1,R1,#0x55
   \   00000064   0C1080E5           STR      R1,[R0, #+12]
     89          }
   \   00000068   1EFF2FE1           BX       LR              ;; return
   \   0000006C                      REQUIRE _A_PLLCON
   \   0000006C                      REQUIRE _A_PLLCFG
   \   0000006C                      REQUIRE _A_PLLFEED
SanvaldYV
Цитата
при пустом цикле время выполнения 5us. Запись в рам требует столько времени? a_buf будет расположена в внутреннем RAM, так?


При пустом цикле и включенной оптимизации компилятор вероятно выкинет и объявление переменной, и сам цикл, так что это скорее всего просто время на переключение пина, по которому вы замеряете время выполнения.
Dato
Код
Нативнм типом для ARM является int а не unsigned char...


Не понял, если Вы имеете ввиду разрядность то да, но при обращении к байтам в памяти, должна падать Производительность ?
sonycman
Цитата(Dato @ Aug 24 2010, 16:45) *
Код
void LPC2294PLLInit(void)

Нет, я имел ввиду код цикла, по которому измеряется время выполнения.

Цитата(Юрий Санвальд @ Aug 24 2010, 16:50) *
При пустом цикле и включенной оптимизации компилятор вероятно выкинет и объявление переменной, и сам цикл, так что это скорее всего просто время на переключение пина, по которому вы замеряете время выполнения.

Время переключения пина, равное пяти микросекундам?
Что-то слишком медленно, тут должны быть десятки/сотни наносекунд.
Dato
Цитата
При пустом цикле и включенной оптимизации компилятор вероятно выкинет и объявление переменной, и сам цикл, так что это скорее всего просто время на переключение пина, по которому вы замеряете время выполнения.


Да Вы прави, об этом не подумал. но значит все еще хуже. 5us только чтоб 100 раз переключить пин

Это функция

Код
void test()
{
   for(unsigned char i=0; i < 100; i++)
    {
      //outBuf[i]=i;
    }
   if(outBuf[99]==99)
    {
      IO1SET = 0x00100000;
    }
    for(unsigned char i=0; i < 100; i++)
    {
      //inBuf[i]=i;
    }  
    if(inBuf[99]==99)
    {
     IO1CLR = 0x00100000;
    }
}


листинг

Код
190          void test()
    191          {
    192             for(unsigned char i=0; i < 100; i++)
    193              {
    194                //outBuf[i]=i;
    195              }
    196             if(outBuf[99]==99)
   \                     test:
   \   00000000   ........           LDR      R0,??DataTable23_7
   \   00000004   0C1090E5           LDR      R1,[R0, #+12]
   \   00000008   6310D1E5           LDRB     R1,[R1, #+99]
   \   0000000C   630051E3           CMP      R1,#+99
    197              {
    198                IO1SET = 0x00100000;
   \   00000010   ........           LDREQ    R1,??DataTable23;; 0xe0028014
   \   00000014   4029A003           MOVEQ    R2,#+1048576
   \   00000018   00208105           STREQ    R2,[R1, #+0]
    199              }
    200              for(unsigned char i=0; i < 100; i++)
    201              {
    202                //inBuf[i]=i;
    203              }  
    204              if(inBuf[99]==99)
   \   0000001C   080090E5           LDR      R0,[R0, #+8]
   \   00000020   6300D0E5           LDRB     R0,[R0, #+99]
   \   00000024   630050E3           CMP      R0,#+99
    205              {
    206               IO1CLR = 0x00100000;
   \   00000028   ........           LDREQ    R0,??DataTable23;; 0xe0028014
   \   0000002C   4019A003           MOVEQ    R1,#+1048576
   \   00000030   08108005           STREQ    R1,[R0, #+8]
    207              }
    208          }
   \   00000034   1EFF2FE1           BX       LR             ;; return
   \   00000038                      REQUIRE _A_IO1SET
   \   00000038                      REQUIRE _A_IO1CLR
    209
sonycman
Цитата(Dato @ Aug 24 2010, 17:13) *
Это функция

Это не функция, а ужас какой-то smile.gif
Она у Вас вообще пин переключать не должна, так как циклов нет (выкинуты при оптимизации как ненужные), и заначению 99 просто неоткуда взяться в массиве.
Dato
сейчас у меня такой код

Код
void test()
{
     IO1SET = 0x00100000;
     IO1CLR = 0x00100000;
}

main()
{
....

for(;;)
{
     test();
}
}



пин в "1" в течении 0.4us и пин в "0" в течении 1.7us

Цитата
Это не функция, а ужас какой-то


smile.gif
Да, но переключает, просто оптимизатор как то странно оптимизиравал, оставил сравнения но выкину переходы biggrin.gif
aaarrr
Цитата(Dato @ Aug 24 2010, 17:38) *
Да, но переключает, просто оптимизатор как то странно оптимизиравал, оставил сравнения но выкину переходы biggrin.gif

Все правильно он сделал. Зачем переходы, если есть условное выполнение.
sonycman
Цитата(Dato @ Aug 24 2010, 17:38) *
Да, но переключает, просто оптимизатор как то странно оптимизиравал, оставил сравнения но выкину переходы biggrin.gif

Она не должна переключать, потому что в массив ничего не пишется - откуда в нём возьмётся значение 99, подумайте? smile.gif

Что ещё могу посоветовать - МАМ у Вас включен? Настройте и включите, или перекиньте код в ОЗУ, чтобы исключить тормоза флеш.
Также включите режим Fast GPIO и пользуйтесь регистрами FIOxSET/FIOxCLR вместо медленных IOxSET/IOxCLR.
Dato
Цитата
Все правильно он сделал. Зачем переходы, если есть условное выполнение.


Цитата
Она не должна переключать, потому что в массив ничего не пишется - откуда в нём возьмётся значение 99, подумайте?


Да Вы правы, я проста не отключал плату после проверки, с записю в массив biggrin.gif

Спасибо за советы, правда я не знаю что такое МАМ и Fast GPIO придется почитать и попробую smile.gif

sonycman
включил MAM, ускорилась почти 2.5 раза smile.gif

Цикл даже с разрешенным прерыванием выполняется за 80us. Это уже другое дело, Спасибо всем, но особенно sonycman smile.gif
sergeeff
Запустили бы стандартный benchmark тест, было бы понятно, что к чему (по крайней мере, естъ что сравнивать), а не разбирали бы адекватностъ вашего теста.
zltigo
Когда-то здесь выкладывал собранный drystone для Олимексовской-же E2294.
demiurg_spb
Цитата(Dato @ Aug 24 2010, 16:54) *
Не понял, если Вы имеете ввиду разрядность то да, но при обращении к байтам в памяти, должна падать Производительность ?
Для счётчика цикла переменная заводится не в памяти а в регистре...
Код
uint8_t* dst = &buf[0];
for (int i=0; i<100; i++)
{
    *dst++ = i;
}
Какой asm-листинг даст?
sergeeff
Когда я писал про стандартный benchmark, имел в виду, что это позволит автору:
1. Понять (сравнить, сопоставить) правильно ли работает его железо.
2. Убедившись в п.1, можно заниматься изучением быстродействия своих программных изысков.
Dato
demiurg_spb
Понятно, но в моем случае, две дополнителние asm команды не имели значения, проблема была в другом

sergeeff
В моих тестах был элементарный код, к стати, определенно проверяющий также железо(проверка перед переключением пина - убедится что данные, не проста выбрасываются на шину а записываются в RAM), о каких программных изысках может быть реч? wink.gif
zltigo
QUOTE (Dato @ Aug 25 2010, 11:31) *
о каких программных изысках может быть реч? wink.gif

О тех, которые не позволили Вам получить даже минимальный удовлетворительно рабочий код sad.gif. Т.е. внимательно разобраться с инициализаций контроллера, для чего всякие PLL,MAM,WS и как ни влияют производительность контроллера, хоть на сколь-нибудь приближенных к реальным задачах.
Dato
zltigo

PLL, MAM и т.д. это обычный справочный материал, по чипу, которых либо знаеш либо нет. мне "не позволили получить даже минимальный удовлетворительно рабочий код" не знание этих справочных фактов, а не как Вы выражаетес, мои программные изыскания. Знающие люди, просто подсказали что, где, надо искать и не начали философствовать о программных изысканиях
demiurg_spb
Цитата(Dato @ Aug 25 2010, 12:31) *
Понятно, но в моем случае, две дополнителние asm команды не имели значения
Внутри цикла всё имеет значение...
zltigo
QUOTE (Dato @ Aug 25 2010, 12:19) *
не знание этих справочных фактов....

О сколько Вам открытий чудных еще предстоит сделать smile.gif. Это отнюдь не справочный материал - взяли справочник, узнали число pi подставили. Вы взяли "справочник", взяли, ну, например для того-же MAM число "2". А почему в этом "справочнике" в отличие от числа pi для MAM еще и другие значения приводятся? Как они на производительность влияют? Мысль у Вас не возникла sad.gif. Ну это дело наживное.



Dato
zltigo

Цитата
Это отнюдь не справочный материал


Нет. это священные эзотерические знания, данные только избранным wink.gif

Цитата
А почему в этом "справочнике" в отличие от числа pi для MAM еще и другие значения приводятся? Как они на производительность влияют? Мысль у Вас не возникла


Справочник без лишней философий отвечает на эти вопросы, разобрался уже, спасибо Всем и извините что побеспокоил smile.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.