Atmega8 LTO (перенос кода с ардуино)

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Приветствую всех, это даже не вопрос - а спросить совет. 

Так как в очередном проекте «целую 328ю ардуину нано использовать жалко», решил купить atmega8 (она и дешевле). Для компиляции проекта использовал MiniCore ядро. Но! Не могу понять (атмега8 ещё едет), после установки MiniCore появилось много дополнительных настроек. Одна из них LTO. Как я понял из гугла - это оптимизатор, не уменьшающий скорость работы кода, но сокращающий объём исполняемо кода. При включении данной опции мой код сократился на 1кб с лишним (что существенно). 

Собственно вопрос - включать данную опцию или нет? Может кто более детально сможет объяснить в чем сокральный смысл оптимизации (ну так, по простому)? Достаточно просто ответов - используй ее или наоборот. То есть целый 1 килобайт из 8 сохранить для дополнительного кода круто, но чем это чревато? Или как? Я запутался...

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

BOOM пишет:

в чем сокральный смысл

сокрали фсё просто. так и живем.

ЗЫ: пипец! еще одного в гугле забанили.... шо "корпорация добра" делает!!! уму не постижимо!

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Вы обычным, из коробки, IDE для какой-нибудь UNO пользовались?

Так вот там LTO включено безо всяких опций.

compiler.cpp.flags=-c -g -Os {compiler.warning_flags} -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -MMD -flto

Если пользовалиcь и пока ещё живы, то пользуйтесь и дальше.

Вот здесь я кратко объяснял что такое LTO

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

В след. раз заказывай Atmega88.  По поведению/регистрам/программированию не отличается от 328, а просто 8 имеет в некоторых моментах существенные различия. 

А по LTO - я всегда включаю. Ну, и тебе советую.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Спасибо всем ответившим, считаю вопрос закрытым. 
ЗЫ: Дракула, хороший человек, опечатался я (или ошибся). Прошу прощения. 

Green
Offline
Зарегистрирован: 01.10.2015

Зато мега8 откалибрована при 5в intrc 1мгц!) Для самоделок временами можно и без кварца.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Да я и на 88 ни разу кварец не ставил.  И она, кста, на 3.3В прекрасно работает на своих 8 МГц. 

Green
Offline
Зарегистрирован: 01.10.2015

Да, 88-я как раз таки на 3в и калибруется. А вот на 5в иногда приходится подстраивать.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

DetSimen пишет:

просто 8 имеет в некоторых моментах существенные различия. 

Кажется я понял о чем ты говорил.

Компилирую (ради интереса) проект с энкодером под ATmega8. На 328й меге для работы прерываний (энкодер подключен к выводам 2 и 3 платы ардуино нано) использую вот такой код:

#include <Rotary.h>

#define ENCODER_A    2                                // Encoder pin A
#define ENCODER_B    3                                // Encoder pin B

Rotary r = Rotary(ENCODER_A, ENCODER_B);

int8_t flagStep;

void setup() {

  PCICR |= (1 << PCIE2);                              // |
  PCMSK2 |= (1 << PCINT18) | (1 << PCINT19);          // | Нужно для работы прерываний ISR (PCINT2_vect)
  sei();                                              // |
}

ISR(PCINT2_vect) {                   

  unsigned char result = r.process();  
  if (result == DIR_CW){
    flagStep = 1;
  } else if (result == DIR_CCW) {
    flagStep = -1;
  }
}

void loop() {
  // что-то делаем
}

При компиляции получаю вот такие ошибки:

In function 'void setup()':
error: 'PCICR' was not declared in this scope
   PCICR |= (1 << PCIE2);                              // |

note: suggested alternative: 'ACIC'
   PCICR |= (1 << PCIE2);                              // |
   ACIC

error: 'PCIE2' was not declared in this scope
   PCICR |= (1 << PCIE2);                              // |

note: suggested alternative: 'OCIE2'
   PCICR |= (1 << PCIE2);                              // |
                  OCIE2

error: 'PCMSK2' was not declared in this scope
   PCMSK2 |= (1 << PCINT18) | (1 << PCINT19);          // | Нужно для работы прерываний ISR (PCINT2_vect)

note: suggested alternative: 'CS12'
   PCMSK2 |= (1 << PCINT18) | (1 << PCINT19);          // | Нужно для работы прерываний ISR (PCINT2_vect)
   CS12

error: 'PCINT18' was not declared in this scope
   PCMSK2 |= (1 << PCINT18) | (1 << PCINT19);          // | Нужно для работы прерываний ISR (PCINT2_vect)

note: suggested alternative: 'INT1'
   PCMSK2 |= (1 << PCINT18) | (1 << PCINT19);          // | Нужно для работы прерываний ISR (PCINT2_vect)
                   INT1

error: 'PCINT19' was not declared in this scope
   PCMSK2 |= (1 << PCINT18) | (1 << PCINT19);          // | Нужно для работы прерываний ISR (PCINT2_vect)

note: suggested alternative: 'INT1'
   PCMSK2 |= (1 << PCINT18) | (1 << PCINT19);          // | Нужно для работы прерываний ISR (PCINT2_vect)
                                    INT1
exit status 1
'PCICR' was not declared in this scope

Дальше я полез в интернет и "накопал" другой код. Деда, посмотри пожалуйста, правильно я все сделал?

#include <Rotary.h>

#define ENCODER_A    2                                // Encoder pin A
#define ENCODER_B    3                                // Encoder pin B

Rotary r = Rotary(ENCODER_A, ENCODER_B);

int8_t  flagStep;

void setup() {

  GICR |= (1 << INT0) | (1 << INT1);                                           // |
  MCUCR |= (1 << ISC00) | (1 << ISC01) | (1 << ISC10) | (1 << ISC11);          // | Нужно для работы прерываний ISR на ATmega8A
  sei();                                                                       // |
}

ISR(INT0_vect) {                   

  unsigned char result = r.process();  
  if (result == DIR_CW){
    flagStep = 1;
  } else if (result == DIR_CCW) {
    flagStep = -1;
  }
}

void loop () {

}

Просто ATmega8A еще едут из китая, проверить нет возможности.  Но код стал прекрасно компилироваться:

Скетч использует 5616 байт (68%) памяти устройства. Всего доступно 8192 байт.
Глобальные переменные используют 536 байт (52%) динамической памяти, оставляя 488 байт для локальных переменных. Максимум: 1024 байт

Я, пока еще, не понимаю все эти регистры и тп. :-(

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Код пока не смотрел, но сказать хочу.

Atmega8  это древняя серия, можно сказать, родоначальнег Atmega16 и Atmega32.  У их опорное напряжение ADC 2.56В, таймер0 не имеет режима работы по совпадению, WDT работает через жо, и т.д.  А вот Atmega88 какрас рашшыряется до 168 и 328 вапще без проблем, ибо кроме памяти в 8Кб ничем от их не отличается.    

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Знать бы это перед тем как заказывать... ((( Ну уже поздно, буду пока ATmega8A пользовать... (((

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

BOOM пишет:

Знать бы это перед тем как заказывать... ((( Ну уже поздно, буду пока ATmega8A пользовать... (((

Не сы, Atmega8 тоже годная для поделок, у мня на их и бочка в теплице наполняется и приемники работают. 

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Все же я посмотрел даташит (на сколько мне сейчас мозгов хватает на него смотреть: https://static.chipdip.ru/lib/292/DOC000292159.pdf ) и изменил код в setup ():

  GICR |= (1 << INT0) | (1 << INT1);                                           // | Нужно для работы прерываний ISR - ATmega8A
  MCUCR &= ~((1 << ISC00) | (1 << ISC01) | (1 << ISC10) | (1 << ISC11));       // | Сбрасываем биты ISCxx в "ноль"
  MCUCR |= (1 << ISC00) | (0 << ISC01) | (1 << ISC10) | (0 << ISC11);          // | Устанавливаем срабатывание по любому изменению логического уровня (для Encoder это же самое "то"?)
  sei();                                                                       // | Разрешаем глобальные прерывания

Я думаю - так правильнее будет, если я верно даташит понял?

А ещё, если можно, простыми словами объясните что происходит когда применяются операторы:

| = ()
&= ~ ()

 

nik182
Offline
Зарегистрирован: 04.05.2015

Биты установить и биты сбросить по маске, которая в скобочках. 

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Спасибо. А сами "настройки" из #12 правильно установил?

nik182
Offline
Зарегистрирован: 04.05.2015

А кто ж его знает. Вернее кто с восьмёркой работал может знает. Я нет.

Вот только хочу предупредить что в строке

MCUCR |= (1 << ISC00) | (0 << ISC01) | (1 << ISC10) | (0 << ISC11); 

нолики ставят исключительно что бы помнить какие биты куда пошли. На конечный результат они не влияют. Больше того, если в регистре была единица, она единицей и останется.  

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

nik182 пишет:

А кто ж его знает. Вернее кто с восьмёркой работал может знает. Я нет.

Вот только хочу предупредить что в строке

MCUCR |= (1 << ISC00) | (0 << ISC01) | (1 << ISC10) | (0 << ISC11); 

нолики ставят исключительно что бы помнить какие биты куда пошли. На конечный результат они не влияют. Больше того, если в регистре была единица, она единицей и останется.  

Я чтобы не забыть и оставил их, а предварительно все в ноль сбрасываю строкой выше (ну как я понял).

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Мда, нада деда ждать. Он точно с ней работал.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

А вопрос то в чём?

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Смысл ждать камни, если в Proteus есть Atmega8 ? Хоть обтестируйся ...

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

BOOM пишет:

nik182 пишет:

А кто ж его знает. Вернее кто с восьмёркой работал может знает. Я нет.

Вот только хочу предупредить что в строке

MCUCR |= (1 << ISC00) | (0 << ISC01) | (1 << ISC10) | (0 << ISC11); 

нолики ставят исключительно что бы помнить какие биты куда пошли. На конечный результат они не влияют. Больше того, если в регистре была единица, она единицей и останется.  

Я чтобы не забыть и оставил их, а предварительно все в ноль сбрасываю строкой выше (ну как я понял).

А сбрасывать в 0 строкой выше вовсе необязательно. Гораздо проще в текущей строке заменить "|=" на "=".

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

DetSimen пишет:

А вопрос то в чём?

Вопрос: Правильно ли я выставил "биты" в #12 для активации внешних прерываний (у пинов, куда подключен энкодер)?

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Я не знаю, отродясь энкодер на прерывания не вешал. Опрашиваю его раз в 5 мс, да и сё. 

nik182
Offline
Зарегистрирован: 04.05.2015

andriano пишет:

А сбрасывать в 0 строкой выше вовсе необязательно. Гораздо проще в текущей строке заменить "|=" на "=".

Так то оно да, но регистр 8 бит и поменяв на = обнулите остальные биты. Если они нули то ладно, а если нет?

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

nik182 пишет:

andriano пишет:

А сбрасывать в 0 строкой выше вовсе необязательно. Гораздо проще в текущей строке заменить "|=" на "=".

Так то оно да, но регистр 8 бит и поменяв на = обнулите остальные биты. Если они нули то ладно, а если нет?

Тоже не читатель, а писатель?

Ясно же написано:

BOOM пишет:

...а предварительно все в ноль сбрасываю

 

Upd. Приношу свои извинения, это я не читатель, а писатель - поверил человеку на слово, не проверив, что на словах и в коде у него далеко не одно и то же.

PS. Кстати, на STM32 эта операция решена изящно - там одновременную установку и в нули, и в единицы можно осуществить единственной записью в порт.

nik182
Offline
Зарегистрирован: 04.05.2015

Не во всех. В f1 можно. В f4 регистр поделили и одной записью стало невозможно.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

DetSimen пишет:

Я не знаю, отродясь энкодер на прерывания не вешал. Опрашиваю его раз в 5 мс, да и сё. 

Можно пример кода как это выглядит?

Я, уже и не помню почему, на внешние прерывания энкодер всегда «вешаю» и все отлично работает. 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

BOOM пишет:

Можно пример кода как это выглядит?

Да прямо вот так 

void loop()
{
    Timers.Run();

    Encoder.Read();

    if (MessageList.Available()) Dispatch(MessageList.GetMessage());
}

 

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Походу я не догоняю еще такое решение, поэтому на прерываниях все еще :-D

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Так как энкодер это не независимый класс, а унаследованный, текст его приводить смысла нет.  Найди тут dtsLibAll\src файл dtsEncoder.h  и  пробежы глазами, если охота. 

nik182
Offline
Зарегистрирован: 04.05.2015

Дед! Напиши на mail.ru. Надо обсудить кое что.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Дак я не знаю твой mail.ru.  Мой - dap68@mail.ru    :)))

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

DetSimen пишет:

Дак я не знаю твой mail.ru.  Мой - dap68@mail.ru    :)))

не из наших ты...nik182 попробуй )))

SAB
Offline
Зарегистрирован: 27.12.2016

 

nik182 пишет:
Дед! Напиши на mail.ru. Надо обсудить кое что.

Так и вспоминается рассказ А. П. Чехова «Ванька» (1886 г.).......На деревню дедушке...:)))) Напиши на mail.ru прямо в меморис.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

ua6em пишет:
nik182 попробуй )))

Чессно говоря, пока некада мне пробовать, я коробки клею, в пятницу сдавать. 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

DetSimen пишет:

ua6em пишет:
nik182 попробуй )))

Чессно говоря, пока некада мне пробовать, я коробки клею, в пятницу сдавать. 

автоматизировал уже бы

Green
Offline
Зарегистрирован: 01.10.2015

SAB пишет:
Напиши на mail.ru прямо в меморис.


Ну не Добродееву же! А всего лишь нику182.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

DetSimen пишет:

ua6em пишет:
nik182 попробуй )))

Чессно говоря, пока некада мне пробовать, я коробки клею, в пятницу сдавать. 

На кондитерской фабрике работал давным давно. Так там под Новый год все отделы напрягали по 2000 коробок «собрать» для новогодних подарков. Ад какой то )))) А в феврале, оставшиеся не проданными, нужно было распаковать, конфеты в одну сторону - коробки разобрать и сложить. Капец блин )))))

Дед, ты конфетами торгуешь?)))

b707
Offline
Зарегистрирован: 26.05.2017

nik182 пишет:
Не во всех. В f1 можно. В f4 регистр поделили и одной записью стало невозможно.

 

На каких F1 и F4? Если брать самые распространенные F103 и F401, то вообще-то все ровно наоборот.

nik182
Offline
Зарегистрирован: 04.05.2015

Какие будут ваши доказательства?
Из описания f103: С GPIOx_BSRR всё чуть интереснее, младшие 16 бит отвечают за установку 1, старшие 16 бит за сброс в 0. Чтобы установить 1 в нулевой бит, надо в нулевой бит GPIOx_BSRR записать 1. Чтобы установить 0 в нулевой бит, надо в 16 бит установить 1.
В f411 тоже есть такой регистр. BRR нет. Вот на эти грабли я наступил. И за давностью лет всё перепутал. Приходится брать слова обратно. Оба могут одной 32 битной командой сбрасывать и устанавливать.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

BOOM пишет:
Дед, ты конфетами торгуешь?)))

Нет. 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

DetSimen пишет:

BOOM пишет:
Дед, ты конфетами торгуешь?)))

Нет. 

обломал, новый года на носу )))

b707
Offline
Зарегистрирован: 26.05.2017

nik182 пишет:
Какие будут ваши доказательства?.

уже полез искать доказательства :) - в частоности референс на F401. пункт 8.3.5 - но Вы и сами поправились

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Наверное сейчас глупость спрошу, но куда деваться?

Забрал я с почты Atmega8A сегодня. Решил проверить - прекрасно читаются и шьются. Ну и решил «моргалку» для теста загрузить:

void setup() {
  pinMode(PB0, OUTPUT);
}

void loop() {
  digitalWrite(PB0, HIGH);  
  delay(1000);
  digitalWrite(PB0, LOW);
  delay(1000);
}

Ну и сначала долго не понимал, почему все прекрасно компилируется, но не работает?

Полез в интернет и нашел, что объявлять пины нужно по другому (ну то есть даже два варианта) - по номерам выводов ардуино и вот так:

void setup() {
  pinMode(PIN_PB0, OUTPUT);
}

void loop() {
  digitalWrite(PIN_PB0, HIGH);  
  delay(1000);
  digitalWrite(PIN_PB0, LOW);
  delay(1000);
}

А что это за "макросы" тогда такие и где (как) их применять? Имею ввиду вот это:

PB0, PB1 .. PB7
PC0, PC1 .. PC7
PD0, PD1 .. PD7

Они точно как-то описаны, но я не нашел как именно. Прошу прощения, за возможно, глупый вопрос. :-)

nik182
Offline
Зарегистрирован: 04.05.2015

c:\Users\user\Documents\ArduinoData\packages\arduino\hardware\avr\1.8.4\variants\standard и вокруг. Лежат файлы pins_arduino.h для установленных плат. 

ddr2
Offline
Зарегистрирован: 27.12.2020

Полноценный проект невозможно перенести с Атмега328 на Атмега8, так недостаточно ОЗУ, даже на Атмега328. 

Проекты надо переносить на Атмегу128, для этого их и сделали, это даст возможность расширять и добавлять новые функции ) 

Даже на Атмеге328 приходится изворачиваться чтобы влезть в 2к ОЗУ, усложняя и урезая код, так что Атмега16 и Атмега8 это не для проектов. 

 

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

nik182 пишет:

c:\Users\user\Documents\ArduinoData\packages\arduino\hardware\avr\1.8.4\variants\standard и вокруг. Лежат файлы pins_arduino.h для установленных плат. 

Может плохо смотрел, но что-то я в этих .h файлах не нашёл этого описания (кстати, описание по типу PIN_PB0, имеется). Получается где-то в другом месте они описаны?

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

ddr2 пишет:

Полноценный проект невозможно перенести с Атмега328 на Атмега8, так недостаточно ОЗУ, даже на Атмега328.

Плохому танцору всегда что-то мешает )))))

Конечно же еще не все написано, но куда такому проекту 328ю? Жалко просто...

Скетч использует 2786 байт (34%) памяти устройства. Всего доступно 8192 байт.
Глобальные переменные используют 112 байт (11%) динамической памяти, оставляя 912 байт для локальных переменных. Максимум: 1024 байт.

 

ddr2
Offline
Зарегистрирован: 27.12.2020

Это не проект, это скетч, тест, хелоу-ворлд)) 

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Нужные функции выполняет, а вы можете и дальше демагогию разводить, если сказать по теме нечего.

Green
Offline
Зарегистрирован: 01.10.2015

Та нормальные эти Мега8, жалко только PCINT нету, в отличие от 88-х. А так всё класс.