그림자.
뗄래야 뗄 수 없는 관계.
매일 따라 다니는 검은 그것은 그림자.
공포영화 제목도 아니고. 쩝.
ㅋ. Shadow는 그림자이지요. 뗄래야 뗄 수 없는 관계. 그렇습니다. Shadow는 그런 의미에요. 같은 놈이지만, 같은 놈이 아닌. 실은 Shadow는 backup과 같은 의미에요. Register에 많이 쓰이는 개념인데요, Register중에 쓰기만 가능하고 읽기가 불가능한 Register들이 있다고 했죠. 그런 녀석들을 전역변수에 backup을 해 놓고, 언제라도 그 값을 읽어 볼 수 있도록 해주는 개념이지요.
보통 Shadow라고 이름 붙인 녀석들은 대부분 이런 backup의 역할을 해줘요. 꼭 Register에만 쓰느냐! 그건 아니고요. ㅋ 대부분 Register에 많이 쓴다는 거죠 뭐. 자, 그러면. Register 얘기를 실컷 하다 보니까, Register라는 게 Bit별로 설정이 가능한 Latch라고 했으니까. Bit를 잘 다뤄야겠다는 생각입니다. 어떤 값에서 Bit만 따로 mask를 씌워서 검사하려면, 어떻게 해야 할 까요. 바로 & 연산자를 이용하는 거죠 뭐. 별거 있나요.
만약에 6번째 bit가 어떤 값인지 보려면 어떻게 해야 할까요.
if (reg_data& 0x20) → binary 100000 이므로, reg_data의 6번째 bit가 1인지 확인이 가능하겠죠. 1이면 if() 값이 True가 될 꺼고, 0이면 if()값이 False가 될 테니까요. 이때, 이런 이때 0x20을 mask라고 불러요. mask를 씌우면 눈구멍 콧구멍 입 구멍만 빼고 모두 감춰주죠. 뭐 그런 의미로 내가 원하는 곳만 보겠다는 의미이에요.
어떨 때는 계산하기 귀찮으면, Shift를 이용해서 원하는 bit의 값을 빼낼 수도 있지요!
if (reg_data>>6 & 0x1) 또는 if (reg_data & (1<<6))으로도 표현 가능하겠죠.
뭐 어떻게든 가능합니다. 저는 Shift하는 방법을 선호합니다. 머리가 좀 나빠서요. ㅋ 원하는 bit의 값을 LSB로 내려올 수 있도록 Shift시켜서 빼낼 수 있겠지요.
이렇게 하면 2bit 짜리도 빼낼 수 있어요.
reg_data>>6 & 0x3 이렇게 해주면 bit 6, 7을 한꺼번에 빼낼 수도 있겠죠. 보통 Register가 bit단위로 control가능하지만 2bit, 3bit짜리 들도 있답니다. 우훗!
그러면 내가 원하는 곳의 값을 빼내기도 했으니까, Bit를 설정하거나, Clear하거나, 반전시키는 방법도 있겠죠. 어떻게 하면 좋을까요. Bit값을 설정할 때는 Mask를 OR 하면 되겠지요 캬캬.
예를 들어 bit 3을 1로 set하고 싶으면 (bit 3은 4번째 bit에요 왜냐하면, bit는 0번째 자리부터 세거든요)
reg_data = reg_data | 0x8;
reg_data = reg_data | (0x1<<3);
또는
reg_data |= (0x1<<3) 등으로 표현하면 되겠죠. 원래 무슨 값이 들어 있던지 1로 setting이 가능합니다.
그럼 반대로 clear하는 방법도 있겠죠. Clear하는 방법은 다른 bit는 모두 1로 만든 후에 원하는 bit를 0으로 해두고 & 해버리면 되겠죠!
reg_data &= ~ (1<<3); 로 구현 가능하겠네요.
~(1<<3)은 3번째 bit만 0이고 나머지는 모두 1을 갖는 mask가 되겠죠!
또는 잘 안 쓰는 방법이긴 한데, 논리합인 XOR를 이용하는 방법도 있어요. XOR는 두 값이 같으면 0, 두 값이 다르면 1의 결과 값을 갖죠.
reg_data ^= (1<<3)을 하게되면? 3번째 bit가 0일 때는 1이 되고 1일 때는 0이 되는 거지요!
그런데 이도 저도 다 귀찮으면 다음의 방법도 bit 단위로 관리할 수 있는 Data type도 있어요. 비트 필드를 이용하는 건데요, 아래처럼 선언하면 bit 단위로 값을 처리할 수 있답니다요. 32bit짜리 REGISTER_SHADOW type을 선언해서, 32 bit를 bit 단위 별로 의미를 두어 field를 만들 수 있답니다.
typedef struct
{
int32 f lag : 3; /* flag 3 bit */
data_1 : 20 ; /* data_1 : 20 bit */
data_2 : 9 ; /* data_2 : 9 bit */
} REGISTER_SHADOW;
요잇! 사용하는 방법은 간단해요. REGISTER_SHADOW type의 변수를 선언 한 다음에 각 bit를 field로 이용하면 되어요.
REGISTER_SHADOW R_0;
R_0.flag = 2;
R_0.data_1 = 16;
R_0.data_2 = 22;
이런 식으로..요.. 정말 무궁무진 하지요?
Shadow의 개념과 Bit operation
친절한 임베디드 개발자 되기 강좌 글 전체 리스트 (링크) -
댓글