C для AVR -- пишем аккуратно.

Обсуждаем контроллеры компании Atmel.
Ответить
Родился
Аватара пользователя
Сообщения: 14
Зарегистрирован: Пн апр 19, 2010 12:42:13

Сообщение drvlas »

Разочаровали.... Это скока же надо было наделать шуму на двух форумах, чтобы родить мышь!
Я читаю Ваши откровения и по-прежнему не вижу ни одного аргументированного возражения по сути приемов, предложенных коллегой avreal. Он просил (и очень справедливо) привести пример, когда его рекомендации могут привести к трудноуловимым глюкам или иным нежелательным последствиям. Конечно же, имелось в виду разумное использование рекомендаций, но Вам простилось бы даже передергивание. И я ожидал, что Вы, с огромным опытом в программировании, с высоты которого тут собралось стадо мартышек, приведете яркие примеры, а мы уж сможем научиться пользоваться калашом быть осторожными со столь непростыми приемами.
Но что же мы получаем:

- общий треп по поводу стадного чувства
- тривиальные замечания (да и то не свои) про goto. Оператор, которого avreal не касался вообще. Да ссылка на срач, разведенный на другом форуме. Очевидно, что ругань просто греет Вам душу.
- совсем уж примитивный пример бездумного программирования с зацикливанием программы на ожидании. Да, если бы Вы сподвигнулись написать что-нибудь конструктивное и включили подобную конструкцию в свой, безусловно эпический, труд, то она имела бы право быть упомянутой. Есть новички, могущие сесть в столь очевидную лужу. Это как раз на уровне мигания светодиодом и бывает. Но! Вам бросили вызов (напоминаю, Вас назвали треплом), а на него следует ответить. Или принять к сведению и задуматься о правилах поведения.

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

Ну и Бог с Вами. Трепитесь далее.
Реклама
Друг Кота
Сообщения: 4583
Зарегистрирован: Вс дек 05, 2010 06:10:34
Откуда: ЮВ

Сообщение HHIMERA »

drvlas писал(а):Разочаровали....
С твоими незнаниями и туповатой упёртостью??? :)))
Уже всё сказали... и здесь и на диахтунге... Ты или читать не умеешь, или делаешь вид...
Читай заново... раз пять... :)))

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

тривиальные замечания (да и то не свои) про goto. 
"Всё уже придумано до нас!" (С)
Было бы странно, если бы я заявил, что замечания мои, и goto тоже придумал я... :)))
Последний раз редактировалось HHIMERA Сб сен 22, 2012 10:54:08, всего редактировалось 1 раз.
"Я не даю готовых решений, я заставляю думать!"(С)
Реклама
Друг Кота
Сообщения: 4583
Зарегистрирован: Вс дек 05, 2010 06:10:34
Откуда: ЮВ

Сообщение HHIMERA »

drvlas писал(а): Но! Вам бросили вызов (напоминаю, Вас назвали треплом), а на него следует ответить. Или принять к сведению и задуматься о правилах поведения.
Тогда напомню тебе... трепло здесь только ТЫ... т.к. абсолютно не владея предметом спора пытаешься расставить акценты и оценки... :)))
"Я не даю готовых решений, я заставляю думать!"(С)
Встал на лапы
Сообщения: 142
Зарегистрирован: Вс фев 05, 2012 11:41:07

Сообщение led_fan »

ёпта.
пришел "парень с призрачным ником" и обосрал безусловно полезную образовательную работу....
Реклама
Эиком - электронные компоненты и радиодетали
Друг Кота
Сообщения: 4583
Зарегистрирован: Вс дек 05, 2010 06:10:34
Откуда: ЮВ

Сообщение HHIMERA »

Ничего в ней полезного нет...
Для новичков нужно писать более развёрнуто и с акцентом на возможные неприятности... и это не каждому под силу...
"Я не даю готовых решений, я заставляю думать!"(С)
Реклама
Опытный кот
Аватара пользователя
Сообщения: 842
Зарегистрирован: Чт дек 31, 2009 19:27:45
Откуда: Бровари, Україна

Сообщение avreal »

HHIMERA писал(а):Ничего в ней полезного нет...
Для новичков нужно писать более развёрнуто и с акцентом на возможные неприятности... и это не каждому под силу...
Да где уж мне, в лаптях да по паркету.
Вот уже «больше одного» знатока разродились на «акцент на возможные неприятности»: «напихивание static куда попало может привести» к каким-то химерным «трудноуловимым глюкам». Может, в их практике такое и было. И теперь гордятся тайным знанием.
Но я вечно что-то делаю не так и у меня таких глюков не было, видать, я сам тут начинающий и мне тоже нужно объяснить «более развернуто».
А вот это им уже «лениво» (трындеть — не мешки ворочать), так на реальный пример до сих пор и не разродились.
Чем глубокомысленнее и туманнее намёк на «возможные» опасности, после чего «с учёным видом знатока хранить молчанье в важном споре», тем легче прослыть знатоком, шаманом?
Проще напустить туману, «когда-нибудь вы все узнаете»?
Ну так скажите сейчас. (хлопая в ладоши) Просим, просим, просим!

p.s. Пассаж про «если привыкнуть ставить static к функциям, то начнёшь их лепить и к переменным» в теме на easyelectronics мне вообще понравился :))). Это ж насколько бездумно нужно писать, чтобы такое началось? Может, пора от них ножи и вилки прятать? А то, привыкнув тыкать ими в котлету, они ткнут ими в соседа за столом?
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
Контактная информация:
Реклама
Друг Кота
Сообщения: 4583
Зарегистрирован: Вс дек 05, 2010 06:10:34
Откуда: ЮВ

Сообщение HHIMERA »

avreal
Тебе скучно... превирать потихоньку начал??? :)))
Не уподобляйся drvlas'у...
"Я не даю готовых решений, я заставляю думать!"(С)
Встал на лапы
Сообщения: 142
Зарегистрирован: Вс фев 05, 2012 11:41:07

Сообщение led_fan »

avreal писал(а):Да где уж мне, в лаптях да по паркету.
не обращай внимания.
Вот уже «больше одного» знатока разродились на «акцент на возможные неприятности»: «напихивание static куда попало может привести» к каким-то химерным «трудноуловимым глюкам». Может, в их практике такое и было. И теперь гордятся тайным знанием.
Ну так скажите сейчас. (хлопая в ладоши) Просим, просим, просим!
p.s. Пассаж про «если привыкнуть ставить static к функциям, то начнёшь их лепить и к переменным» в теме на easyelectronics мне вообще понравился :))).
это все в мой огород. ;)
да, я "слегка" преувеличил. но делал это сознательно.
вон, на изиэлектрониксе drvlas буквально вчера спросил "горячий рестарт на авр - как?" и это после твоего более чем исчерпывающего объяснения. согласись, не дело.
и я эмоционально вовлекал собеседников с одной целью - чтобы отложилось в памяти хоть место, где обсуждалось. видно, не удалось, к сожалению...
Опытный кот
Аватара пользователя
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

Сообщение shads »

Проектик на 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 о подаче питания на устройство*/

volatile char BtnFlags = 0;						//байт флагов кнопок
	#define ShortUp			(1<<0)				/*бит короткого нажатия кнопки вверх*/ 
	#define ShortLeft		(1<<1)				/*бит короткого нажатия кнопки вниз*/ 
	#define ShortDown		(1<<2)				/*бит короткого нажатия кнопки влево*/ 
	#define ShortRight		(1<<3)				/*бит короткого нажатия кнопки вправо*/ 
	#define LongUp			(1<<4)				/*бит длиного нажатия кнопки вверх*/ 
	#define LongLeft		(1<<5)				/*бит длиного нажатия кнопки вниз*/ 
	#define LongDown		(1<<6)				/*бит длиного нажатия кнопки влево*/ 
	#define LongRight		(1<<7)				/*бит длиного нажатия кнопки вправо*/ 
Перенес эти 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 о подаче питания на устройство*/

#define BtnFlags EEDR                            /*байт флагов кнопок будет размещатся в регистре EEDR (т.к. внутренняя EEPROM не исп-ся)*/
    #define ShortUp            (1<<0)                /*бит короткого нажатия кнопки вверх*/ 
    #define ShortLeft        (1<<1)                /*бит короткого нажатия кнопки вниз*/ 
    #define ShortDown        (1<<2)                /*бит короткого нажатия кнопки влево*/ 
    #define ShortRight        (1<<3)                /*бит короткого нажатия кнопки вправо*/ 
    #define LongUp            (1<<4)                /*бит длиного нажатия кнопки вверх*/ 
    #define LongLeft        (1<<5)                /*бит длиного нажатия кнопки вниз*/ 
    #define LongDown        (1<<6)                /*бит длиного нажатия кнопки влево*/ 
    #define LongRight        (1<<7)                /*бит длиного нажатия кнопки вправо*/ 

Flags1 = 0;									//флаговые байты - инициализация
BtnFlags = 0; 
Что вы думаете..... сразу 300 байт высвободилось..... стало 5774 байта

Кто нибудь такое вытворял? Интересно, какие еще регистры портов можно задействовать.....
Можно было бы и другие часто используемые переменные туда ныкать.....
Мудрый кот
Аватара пользователя
Сообщения: 1810
Зарегистрирован: Чт июн 10, 2010 08:55:35
Откуда: Сибирские Афины

Сообщение Kavka »

shads, во втором варианте у вас нет атрибута volatile.
Как результат - уменьшился код прошивки, так как компилятор смог что-то оптимизировать.
Можно было и в исходном коде убрать volatile - прошивка тоже бы уменьшилась.
Если вам volatile реально нужен и вы его вернёте в варианте с регистрами EEPROM, то размер может вырасти опять.
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Опытный кот
Аватара пользователя
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

Сообщение shads »

Kavka писал(а):Можно было и в исходном коде убрать volatile - прошивка тоже бы уменьшилась.
В исходном коде низя убирать volatile, т.к. флаги еще в прерывании используются. А вообще (ради чтобы проверить) пробовал убрать volatile, код уменьшился всего на 70 байт.....
Kavka писал(а):Если вам volatile реально нужен и вы его вернёте в варианте с регистрами EEPROM, то размер может вырасти опять.
Помоему к регистрам портов нет смысла указывать volatile, т.к. они итак в волатильном режиме работают.....
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 1900
Зарегистрирован: Сб фев 21, 2009 13:11:40
Откуда: Москва

Сообщение ibiza11 »

регистры периферии везде объявлены как volatile
Ставим плюсы: )
Мудрый кот
Аватара пользователя
Сообщения: 1810
Зарегистрирован: Чт июн 10, 2010 08:55:35
Откуда: Сибирские Афины

Сообщение Kavka »

Про volatile и регистры в/в - да, тут я дал маху. Признаю.
Был повод повторно проштудировать sfr_defs.h. :)
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Опытный кот
Аватара пользователя
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

Сообщение shads »

Сейчас проверил, одинаково нормально работает со следующими регистрами В/В.
Это конечно при условии, что не используются соответствующие модули.....

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

EEARL - 	EEPROM регистр адреса
EEDR - 	EEPROM регистр данных
UBRRL - 	USART регистр скорости интерфейса
TWBR -	TWI регистр скорости передачи
TWAR - 	TWI регистр адреса
IM1
Грызет канифоль
Аватара пользователя
Сообщения: 268
Зарегистрирован: Вт фев 16, 2010 12:10:38
Откуда: Воронеж, Россия

Сообщение IM1 »

Ув. 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;
}
ПС
Ваш код взят из http://radiokot.ru/forum/download/file.php?id=118730
Опытный кот
Аватара пользователя
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

Сообщение shads »

А для чего перед
int main(void)
пишется
__attribute__((OS_main))

что делает этот атрибут?.....
Мудрый кот
Аватара пользователя
Сообщения: 1810
Зарегистрирован: Чт июн 10, 2010 08:55:35
Откуда: Сибирские Афины

Сообщение Kavka »

http://gcc.gnu.org/onlinedocs/gcc-4.7.3 ... Attributes
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 г.)
Друг Кота
Сообщения: 4583
Зарегистрирован: Вс дек 05, 2010 06:10:34
Откуда: ЮВ

Сообщение HHIMERA »

shads писал(а):А для чего перед
int main(void)
пишется
__attribute__((OS_main))

что делает этот атрибут?.....
Склероз???
http://radiokot.ru/forum/viewtopic.php? ... 4#p1399164
http://radiokot.ru/forum/viewtopic.php? ... 9#p1400279
"Я не даю готовых решений, я заставляю думать!"(С)
Опытный кот
Аватара пользователя
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

Сообщение shads »

Да..... старею постепенно.....
Мудрый кот
Аватара пользователя
Сообщения: 1810
Зарегистрирован: Чт июн 10, 2010 08:55:35
Откуда: Сибирские Афины

Сообщение Kavka »

Вложенные прерывания, 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 г.)
Ответить

Вернуться в «AVR»