Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Скорость ног SAM7
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Iezuit
Добрый день!
На AT91S64 начал программно (т.е. сам через порт, а не через стандартные функции периферии) выводить информацию на ноги частотой ~10-15 МегаГерц но, по осциллографу, выходит не более 1. Подскаже, я чего-то не понимаю или это ошибка, связанная с мои неправильными действиями?
bureau
Приведите листинг своего кода, если вас не затруднит...!
aaarrr
Цитата(Iezuit @ May 4 2008, 16:23) *
На AT91S64 начал программно (т.е. сам через порт, а не через стандартные функции периферии) выводить информацию на ноги частотой ~10-15 МегаГерц но, по осциллографу, выходит не более 1. Подскаже, я чего-то не понимаю или это ошибка, связанная с мои неправильными действиями?

Программно можно выводить с частотой не более 1/4 MCK (две записи APB на цикл, каждая запись 2 такта MCK). Так что с 10-15МГц будут проблемы, но точно должно получаться больше 1.
Iezuit
Ниже привожу код (IAR). Прошу прощения, что не сделал сразу.
Код
#include <inarm.h>
#include "main.h"


void AT91F_LowLevelInit(void) @ "ICODE"
{//low_level_init

    AT91C_BASE_MC->MC_FMR = AT91C_MC_FWS_0FWS;

    AT91C_BASE_PMC->PMC_MOR = (( AT91C_CKGR_OSCOUNT & (0x40 <<8) | AT91C_CKGR_MOSCEN ));
    // Wait Main Oscillator stabilization
    while(!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MOSCS));

    AT91C_BASE_PMC->PMC_PLLR = AT91C_CKGR_USBDIV_1 |
                    (16 << 8) |
                               (AT91C_CKGR_MUL & (405 << 16)) |   //18.432*(405+1)/250=29.933
                               (AT91C_CKGR_DIV & 250);
    // Wait for PLL stabilization
    while( !(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_LOCK) );
    while( !(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY) );

    AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_PRES_CLK;
    // Wait until the master clock is established
    while( !(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY) );

    AT91C_BASE_PMC->PMC_MCKR |= AT91C_PMC_CSS_PLL_CLK;
    // Wait until the master clock is established
    while( !(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY) );

    AT91C_BASE_WDTC->WDTC_WDMR = AT91C_WDTC_WDDIS;
}



int main()
{

  AT91F_LowLevelInit(); //инициализируем рабочую частоту

//разрешаем периферические часы  
  AT91F_PMC_EnablePeriphClock(AT91C_BASE_PMC,(1 << AT91C_ID_PIOA)/);


AT91F_PIO_CfgOutput(AT91C_BASE_PIOA,SCREEN_DB|SCREEN_D_C|SCREEN_RES|SCREEN_WR|SCREEN_RD);

  AT91F_PIO_CfgDirectDrive(AT91C_BASE_PIOA,SCREEN_DB);

while (1)
  {
   AT91F_PIO_ClearOutput(AT91C_BASE_PIOA,SCREEN_WR);
AT91F_PIO_ForceOutput(AT91C_BASE_PIOA,0x5555<<16);
AT91F_PIO_SetOutput(AT91C_BASE_PIOA,SCREEN_WR);
    }  
  
}

Стандартная отладочная плата SAM7S64
При частоте - 30 MHz (от PLL, кварц - 18.432) в режиме Thumb, период главного цикла (по осциллографу) - 2 мкс, 0 на SCREEN_WR примерно 0.5мкс, 1 - 1мкс

в режиме ARM, период главного цикла (по осциллографу) - 2 мкс, 0 на SCREEN_WR 0.75мкс, 1 - 1.25мкс
Скложилось впечатление, что само обращение к порту происходит крайне медленно (ИАР обрезанный, ассемблер посмотреть не могуsad.gif )
Предполагал, что АРМ должен обеспечивать большую скорость - ведь даже на меге результаты лучше!
Или я что-то делаю не так?
aaarrr
А оптимизация-то включена?
Iezuit
Цитата(aaarrr @ May 5 2008, 13:04) *
А оптимизация-то включена?

если я правильно понимаю, что оптимизация на компиляцию в режиме Debug влияет, то от включения оптимизации ничего не меняется.
При переносе содержимого цикла в RAM, период цикла сокращается до 1мкс
bureau
2 Iezuit
Неправильно понимаешь. Ты сравни с и без, и посмотри на АСМовский код что иар генерит.
Iezuit
Цитата(bureau @ May 5 2008, 13:36) *
2 Iezuit
Неправильно понимаешь. Ты сравни с и без, и посмотри на АСМовский код что иар генерит.

У меня к сожалению обрезанный по функциональности ИАР, и посмотреть асмовский код я не могу.
В прочем, разница при включении оптимизации нет только в режиме Thumb - на АРМ оптимизация помогает.
На АРМ оптимизацией получается 0.8 мкс на цикл. Все равно медленно
amw
Цитата(Iezuit @ May 5 2008, 11:00) *
Код
while (1)
  {
   AT91F_PIO_ClearOutput(AT91C_BASE_PIOA,SCREEN_WR);
AT91F_PIO_ForceOutput(AT91C_BASE_PIOA,0x5555<<16);
AT91F_PIO_SetOutput(AT91C_BASE_PIOA,SCREEN_WR);
    }  
  
}

Ну если чуть поразмыслить, то получается что-то вроде
Код
    ldr r0, =AT91C_BASE_PIOA
label:
    ldr r1, SCREEN_WR
    str r1, [r0 + КАК_ЕГО_ТАМ_PIOA_CLR]
    mov r1, #0x5555 lsl 16; Не уверен, что это можно mov
    str r1, [r0 + КАК_ЕГО_ТАМ_PIOA_SET]
    bic r1, r1, 0xFFFFFFFF; ??????
    str r1, [r0 + КАК_ЕГО_ТАМ_PIOA_CLR]
    ldr r1, SCREEN_WR
    str r1, [r0 + КАК_ЕГО_ТАМ_PIOA_SET]
    b label

Посчитайте такты.
Iezuit
Цитата(amw @ May 5 2008, 13:56) *
Посчитайте такты.

Спасибо!
Скачал описание ассемблера с атмела и посчитал. Результат меня расстроил.
А есть ли какие-то альтернативные способы? Задача стоит так: обеспечить общение АРМ с OLED экраном по паралленому интерфейсу (8битная шина). На Меге приемлемая скорость получалось за счет использования механизма работы с внешней памятью (т.е. чтение и запись аппаратно устанавливались). А в АРМе есть какие-нибудь возможности несколько быстрее общаться с шиной?
KAlex
Цитата(Iezuit @ May 5 2008, 12:44) *
У меня к сожалению обрезанный по функциональности ИАР, и посмотреть асмовский код я не могу.

Это как? А куда ж листинги деваются?
Iezuit
Цитата(KAlex @ May 5 2008, 15:10) *
Это как? А куда ж листинги деваются?

Не генерируются листинги, заблокирована эта возможность, т.к. ИАР - кикстарт, версия с кучей ограничений
KAlex
Здесь все давно разжевано.
vet
простое дергание ноги должно выливаться в гораздо меньший объем кода:
Код
//   for (;;) {
//     *AT91C_PIOA_CODR = 50;
//     *AT91C_PIOA_SODR = 50;
//   }

        LDR      R0,??xx_1 ;; 0xfffffffffffff430
        LDR      R1,??xx_1+0x4 ;; 0xfffffffffffff434
        MOVS     R2,#+50
??xx_2:
        STR      R2,[R1, #+0]
        STR      R2,[R0, #+0]
        B        ??xx_2
aaarrr
Ну, amw написал уж очень страшный вариант. На деле на одну запись в порт требуется 3 такта MCK, т.е. конструкция из 3-х записей + переход должна выполняться за 12 тактов процессора или 400 мксек.
Iezuit
Простое - да, но у меня между дерганьями было еще
AT91F_PIO_ForceOutput(AT91C_BASE_PIOA,0x5555<<16);
(т.е. AT91C_BASE_PIOA->PIO_ODSR=a<<16;)
Уважаемый amw привел ассемблерный код вместе с ним.
Как-то очень медленно получаетсяsad.gif Команды-то все сильно не однотактовые, как выяснилосьsad.gif



Цитата(aaarrr @ May 5 2008, 15:31) *
Ну, amw написал уж очень страшный вариант. На деле на одну запись в порт требуется 3 такта MCK, т.е. конструкция из 3-х записей + переход должна выполняться за 12 тактов процессора или 400 мксек.

А как бы заставить ИАР мой код НОРМАЛЬНО странслировать на ассемблер, чтобы получилось таки 12 тактов, о которых Вы пишите? Вроде бы полная оптимизация выставлена, и все-равно...
aaarrr
Цитата(Iezuit @ May 5 2008, 15:33) *
Простое - да, но у меня между дерганьями было еще
AT91F_PIO_ForceOutput(AT91C_BASE_PIOA,0x5555<<16);
(т.е. AT91C_BASE_PIOA->PIO_ODSR=a<<16;)
Уважаемый amw привел ассемблерный код вместе с ним.

0x5555<<16 при нормальной оптимизации никто в цикле загружать не будет, значение будет получено и положено в регистр до начала цикла.

Цитата(Iezuit @ May 5 2008, 15:37) *
А как бы заставить ИАР мой код НОРМАЛЬНО странслировать на ассемблер, чтобы получилось таки 12 тактов, о которых Вы пишите? Вроде бы полная оптимизация выставлена, и все-равно...

Для начала надо бы листинг получить, без него что-либо оптимизировать затруднительно.
Iezuit
Цитата(aaarrr @ May 5 2008, 15:39) *
Для начала надо бы листинг получить, без него что-либо оптимизировать затруднительно.

Ну я в принципе писал, но еще раз:
Функция, которую хочется сделать побыстрее

Код
void write_d(unsigned char a)
{
AT91C_BASE_PIOA->PIO_CODR = SCREEN_WR;
AT91C_BASE_PIOA->PIO_ODSR=a<<16;
AT91C_BASE_PIOA->PIO_SODR = SCREEN_WR;
}


Либо не функция, а просто строчки кода
Код
AT91C_BASE_PIOA->PIO_CODR = SCREEN_WR;
AT91C_BASE_PIOA->PIO_ODSR=data<<16;
AT91C_BASE_PIOA->PIO_SODR = SCREEN_WR;
amw
Цитата(aaarrr @ May 5 2008, 14:31) *
Ну, amw написал уж очень страшный вариант. На деле на одну запись в порт требуется 3 такта MCK, т.е. конструкция из 3-х записей + переход должна выполняться за 12 тактов процессора или 400 мксек.

Ну да. Это типа наихудший вариант.
Если просто 0x5555 << 16 то это просто константа, а если типа a << 16 где a - переменная, то может быть еще что-то. Например с volatile тоже вопрос.
И если это переменная, то в голову не приходит ничего лучше:
Код
ldr r1, =a
ldr r1, [r1]

Хотя конечно оптимизатор должен поработать в этом месте. Да и в приведенном примере даже для переменной, ее значение может быть загружено до цикла. Плюс инверсию тоже можно загрузить до цикла. Но это уже вопрос к компилятору и его оптимизатору.
Точно, что делают макросы из листинка я не знаю. Это попытка догадаться.
Помнится я когда-то в лоб на ассемблере проверял когда SAM7S256 изучал.
На частоте 36 МГц получил чуть больше 2МГц на пине (или 3МГц, точно не помню).
Но что это на много меньше чем хотелось бы - так это точно.
aaarrr
Цитата(Iezuit @ May 5 2008, 15:46) *
Ну я в принципе писал, но еще раз:
Функция, которую хочется сделать побыстрее

Код
void write_d(unsigned char a)
{
AT91C_BASE_PIOA->PIO_CODR = SCREEN_WR;
AT91C_BASE_PIOA->PIO_ODSR=a<<16;
AT91C_BASE_PIOA->PIO_SODR = SCREEN_WR;
}

Эту функцию можно откомпилировать по-разному, в зависимости от уровня оптимизации.
Можно так:
Код
    ldr    r1, =AT91C_PIOA_CODR
    mov    r2, #SCREEN_WR
    str    r2, [r1]
    ldr    r1, =AT91C_PIOA_ODSR
    mov    r2, r0 lsl #16
    str    r2, [r1]
    ldr    r1, =AT91C_PIOA_SODR
    mov    r2, #SCREEN_WR
    str    r2, [r1]
    mov    pc, lr

а можно и так:
Код
    ldr    r1, =AT91C_BASE_PIOA
    mov    r2, #SCREEN_WR
    str    r2, [r1, #PIO_CODR]
    mov    r3, r0 lsl #16
    str    r3, [r1, #PIO_ODSR]
    str    r2, [r1, #PIO_SODR]
    mov    pc, lr

Нужно уточнить, что сделал компилятор в Вашем случае.

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