|
Распределение переменных в ОЗУ, как заставить Keil раскидать данные правильно?? |
|
|
|
 |
Ответов
(1 - 9)
|
Oct 18 2006, 03:24
|
Участник

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

|
Цитата Как заставить Кеил построить для меня всю карту памяти для всего проекта? Что, куда она положила по каким адресам? Хочу найти перекрестные ссылки. Полная карта памяти находится в файле с расширением .М51. Но я бы посоветовал вам другой способ. Установите прерывание по записи в данную ячейку памяти. Debug->Breakpoints, в поле Expression введите что-то типа d:0x73 и установите галочку в Write (думаю вы это знаете, но на всякий случай). После этого при каждой записи в эту ячейку вы увидите место в программе где она изменяется. Цитата Эти глюки у меня проявляются в порче локальных переменных в функции при вызове других фуекций, т.к. компилятор почему-то выделяет для временных операций адреса тех-же переменных... Имеется ввиду при вызове из одной функции другой функции? Потому что в любом другом случае компилятор имеет полное право использовать те же ячейки памяти для другой функции, не сохраняя их в стек. На то они и локальные. Со своей стороны могу посоветовать следующее. Если вы не хотите объявлять переменную в качестве глобальной, то объявите ее через static. При этом компилятор если и будет использовать эту ячейку памяти, то при этом обязательно сохронит ее в стек. Только не совмещайте объявление переменной и ее инициализацию, т.к. переменные static инициализируются один раз. Цитата Какие настройки заставляют Keil раскидывать данные линейно, последовательно для ВСЕГО проекта? Посмотрите в С51.pdf подраздел Linker Locaition Controls. Еще есть вероятность что ошибки с переменными связаны с использованием их в подпрограммах прерывания. Поскольку прерывание может возникнуть в любой момент, то компилятор не может гарантированно отследить правильность использования переменных. На этот случай при объявлении существует дополнительная директива, но сейчас я не помню какая, так что гляньте сами. P.S. По своему опыту скажу, что ошибки компилятора маловероятны. Я делал проекты где использовалась только внутренняя память, и не было случая, где была бы вина компилятора, а не моя собственная от недопонимания языка или возможностей компилятора. YAM, а нельзя прислать кусок программы с глюком, или целиком? Хотелось бы покопаться с этой проблемой.
|
|
|
|
|
Oct 18 2006, 03:42
|
Гуру
     
Группа: Свой
Сообщений: 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 меняется не программно, а аппаратно-непредсказуемо для компилятора, наподобие регистра какого-нибудь порта ввода.
|
|
|
|
|
Oct 18 2006, 06:10
|
Участник

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

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

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

|
Добрый день. Огромное всем спасибо. Буду учить мат часть  Просто подход к изучению Си для 51 был с изучения ANSI Си. Соответственно специфические директивы и объявления приходится изучать по ходу дела. Бум читать. Согласен, что в 99% виноват я сам. Но 1% - это удобное представление информации о компиляции проекта (карта памяти как ОЗУ так и ПЗУ). То DimG: По поводу бряки на изменение ячейки. Не получится это сделать в ядре (можно только в эмуляшке). Потому как в это момент снижается тактовая частота проца. Вернее, думаю, что частота остается прежней, просто отладчик часто тормозит ядро и перечитывает состояние ячейки и далее запускает его. В общем производительность падает, все тайминги растягиваются и приложение получается не работоспособно. Я обычно ставлю в код везде, где есть частый вызов (приревание например, или глобальный цикл) проверку переменной на изменение и после условия ставлю бряк. Это конечно не дает большой эффективности, приходится долго ждать. Взглянул на M51 но там все перемешано. Есть ли возможность вывода всех DATA, CODE и XDATA в свои таблицы???
--------------------
Удачи.
|
|
|
|
|
Oct 18 2006, 08:11
|
Гуру
     
Группа: Свой
Сообщений: 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]; ну и т.д. и т.п. Может показаться, что писанины много, но зато имеем вполне переносимый на другие МК код.
|
|
|
|
|
Dec 1 2006, 16:47
|
практикующий тех. волшебник
    
Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417

|
Цитата(DimG @ Oct 18 2006, 03:24)  .....P.S. По своему опыту скажу, что ошибки компилятора маловероятны..... Кеил2 (в третьем не замечено) азм.. иногда без видимых причин выкидывание кода. в файле lst явно видны огрехи компилятора...в форумах находил человека у которого было такое же проявление...предпологаю - большой объём проекта...хотя хз...глюк пропадает после вставки-клмпиляции-удаления_вставки любой команды..хоть ноп... это так - к размышлению... (круглый)
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|