简体   繁体   中英

How to set bits in registers?

There is address of registry (first?) SPI1. There is structure with offsets. I suppose it means that SPI1_REG_BASE + offset = address of some SPI registry

#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;

There are some definitions and the definition of pointer *spi

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

I misunderstood setting of bits. For example,

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

I understand that SPIDEF - is SPI register which has offset address 4Ch
(0x01F0E000 + 0x4C). But why CSDEF0 is bit 0 ?? There is a field CSDEF in SPIDEF registry (0-7 bits). Is it mean that 7 bit of CSDEF has address 0x00000008 ? and 5 bit has address 0x00000006?

But then why CSHOLD field of SPIDAT1 registry has address 0x10000000 ??

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

SPIDAT1 register has offset address 3Ch (0x01F0E000 + 0x3C) It truly has field CSHOLD (28st bit)

How does |= work in this situation?

I'll be grateful for any help for figuring out... all this %)

I think you are misunderstanding the notions of address and value of the registers.

You are right (based on the structure description you gave) when you say that the CSDEF0 register of the SPI1 module is located at address 0x01F0E000 + 0x4C . This address will never change, it is defined by the hardware design.

Now with the following statements you are not manipulating addresses but values of the registers:

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

The |= operator is a bitwise OR and assign operator. It is equivalent to the following :

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

As CSDEF0 is defined to 0x00000001 , in the first statement you are effectively setting the LSB bit of the SPIDEF register, leaving all other bits to their original value.

But why CSDEF0 is bit 0 ?

Because of:

#define CSDEF0 (0x00000001) //bit 0

What they mean is not a "bit with value 0" but "the bit at position 0".

And concerning the:

#define CSHOLD (0x10000000) //bit 28

Take a look at converting hex-notation to binary-notation and it will become clear.

How does |= work in this situation?

The 1-bits AT those positions (0 and 28) are or'ed into the value that was previously in that variable.

But why CSDEF0 is bit 0 ??

The purpose of this macro is to set bit-0 to 1. If this macro is ORed with any register, then that register's bit-0 is set to 1.

For example

Lets take spi->SPIDEF = 0x050A ie 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

why CSHOLD field of SPIDAT1 registry has address 0x10000000??

Same-way how CSDEF0 is used to represent 0th bit, CSHOLD is used for 28th bit.

I guess you confused with Hexa-deciamal and binary representation of 0x000001 and 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

Bits don't have individual addresses.

Instead a common practise in embedded world is to concatenate several small attributes to a larger register. eg one could define some internals of realtime scheduler as:

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

Here max_priority would be 5-bit unsigned integer having values 0-31; One could as well define max_priority0 being the least significant bit of that value. All these parameters would be accessed within the same absolute address (REG_BASE + offset).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM