Страница 165 из 386

Re: Вопросы по С/С++ (СИ)

Добавлено: Пт авг 30, 2013 09:01:26
aam
У меня так щас стоит все:
Изображение
Это по максимуму или можно еще в каких-то настройках порыться?
Насчет инлайна - я попробовал просто кусок кода вставить вместо функции - как ни странно, размер увеличился :shock:


Еще вот что. Сколько памяти сжирают union и битовые поля? Я их интенсивно юзал в проге))
И еще что лучше для кнопочного меню в плане занимаемого объема - Свич или массив указателей на функции? Я юзал свич.

Re: Вопросы по С/С++ (СИ)

Добавлено: Пт авг 30, 2013 09:17:04
Psych
aam писал(а):Насчет инлайна - я попробовал просто кусок кода вставить вместо функции - как ни странно, размер увеличился
А посмотреть что компиль на "ассемблировал" не пробывали??!!
aam писал(а):И еще что лучше для кнопочного меню в плане занимаемого объема - Свич или массив указателей на функции? Я юзал свич.
Массив указателей очень много места сэкономит, а свитч это куча cmp и jmp.

У вас прошивка влезает в кристалл, а вот какая то хня в определенный сегмент не помещается. Помоему надо править файл линкера.

Re: Вопросы по С/С++ (СИ)

Добавлено: Пт авг 30, 2013 16:37:17
pokk
http://radiokot.ru/forum/viewtopic.php? ... 3#p1773303
А что по моему вопросу ?

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. :dont_know:
То, что hex-файл размером со всю память - это нормально, этот самый Tiny_id просто хочет всегда занимать последние 40 байт памяти.

INLINE функции при более чем 2ухкратном использовании всегда увеличивают объём кода - ведь при нескольких вхождениях текст функции _повторяется_ в коде. Зато работает быстрее.

Re: Вопросы по С/С++ (СИ)

Добавлено: Сб авг 31, 2013 22:18:16
aam
Попробовал с указателями на функции и массивом - занимает места больше. Причина - избыточность кода, т. к. трудно группировать кнопки по функциональным блокам.
Desutorakuta писал(а):Ищите где сегмент обрастает жиром
У меня щас другой вопрос - мне за процем другим в магаз идти или я что-то не въехал в этих IARах и компиляторах? :roll:
Речь шла об однократном использовании функций ,которое повышает читаемость проги.

Интересно, а использование структур, юнионов и битовых полей по сравнению с "ручной" работой с флагами и разбором байт на биты увеличивает объем кода или нет?
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]
и этот адрес опять в структуру записывается. :o :dont_know:

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]
и этот адрес опять в структуру записывается. :o :dont_know:
"структура[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_connr->tcpstateflags == TIME_WAIT;
Теперь всё что понял берём массив структур uip_conns выбираем от туда текущую структуру(conn) дальше адрес этой структуры присваиваем указателю uip_conn и работаем с структурой выбранной

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

uip_connr = uip_conn;
а это наверное что бы просто перепутаться ?

Проблема с циклом While

Добавлено: Пт сен 06, 2013 15:37:10
Торвальд
В процессе программирования я столкнулся со странным поведением цикла While.
Например, в программе есть такая конструкция:

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

while (flag != 0);
Т.е. простое ожидание события 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
Кароче, немогу понять в чем дело... :dont_know:
В листинге 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
Т. е. компиляция прошла успешно.
Чего там творит линкер, что так прогу раздувает - ХЗ :dont_know:
***
Включил создание листинга линкера. Вот что он выдает в первом случае (при успешном создании 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 и как уменьшить размер кода? Нелезит прога нифига :cry:

Re: Вопросы по С/С++ (СИ)

Добавлено: Вс сен 15, 2013 20:00:30
FreshMan
в каких случаях перед названием ф-ции ставится префикс static ?

Re: Вопросы по С/С++ (СИ)

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