Страница 165 из 386
Re: Вопросы по С/С++ (СИ)
Добавлено: Пт авг 30, 2013 09:01:26
aam
У меня так щас стоит все:

Это по максимуму или можно еще в каких-то настройках порыться?
Насчет инлайна - я попробовал просто кусок кода вставить вместо функции - как ни странно, размер увеличился
Еще вот что. Сколько памяти сжирают union и битовые поля? Я их интенсивно юзал в проге))
И еще что лучше для кнопочного меню в плане занимаемого объема - Свич или массив указателей на функции? Я юзал свич.
Re: Вопросы по С/С++ (СИ)
Добавлено: Пт авг 30, 2013 09:17:04
Psych
aam писал(а):Насчет инлайна - я попробовал просто кусок кода вставить вместо функции - как ни странно, размер увеличился
А посмотреть что компиль на "ассемблировал" не пробывали??!!
aam писал(а):И еще что лучше для кнопочного меню в плане занимаемого объема - Свич или массив указателей на функции? Я юзал свич.
Массив указателей очень много места сэкономит, а свитч это куча cmp и jmp.
У вас прошивка влезает в кристалл, а вот какая то хня в определенный сегмент не помещается. Помоему надо править файл линкера.
Re: Вопросы по С/С++ (СИ)
Добавлено: Пт авг 30, 2013 16:37:17
pokk
Re: Вопросы по С/С++ (СИ)
Добавлено: Пт авг 30, 2013 17:48:32
aam
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 прямо писал сколько процентов уже занято. Может и тут можно где-то такую опцию включить?
Re: Вопросы по С/С++ (СИ)
Добавлено: Сб авг 31, 2013 09:02:15
Desutorakuta
aam писал(а):Закончилась моя прога(
Код: Выделить всё
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ухкратном использовании всегда увеличивают объём кода - ведь при нескольких вхождениях текст функции _повторяется_ в коде. Зато работает быстрее.
Re: Вопросы по С/С++ (СИ)
Добавлено: Сб авг 31, 2013 22:18:16
aam
Попробовал с указателями на функции и массивом - занимает места больше. Причина - избыточность кода, т. к. трудно группировать кнопки по функциональным блокам.
Desutorakuta писал(а):Ищите где сегмент обрастает жиром
У меня щас другой вопрос - мне за процем другим в магаз идти или я что-то не въехал в этих IARах и компиляторах?
Речь шла об однократном использовании функций ,которое повышает читаемость проги.
Интересно, а использование структур, юнионов и битовых полей по сравнению с "ручной" работой с флагами и разбором байт на биты увеличивает объем кода или нет?
Desutorakuta писал(а):INLINE функции при более чем 2ухкратном использовании всегда увеличивают объём кода
Общий вопрос:
В проге в основном цикле крутится много функциональных частей устройства. Если писать все сплошным кодом - то потом без пол литра не разберешься даже в своей собственной проге.
Если разбивать код на модули с помощью обычных функций - они все равно в программе используются только ОДИН раз, а имеют полноценные заголовки - нерационально. Но с другой стороны, целый кусок кода может выходить (и в 99% реальных случаев выходит) за размеры rjmp. Соответственно, компилятор сам начнет дробить код на функции. Как правильно поступать применительно к микроконтроллерам при написании главного цикла?
Re: Вопросы по С/С++ (СИ)
Добавлено: Вт сен 03, 2013 09:15:33
Desutorakuta
Что то не понимаете с 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'ов.
Re: Вопросы по С/С++ (СИ)
Добавлено: Вт сен 03, 2013 12:39:37
aam
Desutorakuta писал(а):На си, в принципе, тоже - gcc лучше разберёт, как организовать код.
"Тоже" - в смысле, через дефайны и "\" ?
Desutorakuta писал(а):Однако синтаксис этих полей громоздкий
Ну я там структуру объявил и обращаюсь типа:
flags.ready=1
if(flags.error)
и т. п.
Когда все это пробовал, ассемблерный код вроде хороший получался конкретно для таких записей, но щас прога уже большая, малоли чего он там накомпилит...
Desutorakuta писал(а):Структуры вручную полностью эмулировать не получится.
А я и не эмулировал. Я прямо писал типа:
Код: Выделить всё
union {
unsigned int buf;
struct {unsigned char cmd;
unsigned adr:5;
unsigned T:1;
unsigned S2:1;
unsigned S1:1;
};
} RC5_pack;
и для флагов битовые поля:
Код: Выделить всё
//Флаги
struct {
unsigned error:1; //Ошибка
unsigned ready:1; //Принят новый пакет
unsigned btn_hold:1; //Кнопка удерживается
unsigned prev_toggle:1; //Предыдущее значение Toggle-бита
unsigned first_event:1; //После включения питания принята хотябы одна команда
} RC5_flags;
Юнион замутил для облегчения отделения команды и кода системы
Стоит так делать для МК?
Re: Вопросы по С/С++ (СИ)
Добавлено: Ср сен 04, 2013 04:46:42
pokk
Здравствуйте я вот тут с таким вопросом в главном цикле вызывается вот такой дефаин conn изменяется от 0 до 10
Код: Выделить всё
#define uip_periodic(conn) do { uip_conn = &uip_conns[conn]; \
uip_process(UIP_TIMER); } while (0)
меня тут интересует uip_conn = &uip_conns[conn]; присвоили uip_conn адрес с uip_conns[0..10]
смотрим дальше там объявление uip_conns
Код: Выделить всё
extern struct uip_conn uip_conns[UIP_CONNS];
значит uip_conns это структура uip_conn
выглядит она так:
Спойлер
Код: Выделить всё
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]
и этот адрес опять в структуру записывается.

Re: Вопросы по С/С++ (СИ)
Добавлено: Ср сен 04, 2013 07:27:01
blackx
Ваш код видимо индусы писали
В си, по каким-то причинам, можно переменные называть так же как и структуры, главное чтобы парсер компилятора смог определить по порядку следования слов где что
То есть, вот так можно невозбранно делать:
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". возможно она глобальная. Вот с ней и происходит работа в макросе.
Re: Вопросы по С/С++ (СИ)
Добавлено: Ср сен 04, 2013 08:28:24
pokk
Ищите в своем коде объявление переменной "struct uip_conn uip_conn"
нашёл только такое
Код: Выделить всё
struct uip_conn *uip_conn; /* uip_conn always points to the current connection. */
а в самой функции uip_process(UIP_TIMER) есть такое
Код: Выделить всё
register struct uip_conn *uip_connr = uip_conn;
и дальше с ним работают вот так вот
Теперь всё что понял берём массив структур uip_conns выбираем от туда текущую структуру(conn) дальше адрес этой структуры присваиваем указателю uip_conn и работаем с структурой выбранной
а это наверное что бы просто перепутаться ?
Проблема с циклом While
Добавлено: Пт сен 06, 2013 15:37:10
Торвальд
В процессе программирования я столкнулся со странным поведением цикла While.
Например, в программе есть такая конструкция:
Т.е. простое ожидание события flag=0. Это событие наступает при нажатии кнопки (опрос кнопки - по прерыванию таймера). Но когда событие наступает, выхода из цикла не происходит - программа так и висит на этом месте, хотя условие while не выполняется.
Однако, если добавить в этот цикл какое-нибудь полезное действие, например, вывод информации на дисплей:
Код: Выделить всё
while (flag != 0)
{
wr_data('T');
wr_data('i');
wr_data('m');
wr_data('e');
wr_data('r');
wr_data('=');
wr_data(timer/10000+0x30);
wr_data((timer%10000)/1000+0x30);
wr_data((timer%1000)/100+0x30);
wr_data((timer%100)/10+0x30);
wr_data((timer%10)+0x30);
}
То выход из цикла происходит нормально. Причём это "полезное действие" должно нагружать проц. Например, добавление в цикл _delay_ms(1000); никакого эффекта не даёт.
Подскажите, пожалуйста, в чём может быть проблема?
Re: Вопросы по С/С++ (СИ)
Добавлено: Пт сен 06, 2013 15:44:53
ploop
Отключите оптимизацию компилятора.
Re: Вопросы по С/С++ (СИ)
Добавлено: Пт сен 06, 2013 16:03:31
Торвальд
С отключённой оптимизацией проект вовсе не компилируется.
А других способов нет? Вообще, какой механизм данной проблемы? Во что превращается пустой цикл после оптимизации компилятором?
Re: Вопросы по С/С++ (СИ)
Добавлено: Пт сен 06, 2013 17:17:23
a_skr
volatile char(ну, или, какой там тип у Вас) flag;
_delay_ms() ... AVR? - ну, тогда, точно, см. выше.
Re: Проблема с циклом While
Добавлено: Пт сен 06, 2013 18:47:24
Kavka
Торвальд, а flag у вас гле выставляется? В прерывании? Если да, то она объявлена у вас без volatile (как вам уже подсказали). Это указывает компилятору, что при любом обращении к переменной её надо обязательно считывать из ячейки памяти, и не допускать повторного использования если она загружена из памяти в регистр.
Re: Вопросы по С/С++ (СИ)
Добавлено: Сб сен 07, 2013 12:21:35
Торвальд
a_skr писал(а):volatile char(ну, или, какой там тип у Вас) flag;
_delay_ms() ... AVR? - ну, тогда, точно, см. выше.
Да, AVR. Это модератор сюда сообщение перенёс. Изначально в профильном разделе писал.
С volatile не пробовал, спасибо за подсказку.
Kavka писал(а):Торвальд, а flag у вас гле выставляется? В прерывании? Если да, то она объявлена у вас без volatile (как вам уже подсказали). Это указывает компилятору, что при любом обращении к переменной её надо обязательно считывать из ячейки памяти, и не допускать повторного использования если она загружена из памяти в регистр.
Вот за это огромное спасибо! Про volatile раньше читал, но не понимал её значения.
Re: Вопросы по С/С++ (СИ)
Добавлено: Вс сен 08, 2013 13:14:58
aam
Кароче, немогу понять в чем дело...
В листинге main.lst после компиляции в конце такие записи:
Код: Выделить всё
20 bytes in segment ABSOLUTE
1 554 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 617 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-е в программаторе я вижу это:
Т. е. проц уже забит под завязку. Еще пара строк - и вылетит ошибка типа такой:
Код: Выделить всё
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
HEX после этого естественно не создается.
В листинге при этом появляется такая запись:
Код: Выделить всё
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а):
Код: Выделить всё
****************************************
* *
* MODULE SUMMARY *
* *
****************************************
Module CODE DATA XDATA
------ ---- ---- -----
(Rel) (Rel) (Abs) (Rel)
?C_MUL_L01 16
?C_STARTUP 20
?EEPROM_8 44
?FILLER_BYTES 14
+ common 24
?RESET
+ common 2
?S_MUL_L02 32
?S_SHL_L02 12
?US_SHR_L02 12
?__exit 6
?low_level_init 4
?segment_init 64
?xV_SWITCH_L06 156
main 1 621 28 20 28
+ common 24
N/A (command line) 64
N/A (alignment)
---------- ----- -- -- --
Total: 2 001 92 20 28
+ common 24
Что такое ?xV_SWITCH_L06 и как уменьшить размер кода? Нелезит прога нифига

Re: Вопросы по С/С++ (СИ)
Добавлено: Вс сен 15, 2013 20:00:30
FreshMan
в каких случаях перед названием ф-ции ставится префикс static ?
Re: Вопросы по С/С++ (СИ)
Добавлено: Вс сен 15, 2013 20:18:14
coredumped
FreshMan писал(а):в каких случаях перед названием ф-ции ставится префикс static ?
Если нужно ограничить видимость имени этой ф-ции модулем, в котором она объявлена. Это касается любых глобальных идентификаторов (константы, переменные итп) - если их объявить static, они будут видны/доступны только из модуля в котором объявлены.