Как установить биты в регистры?

Есть адрес реестра (первый?) SPI1. Существует структура с смещениями. Я полагаю, это означает, что SPI1_REG_BASE + offset = адрес какого-либо реестра SPI

#define SPI1_REG_BASE         (0x01F0E000)
//-----------------------------------------------------
//Register Structure & Defines
//-----------------------------------------------------
typedef struct
{
  volatile uint32_t SPIGCR0;       //0x0000
  volatile uint32_t SPIGCR1;       //0x0004
  volatile uint32_t SPIINT;        //0x0008
  volatile uint32_t SPILVL;        //0x000C
  volatile uint32_t SPIFLG;        //0x0010
  volatile uint32_t SPIPC0;        //0x0014
  volatile uint32_t SPIPC1;        //0x0018
  volatile uint32_t SPIPC2;        //0x001C
  volatile uint32_t SPIPC3;        //0x0020
  volatile uint32_t SPIPC4;        //0x0024
  volatile uint32_t SPIPC5;        //0x0028
  volatile uint32_t RSVD0[3];      //0x002C
  volatile uint32_t SPIDAT0;       //0x0038
  volatile uint32_t SPIDAT1;       //0x003C
  volatile uint32_t SPIBUF;        //0x0040
  volatile uint32_t SPIEMU;        //0x0044
  volatile uint32_t SPIDELAY;      //0x0048
  volatile uint32_t SPIDEF;        //0x004C
  volatile uint32_t SPIFMT0;       //0x0050
  volatile uint32_t SPIFMT1;       //0x0054
  volatile uint32_t SPIFMT2;       //0x0058
  volatile uint32_t SPIFMT3;       //0x005C
  volatile uint32_t INTVEC0;       //0x0060
  volatile uint32_t INTVEC1;       //0x0064
} spi_regs_t;

Существуют некоторые определения и определение указателя * spi

#define CSDEF0 (0x00000001) //bit 0
#define CSHOLD (0x10000000) //bit 28
spi_regs_t *spi = (spi_regs_t *)SPI1_REG_BASE; 

Я неправильно понял бит. Например,

spi->SPIDEF |= CSDEF0 //set 0 bit in the registry field 

Я понимаю, что SPIDEF - это регистр SPI, который имеет адрес смещения 4Ch
(0x01F0E000 + 0x4C). Но почему CSDEF0 бит 0 ?? В реестре SPIDEF есть поле CSDEF (0-7 бит). Это означает, что 7 бит CSDEF имеет адрес 0x00000008? и 5 бит имеет адрес 0x00000006?

Но тогда почему в поле CSHOLD реестра SPIDAT1 есть адрес 0x10000000 ??

spi->SPIDAT1 |= CSHOLD  //set bit 28

Регистр SPIDAT1 имеет адрес смещения 3Ch (0x01F0E000 + 0x3C) У этого действительно есть поле CSHOLD (28-й бит)

Как работает = в этой ситуации?

Буду благодарен за любую помощь в выяснении ... все это%)

1
nl ja de

4 ответы

Я думаю, вы недооцениваете понятия адреса и ценности регистров.

Вы правы (на основе описания структуры, которое вы указали), когда вы говорите, что регистр CSDEF0 модуля SPI1 расположен по адресу 0x01F0E000 + 0x4C . Этот адрес никогда не изменится, он определяется аппаратным дизайном.

Теперь со следующими утверждениями вы не манипулируете адресами, а значениями регистров:

spi->SPIDEF |= CSDEF0; //set 0 bit in the registry field 
spi->SPIDAT1 |= CSHOLD;  //set bit 28

Оператор | = является побитовым OR и назначает оператор. Это эквивалентно следующему:

spi->SPIDEF = spi->SPIDEF | CSDEF0; //set 0 bit in the registry field 
spi->SPIDAT1 = spi->SPIDAT1 | CSHOLD;  //set bit 28

Поскольку CSDEF0 определяется как 0x00000001 , в первом утверждении вы эффективно устанавливаете бит LSB регистра SPIDEF , оставляя все остальные биты в своих первоначальное значение.

4
добавлено
greydet, спасибо! spi-> SPIDEF | = 0x00000002 установит 1-й бит значения, который хранится в этом реестре, потому что 0x00000002 - 10 в двоичном представлении, поэтому мы устанавливаем 1-й бит.
добавлено автор Myosotis, источник

Но почему CSDEF0 бит 0 ??

Цель этого макроса - установить бит-0 в 1. Если этот макрос ORed с любым регистром, то бит-0 этого регистра установлен в 1.

Например

Lets take spi->SPIDEF = 0x050A i.e 0x050A ==> 0000 0101 0000 1010

Now setting 0th bit of spi->SPIDEF using CSDEF0 .

0x050A     ==> 0000 0101 0000 1010 
CSDEF0     ==> 0000 0000 0000 0001
               --------------------

spi->SPIDEF ==> 0000 0101 0000 1011

почему в поле CSHOLD реестра SPIDAT1 есть адрес 0x10000000 ??

Точно так же, как CSDEF0 используется для представления 0-го бита, CSHOLD используется для 28-го бита.

Я думаю, вы запутались с гекса-дециамальным и двоичным представлением 0x000001 и 000001 (???).

0x01 is 01. 
0x02 is 10. 
0x100 is 1 0000 0000 
0x1000 is 1 0000 0000 0000 
0x10000000 is 1 0000 0000 0000 0000 0000 0000 0000
              ^-- Bit 28 starting from bit-0
1
добавлено
Верный. вы можете использовать этот CSDEF5 для установки 5-го бита другого регистра на 1 тоже :)
добавлено автор Jeyaram, источник
причина для downvote ??
добавлено автор Jeyaram, источник
Jeyaram, большое вам спасибо за подробное объяснение! CSDEF5 = 0x20 (HEX) 0000 0000 0010 0000 (bin) и представляет 5-й бит значения в spi-> SPIDEF? Правильно ли это?
добавлено автор Myosotis, источник

Но почему CSDEF0 бит 0?

Из-за:

#define CSDEF0 (0x00000001) //bit 0

То, что они означают, не является «бит со значением 0», а «бит в позиции 0».

И относительно:

#define CSHOLD (0x10000000)//бит 28

Взгляните на преобразование шестнадцатеричной нотации в двоичную нотацию, и это станет ясно.

Как работает | = в этой ситуации?

1-бит AT эти позиции (0 и 28) равны or'ed в значение, которое было ранее в этой переменной.

1
добавлено
@Myosotis 0x10000000 - b10000000000000000000000000000 бит в индексе 28 имеет значение 1.
добавлено автор Bernd Elkemann, источник
Спасибо, за ответ! Я преобразовал CSHOLD в HEX. Это 128. Я до сих пор не понимаю, как определить адрес бит в позиции 29?
добавлено автор Myosotis, источник
@eznme точно! 0x10000000 - это шестнадцатеричное представление, а не двоичное. еще раз спасибо :)
добавлено автор Myosotis, источник
Нет адресов бит . Для работы с бит 29 вы используете integer , у которого установлен бит 29. Это целое число (1u << 29) , a.k.a. 0x20000000 . Вы используете something | = (1u << 29) , чтобы установить бит 29, something & = ~ (1u << 29) , чтобы очистить бит 29, и ( something & (1u << 29)) >> 29 для проверки бит 29.
добавлено автор Anton Kovalenko, источник

Биты не имеют индивидуальных адресов.

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

   31 30 29 28 27     26 25 24 32 22     21 20 19     18          0
 [ max_priority  ] [ current_priority] [ reserved]   [  address_xxxx ]

Здесь max_priority будет 5-битным беззнаковым целочисленным числом, имеющим значения 0-31; Можно также определить max_priority0 как наименее значащий бит этого значения. Все эти параметры будут доступны в пределах одного и того же абсолютного адреса (смещение REG_BASE +).

1
добавлено