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

 
 
> Распределение переменных в ОЗУ, как заставить Keil раскидать данные правильно??
AndreyS
сообщение Oct 17 2006, 10:30
Сообщение #1


Местный
***

Группа: Участник
Сообщений: 235
Регистрация: 28-01-05
Из: Санкт-Петербург
Пользователь №: 2 276



Добрый день всем.


Возник вопрос.

Какие настройки заставляют Keil раскидывать данные линейно, последовательно для ВСЕГО проекта?

Поясню.

Имею проект с 5 файлами. В каждом из файлов определил переменные доступные только для этого файла. При работе программы наблюдаю как одна (пока одна может и больше) переменная меняется не помоим законам. Что-то туда еще перекидывает данные. Закомментил все процедуры связанные с изменением этой переменной и все равно переменная дергается.

Как заставить Кеил построить для меня всю карту памяти для всего проекта? Что, куда она положила по каким адресам? Хочу найти перекрестные ссылки.

И еще как в настройках компилятора (не в коде) задать SP??? Хочется чтобы SP устанавливался один раз, а не дважды.


--------------------
Удачи.
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов (1 - 9)
rezident
сообщение Oct 17 2006, 10:35
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



С Keil не работаю, но хочу заметить, что самопроизвольное изменение данных бывает в основном в двух случаях:
1. "наползание" стека на область статических переменных (общий случай)
2. неправильная работа с указателями и/или работа с невыровненными структурами (это для программ на Си)
Go to the top of the page
 
+Quote Post
YAM
сообщение Oct 17 2006, 16:31
Сообщение #3


Местный
***

Группа: Свой
Сообщений: 256
Регистрация: 7-07-04
Из: Ukraine
Пользователь №: 291



Имею ту же давнюю проблему в Keil для 51-го... И это тянется практически от начала проекта (2001 год) и до текущей V8.02 компилятора. Так как проект очень большой и я использую far memory type support для доступа к данным, хранящимся во внешних EEPROM, да и проект довольно старый, уже и нет смысла переходить на IAR. В IAR я таких "глюков" не наблюдал, правда использую в нем только ARV и ARM. Эти глюки у меня проявляются в порче локальных переменных в функции при вызове других фуекций, т.к. компилятор почему-то выделяет для временных операций адреса тех-же переменных... Поэтому приходится извращаться таким способом:
uchar * data TDST;
uint data TSIZE;
void ymemclr(uchar *uk, uint size)
{
TDST = (uchar*)uk;
TSIZE = size;
do
{
*TDST++ = 0;
} while(--TSIZE);
}


--------------------
Go to the top of the page
 
+Quote Post
DimG
сообщение Oct 18 2006, 03:24
Сообщение #4


Участник
*

Группа: Свой
Сообщений: 70
Регистрация: 4-04-06
Из: г. Омск
Пользователь №: 15 777



Цитата
Как заставить Кеил построить для меня всю карту памяти для всего проекта? Что, куда она положила по каким адресам? Хочу найти перекрестные ссылки.

Полная карта памяти находится в файле с расширением .М51. Но я бы посоветовал вам другой способ. Установите прерывание по записи в данную ячейку памяти. Debug->Breakpoints, в поле Expression введите что-то типа d:0x73 и установите галочку в Write (думаю вы это знаете, но на всякий случай). После этого при каждой записи в эту ячейку вы увидите место в программе где она изменяется.
Цитата
Эти глюки у меня проявляются в порче локальных переменных в функции при вызове других фуекций, т.к. компилятор почему-то выделяет для временных операций адреса тех-же переменных...

Имеется ввиду при вызове из одной функции другой функции? Потому что в любом другом случае компилятор имеет полное право использовать те же ячейки памяти для другой функции, не сохраняя их в стек. На то они и локальные.
Со своей стороны могу посоветовать следующее. Если вы не хотите объявлять переменную в качестве глобальной, то объявите ее через static. При этом компилятор если и будет использовать эту ячейку памяти, то при этом обязательно сохронит ее в стек. Только не совмещайте объявление переменной и ее инициализацию, т.к. переменные static инициализируются один раз.
Цитата
Какие настройки заставляют Keil раскидывать данные линейно, последовательно для ВСЕГО проекта?

Посмотрите в С51.pdf подраздел Linker Locaition Controls.

Еще есть вероятность что ошибки с переменными связаны с использованием их в подпрограммах прерывания. Поскольку прерывание может возникнуть в любой момент, то компилятор не может гарантированно отследить правильность использования переменных. На этот случай при объявлении существует дополнительная директива, но сейчас я не помню какая, так что гляньте сами.

P.S. По своему опыту скажу, что ошибки компилятора маловероятны. Я делал проекты где использовалась только внутренняя память, и не было случая, где была бы вина компилятора, а не моя собственная от недопонимания языка или возможностей компилятора.

YAM, а нельзя прислать кусок программы с глюком, или целиком? Хотелось бы покопаться с этой проблемой.
Go to the top of the page
 
+Quote Post
rezident
сообщение Oct 18 2006, 03:42
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(DimG @ Oct 18 2006, 09:24) *
Цитата
Эти глюки у меня проявляются в порче локальных переменных в функции при вызове других фуекций, т.к. компилятор почему-то выделяет для временных операций адреса тех-же переменных...

Имеется ввиду при вызове из одной функции другой функции? Потому что в любом другом случае компилятор имеет полное право использовать те же ячейки памяти для другой функции, не сохраняя их в стек. На то они и локальные.

C этим я согласен.
Цитата(DimG @ Oct 18 2006, 09:24) *
Со своей стороны могу посоветовать следующее. Если вы не хотите объявлять переменную в качестве глобальной, то объявите ее через static. При этом компилятор если и будет использовать эту ячейку памяти, то при этом обязательно сохронит ее в стек. Только не совмещайте объявление переменной и ее инициализацию, т.к. переменные static инициализируются один раз.

А вот с этим не могу полностью согласиться. Статическая переменная отличается от глобальной лишь областью "видимости". "Видимость" у нее в пределах той функции в которой она объявлена. Ее значение в стек сохранять нет необходимости. Компилятор и так под нее выделяет постоянную ячейку ОЗУ, которая другими переменными не используется.
Цитата(DimG @ Oct 18 2006, 09:24) *
Еще есть вероятность что ошибки с переменными связаны с использованием их в подпрограммах прерывания. Поскольку прерывание может возникнуть в любой момент, то компилятор не может гарантированно отследить правильность использования переменных. На этот случай при объявлении существует дополнительная директива, но сейчас я не помню какая, так что гляньте сами.

Директива называется volatile. Например, обявление типа
Код
volatile unsigned cntr;

заставляет компилятор "перечитывать" значение переменной cntr каждый раз как оно используется так, как будто cntr меняется не программно, а аппаратно-непредсказуемо для компилятора, наподобие регистра какого-нибудь порта ввода.
Go to the top of the page
 
+Quote Post
DimG
сообщение Oct 18 2006, 06:10
Сообщение #6


Участник
*

Группа: Свой
Сообщений: 70
Регистрация: 4-04-06
Из: г. Омск
Пользователь №: 15 777



Цитата
(DimG @ Oct 18 2006, 09:24) quotecСо своей стороны могу посоветовать следующее. Если вы не хотите объявлять переменную в качестве глобальной, то объявите ее через static. При этом компилятор если и будет использовать эту ячейку памяти, то при этом обязательно сохронит ее в стек. Только не совмещайте объявление переменной и ее инициализацию, т.к. переменные static инициализируются один раз.QuoteEndQuoteEEndА вот с этим не могу полностью согласиться. Статическая переменная отличается от глобальной лишь областью "видимости". "Видимость" у нее в пределах той функции в которой она объявлена. Ее значение в стек сохранять нет необходимости. Компилятор и так под нее выделяет постоянную ячейку ОЗУ, которая другими переменными не используется.

Это уже на усмотрение компилятора, ведь ничего не мешает компилятору использовать эту ячейку под локальную переменную, сохранив ее значение, а после восстановив. Правда сказать, что компилятор Keil имеет такую возможность не могу. Но если она есть то будет использована только при нехватке памяти, это точно.
Go to the top of the page
 
+Quote Post
AndreyS
сообщение Oct 18 2006, 07:37
Сообщение #7


Местный
***

Группа: Участник
Сообщений: 235
Регистрация: 28-01-05
Из: Санкт-Петербург
Пользователь №: 2 276



Добрый день.

Огромное всем спасибо.

Буду учить мат часть wink.gif Просто подход к изучению Си для 51 был с изучения ANSI Си. Соответственно специфические директивы и объявления приходится изучать по ходу дела.

Бум читать.

Согласен, что в 99% виноват я сам. Но 1% - это удобное представление информации о компиляции проекта (карта памяти как ОЗУ так и ПЗУ).

То DimG:
По поводу бряки на изменение ячейки. Не получится это сделать в ядре (можно только в эмуляшке). Потому как в это момент снижается тактовая частота проца. Вернее, думаю, что частота остается прежней, просто отладчик часто тормозит ядро и перечитывает состояние ячейки и далее запускает его. В общем производительность падает, все тайминги растягиваются и приложение получается не работоспособно. Я обычно ставлю в код везде, где есть частый вызов (приревание например, или глобальный цикл) проверку переменной на изменение и после условия ставлю бряк. Это конечно не дает большой эффективности, приходится долго ждать.

Взглянул на M51 но там все перемешано. Есть ли возможность вывода всех DATA, CODE и XDATA в свои таблицы???


--------------------
Удачи.
Go to the top of the page
 
+Quote Post
rezident
сообщение Oct 18 2006, 08:11
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(AndreyS @ Oct 18 2006, 13:37) *
Согласен, что в 99% виноват я сам. Но 1% - это удобное представление информации о компиляции проекта (карта памяти как ОЗУ так и ПЗУ).

Если вам нужно наглядное представление глобальных переменных, то объявите одну глобальную структуру данных, которая будет состоять их мелких под-структур. Тогда точно все глобальные перменные будет лежать в одном месте ОЗУ и последовательно. Структуры удобно создавать с помощью typdef. А обращаться к ним через указатели.
например
Код
typdef struct st_uart
{
....
unsigned char uartBuf[20];
} st_uart;

typdef struct st_adc
{
....
} st_adc;

typdef struct st_var
{
.....
} st_var;

typedef struct st_globalData
{ st_uart uart0;
   st_adc adc0;
   st_val varl;
} st_globalData;


А потом перед main-ом объявляете
Код
st_globalData globalData;
st_globalData *pGD=&globalData;

Чтобы, например, обратиться ко 2-му символу в буфере UART в программе пишете
Код
unsigned char a;
a = pGD->uart0->uartBuf[1];

ну и т.д. и т.п. Может показаться, что писанины много, но зато имеем вполне переносимый на другие МК код.
Go to the top of the page
 
+Quote Post
Miron
сообщение Oct 18 2006, 08:34
Сообщение #9


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

Группа: Validating
Сообщений: 149
Регистрация: 11-02-05
Из: Рязань
Пользователь №: 2 574



Для 51 такие вещи встречались но как правило это
ошибка программиста. Это бывает в случае когда
прерывание объявлено для выполнения в одном
банке регистров а вызывает функцию скомпилированную
для другого банка.
SP устанавливается Keil обычно Startup по адресу
за всеми глобальными преременными + максимум
локальных. Я ни разу здесь у них ошибки не встречал.
Все переменные можно расположить по порядку их
объявления в программах воспользовавшись
флажком "Keep variables in order" закладка С51
"Options for target"
Go to the top of the page
 
+Quote Post
kolobok0
сообщение Dec 1 2006, 16:47
Сообщение #10


практикующий тех. волшебник
*****

Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417



Цитата(DimG @ Oct 18 2006, 03:24) *
.....P.S. По своему опыту скажу, что ошибки компилятора маловероятны.....



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

это так - к размышлению...
(круглый)
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


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


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