How to change a 32bit registers specific bits without changing other bits?

别等时光非礼了梦想. 提交于 2019-12-12 08:47:46

问题


I want to manipulate some bits of a register directly using its physical address. However I couldn't find a way to make this. I saw some posts about setting bit masks but I find them too confusing.

My registers physical address is: 0x4A10005C

I want to manipulate its bit which was between 18-16 bits. I want to set 0x3 inside those bits.

I will be really glad if you guys can provide an answer or a way to do it. Thanks.


回答1:


You can just define a pointer to the register and then use normal C bitwise operations to manipulate the individual bits:

volatile uint32_t * const my_register = (uint32_t *) 0x4A10005C;
                              // set up a pointer to the register

uint32_t val = *my_register;  // read register

val &= ~(0x7 << 16);          // clear bits 16..18

val |= (0x3 << 16);           // set bits 16..18 to 0x03 (i.e. set bits 16 and 17)

*my_register = val;           // write register

(The above assumes that you are talking about three bits within the register, bits 16, 17 and 18, and that you want to set bit 18 to zero and bits 16 and 17 to 1.)




回答2:


bit masks are pretty easy to understand so let’s run through that first:

Let say your 32bit register contains some value right now I'll arbitrarily pick 0xF48C621916

I assume you know how to convert hex to binary, if not... let's just say use a calculator or google (rather than go into the nitty gritty of that too). So our hex value can be represented in binary as:

+-- bit 31                            +-- bit 0
|                                     |
v                                     v 
1111 0100 1000 1100 0110 0010 0001 1001
                ^ ^                       
                | |
                +-+-- bits you want to set, 16-18

Boolean logic tells us that:
1) anything OR'd (|) with 1 gives you a value of 1. Or "sets" the bit.
2) anything AND'd (&) with 0 gives you a value of 0. Or "clears" the bit.

So if we wanted to clear bits 16-18 you can AND it with a mask like:

base number: 1111 0100 1000 1100 0110 0010 0001 10012 == 0xF48C621916
mask number: 1111 1111 1111 1000 1111 1111 1111 11112 == 0xFFF8FFF16

   1111 0100 1000 1100 0110 0010 0001 1001
&  1111 1111 1111 1000 1111 1111 1111 1111
------------------------------------------
   1111 0100 1000 1000 0110 0010 0001 1001

Now you can OR it with whatever you want to set there:

new mask number: 0000 0000 0000 0011 0000 0000 0000 00002 == 0x0003000016

  1111 0100 1000 1000 0110 0010 0001 1001
| 0000 0000 0000 0011 0000 0000 0000 0000
-----------------------------------------
  1111 0100 1000 1011 0110 0010 0001 1001

So in the code:

#define CLEAR_MASK 0x70000 //70000 is shorter to write, so just do this and flip it
#define SET_3_MASK 0x30000

volatile uint32_t * const reg = (uint32_t *) 0x4A10005C;//set a pointer to the register
*reg &= ~CLEAR_MASK; //~ filps the bits
*reg |= SET_3_MASK;

You can do tricks with shifting bits and so forth, but this is the basics of bit masks and how they work. Hope it helps.




回答3:


structure r32 {
unsigned int bit0  :1;
unsigned int bit1  :1;
unsigned int bit2  :1;
unsigned int bit3  :1;
unsigned int bit4  :1;
unsigned int bit5  :1;
.
.
.
unsigned int bit31 :1;
}

in your main

structure r32 *p;
volatile uint32_t * const my_register = (uint32_t *) 0x4A10005C;

p = (structure r32 *) my_register;

and then to access to bit 5 for example

p->bit4 = 0;


来源:https://stackoverflow.com/questions/13196387/how-to-change-a-32bit-registers-specific-bits-without-changing-other-bits

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!