2013-03-07 5 views
7

Поскольку я относительно новичок в C, я должен использовать для одного из своих проектов следующее: Я должен объявить некоторые глобальные переменные, которые нужно хранить каждый раз, когда программа работает с одним и тем же адресом памяти. Я прочитал некоторые, и я обнаружил, что я объявляю его «статическим», он будет храниться в том же месте памяти.Как сохранить переменную в определенной ячейке памяти?

Но мой вопрос: могу ли я указать программу, где хранить эту переменную или нет. Например: int a для сохранения в 0xff520000. Можно ли это сделать или нет? Я искал здесь, но не нашел подходящего примера. Если это какой-то старый пост, касающийся этого, пожалуйста, будьте добры, чтобы поделиться ссылкой.

Благодарим вас заблаговременно. Лауренцию

Обновление: Я не буду с помощью 32uC

+1

Это общепринятое на встраиваемые системы, чтобы иметь аппаратные регистры по конкретным адресам. Тем не менее, на обычном ПК невозможно предсказать, где ваши переменные закончатся, и вы можете аналогичным образом не размещать переменные в определенных ячейках памяти, так как карта памяти программы не фиксирована. Это для встроенной системы или для обычного ПК? –

+1

Почему адрес имеет значение? В любом случае это ** виртуальная ** память. – UmNyobe

+0

Здравствуйте, я должен сделать следующее. Сделайте своего рода тестовую платформу для 32-битного UC, но после прошивки через OCD платформа должна иметь (запускать) связь UART. И, допустим, у меня есть счетчик, который подсчитывает, сколько времени программа запустила, или счетчик, сохраняющий, сколько раз программа запускается без ошибок, а затем мой профессор, что дать в качестве входа через Hyper Terminal адрес, где находится этот счетчик переменных, чтобы получить его ценность. Это то, что мне нужно .. любые идеи: – Laurentiu

ответ

10

В вашей IDE появится карта памяти, доступная через какой-либо файл-линкера. Он будет содержать все адреса в программе. Прочтите руководство MCU, чтобы узнать, на каких адресах есть действительная память для вашей цели, а затем зарезервируйте часть этой памяти для своей переменной. Вы должны прочитать документацию своей конкретной платформы разработки.

Далее, обратите внимание, что нет смысла сопоставлять переменные по конкретным адресам, если они не являются либо аппаратными регистрами, либо энергонезависимыми переменными, находящимися во флэш-памяти или EEPROM.

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

У конкретного компилятора, скорее всего, есть нестандартный способ распределения переменных по конкретным адресам, например, #pragma или иногда странный нестандартный оператор @. Единственный разумный способ можно выделить переменную в фиксированном положении в стандартном C, заключается в следующем:

#define MY_REGISTER (*(volatile uint8_t*)0x12345678u) 

где 0x12345678 это адрес, где 1 байт, который расположен. Если у вас есть макрос заявление, как это, вы можете использовать его, как если бы это была переменная:

void func (void) 
{ 
    MY_REGISTER = 1; // write 
    int var = MY_REGISTER; // read 
} 

Чаще всего вы хотите такого рода переменных находятся в глобальном пространстве имен, следовательно, макрос. Но если вы по какой-то причине хотите область переменного быть уменьшены, а затем пропустить макрос и получить доступ к адресу вручную в коде:

void func (void) 
{ 
    *(volatile uint8_t*)0x12345678u = 1; // write 
    int var = *(volatile uint8_t*)0x12345678u; // read 
} 
+0

Спасибо.Это то, чего я хотел. Я взял ваш совет и нашел следующую: ПАМЯТЬ Ира \t: ORIGIN = 0x00000000, \t LENGTH = 3072k Ирам \t: ORIGIN = 0xFEDC0000, \t LENGTH = 256k Буров \t: ORIGIN = 0xFF760000, \t LENGTH = 16k
Я полагаю, я нужно выбрать некоторый диапазон из ОЗУ из того, что мне нужно? – Laurentiu

+1

Кстати: Я почему вы использовали адрес, как 0x12345678u? что представляют собой от конца? – Laurentiu

+2

@ Laurentiu Суффикс 'u' (или' U') означает, что целочисленный литерал имеет тип 'unsigned'. Именно там, чтобы гарантировать, что используется отступы, я написал его в основном из старой привычки. Целочисленный литерал в источнике C имеет тип (подписанный) 'int' по умолчанию, но поскольку адрес никогда не может быть отрицательным, нет смысла использовать подписанную переменную для его хранения. В общем, вы никогда не хотите использовать тип 'int' по умолчанию во встроенных системах. В некоторых случаях при выполнении простой арифметики вы можете использовать типы 'sintN_t', где N = 8, 16 и т. Д. Но большую часть времени вы используете только неподписанные переменные. – Lundin

1

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

0

Не на уровне C. Если вы работаете со языком ассемблера, вы можете напрямую управлять макетом памяти. Но компилятор C делает это за вас. Вы не можете с этим покончить.

Даже с монтажом это контролирует только относительную компоновку. Виртуальная память может разместить это в любом удобном физическом месте.

8

Вы можете делать подобные вещи с помощью сценариев компоновщика, что довольно часто встречается во встроенном программировании.

В системе Linux вы, возможно, никогда не получите тот же виртуальный адрес из-за рандомизации адресного пространства (функция безопасности, чтобы избежать эксплойтов, которые полагались бы на то, чтобы точно знать местоположение переменной, как вы описали).

Если это всего лишь повторяемый указатель, который вы хотите, вы можете сопоставить определенный адрес с mmap, но это не гарантируется.

+0

Правда. Как я думаю, используя mmap, чтобы отобразить адресное пространство в файл, можно решить проблему. Его просто нужно будет позаботиться о том, чтобы mmap (CONST_ADDR, ....., fd, CONST_FILE_OFFSET); (или карта на diff-addr, чем COSNT_ADDR). Затем CONST_ADDR становится адресом глобальной переменной, и изменения, внесенные в этот глобальный счетчик, будут отображаться в файле, который может быть использован далее в следующей программе. –

0

Вы можете сделать это с помощью некоторых расширений для компилятора, но это, вероятно, не то, что вы хотите сделать. Операционная система обрабатывает вашу память и будет размещать вещи там, где они хотят. Как вы даже знаете, что адрес памяти, который вы хотите, будет отображаться в вашей программе? Игнорируйте все в этом абзаце, если вы находитесь на встроенной платформе, тогда вы должны прочитать руководство для этой платформы/компилятора или хотя бы упомянуть об этом здесь, чтобы люди могли дать более конкретный ответ.

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

0

Вы можете объявить указатель на определенный адрес памяти, и использовать содержимое этого указателя в качестве переменной, я полагаю:

int* myIntPointer = 0xff520000; 
+0

typecast it .... – anishsane

1

Как упоминалось в других ответах - вы не можете. Но у вас может быть обходной путь. Если это нормально для глобалов быть инициализированы в main(), вы можете сделать что-то такого рода:

int addr = 0xff520000; 

int main() 
{ 
    *((int*)addr) = 42; 
    ... 
    return 0; 
} 

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

+0

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

+0

@Laurentiu В вашей среде IDE появится карта памяти, доступная через какой-либо файл-линкера. Он будет содержать все адреса в программе. Прочтите руководство MCU, чтобы узнать, на каких адресах есть действительная память для вашей цели, а затем зарезервируйте часть этой памяти для своей переменной. Вы должны прочитать документацию своей конкретной платформы разработки. – Lundin

Смежные вопросы