|
Скорость ног SAM7, проблема с выводом |
|
|
|
May 4 2008, 12:23
|
Участник

Группа: Новичок
Сообщений: 16
Регистрация: 13-12-07
Пользователь №: 33 263

|
Добрый день! На AT91S64 начал программно (т.е. сам через порт, а не через стандартные функции периферии) выводить информацию на ноги частотой ~10-15 МегаГерц но, по осциллографу, выходит не более 1. Подскаже, я чего-то не понимаю или это ошибка, связанная с мои неправильными действиями?
|
|
|
|
2 страниц
1 2 >
|
 |
Ответов
(1 - 20)
|
May 5 2008, 08:00
|
Участник

Группа: Новичок
Сообщений: 16
Регистрация: 13-12-07
Пользователь №: 33 263

|
Ниже привожу код (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мкс Скложилось впечатление, что само обращение к порту происходит крайне медленно (ИАР обрезанный, ассемблер посмотреть не могу  ) Предполагал, что АРМ должен обеспечивать большую скорость - ведь даже на меге результаты лучше! Или я что-то делаю не так?
Сообщение отредактировал Iezuit - May 5 2008, 08:11
|
|
|
|
|
May 5 2008, 09:25
|
Участник

Группа: Новичок
Сообщений: 16
Регистрация: 13-12-07
Пользователь №: 33 263

|
Цитата(aaarrr @ May 5 2008, 13:04)  А оптимизация-то включена? если я правильно понимаю, что оптимизация на компиляцию в режиме Debug влияет, то от включения оптимизации ничего не меняется. При переносе содержимого цикла в RAM, период цикла сокращается до 1мкс
Сообщение отредактировал Iezuit - May 5 2008, 09:29
|
|
|
|
|
May 5 2008, 09:44
|
Участник

Группа: Новичок
Сообщений: 16
Регистрация: 13-12-07
Пользователь №: 33 263

|
Цитата(bureau @ May 5 2008, 13:36)  2 Iezuit Неправильно понимаешь. Ты сравни с и без, и посмотри на АСМовский код что иар генерит. У меня к сожалению обрезанный по функциональности ИАР, и посмотреть асмовский код я не могу. В прочем, разница при включении оптимизации нет только в режиме Thumb - на АРМ оптимизация помогает. На АРМ оптимизацией получается 0.8 мкс на цикл. Все равно медленно
|
|
|
|
|
May 5 2008, 09:56
|
Знающий
   
Группа: Свой
Сообщений: 601
Регистрация: 22-09-05
Из: Kharkov
Пользователь №: 8 847

|
Цитата(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 Посчитайте такты.
--------------------
- А мораль отсюда такова: всякому овощу свое время. Или, хочешь, я это сформулирую попроще: никогда не думай, что ты иная, чем могла бы быть иначе, чем будучи иной в тех случаях, когда иначе нельзя не быть. © Lewis Carroll. Alice's adventures in wonderland.
|
|
|
|
|
May 5 2008, 10:59
|
Участник

Группа: Новичок
Сообщений: 16
Регистрация: 13-12-07
Пользователь №: 33 263

|
Цитата(amw @ May 5 2008, 13:56)  Посчитайте такты. Спасибо! Скачал описание ассемблера с атмела и посчитал. Результат меня расстроил. А есть ли какие-то альтернативные способы? Задача стоит так: обеспечить общение АРМ с OLED экраном по паралленому интерфейсу (8битная шина). На Меге приемлемая скорость получалось за счет использования механизма работы с внешней памятью (т.е. чтение и запись аппаратно устанавливались). А в АРМе есть какие-нибудь возможности несколько быстрее общаться с шиной?
|
|
|
|
|
May 5 2008, 11:14
|
Участник

Группа: Новичок
Сообщений: 16
Регистрация: 13-12-07
Пользователь №: 33 263

|
Цитата(KAlex @ May 5 2008, 15:10)  Это как? А куда ж листинги деваются? Не генерируются листинги, заблокирована эта возможность, т.к. ИАР - кикстарт, версия с кучей ограничений
|
|
|
|
|
May 5 2008, 11:21
|
Знающий
   
Группа: Свой
Сообщений: 550
Регистрация: 16-06-04
Из: Казань
Пользователь №: 32

|
простое дергание ноги должно выливаться в гораздо меньший объем кода: Код // 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
--------------------
Главная линия этого опуса ясна мне насквозь!
|
|
|
|
|
May 5 2008, 11:37
|
Участник

Группа: Новичок
Сообщений: 16
Регистрация: 13-12-07
Пользователь №: 33 263

|
Простое - да, но у меня между дерганьями было еще AT91F_PIO_ForceOutput(AT91C_BASE_PIOA,0x5555<<16); (т.е. AT91C_BASE_PIOA->PIO_ODSR=a<<16;) Уважаемый amw привел ассемблерный код вместе с ним. Как-то очень медленно получается  Команды-то все сильно не однотактовые, как выяснилось  Цитата(aaarrr @ May 5 2008, 15:31)  Ну, amw написал уж очень страшный вариант. На деле на одну запись в порт требуется 3 такта MCK, т.е. конструкция из 3-х записей + переход должна выполняться за 12 тактов процессора или 400 мксек. А как бы заставить ИАР мой код НОРМАЛЬНО странслировать на ассемблер, чтобы получилось таки 12 тактов, о которых Вы пишите? Вроде бы полная оптимизация выставлена, и все-равно...
|
|
|
|
|
May 5 2008, 11:39
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Цитата(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 тактов, о которых Вы пишите? Вроде бы полная оптимизация выставлена, и все-равно... Для начала надо бы листинг получить, без него что-либо оптимизировать затруднительно.
|
|
|
|
|
May 5 2008, 11:46
|
Участник

Группа: Новичок
Сообщений: 16
Регистрация: 13-12-07
Пользователь №: 33 263

|
Цитата(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;
|
|
|
|
|
May 5 2008, 11:59
|
Знающий
   
Группа: Свой
Сообщений: 601
Регистрация: 22-09-05
Из: Kharkov
Пользователь №: 8 847

|
Цитата(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МГц, точно не помню). Но что это на много меньше чем хотелось бы - так это точно.
--------------------
- А мораль отсюда такова: всякому овощу свое время. Или, хочешь, я это сформулирую попроще: никогда не думай, что ты иная, чем могла бы быть иначе, чем будучи иной в тех случаях, когда иначе нельзя не быть. © Lewis Carroll. Alice's adventures in wonderland.
|
|
|
|
|
May 5 2008, 12:04
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Цитата(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 образ экрана и перебрасывать его одной максимально оптимизированной функцией.
|
|
|
|
|
May 5 2008, 12:24
|
Участник

Группа: Новичок
Сообщений: 16
Регистрация: 13-12-07
Пользователь №: 33 263

|
Большое спасибо! Пробую...
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|