Разочаровали.... Это скока же надо было наделать шуму на двух форумах, чтобы родить мышь! Я читаю Ваши откровения и по-прежнему не вижу ни одного аргументированного возражения по сути приемов, предложенных коллегой avreal. Он просил (и очень справедливо) привести пример, когда его рекомендации могут привести к трудноуловимым глюкам или иным нежелательным последствиям. Конечно же, имелось в виду разумное использование рекомендаций, но Вам простилось бы даже передергивание. И я ожидал, что Вы, с огромным опытом в программировании, с высоты которого тут собралось стадо мартышек, приведете яркие примеры, а мы уж сможем научиться пользоваться калашом быть осторожными со столь непростыми приемами. Но что же мы получаем:
- общий треп по поводу стадного чувства - тривиальные замечания (да и то не свои) про goto. Оператор, которого avreal не касался вообще. Да ссылка на срач, разведенный на другом форуме. Очевидно, что ругань просто греет Вам душу. - совсем уж примитивный пример бездумного программирования с зацикливанием программы на ожидании. Да, если бы Вы сподвигнулись написать что-нибудь конструктивное и включили подобную конструкцию в свой, безусловно эпический, труд, то она имела бы право быть упомянутой. Есть новички, могущие сесть в столь очевидную лужу. Это как раз на уровне мигания светодиодом и бывает. Но! Вам бросили вызов (напоминаю, Вас назвали треплом), а на него следует ответить. Или принять к сведению и задуматься о правилах поведения.
Поэтому Ваш выверт
HHIMERA писал(а):
Предвкушая вопрос одиозных личностей "А к чему это всё?", напоминаю, тема называется "C для AVR -- пишем аккуратно."...
не катит. Вам нечего сказать по сути. Вы не можете ни уточнить предложенное автором, ни выдать сколь-нибудь вменяемые свои рекомендации.
С твоими незнаниями и туповатой упёртостью??? Уже всё сказали... и здесь и на диахтунге... Ты или читать не умеешь, или делаешь вид... Читай заново... раз пять...
Код:
тривиальные замечания (да и то не свои) про goto.
"Всё уже придумано до нас!" (С) Было бы странно, если бы я заявил, что замечания мои, и goto тоже придумал я...
_________________ "Я не даю готовых решений, я заставляю думать!"(С)
Последний раз редактировалось HHIMERA Сб сен 22, 2012 10:54:08, всего редактировалось 1 раз.
Ничего в ней полезного нет... Для новичков нужно писать более развёрнуто и с акцентом на возможные неприятности... и это не каждому под силу...
Да где уж мне, в лаптях да по паркету. Вот уже «больше одного» знатока разродились на «акцент на возможные неприятности»: «напихивание static куда попало может привести» к каким-то химерным «трудноуловимым глюкам». Может, в их практике такое и было. И теперь гордятся тайным знанием. Но я вечно что-то делаю не так и у меня таких глюков не было, видать, я сам тут начинающий и мне тоже нужно объяснить «более развернуто». А вот это им уже «лениво» (трындеть — не мешки ворочать), так на реальный пример до сих пор и не разродились. Чем глубокомысленнее и туманнее намёк на «возможные» опасности, после чего «с учёным видом знатока хранить молчанье в важном споре», тем легче прослыть знатоком, шаманом? Проще напустить туману, «когда-нибудь вы все узнаете»? Ну так скажите сейчас. (хлопая в ладоши) Просим, просим, просим!
p.s. Пассаж про «если привыкнуть ставить static к функциям, то начнёшь их лепить и к переменным» в теме на easyelectronics мне вообще понравился . Это ж насколько бездумно нужно писать, чтобы такое началось? Может, пора от них ножи и вилки прятать? А то, привыкнув тыкать ими в котлету, они ткнут ими в соседа за столом?
_________________ Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
Вот уже «больше одного» знатока разродились на «акцент на возможные неприятности»: «напихивание static куда попало может привести» к каким-то химерным «трудноуловимым глюкам». Может, в их практике такое и было. И теперь гордятся тайным знанием.
Цитата:
Ну так скажите сейчас. (хлопая в ладоши) Просим, просим, просим!
Цитата:
p.s. Пассаж про «если привыкнуть ставить static к функциям, то начнёшь их лепить и к переменным» в теме на easyelectronics мне вообще понравился .
это все в мой огород. да, я "слегка" преувеличил. но делал это сознательно. вон, на изиэлектрониксе drvlas буквально вчера спросил "горячий рестарт на авр - как?" и это после твоего более чем исчерпывающего объяснения. согласись, не дело. и я эмоционально вовлекал собеседников с одной целью - чтобы отложилось в памяти хоть место, где обсуждалось. видно, не удалось, к сожалению...
Проектик на MEGA8 постепенно приближается к 8кб коду (ну пока 6092) но еще надо встроить несколько ресурсоемких вещей. Поэтому начал уже сейчас кумекать, что можно подправить, чтобы места освободить..... Пришла идея (гдето раньше попадалось на глаза) переменные с флагами (т.к. к ним частое обращение в разных местах) перенести в область портов. У меня было 2 байта с флагами:
Код:
//ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ volatile char Flags1 = 0; //байт флагов №1 #define b1DispFlash (1<<0) /*флаг включения мигающего режима дисплея*/ #define b1OneWireStart (1<<1) /*флаг необходимости старта команды преобразования температуры в 1wire устройствах*/ #define b1OneWireData (1<<2) /*флаг необходимости считать данные температуры*/ #define b1ClockRead (1<<3) /*флаг чтения данных времени с МС часов 10 раз\сек*/ #define b1ClockDot (1<<4) /*флаг включения мигающей точки часов*/ #define b1BeepAlarmOn (1<<5) /*флаг включения зуммера*/ #define b1StartDevice (1<<6) /*флаг необходимости внесения записи в EEPROM о подаче питания на устройство*/
Перенес эти 2 байта флагов в регистры работы с внутренней EEPROM - EEARL, EEDR (внутренняя у меня не используется т.к. имеется внешня флэш на 8Кб - 24C64) получилось так:
Код:
//ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ #define Flags1 EEARL /*байт флагов №1 будет размещатся в регистре EEARL (т.к. внутренняя EEPROM не исп-ся)*/ #define b1DispFlash (1<<0) /*флаг включения мигающего режима дисплея*/ #define b1OneWireStart (1<<1) /*флаг необходимости старта команды преобразования температуры в 1wire устройствах*/ #define b1OneWireData (1<<2) /*флаг необходимости считать данные температуры*/ #define b1ClockRead (1<<3) /*флаг чтения данных времени с МС часов 10 раз\сек*/ #define b1ClockDot (1<<4) /*флаг включения мигающей точки часов*/ #define b1BeepAlarmOn (1<<5) /*флаг включения зуммера*/ #define b1StartDevice (1<<6) /*флаг необходимости внесения записи в EEPROM о подаче питания на устройство*/
Что вы думаете..... сразу 300 байт высвободилось..... стало 5774 байта
Кто нибудь такое вытворял? Интересно, какие еще регистры портов можно задействовать..... Можно было бы и другие часто используемые переменные туда ныкать.....
shads, во втором варианте у вас нет атрибута volatile. Как результат - уменьшился код прошивки, так как компилятор смог что-то оптимизировать. Можно было и в исходном коде убрать volatile - прошивка тоже бы уменьшилась. Если вам volatile реально нужен и вы его вернёте в варианте с регистрами EEPROM, то размер может вырасти опять.
_________________ Когда уже ничего не помогает - прочтите, наконец, инструкцию. Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII) Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Можно было и в исходном коде убрать volatile - прошивка тоже бы уменьшилась.
В исходном коде низя убирать volatile, т.к. флаги еще в прерывании используются. А вообще (ради чтобы проверить) пробовал убрать volatile, код уменьшился всего на 70 байт.....
Kavka писал(а):
Если вам volatile реально нужен и вы его вернёте в варианте с регистрами EEPROM, то размер может вырасти опять.
Помоему к регистрам портов нет смысла указывать volatile, т.к. они итак в волатильном режиме работают.....
Про volatile и регистры в/в - да, тут я дал маху. Признаю. Был повод повторно проштудировать sfr_defs.h.
_________________ Когда уже ничего не помогает - прочтите, наконец, инструкцию. Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII) Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Ув. avreal с удовольствием читаю Ваш мастер-класс по C, правда хочу сделать маленькое, но как мне кажется полезное замечание по работе с EEPROM:
avreal писал(а):
Не ленимся и пишем свои функции, принимающие 8-битный номер ячейки. Тоже NOINLINE, так как иначе некоторые версии компилятора их встраивают (особенно Read, она совсем короткая).
Ваша функция записи в EEPROM:
Код:
static void EEWrite(uint8_t addr, uint8_t data) { while (EECR & (1<<EEPE)) ; EECR = (0 << EEPM1) | (0 << EEPM0); EEAR = addr; EEDR = data; // Теперь уже в запись может влезть прерывание, запрещаем на время запуска CLI(); EECR |= (1 << EEMPE); EECR |= (1 << EEPE); SEI(); }
Функция разрешает прерывания независимо от того были они запрещены до этого или нет. Т.е. она справедлива для частного случая, где прерывания разрешены всегда. Предлагаю немного измененный вариант для универсального применения:
Код:
static void EEWrite(uint8_t addr, uint8_t data) { while (EECR & (1<<EEWE)); EECR = (0 << EEPM1) | (0 << EEPM0); EEAR = addr; EEDR = data; // Теперь уже в запись может влезть прерывание, запрещаем на время запуска uint8_t srbuf = SREG; cli(); EECR |= (1 << EEMWE); EECR |= (1 << EEWE); SREG = srbuf; }
OS_main/OS_task On AVR, functions with the OS_main or OS_task attribute do not save/restore any call-saved register in their prologue/epilogue.
The OS_main attribute can be used when there is guarantee that interrupts are disabled at the time when the function is entered. This will save resources when the stack pointer has to be changed to set up a frame for local variables.
The OS_task attribute can be used when there is no guarantee that interrupts are disabled at that time when the function is entered like for, e.g. task functions in a multi-threading operating system. In that case, changing the stack pointer register will be guarded by save/clear/restore of the global interrupt enable flag.
OS_main и OS_task указывают компилятору, что процедура не сохраняет и не восстанавливает регистры. Это можно сделать, так как main ниоткуда не вызывается и из процедуры никогда не "выходиться" (так как внутри "вечный" цикл). Обычная процедура должна это делать. В итоге экономиться чуть-чуть памяти. OS_main - если гарантируется, что прерывания запрещены. Иначе OS_task.
_________________ Когда уже ничего не помогает - прочтите, наконец, инструкцию. Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII) Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Вложенные прерывания, avr-gcc, avr-libc. Часто видел запись такого вида.
Код:
ISR(PCINT0_vect) { sei(); .......... }
Команда разрешения прерывания будет после пролога. Но там где надо задержку сделать минимальной есть лучший способ, с меньшей задержкой. Тактов на 5-6 минимум (avr-gcc 4.7). Не много, но кому-то может пригодиться.
Код:
ISR_NOBLOCK ISR(PCINT0_vect) { .......... }
ISR_NOBLOCK определено в avr/interrupt.h из avr-libc (WinAVR или AVR toolchain) как __attribute__((interrupt)) В этом случае команда разрешения прерывания будет вставлена компилятором, и она будет первой в прологе процедуры.
_________________ Когда уже ничего не помогает - прочтите, наконец, инструкцию. Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII) Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 9
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения