Atmega128 тормозит? AVRStudio+Proteus

Вопросы настройки, программирования, прошивки микроконтроллеров и микросхем программируемой логики
mbzyab
Родился
Сообщения: 9
Зарегистрирован: Пт фев 11, 2011 19:24:43

Atmega128 тормозит? AVRStudio+Proteus

Сообщение mbzyab »

Ситуация следующая: пишу в аврстудии на си, эмулирую в протеусе, МК - Atmega128. Поставил ему частоту 8МГц, рассуждая, что при такой частоте каждый такт будет длится 1/8 микросекунды.
Захотел это проверить.
Предположил, что команды типа записи в регистр и побитной инверсии должны выполнятся за один такт. Предположил, что в эмуляции ножки у МК мгновенно состояние меняют.
В протеусе прицепил осцилограф к ноге МК и запустил вот такой код:

Код: Выделить всё

PORTF = ~PORTF;
PORTF = ~PORTF;
PORTF = ~PORTF;
PORTF = ~PORTF;
PORTF = ~PORTF;
PORTF = ~PORTF;

По осциллографу увидел, что состояние ноги меняется через целую (!) микросекунду (я надеялся увидеть ту самую 1/8).

Далее, включил таймер-счетчик с частотой МК (без предделения), в режиме СТС и сбросом через 1 такт (OCR = 1 то есть).
И проверил два кусочка кода (вроде бы совершенно аналогичных).
Первый кусочек, через прерывание:

Код: Выделить всё

ISR(TIMER1_COMPA_vect)
{
   PORTF=~PORTF;
}

Второй кусочек, через флаг:

Код: Выделить всё

while(1)
{

   if(TIFR & (1 << OCF1A)); // CTC Flag
   {
      TIFR |= 1 << OCF1A; // drop flag
      TCCR1B = 0; // stop timer
      TCNT1 = 0;
      PORTF=~PORTF;
      TCCR1B = (1 << WGM12) | (1 << CS10); //resume timer
   }

И опять осциллографом на ногу смотрел.
Увиденное меня просто поразило - при использовании флага состояние ноги менялось через каждые ~5 мкс, а при использовании прерывания - через ~10 мкс. Почему так долго?! :shock:

Вопрос такой: это я дурак и что-то неправильно делаю (или непонимаю), протеус глючит или все нормально и быстрее таймер тикать и не может?
Murav
Опытный кот
Сообщения: 877
Зарегистрирован: Чт фев 18, 2010 13:51:56

Re: Atmega128 тормозит? AVRStudio+Proteus

Сообщение Murav »

mbzyab писал(а):По осциллографу увидел, что состояние ноги меняется через целую (!) микросекунду (я надеялся увидеть ту самую 1/8).

Всё правильно - строка PORTF = ~PORTF - это далеко не одна машинная команда. Так же проверь, правильные ли выставлены настройки частоты(в том числе деление на 8).

mbzyab писал(а):Далее, включил таймер-счетчик с частотой МК (без предделения), в режиме СТС и сбросом через 1 такт (OCR = 1 то есть).

Вообще в этом случае период - два такта, а не один.

mbzyab писал(а):Первый кусочек, через прерывание

На это прерывание нужно кучу тактов, особенно если учесть, что WinAVR для небольших прерываний всё равно делает достаточно большие прологи и эпилоги. Так что на такое прерывание уйдёт как минимум 20 тактов.

Так что если хочешь получить большую частоту на выходе используй полностью аппаратный вывод на соответсвующий выход OCR.
Аватара пользователя
Satyr
Друг Кота
Сообщения: 7439
Зарегистрирован: Чт ноя 04, 2010 01:56:36
Откуда: г. Москва

Re: Atmega128 тормозит? AVRStudio+Proteus

Сообщение Satyr »

mbzyab писал(а):Предположил, что команды типа записи в регистр и побитной инверсии должны выполнятся за один такт.

Ну ооочень смелое предположение -)))
Какая операция (а их тут отнюдь не одна) сколько тактов берет можно почитать в даташите на AVR ядро.
mbzyab
Родился
Сообщения: 9
Зарегистрирован: Пт фев 11, 2011 19:24:43

Re: Atmega128 тормозит? AVRStudio+Proteus

Сообщение mbzyab »

Satyr писал(а):
mbzyab писал(а):Предположил, что команды типа записи в регистр и побитной инверсии должны выполнятся за один такт.

Ну ооочень смелое предположение -)))
Какая операция (а их тут отнюдь не одна) сколько тактов берет можно почитать в даташите на AVR ядро.


Подозревал, очень, очень жаль :)

Murav писал(а):На это прерывание нужно кучу тактов, особенно если учесть, что WinAVR для небольших прерываний всё равно делает достаточно большие прологи и эпилоги. Так что на такое прерывание уйдёт как минимум 20 тактов.

Так что если хочешь получить большую частоту на выходе используй полностью аппаратный вывод на соответсвующий выход OCR.


Фигово :(
Мне, к сожалению, нужно не просто мигание одной ноги, мне нужно, чтобы код (достаточно объемный) выполнялся через каждые несколько микросекунд.. но если даже между двумя записями в разные порты проходит аж по три микросекунды, то я прям не знаю.

Спасибо всем за пояснения :beer:

Вообще, у меня задача - управление сервоприводами с помощью ШИМ, но сервоприводов аж 18 штук и повороты нифига не согласованные. И пока по переполнению таймера для первого привода импульс прекратится - последний успевает повернуться еще градусов на 5.

Можно сформулировать вопрос так: как генерировать много ШИМ (с одинаковой частотой порядка 100 миллисекунд, но с разной скважностью) на разных ножках с точностью до единиц микросекунд? Может я какой-то очень индусский способ изобрел?
Аватара пользователя
Satyr
Друг Кота
Сообщения: 7439
Зарегистрирован: Чт ноя 04, 2010 01:56:36
Откуда: г. Москва

Re: Atmega128 тормозит? AVRStudio+Proteus

Сообщение Satyr »

mbzyab писал(а):Вообще, у меня задача - управление сервоприводами с помощью ШИМ, но сервоприводов аж 18 штук и повороты нифига не согласованные. И пока по переполнению таймера для первого привода импульс прекратится - последний успевает повернуться еще градусов на 5.

Взять контроллер с кучей каналов ШИМ -)
AT32UC3L016 - 48 ног, 35 каналов ШИМ

ну и полно АРМов с 14 каналами, если хватит.
mbzyab
Родился
Сообщения: 9
Зарегистрирован: Пт фев 11, 2011 19:24:43

Re: Atmega128 тормозит? AVRStudio+Proteus

Сообщение mbzyab »

Satyr писал(а):Взять контроллер с кучей каналов ШИМ -)
AT32UC3L016 - 48 ног, 35 каналов ШИМ

ну и полно АРМов с 14 каналами, если хватит.


Не могу, к сожалению :( Прикован к Атмеге128.
Аватара пользователя
Satyr
Друг Кота
Сообщения: 7439
Зарегистрирован: Чт ноя 04, 2010 01:56:36
Откуда: г. Москва

Re: Atmega128 тормозит? AVRStudio+Proteus

Сообщение Satyr »

mbzyab писал(а):Не могу, к сожалению :( Прикован к Атмеге128.

Тогда только скучно, нудно и совершенно уныло изобретать давно изобретенный велосипед -))
mbzyab
Родился
Сообщения: 9
Зарегистрирован: Пт фев 11, 2011 19:24:43

Re: Atmega128 тормозит? AVRStudio+Proteus

Сообщение mbzyab »

Satyr писал(а):
mbzyab писал(а):Не могу, к сожалению :( Прикован к Атмеге128.

Тогда только скучно, нудно и совершенно уныло изобретать давно изобретенный велосипед -))


Это какой?
Или он настолько секретный, что всем положено изобрести его самостоятельно, для пущего просветления? -_-'
Аватара пользователя
Engineer_Keen
Друг Кота
Сообщения: 3868
Зарегистрирован: Пт янв 29, 2010 10:27:40
Откуда: Москва

Re: Atmega128 тормозит? AVRStudio+Proteus

Сообщение Engineer_Keen »

Можно использовать табличный метод. Записать последовательно каждый шаг ШИМ в память и в цикле выдавать их на порты.

Код: Выделить всё

LOOP:   
//----------
тут проверка на надобность изменения
одного из каналов и собственно изменение
10-20 тактов
//----------
   LD   R16,X+ //загрузка значения первого порта (2 такта)
   LD   R17,Y+ //второго (2 такта)
   LD   R18,Z+ //третьего (2 такта)
   LDI   XH,0x01 //организация (1 такт)
   LDI   YH,0x02 //цикличного (1 такт)
   LDI   ZH,0x03 //вывода (1 такт)
   OUT   PORTA,R16 //вывод (1 такт)
   OUT   PORTB,R17 //данных (1 такт)
   OUT   PORTC,R18 //в порты (1 такт)
   RJMP   LOOP

Тогда можно получить частоту порядка 1-1.5 кГц при 24 каналах 8-битной ШИМ. (Проверено в протеусе)
Минус - величину одного из 24 каналов можно менять только за 1 полный цикл (256 отсчетов ШИМ). Или выполнять его отдельной процедурой, но она будет длится порядка 1000 тактов. Может еще как-то можно изменять, но уже мозг не варит...
Можно тупо сделать кучу сравнений счетчика с регистрами, тогда будет ШИМ с частотой в сотню герц, но можно менять все и сразу и не занимать 728 байт RAM. Большего из программной ШИМ думаю не вытянуть :dont_know:
mbzyab
Родился
Сообщения: 9
Зарегистрирован: Пт фев 11, 2011 19:24:43

Re: Atmega128 тормозит? AVRStudio+Proteus

Сообщение mbzyab »

Engineer_Keen писал(а):Можно использовать табличный метод. Записать последовательно каждый шаг ШИМ в память и в цикле выдавать их на порты.

Engineer_Keen писал(а):Тогда можно получить частоту порядка 1-1.5 кГц при 24 каналах 8-битной ШИМ. (Проверено в протеусе)
Минус - величину одного из 24 каналов можно менять только за 1 полный цикл (256 отсчетов ШИМ). Или выполнять его отдельной процедурой, но она будет длится порядка 1000 тактов. Может еще как-то можно изменять, но уже мозг не варит...
Можно тупо сделать кучу сравнений счетчика с регистрами, тогда будет ШИМ с частотой в сотню герц, но можно менять все и сразу и не занимать 728 байт RAM. Большего из программной ШИМ думаю не вытянуть :dont_know:


Давно я себя таким тупым не чувствовал :( Потому что я, кажись, ничего не понял, из того что вы сказали (и асм я тоже не очень понимаю).
Я сделал как - я сделал массив из 18-ти счетчиков, в которых хранится длительность импульсов (не в мкс, а в "квантах", один квант - это типо счетчик от нуля до OCR досчитал). И потом в каждом кванте всем счетчикам делал инкремент.
Как только счетчик доходит до нуля - на соответствующую ногу подается ноль.
(плюс каждые 10000 квантов делается проверка, не пришло ли по УСАРТу новое значение, это не важно, суть в том, что заранее неизвестно значение скважности для следующего периода).

Проблема в том, что вот эти счетчики и проверки сделаны вот так:

Код: Выделить всё

#define motor_0 PORTA, 0
#define motor_1   PORTA, 1
#define motor_2   PORTA, 2
#define motor_3   PORTA, 3

(и так далее до 18-ти, но по идее, они могут и не подряд идти)

Код: Выделить всё

#define _off(port, bit)   port &= (~(1 << bit))
#define off(p)   _off(p)

#define _all_motors_on()   PORTA = 0xFF; PORTB = 0xFF; PORTC |= 3

Вот благодаря _all_motors_on они врубаются более-менее одновременно (и только те, которые на одном порту висят). (Хотя я сейчас проверил, и если врубать их тоже неодновременно, то разница поменьше %), мне, по факту, не нужна полная одновременность импульсов, мне нужна одинаковая длительность. Вот вы меня сейчас натолкнули на мысль, как сделать извращение извращения!)

А потом в цикле через каждый "квант" времени делается

Код: Выделить всё

if( Drive_Quants[0] == 0) off(motor_0); 
if( Drive_Quants[1] == 0) off(motor_1);
if( Drive_Quants[2] == 0) off(motor_2);
if( Drive_Quants[3] == 0) off(motor_3);
if( Drive_Quants[4] == 0) off(motor_4);
if( Drive_Quants[5] == 0) off(motor_5);

и до 18.

Но если на всех каналах нужно сделать одинаковую длину импульса, то все счетчики превращаются в ноль одновременно и вот эти 18 ифов выполняются друг за другом. В результате, два соседних импульса прекращаются с разницей в ~5-10 микросекунд, а это уже слишком много.
Вот.
Если я правильно понимаю, это нечто наподобии вашего второго предложения, только реализованного через Ж -_-


Вы извините, что я на вас все вот это вываливаю, у меня уже ощущение, что я какого-то жуткого монстра-извращенца написал :oops:

UPD: Так вот, вы меня на мысль натолкнули, спасибо :)
Я переписал стартовые импульсы, чтобы они ТОЖЕ были неодновременными! И погрешность длины импульсов резко снизилась, муахахахахаха!! МУААХАХАХАХАХА!!
Простите, приступ.

Код: Выделить всё

on(motor_0);
PORTF = ~PORTF;
on(motor_1);
PORTF = ~PORTF;
on(motor_2);
PORTF = ~PORTF;
on(motor_3);
PORTF = ~PORTF;
on(motor_4);
PORTF = ~PORTF;

Теперь это почти идеально накладывается на те 18 ифов :))
(вместо инверсии порта наверное лучше какой-нибудь NOP, но я не знаю, как его в Си сделать
-_-)
Аватара пользователя
Engineer_Keen
Друг Кота
Сообщения: 3868
Зарегистрирован: Пт янв 29, 2010 10:27:40
Откуда: Москва

Re: Atmega128 тормозит? AVRStudio+Proteus

Сообщение Engineer_Keen »

mbzyab писал(а):

Код: Выделить всё

if( Drive_Quants[0] == 0) off(motor_0); 
if( Drive_Quants[1] == 0) off(motor_1);
if( Drive_Quants[2] == 0) off(motor_2);
if( Drive_Quants[3] == 0) off(motor_3);
if( Drive_Quants[4] == 0) off(motor_4);
if( Drive_Quants[5] == 0) off(motor_5);

и до 18.
Но если на всех каналах нужно сделать одинаковую длину импульса, то все счетчики превращаются в ноль одновременно и вот эти 18 ифов выполняются друг за другом. В результате, два соседних импульса прекращаются с разницей в ~5-10 микросекунд, а это уже слишком много.
Вот.
Если я правильно понимаю, это нечто наподобии вашего второго предложения, только реализованного через Ж -_-

Вы правы, это похоже на мое второе предложение, только наоборот :))) . Проблема в том, что во-первых: если в качестве Drive_Quants Си использует RAM, то для каждого изменения их значений будет тратится по 5 тактов минимум

Код: Выделить всё

//как Си переведет это на асм
LDS R16,Drive_Quants
DEC R16
STS Drive_Quants,R16

и на if еще 3 такта

Код: Выделить всё

LDS R16,Drive_Quants
CPI R16,0x00

А если использовать регистры (нам ведь нужно всего 18), то на декремент и сравнение нужно всего по одному такту. Вот поэтому я предпочитаю ассемблер.
Во-вторых, может я не так понял, но зачем уменьшать все 18 счетчиков? Пусть эти 18 значений будут постоянными, а с ними сравнивать всего 1 счетчик, который и будет уменьшаться.

Код: Выделить всё

//CNT - наш главный счетчик для ШИМ
//TMP1-TMP3 временные переменные
//V1-V18 - пороги
//далее индусский код
CNT = 0 -> TMP1=0b11111111,TMP2=0b11111111,TMP3=0b00000011 //включаем все порты
CNT = V1 -> TMP1.0 = 0 //если счетчик совпадает с первым значением, выключаем первый канал ШИМ
CNT = V2 -> TMP1.1 = 0 //если счетчик совпадает с первым значением, выключаем второй канал ШИМ
...
...
...
CNT = V18 -> TMP3.1 = 0 //если счетчик совпадает с первым значением, выключаем 18-й канал ШИМ
PORTA=TMP1 //выводим
PORTB=TMP2 //данные в порты
PORTC=TMP3 //почти одновременно
Переход на начало цикла

mbzyab писал(а):(вместо инверсии порта наверное лучше какой-нибудь NOP, но я не знаю, как его в Си сделать

Что-то вроде

Код: Выделить всё

ASM("NOP");

если не ошибаюсь...
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Atmega128 тормозит? AVRStudio+Proteus

Сообщение ARV »

http://arv.radioliga.com/content/view/150/44/ по ссылке проект 6-канального ШИМ на attiny13, в котором ВСЕ каналы синхронны. сделать 16 каналов на многопиновом МК элементарно, но между первой восьмеркой и второй будет небольшой сдвиг, 18 - похуже, но тоже реально. особенно если затактировать от кварца 16 Мгц - выжать 100 Гц для 24 каналов ШИМ, думаю, вполне можно, правда третья восьмерка еще чуть-чуть будет отставать от второй и, соответственно, от первой... с небольшой ассемблерной вставкой сдвиг можно уменьшить до 1 машинного такта.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Murav
Опытный кот
Сообщения: 877
Зарегистрирован: Чт фев 18, 2010 13:51:56

Re: Atmega128 тормозит? AVRStudio+Proteus

Сообщение Murav »

Вот тут есть пример работы с кучей сервомашинок: http://easyelectronics.ru/upravlenie-mn ... hinok.html

А вообще весь код, который должен работать с очень высокой скоростью нужно писать на ассемблере. Если ассемблер не знаешь, то можно сначала написать код на C и скомпилить его, а затем найти в lst-файле(его создание включается в настройках компиляции) полученный ассемблерный код, скопировать его в свой asm-файл(AVR Studio позволяет использовать в одном проекте и C и ассемблер одновременно), привести его к приемлемому виду(WinAVR записывает уже рассчитаные значение в jamp'ы, а не метки, так что это надо будет исправить) и убрать лишний код.

Так же советую изучить особенности компилятора и учитывать их: во-первых WinAVR крайне плохо оптимизирует работу с 16 и 32-битными(int - 16-битное число) переменными, так что их не стоит использовать при ограничения по времени работы и размеру. Во-вторых не стоит делать вызовы функций из прерываний - WinAVR в этом случае сохраняет при входе в прерывание все возможные регистры(а это около 80 тактов).
Так же стоит использовать хранение переменных в регистрах - это заметно уменьшает размер кода при работе с этой переменной:

Код: Выделить всё

register unsigned char counter1 asm ("r2");

В качестве регистров можно использовать r2-r8(от чего зависит - не знаю).
mbzyab
Родился
Сообщения: 9
Зарегистрирован: Пт фев 11, 2011 19:24:43

Re: Atmega128 тормозит? AVRStudio+Proteus

Сообщение mbzyab »

Engineer_Keen писал(а):Вы правы, это похоже на мое второе предложение, только наоборот :))) . Проблема в том, что во-первых: если в качестве Drive_Quants Си использует RAM, то для каждого изменения их значений будет тратится по 5 тактов минимум

Код: Выделить всё

//как Си переведет это на асм
LDS R16,Drive_Quants
DEC R16
STS Drive_Quants,R16

и на if еще 3 такта

Код: Выделить всё

LDS R16,Drive_Quants
CPI R16,0x00

А если использовать регистры (нам ведь нужно всего 18), то на декремент и сравнение нужно всего по одному такту. Вот поэтому я предпочитаю ассемблер.
Во-вторых, может я не так понял, но зачем уменьшать все 18 счетчиков? Пусть эти 18 значений будут постоянными, а с ними сравнивать всего 1 счетчик, который и будет уменьшаться.

Капец, вот как мне это в голову не пришло? :oops: Стыдоба :) Это я про один счетчик вместо 18
-_-
Как вы уже наверное догадались, я не очень хороший программист (мягко говоря). Я вполне искренне считал, что свободных регистров в МК нету, только служебные... пойду даташит штудировать.

Спасибо большое! (Ох стыдно-то каак :?)

ARV писал(а):http://arv.radioliga.com/content/view/150/44/ по ссылке проект 6-канального ШИМ на attiny13, в котором ВСЕ каналы синхронны.

Честно говоря (стучит по голове дубовой), не могу понять, как они там могутт быть синхронны, если они просто в цикле перебираются и при включении и при выключении :(

Впринципе, мне полная синхронность и не нужна, мне нужна равная длительность импульсов, пусть бы и со сдвигом. Или вы это и имели ввиду?
Аватара пользователя
Satyr
Друг Кота
Сообщения: 7439
Зарегистрирован: Чт ноя 04, 2010 01:56:36
Откуда: г. Москва

Re: Atmega128 тормозит? AVRStudio+Proteus

Сообщение Satyr »

Murav писал(а):Так же советую изучить особенности компилятора и учитывать их: во-первых WinAVR крайне плохо оптимизирует работу с 16 и 32-битными(int - 16-битное число) переменными

GCC компилеры вобще крайне дерьмовы в смысле оптимизации, все что попадались. WinAVR лишь оболочка к GCC.
Порой использование компиляторов IAR дает выигрышь и по скорости, и ОДНОВРЕМЕННО по объему аж в 2 раза.
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Atmega128 тормозит? AVRStudio+Proteus

Сообщение ARV »

Satyr, вы, похоже, находитесь в плену устаревших сведений :) WinAVR давным-давно отстает от IAR максимум на 15-20% по объему/скорости... повторяю - МАКСИМУМ. а иногда и опережает, но это уже трюки. во всяком случае на счет дерьмовой оптимизации я бы на вашем месте поостерегся высказываться - очень неплохая оптимизация, очень гибкая.
да, еще одно: WinAVR - это сборка GCC для AVR - а вовсе не оболочка! ваши знания позволяют усомниться в вашей компетенции...
Murav, а с вами соглашусь на счет 32-битных переменных, но вот на счет 16-битных... я бы так же не стал утверждать, что с ними оптимизатр работает "крайне плохо". и на счет функций из обработчиков прерываний тоже не стоит утверждать так однозначно - просто про волшебное слово static многие забывают (а может, и не знают)... а оно в плане оптимизации иной раз стоит очень много....
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Murav
Опытный кот
Сообщения: 877
Зарегистрирован: Чт фев 18, 2010 13:51:56

Re: Atmega128 тормозит? AVRStudio+Proteus

Сообщение Murav »

ARV писал(а):Murav, а с вами соглашусь на счет 32-битных переменных, но вот на счет 16-битных... я бы так же не стал утверждать, что с ними оптимизатр работает "крайне плохо"

Судя по всему GCC не знает, что инструкций для работы с 16 и 32-битными числами в AVR нет и в результате всегда работают с парой(или четвёркой) регистров как с одним целым. В результате постоянно к коде встречаются регистры в которые сначала записывается 0, а потом AND'ится(или производится любая другая такая же операция) с каким-нибудь ещё регистром. То же самое относится к работе с памятью - читаются/записываются значения всегда целиком, даже в случаях типа a&=0xFF . А ведь даже в случае a++ совершенно не требуется читать и записывать каждый раз старший байт(в случае оптимизации по скорости) - его нужно менять только при появлении флага переноса.
ARV писал(а):и на счет функций из обработчиков прерываний тоже не стоит утверждать так однозначно

Тем не менее прологи и эпилоги функций avr-gcc генерит явно не оптимальные: например SREG всегда сохраняется через r0, который обычно нигде в коде не используется, а так же непонятно зачем всегда обнуляет r1.
ARV писал(а):просто про волшебное слово static многие забывают (а может, и не знают)... а оно в плане оптимизации иной раз стоит очень много....

Насколько я понял имеется в виду inline? Или компилятор не видит, что в его же файле находится функция, если у неё не указано static?
ARV писал(а):WinAVR - это сборка GCC для AVR

Вообще то WinAVR - это набор из avr-gcc, binutils, gdb, avrdude и других таких же программ, скомпилённых, насколько я понимаю, с помощью MinGW, а так же библиотеки avr-libc.
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Atmega128 тормозит? AVRStudio+Proteus

Сообщение ARV »

на счет того, что 32-битные числа действительно кошмарно обрабатываются как компилятром, так и оптимизатором, я, как уже говорил, спорить и не собираюсь. а вот на счет 16 битных чисел все-таки немножко поспорю. опций оптимизации у WinAVR (точнее, у AVR-GCC) гораздо больше, чем всем известные 4. оптимизация по размеру -Os, самая популярная, пожалуй, приводит к генерации кода, как вы сказали: всегда берется старший байт переменной даже для ++, так как в случае добавления проверки на наличие переноса код уже не будет минимальным по размеру :) но есть еще множество опций тонкой настройки оптимизатора и компилятора (кто их разберет, кого именно), которые, если я не ошибаюсь, в том числе позволяют для работы с int использовать операции над ПАРАМИ регистров, вроде ADIW, что генерирует код, меньше которого уже и не придумать. так же есть и другие фичи, дающие в итоге заметную экономию памяти, просто о них многие не знают или не умеют их использовать...

а на счет r0 и r1 - тут все просто: первый регистр компилятором используется, как промежуточный, т.е. никому НИКОГДА не нужный, а второй - ВСЕГДА равен нулю. то есть ВСЕ библиотечные функции написаны исходя из того, что R1 всегда обнулен и во многих случаях это позволяет выиграть в математике.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Murav
Опытный кот
Сообщения: 877
Зарегистрирован: Чт фев 18, 2010 13:51:56

Re: Atmega128 тормозит? AVRStudio+Proteus

Сообщение Murav »

ARV писал(а):а вот на счет 16 битных чисел все-таки немножко поспорю. опций оптимизации у WinAVR (точнее, у AVR-GCC) гораздо больше, чем всем известные 4.

Что-то я не нашёл там опций, позволяющих указать компилятору, что в AVR работа в основном идёт с 8-битными данными, а не 16-битными.
ARV писал(а):оптимизация по размеру -Os, самая популярная, пожалуй, приводит к генерации кода, как вы сказали: всегда берется старший байт переменной даже для ++, так как в случае добавления проверки на наличие переноса код уже не будет минимальным по размеру

Тем не менее в режиме оптимизации -O2 генерируемый в таком случае код не менятеся. Сейчас специально проверил - a&=0xFF превратилось в два чтения из памяти, обнуление одного из регистров и две записи в память, что явно не является оптимальным ни при оптимизации по размеру ни по скорости.
ARV писал(а):если я не ошибаюсь, в том числе позволяют для работы с int использовать операции над ПАРАМИ регистров, вроде ADIW, что генерирует код, меньше которого уже и не придумать.

Эти инструкции всегда используются, если они есть в МК и вставляются они не оптимизатором, а ассемблером, который так обрабатывает операцию сложения(а если инструкции adiw нет, то он туда вставит две соответствующие инструкции вне зависимости от того можно ли обойтись одной). Кстати инструкций для работы со словами в AVR всего три: adiw, sbiw и movw и использовать их получается в очень ограниченном числе ситуаций.

И кстати при работе с памятью avr-gcc никогда кроме массивов и структур не использует косвенную адресацию(сначала загрузку адреса в регистр Y или Z, а затем обращение к соседним переменным инструкциями ldd и std), хотя это экономит место уже при трёх(а в удачных случаях и при двух) обращениях к памяти.
ARV писал(а):а на счет r0 и r1 - тут все просто: первый регистр компилятором используется, как промежуточный, т.е. никому НИКОГДА не нужный, а второй - ВСЕГДА равен нулю. то есть ВСЕ библиотечные функции написаны исходя из того, что R1 всегда обнулен и во многих случаях это позволяет выиграть в математике.

Тем не менее, если эти регистры не используются в прерывании(из которого не вызывается ни одна функция), то зачем их инициализовывать?
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Atmega128 тормозит? AVRStudio+Proteus

Сообщение ARV »

я думаю, сильно разводить споры не стоит, ибо в спорах на форумах истина не рождается, а умирает. давайте соберем какой-нибудь проектик - я в WinAVR, вы в IAR и поглядим, действительно ли результат WinAVR настолько ужасен, чтобы об этом говорить. для объективности можно взять в качестве платформы attiny13 и atmega128 - то есть один из самых мелких и один из самых "просторных" МК. только вот с проектами не ясно, откуда их брать... может, что предложите?

WinAVR, как плод коллективного труда, вероятнее всего будет уступать коммерческому продукту, но интересно разобраться, таким ли катастрофическим это отставание будет, раз уж ранее известным тестам нет доверия :)))
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Закрыто

Вернуться в «Микроконтроллеры и ПЛИС»