реклама на сайте
подробности

 
 
7 страниц V  « < 4 5 6 7 >  
Reply to this topicStart new topic
> Новичок на С, Помогите разобраться со структурой проекта
SasaVitebsk
сообщение Mar 19 2006, 13:05
Сообщение #76


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



osnwt спасибо за расширенный ответ. Детали и нюансы не почерпнёшь в мануалах. Там всё лаконично.
Массив пересчёта я поместил в const __flash, бузусловно. Использовать 256 байт озу под это для меня слишком расточительно. Помещать Вам на рассмотрение ещё и фрагменты текста, по-моему это уж слишком. smile.gif Это уж самом-самом крайнем случае. Буду разбираться сам. Ваши советы мне помогли обрести уверенность. Я теперь больше доверяю компилятору и меньше себе. smile.gif Если что-то не так, - более детально разбираю программу.
На счёт "легендарных" 11 байт. biggrin.gif
Ещё раз внимательно всё просмотрел (в который уже раз). У меня в программе очень много различных данных находится в sram. И разнотипных к тому же.
Чё делает компилятор? - Он выбирает группу переменных (возможно использующихся в одном месте) и для обращения к переменным использует одно имя. А к остальным переменным обращается LDD Rx, Z+ (смещение в группе). Вот так и получилось 11 байт. laugh.gif На самом деле это определённое количество переменных начинающихся с переменной "flag".

В моём случае вычисление типа:
Oport0 &= ((EkrToPort[*AdrShowEkr++ ^ Cycl_Ekr] & 0xf) | (EkrToPort[*AdrShowEkr++ ^ Cycl_Ekr] & 0xf0));
Заняло больше места чем
l = (EkrToPort[*AdrShowEkr++ ^ Cycl_Ekr] & 0xf);
Oport0 &= (l | (EkrToPort[*AdrShowEkr++ ^ Cycl_Ekr] & 0xf0));
(l - переменная локальная)
Go to the top of the page
 
+Quote Post
osnwt
сообщение Mar 19 2006, 14:32
Сообщение #77


Частый гость
**

Группа: Свой
Сообщений: 175
Регистрация: 26-01-06
Из: Sevastopol
Пользователь №: 13 664



Цитата(SasaVitebsk @ Mar 19 2006, 15:05) *
В моём случае вычисление типа:
Oport0 &= ((EkrToPort[*AdrShowEkr++ ^ Cycl_Ekr] & 0xf) | (EkrToPort[*AdrShowEkr++ ^ Cycl_Ekr] & 0xf0));
Заняло больше места чем
l = (EkrToPort[*AdrShowEkr++ ^ Cycl_Ekr] & 0xf);
Oport0 &= (l | (EkrToPort[*AdrShowEkr++ ^ Cycl_Ekr] & 0xf0));
(l - переменная локальная)

Хочу заметить, что первое (сложное) выражение, помимо того, что не очень наглядно, еще и неоднозначно с точки зрения порядка вычислений (иногда при этом можно получить и разную длину кода).

Использованное там выражение *p++ имеет побочный эффект в виде инкремента указателя. В выражении e1 | e2 порядок вычисления выражений e1 и e2 вообще не определен (в отличие от e1 || e2, где вычисление идет слева направо - смысл операций, разумеется, разный). Потому в общем случае компилятор может сначала посчитать правое выражение, а потом левое. Очевидно, что результаты будут различные, так как *p++ (где p - это EkrToPort) даст разные результаты в этих двух случаях.

Потому в таких случаях особенно важно писать однозначно и наглядно.
Go to the top of the page
 
+Quote Post
defunct
сообщение Mar 19 2006, 16:50
Сообщение #78


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Как говорит уважаемый АП - лучше написать два раза if чем, слепив условие для одного оператора if, получить неоднозначность..
Go to the top of the page
 
+Quote Post
osnwt
сообщение Mar 19 2006, 18:38
Сообщение #79


Частый гость
**

Группа: Свой
Сообщений: 175
Регистрация: 26-01-06
Из: Sevastopol
Пользователь №: 13 664



Цитата(osnwt @ Mar 19 2006, 16:32) *
*p++ (где p - это EkrToPort)

Ошибка: имелось в виду AdrShowEkr в выражении
Код
Oport0 &= ((EkrToPort[*AdrShowEkr++ ^ Cycl_Ekr] & 0xf) | (EkrToPort[*AdrShowEkr++ ^ Cycl_Ekr] & 0xf0));
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Mar 19 2006, 20:27
Сообщение #80


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



Я это обнаружил с самого начала, но решил посмотреть как это сделает компилятор. Потом убрал чтобы не было неоднозначности. Написанная мной подпрограмма прерывания на ASMе оказалась быстрее примерно в четыре раза. Я конечно ещё поэкспериментирую с СИ (программой прерывания), но вероятней всего в конечном варианте будет программа на асемблере. (Самый быстрый вариант на СИ тоже оставлю для возможного перехода на другой МП)

Я приступил к отладке, поскольку в настоящий момент начинаю "терять из под контроля программу". smile.gif (Не знаю как у кого, а у меня при большой длине проги наступает такой момент, когда она живёт своей жизнью)
После того как я отлажу (в симуляторе) некоторые независимые части, то начну её дописывать. Осталось процентов 20-25. И вот сейчас у меня непонятная ошибка.

TekAdrActive = LastAdrActive = malloc(SIZE_FREE); // Âûäåëèòü ïàìÿòü

При отладке в указатели заносится значение при SIZE_FREE менее 10. Фишка в том, что я пишу под atmega2560 (sram 8k). Компилятор выдаёт следующие значения занятой программы.

//
// 43 bytes in segment ABSOLUTE
// 2 668 bytes in segment CODE
// 3 002 bytes in segment FARCODE
// 7 bytes in segment INITTAB
// 12 bytes in segment INTVEC
// 855 bytes in segment NEAR_Z
//
// 5 670 bytes of CODE memory (+ 19 bytes shared)
// 855 bytes of DATA memory (+ 43 bytes shared)

И ещё указатель на свободный адрес она выдаёт типа 229h. Может быть там и есть дырка байт 10. smile.gif Но потом идут массивы и прочее. Короче менее 5bfh этот адрес не должен быть. Где-то ошибка. Может быть это связано с сегментами? Дело в том что я с ними не работал и пока убей-непонимаю зачем они нужны (применительно к AVR. На процессоре 80x8х когда-то сталкивался под ассемблером. Там это очевидно). Помогите разобраться.
Go to the top of the page
 
+Quote Post
osnwt
сообщение Mar 19 2006, 23:04
Сообщение #81


Частый гость
**

Группа: Свой
Сообщений: 175
Регистрация: 26-01-06
Из: Sevastopol
Пользователь №: 13 664



Цитата(SasaVitebsk @ Mar 19 2006, 22:27) *
TekAdrActive = LastAdrActive = malloc(SIZE_FREE); // Âûäåëèòü ïàìÿòü

При отладке в указатели заносится значение при SIZE_FREE менее 10. Фишка в том, что я пишу под atmega2560 (sram 8k). Компилятор выдаёт следующие значения занятой программы.
...
Может быть это связано с сегментами? Дело в том что я с ними не работал и пока убей-непонимаю зачем они нужны (применительно к AVR. На процессоре 80x8х когда-то сталкивался под ассемблером. Там это очевидно). Помогите разобраться.

Каждый байт кода или данных помечается, как располагаемый в определенном именованном сегменте. Имеется некоторое количество предопределенных сегментов, используемых компилятором. Можно также создавать свои собственные.

Раскладыванием сегментов по адресам занимается линкер под управлением файла конфигурации *.lnk. По умолчанию в IAR среда определяет основные размеры областей, а дальше используется файл конфигурации для соответствующего контроллера. Там указано, что сегмент такой-то занимает адреса такие-то. Это делается (по умолчанию) с учетом заданных в конфигурации проекта размеров стеков, кучи и т.п.

При работе с *alloc функциями надо выделить достаточный размер "кучи" (heap) в конфигурации проекта. А потом посмотреть, где линкер разместит сегменты HEAP и NEAR_HEAP. Если выделяемый адрес не попадает в эти области, то что-то не так с программой.

Подробнее RTFM по линкеру, там все хорошо расписано. В данном случае сегменты не имеют ничего общего с сегментами x86, это просто средство управления распределением адресов под код и данные при окончательной компоновке.
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Mar 20 2006, 18:19
Сообщение #82


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



Спасибо всем помогавшим. Сегодня в общих чертах проект закончен. 22кб из них 8кб прога. Основные моменты проверены на AVR Studio. smile.gif Даже полностью написанный на Си (без ассемблерных вставок) укладывается по времени с учётом выбраной частоты (С хорошим запасом).
Время написания достаточно малое, с учётом обучения. Очеть наглядная программа. По этому параметру программа на Си значительно лучше чем на ASMе.
Короче я очень доволен и перехожу к следующим стадиям проекта. smile.gif
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Mar 22 2006, 10:48
Сообщение #83


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



Подскажите спецы (IAR). Компилятор очищает переменные до запуска main, но после __low_level_init.
Поэтому переменные которые я инициализирую в __low_level_init теряются. Я стал их инициализировать при объявлении. Это помогло. Но у меня есть переменные которые должны инициализироваться в начале __low_level_init, т.к по ним потом иниц. оборудование.
Вопрос. Как объявить переменную, чтобы компилятор не инициализировал её? volatile вроде не для этих целей
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Mar 22 2006, 11:03
Сообщение #84


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



Подскажите спецы (IAR). Компилятор очищает переменные до запуска main, но после __low_level_init.
Поэтому переменные которые я инициализирую в __low_level_init теряются. Я стал их инициализировать при объявлении. Это помогло. Но у меня есть переменные которые должны инициализироваться в начале __low_level_init, т.к по ним потом иниц. оборудование.
Вопрос. Как объявить переменную, чтобы компилятор не инициализировал её? volatile вроде не для этих целей
Go to the top of the page
 
+Quote Post
defunct
сообщение Mar 22 2006, 11:17
Сообщение #85


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



__no_init ?
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Mar 22 2006, 12:29
Сообщение #86


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



Спасибо.
Сегодня ине глючит у меня. Поэтому топик попал дважды да не весь. smile.gif Передаю вторую часть
Подскажите спецы (IAR).
Более сложный вопрос. smile.gif
Переменные объявлены следующим образом:

void static *AdrActiveKom[MAX_ACTIVE_KOM+1]; // Адреса указателей на начало активных команд
uint8_t i, j, c, *adrnpict;

Имею такой цикл (или он меня smile.gif )
j= (uint8_t *)AdrActiveKom[i+1]-(uint8_t *)AdrActiveKom[i]; // Высчитать длину команды
for(adrnpict=(AdrActiveKom[i]);adrnpict<(AdrActiveKom[NumbActiveKom+1]-j);adrnpict++)
*adrnpict = *(adrnpict+j);// перенесли команду

Если цикл описать так, то синтаксич. ошибка несовместимости типов, а если так как ниже то всё OK
j= (uint8_t *)AdrActiveKom[i+1]-(uint8_t *)AdrActiveKom[i]; // Высчитать длину команды
for(adrnpict=((uint8_t *)AdrActiveKom[i]);adrnpict<((uint8_t *)AdrActiveKom[NumbActiveKom+1]-j);adrnpict++)
*adrnpict = *(adrnpict+j);// перенесли команду

Но при вычислениях (не в теле цикла, а при выч. переменных цикла) компилятор использует адреса а не содержимое массива.
Можно конечно поизголятся используя адресную арифметику, но я хочу выяснить где у меня ошибка? Что я не правильно понимаю?
С уважением.
Go to the top of the page
 
+Quote Post
defunct
сообщение Mar 22 2006, 13:09
Сообщение #87


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(SasaVitebsk @ Mar 22 2006, 14:29) *
Можно конечно поизголятся используя адресную арифметику, но я хочу выяснить где у меня ошибка?

Ошибка на стадии проектирования..
Я извиняюсь, но алгоритм у Вас если мягко сказать - очень замороченный. Что приводит к просто ужасной реализации в коде.
Задача вроде бы простая - скопировать тело команды в буфер команды, соответственно должна решаться простым способом даже без вычисления длины команды.
Пока не поздно упрощайте алгоритм (если уже не поздно..)..
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Mar 22 2006, 20:42
Сообщение #88


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



Всё ещё сложнее чем Вы думаете. smile.gif И вто же время достаточно симпатично в реализации.

На самом деле команд много и поступают непрерывно. Команды имеют переменную длину и структуру. Заносятся последовательно и там проблем не возникает. Исполняются только те команды которым подошло время. Т.н. активные. Исполняются пока не завершится время исполнения. С исполнением тоже проблем нет.
То что Вы видите, - это не занесение в буфер а "смерть" команды. Т.е. она отработала, и её надо выкинуть из буфера. Я конечно могу просто удалить указатель на данную команду, но тогда в памяти появится "дырка". Короче стандартная ситуация "сборки мусора", которая, как говорят, эффективно решена в UNIX, но плохо в Windows. smile.gif Известно и её решение в файловой системе диска начиная с FAT. По известной причине данные решения я применить не могу. smile.gif Поэтому я переписываю все команды следующие за удаляемой на место начиная с освобождённого. А также пересчитываю массив указателей на начало команд и уменьшаю их число. Всё это на PC работает и здесь ошибки нет, но компилятор почему-то не верно компилирует (точнее не так как я от него хочу).
Go to the top of the page
 
+Quote Post
defunct
сообщение Mar 22 2006, 21:37
Сообщение #89


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



1. избавляться от "дыр" в массиве можно скопировав последний элемент массива на место удаленного элемента и уменьшив размер массива на еденицу.
2. Для того чтобы было все гладко и смотрелось красиво, то неплохо бы для чистки "кучи" (если вы ее имели в виду) пользоваться прототипами функций memcopy, fillchar и т.п.

Сообщение отредактировал defunct - Mar 22 2006, 21:39
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Mar 23 2006, 21:39
Сообщение #90


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



В массиве только указатели на "команды". Команда представляет собой структуру. Разные команды - разные структуры. Одна занимает 14 байт, - другая - 150 байт. Друг в друга ни как не скопируешь. Насчёт мемcopy посмотрю. Не видел такой функции.
А всётаки что на счёт программы. Там 4 строчки. Описания переменных я дал. Смысл того что хочу сделать вроде объяснил. Где ошибка?
Алгоритм мой оценивать сложно так как вы видите очень малую часть общей картины.
Go to the top of the page
 
+Quote Post

7 страниц V  « < 4 5 6 7 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th July 2025 - 22:03
Рейтинг@Mail.ru


Страница сгенерированна за 0.01479 секунд с 7
ELECTRONIX ©2004-2016