записать данные для регистрации - PullRequest
8 голосов
/ 16 апреля 2010

У меня есть адрес памяти определенного регистра (адрес LCDCW1 - C000).

c коды:

#define LCDCW1 0xC000

*LCDCW1=0x31;

Я просто хочу записать данные в этот регистр. Коды имеют проблемы, как это исправить?

ТНХ!

Ответы [ 5 ]

19 голосов
/ 16 апреля 2010

Вы можете, как другие предложили, объявить соответствующий указатель, т. Е.

volatile uint32_t *reg = (volatile uint32_t *)0xc000;

Обратите внимание, что я добавил квалификатор volatile. Это всегда хорошая идея при чтении или записи аппаратных регистров, поскольку она гарантирует, что каждый доступ, который вы выполняете в своем коде C, действительно отображается в сгенерированном коде.

Однако я обычно предпочитаю писать макросы вот так

#define READ_LCDCW1() ...
#define WRITE_LCDCW1(value) ...

и затем заполните их соответствующими gcc asms. Мне они нравятся лучше, чем прямое использование указателей, потому что:

  • Я думаю, что они читают лучше в коде, идентифицируя, что я делаю, читая регистр, вместо того, чтобы сосредоточиться на том, как я это делаю.
  • Для некоторых регистров требуется многоэтапный процесс чтения с аппаратного обеспечения. Это легко скрывается в макросах этого стиля, и большая часть моего кода все еще относится к интересующим меня регистрам, а не к сложному способу, которым аппаратные средства заставляют меня их трогать.
  • Наконец, используя asm s, я точно знаю, как я получаю доступ к регистру. Иногда существуют специальные инструкции или адресные пространства, необходимые для доступа к регистру, которые обычно не могут быть сгенерированы компилятором C.
  • Даже если вы не согласны с мотивацией использования операторов asm, я бы по-прежнему предлагал обернуть ваши обращения к реестру в макросы (или встроенные функции), подобные этим.

В вашем случае самые простые определения должны быть:

#define LCDCW1_ADDR       0xc000
#define READ_LCDCW1()     (*(volatile uint32_t *)LCDCW1_ADDR)
#define WRITE_LCDCW1(val) ((*(volatile uint32_t *)LCDCW1_ADDR) = (val))
4 голосов
/ 17 апреля 2010

Я полагаю, что одно слово предостережения относительно использования ключевого слова volatile в порядке.

Иногда (часто) то, что компилятор считает изменчивым, означает не то, что задумал программист (и наоборот). Рекомендуется всегда проверять полученный машинный код при использовании ключевого слова volatile во избежание неожиданностей.

Дополнительные ссылки см., Например, http://www.cs.utah.edu/~regehr/papers/emsoft08-preprint.pdf

1 голос
/ 16 апреля 2010

LCDCW1 это просто целочисленное значение. Вы не можете сделать * на этом. Вам нужно привести его к целочисленному (или нужному вам типу) указателю, а затем использовать его. Например: *(int*)LCDCW1=0x31;

1 голос
/ 16 апреля 2010

Предполагая, что регистр имеет тот же размер, что и long:

volatile long * ldccw1 = (long*)0xc000;

*lcdcw1 = myValue;
0 голосов
/ 16 апреля 2010

Я не знаю, что означает LCDCW1, но писать на постоянный адрес:

*(int*)0xC000 = 42;

Подгоните под костюм (ваш регистр может не иметь размер int).

...