Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Сбылась мечта идиота - приехали программатор и SAM7S256
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > ARM, 32bit
Страницы: 1, 2, 3
toweroff
Цитата(ViKo @ May 15 2010, 14:47) *
Да, есть такая шняга.

есть в XP, в 7 нет (по крайней мере - W7 x64)
zheka
ПРодолжаю экспериментировать.
Код
unsigned char data[8] = {0xFF,0xAA,0xBB,0x00,0x80,0x7F,0x5B,0xAC};

................................................................................
.................................

  // Enable the Clock of the PIO
  AT91C_BASE_PMC->PMC_PCER  = 1 << AT91C_ID_PIOA;

  // Configure the PIO Lines corresponding to LED1..LED4 as Outputs
  AT91C_BASE_PIOA->PIO_PER  = 0xFFFFFFFF;
  AT91C_BASE_PIOA->PIO_OER  = 0xFFFFFFFF;
  AT91C_BASE_PIOA->PIO_OWER  = 0xFFFFFFFF;

   AT91C_BASE_PIOA->PIO_ODSR =0xAA00AA00;

while(1)
{  
   for(i=0;i<8;i++)
   {
     AT91C_BASE_PIOA->PIO_ODSR |= data[i];
     wait();
   }
  }



Я включил в нужном мне сочетании биты 8-31, а в биты 0-7 хочу в цикле писать байт data, не меняя остальные биты. Так как я сделал, не получается, последующий байт миксуется с предыдущим. Как сделать это, манипулируя OWER я догадываюсь. А можно это сделать изменив лишь строку AT91C_BASE_PIOA->PIO_ODSR |= data[i];

Хм.. то что я хотел получилось так:
Код
AT91C_BASE_PIOA->PIO_PER  = 0xFFFFFFFF;
  AT91C_BASE_PIOA->PIO_OER  = 0xFFFFFFFF;
  AT91C_BASE_PIOA->PIO_OWER  = 0x000000FF;

   AT91C_BASE_PIOA->PIO_SODR =0xAA00AA00;

while(1)
{  
   for(i=0;i<8;i++)
   {
     AT91C_BASE_PIOA->PIO_ODSR = data[i];
     wait();
   }
  }


Но все равно мне не дает покоя - как одной командой на однородно настроенном порту записать данные в первые 8 бит с замещением их предыдущего состояния, не трогая остальные биты?
Genadi Zawidowski
Цитата(zheka @ May 14 2010, 22:29) *
С помощью таймера можно было и в АВР. А можно было и библиотечной функцией
Неужели нет каких-нибудь библиотек?

если нет необходимости отдавать время други тредам (процессам) - я при переносе проекта с ATMega на AT91SAM7S сделал просто так:


Код
// for 48 MHz CPU clock, execute from RAM rom with 1 read wait state
//
void RAMFUNC_NONILINE _delay_us(int timeUS)
{
    // CPU_FREQ / 6500000 = 7
    const int top = timeUS * 25 / (CPU_FREQ / 6500000);
    volatile int n;
    for (n = 0; n < top; ++ n)
    {
    }
}
// exactly as required
//
void _delay_ms(int timeMS)
{
    volatile int n;
    for (n = 0; n < timeMS; ++ n)
    {
        _delay_us(1000);
    }
}


а вообще - пример переноса проекта в аттачменте (продолжает работать и на атмеге и на ARM).
zheka
Спасибо, Геннадий!
Компилятор заругался на RAMFUNC_NONILINE. Я этор убрал, заменил CPU_FREQ на MCK и все заработало. Пощупал осциллографом - получилось точно.


Почти перенес нужный мне проект.
Компилятор ругается на функцию pgm_read_byte (оригинальный проект вроде бы под WinAVR). Как вызвать эту функцию в KEIL? Какой хидер подключить, или может есть аналоги?
ПРимер использования ее в проекте:
Код
void lcd_bitmap(uint8_t *data)
{
uint16_t x,y;
uint16_t bmp_x = (pgm_read_byte(data++) << 8) + pgm_read_byte(data++);        
uint16_t bmp_y = (pgm_read_byte(data++) << 8) + pgm_read_byte(data++);                                 

lcd_set_window(lcd_window.X1, lcd_window.Y1, lcd_window.X2, lcd_window.Y2);    

lcd_write_byte(RAMWR,0);                            
for(y = 0; y < bmp_y; y++)                  
  for(x = 0; x < bmp_x; x++)                 
   {
    lcd_write_byte(pgm_read_byte(data++), 1);        
    lcd_write_byte(pgm_read_byte(data++), 1);        
    lcd_write_byte(pgm_read_byte(data++), 1);        
   }
}
Genadi Zawidowski
Цитата(zheka @ May 15 2010, 22:16) *
Спасибо, Геннадий!
Компилятор заругался на RAMFUNC_NONILINE. Я этор убрал, заменил CPU_FREQ на MCK и все заработало. Пощупал осциллографом - получилось точно.


О! а попробуйте такой вариант расчёта -

Код
const int top = timeUS * 1625 / (CPU_FREQ / 100000);


Макрос RAMFUNC_NONILINE запрещал подстановку (инлайн) функции и требовал размещения кода в ОЗУ.
Это нужно для работы в конфигурации с основным кодом в более медленном ПЗУ для того, чобы не изменялись расчётные времена. Так что не убирайте, а замените на то, что в Вашем компиляторе делает те же действия.

pgm_read_byte в AT91SAM7S заменить на соответствующее обращение к памяти по указателю - этот процессор фон-неймановский, в отличии от гавардского ATMega. (или правильнее писать гарвардский?).
aaarrr
Цитата(zheka @ May 15 2010, 22:36) *
Компилятор ругается на функцию pgm_read_byte (оригинальный проект вроде бы под WinAVR). Как вызвать эту функцию в KEIL?

Подумайте сначала, зачем ее вызывать. Поле памяти-то общее.
Genadi Zawidowski
Блин, zheka, ну ведь дал же я образец переноса проекта... скачайте, посмотрите как сделано... Эти все вопросы там сделаны...

Код
typedef uint32_t prog_uint32_t;
typedef char prog_char;
#define PROGMEM /* */
#define pgm_read_byte(val) ((unsigned char) (* (val)))
zheka
Цитата
#define PROGMEM /* */


Это для игнорирования компилятором? Я уже и так все поубирал)))
А вот #define pgm_read_byte(val) ((unsigned char) (* (val))) помогло - в смысле компилятор не ругается. Проверить пока не могу - нет дисплея.
Genadi Zawidowski
Цитата(zheka @ May 15 2010, 17:04) *
Но все равно мне не дает покоя - как одной командой на однородно настроенном порту записать данные в первые 8 бит с замещением их предыдущего состояния, не трогая остальные биты?


Зачем "однородно" настраивать?
Выделите в порту те биты, которые работают шиной - в регистр PIO_OWER запишите единицы в эти биты.
Это сделать при настройке.
А в "быстрой" части программы писать в регистр PIO_ODSR нужное значение.
Битики стробов и адресов дёргать через PIO_SODR и PIO_CODR
zheka
Я так и сделал.

Кстати, слышал я байку, будто бы ногодрыганье на SAM7 возможно на частоте всего 3 МГц, и это якобы меньше чем в АВР. Это правда?
Genadi Zawidowski
Цитата(zheka @ May 16 2010, 00:00) *
Я так и сделал.

Кстати, слышал я байку, будто бы ногодрыганье на SAM7 возможно на частоте всего 3 МГц, и это якобы меньше чем в АВР. Это правда?


в том проекте, на который я ссылаюсь, есть кусочек теста скорости.
Находящийся в ОЗУ (тактовая - 48 МГц, 1WS) кусочек кода переключает состояние выхода. Минимальный интервал между изменениями состояния - около 55 наносекунд. Максимальный побольше (переход в цикле добавляет пару тактов). Частота сигнала на выводе получается 8 с чем-то мегагерц.
Это в процессоре питаемом от 3.3 вольта - атмеги при этом тактовую 8 МГц позволяют. Надо бы конечно и потребление сраавнить. Но мне кажется, удобства программирования (фон-нейман! 32-бита арифметика!) велики.
aaarrr
Цитата(zheka @ May 16 2010, 00:00) *
Кстати, слышал я байку, будто бы ногодрыганье на SAM7 возможно на частоте всего 3 МГц, и это якобы меньше чем в АВР. Это правда?

3 такта на запись в порт, так что теоретический предел - MCK/6.
ViKo
Для сравнения.
Для STM32F103, чуть-чуть измененный код, по сравнению с тем, что уже приводил (чтобы получить скважность 50%)
Код
  while (1) {
    GPIOB->BSRR = 0x0002;
    __nop(), __nop(), __nop();
    GPIOB->BRR = 0x0002;

Лично видел осциллографом на ноге частоту 6.0 MHz. Т.е., 12 тактов. А в симуляторе было 10. На записи в порт приходилось по 2 такта, на переход 3 такта, nop'ы по 1 такту. И два такта добавились при чтении команды из flash.
sonycman
Цитата(ViKo @ May 16 2010, 01:58) *
Для сравнения.
Для STM32F103, чуть-чуть измененный код, по сравнению с тем, что уже приводил (чтобы получить скважность 50%)
Код
  while (1) {
    GPIOB->BSRR = 0x0002;
    __nop(), __nop(), __nop();
    GPIOB->BRR = 0x0002;

Лично видел осциллографом на ноге частоту 6.0 MHz. Т.е., 12 тактов. А в симуляторе было 10. На записи в порт приходилось по 2 такта, на переход 3 такта, nop'ы по 1 такту. И два такта добавились при чтении команды из flash.

Хе, на LPC1768 на 100 МГц ногодрыжством организован 8 битный CPU интерфейс для LCD.
Макс. частота строба получается около 9 МГц - за 17 миллисекунд производится заливка 320*240 пикселей 16 бит.
ViKo
Цитата(sonycman @ May 16 2010, 14:53) *
Хе, на LPC1768 на 100 МГц ногодрыжством организован 8 битный CPU интерфейс для LCD.
Макс. частота строба получается около 9 МГц - за 17 миллисекунд производится заливка 320*240 пикселей 16 бит.

Пропорция примерно та же - 11,11. Потому что архитектура близкая. А 100 MHz тактовой частоты - конечно лучше, кто ж спорит.
К тому же, у меня есть еще 3 nop'а. Я просто показал, на что можно рассчитывать с этим процессором.
upd. А на MCO я вывел все 36 MHz smile.gif
zheka
Таки делаю успехи - уже получается выводить на экран дисплея от NOKIA 6280 (QVGA 320x240) текст. Правда медленно как-то получается.

Скажите, одинаковы ли по количеству тактов два этих варианта или нет?

1. ...SODR=(1<<4);
2. ... SODR=0x10;

При условии что эти операции прописаны в #define. Короче вот так:
Код
// первый вариант
#define CS_ON AT91C_BASE_PIOA->PIO_SODR=(1<<4);

int void main()
{
CS_ON;
}


// второй вариант
#define CS_ON AT91C_BASE_PIOA->PIO_SODR=0x10;

int void main()
{
CS_ON;
}
Сергей Борщ
Цитата(zheka @ May 18 2010, 13:15) *
Скажите, одинаковы ли по количеству тактов два этих варианта или нет?

1. ...SODR=(1<<4);
2. ... SODR=0x10;
Абсолютно. При том, что компилятор превращает константное выражение (1<<4) в 0x10, а потом он же или ассемблер может задействовать сдвигатель и превратить 0x10 обратно в сдвиг 1 на 4 разряда.
P.S. А скомпилировать оба варианта и в листинг посмотреть?
ViKo
Цитата(Сергей Борщ @ May 18 2010, 13:57) *
P.S. А скомпилировать оба варианта и в листинг посмотреть?

Лучше в симулятор
zheka
эээ... понимаете... сижу я на работе. Работы сегодня нет. Отладочная плата дома. Фантазирую. ДОма конечно же посмотрю в листинг.
Сергей Борщ
Цитата(ViKo @ May 18 2010, 14:15) *
Лучше в симулятор
Да там и в листинге будут видны две идентичные команды.
ViKo
Цитата(Сергей Борщ @ May 18 2010, 14:24) *
Да там и в листинге будут видны две идентичные команды.

Это конечно, только в симуляторе еще и такты видны.
"Медленно как-то получается" - явно не из-за этих команд.
zheka
Хорошо, а если так:
Код
#define CS 4

#define CS_ON AT91C_BASE_PIOA->PIO_SODR=(1<<CS);

int void main()
{
CS_ON;
}

Это копилятор оптимизирует?

Цитата
"Медленно как-то получается" - явно не из-за этих команд.


Приду домой выложу код. Скорость проверялась на однородном заполнении экрана, там всего три команды.
Сергей Борщ
Цитата(zheka @ May 18 2010, 14:52) *
Это копилятор оптимизирует?
Конечно. Выражение-то константное, значит может и будет расчитано на этапе компиляции.
ViKo
Лучше написать
Код
#define CS_ON() AT91C_BASE_PIOA->PIO_SODR=(1<<CS);
int main()
{
CS_ON();
}

Чтобы было видно, что это функция, а не константа.
Ой, а что это за int void main?
zheka
Еслои быть точным, то в Кейловском примере пишется "int main (void) {"

Вот функции,выполняющие заливку экрана.
Код
void lcd_write_byte(uint8_t data, uint8_t D_C)
{    
unsigned long d;
CS_OFF;                                //Выбор LCD
if (D_C) DCX_ON else DCX_OFF;     //Если данные то DCX =1  если команда то DCX = 0
  AT91C_BASE_PIOA->PIO_ODSR = data;    //Данные в порт
WRX_OFF;                            //Установка сигнала записи
WRX_ON;                             //Снятие сигнала записи

}


void lcd_fill_screen(uint32_t color)
{
uint32_t num;
lcd_write_byte(RAMWR, 0);
for(num = 0; num < 0x012C00; num++)
  {
   lcd_write_byte(r(color),1);     
   lcd_write_byte(g(color),1);     
   lcd_write_byte(b(color),1);     
  }
}


Приведены в оригинале. Мне удалось увеличить скорость. ПОка измерял на глазок - 16 заливок раньше выполнялось за 6 секунд, теперь за 4.
Что я сделал - убрал из lcd_write_byte строку проверки data_or_command (D_C) и сделал две разные - одну для вывода данных, другую для вывода команды, убрал и включение и выключение DCX в этих функциях, включаю принудительно перед каждым блоком работы с данными.
Далее, убрал из lcd_write_byte CS_OFF (выбор чипа) и прописал эту команду в местах где начинается работа с LCD.
В lcd_fill_screen я заменил lcd_write_byte(b(color),1); на bb=b(color); lcd_write_byte_data(bb); То есть составляющие цвета не вычленяются каждый раз при записи байта.

Получилось вот что:
Код
void lcd_write_byte(uint8_t data, uint8_t D_C)
{    
CS_OFF;                                //Выбор LCD
if (D_C) DCX_ON else DCX_OFF;     //Если данные то DCX =1  если команда то DCX = 0
  AT91C_BASE_PIOA->PIO_ODSR = data;    //Данные в порт
WRX_OFF;                            //Установка сигнала записи
WRX_ON;                             //Снятие сигнала записи

}


void lcd_write_byte_data(uint8_t data)
{    
  AT91C_BASE_PIOA->PIO_ODSR = data;    //Данные в порт
WRX_OFF;                            //Установка сигнала записи
WRX_ON;                             //Снятие сигнала записи

}

void lcd_write_byte_command(uint8_t data)
{    
  AT91C_BASE_PIOA->PIO_ODSR = data;    //Данные в порт
WRX_OFF;                            //Установка сигнала записи
WRX_ON;                             //Снятие сигнала записи

}



void lcd_fill_screen(uint32_t color)
{
uint32_t num;
uint8_t rr,gg,bb;
rr=r(color); // выделяем
gg=g(color); // цветовые составляющие
bb=b(color); //заранее
DCX_OFF; // строб команды
lcd_write_byte_command(RAMWR);
DCX_ON;  // строб данных
for(num = 0; num < 0x012C00; num++)
  {
   lcd_write_byte_data(rr);  // передаем данные с помощью оптимизированной функции
   lcd_write_byte_data(gg);     
   lcd_write_byte_data(bb);     
  }
DCX_ON;
}


Что еще господа посоветуют для акселерации работы с дисплеем?.
aaarrr
Цитата(zheka @ May 18 2010, 17:47) *
Что еще господа посоветуют для акселерации работы с дисплеем?.

Оптимизацию включить и заинлайнить все. Заполнять он должен явно быстрее четырех раз в секунду.
zheka
уважаемый. Не хочу потратить еще 5 часов на поиски и чтение. В двух словах - как в KEIL это сделать?
Еще раз все перепроверил, нашел пару мест, где недосмотрел, запустил во флеш - получилось - до переделки заполнение за 247 мс, после - за 72 мс.

Кстати, в RAM работает в 2 раза медленнее. Это нормально?

продолжаем экспериментировать - thumb режим - 59 мс.

Оптимизация уровня 0 затормозила работу. Уровень 3 - привел к тем же 72 мс.
aaarrr
Цитата(zheka @ May 18 2010, 19:50) *
Кстати, в RAM работает в 2 раза медленнее. Это нормально?

Нет, это не нормально.

Цитата(zheka @ May 18 2010, 19:50) *
Оптимизация уровня 0 затормозила работу. Уровень 3 - привел к тем же 72 мс.

Optimize for Time стоит?
zheka
Да, есть такая галка.
А что же с RAM ?
aaarrr
Цитата(zheka @ May 18 2010, 20:53) *
А что же с RAM ?

Предлагаете угадать? Проект лучше выложите, тогда посмотрим.
zheka
Вот проект
aaarrr
В конфигурации RAM оптимизация просто выключена.
zheka
Я включил - ничего не изменилось
В настройках вкладка С++, галка Optimize for time, галка Enable ARM/THUMB interworking, и optimization level 3. Я все правильно сделал?
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.