У меня так щас стоит все:
Это по максимуму или можно еще в каких-то настройках порыться?
Насчет инлайна - я попробовал просто кусок кода вставить вместо функции - как ни странно, размер увеличился
Еще вот что. Сколько памяти сжирают union и битовые поля? Я их интенсивно юзал в проге))
И еще что лучше для кнопочного меню в плане занимаемого объема - Свич или массив указателей на функции? Я юзал свич.
Psych писал(а):Массив указателей очень много места сэкономит, а свитч это куча cmp и jmp
Но ведь к массиву указателей будут еще функции, у которых До и После полезного кода всякая лабуда с сохраненнием/извлечением из стека используемых в ней регистров. В свиче же место занимают rjmp'ы и т. п. Так что вопрос достаточно спорный. Но ради интереса попробую - и сравню что окажется меньше.
Psych писал(а):а вот какая то хня в определенный сегмент не помещается
Это врят ли - оперативы и ЭСППЗУ у Тини2313 по 128 байт. Там же написано:
38 bytes of DATA memory (+ 20 bytes shared)
31 bytes of XDATA memory
Т. е. меньше половины. Кроме того, из самого "жестокого" в ЭСППЗУ - это мой массив на 23 кнопки. В оперативе только переменные и стек, ничего сверхъестественного.
Всбрык линкера происходил после добавления одного if, в котором только вызов функции. Тот же вызов, но до помещения перед ним if еще помещался указанными результатами, но когда я открывал HEX в проге-программаторе, было видно ,что до конца флеши проца оставалось чуть ли не пару строчек.
Но ведь 1 374 байт - это не 2 свободный строчки из 2048 байт. Вот что удивило. Каким образом линкер мог ТАК раздуть код?
Вообще как-то странно у этого IARa отображается состояние памяти. CVAVR прямо писал сколько процентов уже занято. Может и тут можно где-то такую опцию включить?
Error[e16]: Segment TINY_ID (size: 0x2a align: 0) is too long for segment definition. At least 0x2 more bytes needed...
Reserved ranges relevant to this placement:
...
CODE:7d8-7ff TINY_ID
...
Error[e16]: Сегмент TINY_ID (размер: 0x2a (42 байта) выравнивание: 0) слишком большой для распределения сегментов. Ещё 0x2 байта нужно. ...
Зарезервированные диапазоны для этих значений:
...
CODE:7d8-7ff TINY_ID (40 байт)
...
У вас не влазит конкретный сегмент TINY_ID, причём кодогенератор делает его размером 38 байт, а линкер видит размер 42 байта из 40 возможных. Ищите где сегмент обрастает жиром. К сожалению конкретно указать не могу - никогда не работал ни с AMTEL-ами, ни с IAR.
То, что hex-файл размером со всю память - это нормально, этот самый Tiny_id просто хочет всегда занимать последние 40 байт памяти.
INLINE функции при более чем 2ухкратном использовании всегда увеличивают объём кода - ведь при нескольких вхождениях текст функции _повторяется_ в коде. Зато работает быстрее.
Deshalb, liebe Kolleginnen und Kollegen,
Es werd Hölle.
Попробовал с указателями на функции и массивом - занимает места больше. Причина - избыточность кода, т. к. трудно группировать кнопки по функциональным блокам.
Desutorakuta писал(а):Ищите где сегмент обрастает жиром
У меня щас другой вопрос - мне за процем другим в магаз идти или я что-то не въехал в этих IARах и компиляторах?
Речь шла об однократном использовании функций ,которое повышает читаемость проги.
Интересно, а использование структур, юнионов и битовых полей по сравнению с "ручной" работой с флагами и разбором байт на биты увеличивает объем кода или нет?
Desutorakuta писал(а):INLINE функции при более чем 2ухкратном использовании всегда увеличивают объём кода
Общий вопрос:
В проге в основном цикле крутится много функциональных частей устройства. Если писать все сплошным кодом - то потом без пол литра не разберешься даже в своей собственной проге.
Если разбивать код на модули с помощью обычных функций - они все равно в программе используются только ОДИН раз, а имеют полноценные заголовки - нерационально. Но с другой стороны, целый кусок кода может выходить (и в 99% реальных случаев выходит) за размеры rjmp. Соответственно, компилятор сам начнет дробить код на функции. Как правильно поступать применительно к микроконтроллерам при написании главного цикла?
Что то не понимаете с IARом - зарезервировано памяти под сегмент код в камне 1957 байт, а ваш сегмент кода - 1374 байта. Т.е. - ещё треть сегмента свободна.
Reserved ranges relevant to this placement:
CODE:26-2e NEAR_F
CODE:2f-32 INITTAB CODE:33-7d7 CODE
CODE:7d8-7ff TINY_ID
0x7d7-0x32=0x7A5=1957
20 bytes in segment ABSOLUTE 1 374 bytes in segment CODE
31 bytes in segment EEPROM_I
4 bytes in segment INITTAB
6 bytes in segment INTVEC
9 bytes in segment NEAR_F
38 bytes in segment TINY_I
38 bytes in segment TINY_ID
На ассемблере я бы написал макаронную процедуру, разбитую комментариями. На си, в принципе, тоже - gcc лучше разберёт, как организовать код.
Использование сишных битовых полей vs. логических функций - в теории без разницы, на практике - зависит от компилятора. Однако синтаксис этих полей громоздкий.
Структуры вручную полностью эмулировать не получится. Перечисления абсолютно идентичны использованию целочисленных переменным + списоков #defin'ов.
Deshalb, liebe Kolleginnen und Kollegen,
Es werd Hölle.
Desutorakuta писал(а):На си, в принципе, тоже - gcc лучше разберёт, как организовать код.
"Тоже" - в смысле, через дефайны и "\" ?
Desutorakuta писал(а):Однако синтаксис этих полей громоздкий
Ну я там структуру объявил и обращаюсь типа:
flags.ready=1
if(flags.error)
и т. п.
Когда все это пробовал, ассемблерный код вроде хороший получался конкретно для таких записей, но щас прога уже большая, малоли чего он там накомпилит...
Desutorakuta писал(а):Структуры вручную полностью эмулировать не получится.
struct uip_conn {
u16_t ripaddr[2]; /**< The IP address of the remote host. */
u16_t lport; /**< The local TCP port, in network byte order. */
u16_t rport; /**< The local remote TCP port, in network byte
order. */
u8_t rcv_nxt[4]; /**< The sequence number that we expect to
receive next. */
u8_t snd_nxt[4]; /**< The sequence number that was last sent by
us. */
u16_t len; /**< Length of the data that was previously sent. */
u16_t mss; /**< Current maximum segment size for the
connection. */
u16_t initialmss; /**< Initial maximum segment size for the
connection. */
u8_t sa; /**< Retransmission time-out calculation state
variable. */
u8_t sv; /**< Retransmission time-out calculation state
variable. */
u8_t rto; /**< Retransmission time-out. */
u8_t tcpstateflags; /**< TCP state and flags. */
u8_t timer; /**< The retransmission timer. */
u8_t nrtx; /**< The number of retransmissions for the last
segment sent. */
/** The application state. */
u8_t appstate[UIP_APPSTATE_SIZE];
};
пусть будет conn=5 uip_conn = &uip_conn[5];
так вот вопрос чего это мы сделали ? и что это значит структура[5]
и этот адрес опять в структуру записывается.
В си, по каким-то причинам, можно переменные называть так же как и структуры, главное чтобы парсер компилятора смог определить по порядку следования слов где что
То есть, вот так можно невозбранно делать:
int a() {
struct uip_conn uip_conn; // объявляем переменную uip_conn с типом struct uip_conn
}
uip_conns в данном случае это массив структур. Он объявлен как надо.
pokk писал(а):пусть будет conn=5 uip_conn = &uip_conn[5];
так вот вопрос чего это мы сделали ? и что это значит структура[5]
и этот адрес опять в структуру записывается.
"структура[5]" это просто берется структура uip_conn из массива uip_conns. Почитайте про массивы.
Мораль: ищите в своем коде объявление переменной "struct uip_conn uip_conn". возможно она глобальная. Вот с ней и происходит работа в макросе.
Теперь всё что понял берём массив структур uip_conns выбираем от туда текущую структуру(conn) дальше адрес этой структуры присваиваем указателю uip_conn и работаем с структурой выбранной
Т.е. простое ожидание события flag=0. Это событие наступает при нажатии кнопки (опрос кнопки - по прерыванию таймера). Но когда событие наступает, выхода из цикла не происходит - программа так и висит на этом месте, хотя условие while не выполняется.
Однако, если добавить в этот цикл какое-нибудь полезное действие, например, вывод информации на дисплей:
То выход из цикла происходит нормально. Причём это "полезное действие" должно нагружать проц. Например, добавление в цикл _delay_ms(1000); никакого эффекта не даёт.
Подскажите, пожалуйста, в чём может быть проблема?
С отключённой оптимизацией проект вовсе не компилируется.
А других способов нет? Вообще, какой механизм данной проблемы? Во что превращается пустой цикл после оптимизации компилятором?
Торвальд, а flag у вас гле выставляется? В прерывании? Если да, то она объявлена у вас без volatile (как вам уже подсказали). Это указывает компилятору, что при любом обращении к переменной её надо обязательно считывать из ячейки памяти, и не допускать повторного использования если она загружена из памяти в регистр.
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
a_skr писал(а):volatile char(ну, или, какой там тип у Вас) flag;
_delay_ms() ... AVR? - ну, тогда, точно, см. выше.
Да, AVR. Это модератор сюда сообщение перенёс. Изначально в профильном разделе писал.
С volatile не пробовал, спасибо за подсказку.
Kavka писал(а):Торвальд, а flag у вас гле выставляется? В прерывании? Если да, то она объявлена у вас без volatile (как вам уже подсказали). Это указывает компилятору, что при любом обращении к переменной её надо обязательно считывать из ячейки памяти, и не допускать повторного использования если она загружена из памяти в регистр.
Вот за это огромное спасибо! Про volatile раньше читал, но не понимал её значения.
Building configuration: LED_cnt - Debug
Updating build tree...
Linking
Error[e16]: Segment CODE (size: 0x7e2 align: 0x1) is too long for segment definition. At least 0x30 more bytes needed.
The problem occurred while processing the segment placement command
"-Z(CODE)CODE=_..X_FLASH_BASE-_..X_FLASH_END", where at the moment of placement the available memory
ranges were "CODE:4e-7ff"
Reserved ranges relevant to this placement:
CODE:26-2e NEAR_F
CODE:2f-49 SWITCH
CODE:4a-4d INITTAB
CODE:4e-7ff CODE
Error while running Linker
Total number of errors: 1
Total number of warnings: 0
20 bytes in segment ABSOLUTE
1 558 bytes in segment CODE
29 bytes in segment EEPROM_I
4 bytes in segment INITTAB
4 bytes in segment INTVEC
9 bytes in segment NEAR_F
26 bytes in segment SWITCH
28 bytes in segment TINY_I
28 bytes in segment TINY_ID
1 621 bytes of CODE memory (+ 8 bytes shared)
28 bytes of DATA memory (+ 20 bytes shared)
29 bytes of XDATA memory
Errors: none
Warnings: none
Т. е. компиляция прошла успешно.
Чего там творит линкер, что так прогу раздувает - ХЗ
***
Включил создание листинга линкера. Вот что он выдает в первом случае (при успешном создании HEXа):
FreshMan писал(а):в каких случаях перед названием ф-ции ставится префикс static ?
Если нужно ограничить видимость имени этой ф-ции модулем, в котором она объявлена. Это касается любых глобальных идентификаторов (константы, переменные итп) - если их объявить static, они будут видны/доступны только из модуля в котором объявлены.
Последний раз редактировалось coredumped Вс сен 15, 2013 20:23:05, всего редактировалось 1 раз.