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

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Аватара пользователя
aam
Собутыльник Кота
Сообщения: 2994
Зарегистрирован: Сб фев 20, 2010 14:00:12
Откуда: Москва

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

Сообщение aam »

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


Еще вот что. Сколько памяти сжирают union и битовые поля? Я их интенсивно юзал в проге))
И еще что лучше для кнопочного меню в плане занимаемого объема - Свич или массив указателей на функции? Я юзал свич.
Вложения
compil.JPG
(62.54 КБ) 322 скачивания
Реклама
Аватара пользователя
Psych
Опытный кот
Сообщения: 848
Зарегистрирован: Ср мар 02, 2011 07:47:39
Откуда: Уфа

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

Сообщение Psych »

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

У вас прошивка влезает в кристалл, а вот какая то хня в определенный сегмент не помещается. Помоему надо править файл линкера.
Реклама
pokk
Вымогатель припоя
Сообщения: 574
Зарегистрирован: Вт ноя 02, 2010 17:46:37

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

Сообщение pokk »

http://radiokot.ru/forum/viewtopic.php? ... 3#p1773303
А что по моему вопросу ?
Аватара пользователя
aam
Собутыльник Кота
Сообщения: 2994
Зарегистрирован: Сб фев 20, 2010 14:00:12
Откуда: Москва

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

Сообщение 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 прямо писал сколько процентов уже занято. Может и тут можно где-то такую опцию включить?
Реклама
Эиком - электронные компоненты и радиодетали
Аватара пользователя
Desutorakuta
Встал на лапы
Сообщения: 144
Зарегистрирован: Вт мар 19, 2013 15:59:51

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

Сообщение 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ухкратном использовании всегда увеличивают объём кода - ведь при нескольких вхождениях текст функции _повторяется_ в коде. Зато работает быстрее.
Deshalb, liebe Kolleginnen und Kollegen,
Es werd Hölle.
Реклама
Аватара пользователя
aam
Собутыльник Кота
Сообщения: 2994
Зарегистрирован: Сб фев 20, 2010 14:00:12
Откуда: Москва

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

Сообщение aam »

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

Интересно, а использование структур, юнионов и битовых полей по сравнению с "ручной" работой с флагами и разбором байт на биты увеличивает объем кода или нет?
Desutorakuta писал(а):INLINE функции при более чем 2ухкратном использовании всегда увеличивают объём кода
Общий вопрос:
В проге в основном цикле крутится много функциональных частей устройства. Если писать все сплошным кодом - то потом без пол литра не разберешься даже в своей собственной проге.
Если разбивать код на модули с помощью обычных функций - они все равно в программе используются только ОДИН раз, а имеют полноценные заголовки - нерационально. Но с другой стороны, целый кусок кода может выходить (и в 99% реальных случаев выходит) за размеры rjmp. Соответственно, компилятор сам начнет дробить код на функции. Как правильно поступать применительно к микроконтроллерам при написании главного цикла?
Реклама
Аватара пользователя
Desutorakuta
Встал на лапы
Сообщения: 144
Зарегистрирован: Вт мар 19, 2013 15:59:51

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

Сообщение 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'ов.
Deshalb, liebe Kolleginnen und Kollegen,
Es werd Hölle.
Аватара пользователя
aam
Собутыльник Кота
Сообщения: 2994
Зарегистрирован: Сб фев 20, 2010 14:00:12
Откуда: Москва

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

Сообщение 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;
Юнион замутил для облегчения отделения команды и кода системы
Стоит так делать для МК?
pokk
Вымогатель припоя
Сообщения: 574
Зарегистрирован: Вт ноя 02, 2010 17:46:37

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

Сообщение 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:
Аватара пользователя
blackx
Говорящий с текстолитом
Сообщения: 1518
Зарегистрирован: Пт дек 28, 2012 21:56:46
Откуда: St. Petersburg

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

Сообщение 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". возможно она глобальная. Вот с ней и происходит работа в макросе.
Изображение only pure true norwegian blackx Изображение
pokk
Вымогатель припоя
Сообщения: 574
Зарегистрирован: Вт ноя 02, 2010 17:46:37

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

Сообщение 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;
а это наверное что бы просто перепутаться ?
Торвальд
Родился
Сообщения: 6
Зарегистрирован: Сб июл 10, 2010 10:45:40

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

Сообщение Торвальд »

В процессе программирования я столкнулся со странным поведением цикла 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); никакого эффекта не даёт.

Подскажите, пожалуйста, в чём может быть проблема?
Аватара пользователя
ploop
Модератор
Сообщения: 13490
Зарегистрирован: Ср ноя 26, 2008 16:34:25
Откуда: Тамбовская обл.

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

Сообщение ploop »

Отключите оптимизацию компилятора.
Торвальд
Родился
Сообщения: 6
Зарегистрирован: Сб июл 10, 2010 10:45:40

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

Сообщение Торвальд »

С отключённой оптимизацией проект вовсе не компилируется.
А других способов нет? Вообще, какой механизм данной проблемы? Во что превращается пустой цикл после оптимизации компилятором?
a_skr
Вымогатель припоя
Сообщения: 630
Зарегистрирован: Пн июн 14, 2010 13:07:29
Откуда: Жуковский

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

Сообщение a_skr »

volatile char(ну, или, какой там тип у Вас) flag;

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

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

Сообщение Kavka »

Торвальд, а flag у вас гле выставляется? В прерывании? Если да, то она объявлена у вас без volatile (как вам уже подсказали). Это указывает компилятору, что при любом обращении к переменной её надо обязательно считывать из ячейки памяти, и не допускать повторного использования если она загружена из памяти в регистр.
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Торвальд
Родился
Сообщения: 6
Зарегистрирован: Сб июл 10, 2010 10:45:40

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

Сообщение Торвальд »

a_skr писал(а):volatile char(ну, или, какой там тип у Вас) flag;

_delay_ms() ... AVR? - ну, тогда, точно, см. выше.
Да, AVR. Это модератор сюда сообщение перенёс. Изначально в профильном разделе писал.
С volatile не пробовал, спасибо за подсказку.
Kavka писал(а):Торвальд, а flag у вас гле выставляется? В прерывании? Если да, то она объявлена у вас без volatile (как вам уже подсказали). Это указывает компилятору, что при любом обращении к переменной её надо обязательно считывать из ячейки памяти, и не допускать повторного использования если она загружена из памяти в регистр.
Вот за это огромное спасибо! Про volatile раньше читал, но не понимал её значения.
Аватара пользователя
aam
Собутыльник Кота
Сообщения: 2994
Зарегистрирован: Сб фев 20, 2010 14:00:12
Откуда: Москва

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

Сообщение 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:
Аватара пользователя
FreshMan
Друг Кота
Сообщения: 6296
Зарегистрирован: Пн ноя 22, 2010 00:57:15
Откуда: Ukraine

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

Сообщение FreshMan »

в каких случаях перед названием ф-ции ставится префикс static ?
Tell Me The Truth
Аватара пользователя
coredumped
Опытный кот
Сообщения: 838
Зарегистрирован: Вт апр 12, 2011 18:38:19
Откуда: с Земли

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

Сообщение coredumped »

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

Вернуться в «Разные вопросы по МК»