임베디드

16. 구조체

sdafdq 2026. 2. 4. 12:26
typedef struct
{
  __IO uint32_t ACR;
  __IO uint32_t KEYR;
  __IO uint32_t OPTKEYR;
  __IO uint32_t SR;
  __IO uint32_t CR;
  __IO uint32_t AR;
  __IO uint32_t RESERVED;
  __IO uint32_t OBR;
  __IO uint32_t WRPR;
} FLASH_TypeDef;

여기서 uint32_t란 무엇이냐.

 

일단 u, unsigned int 32bit type 이란 뜻.

저건 우리가 평상시 쓰는 기본 타입은 아니고,

기본 라이브러리 중 stdint.h  에 정의되어 있음.

 

저걸 쓰는 이유. MCU같은 것은 정확히 32bit 맞춰야 하기 때문.

하드웨어랑 맞췄다고 보면 됨. 그래야 딱 주소도 정확히 짚으니까.

 

 

그래서 만약 ACR 주소를 0번지로 해 놓으면, KEYR값은 4번지(32비트, 4바이트)가 됨.

구조체도 배열이랑 비슷하게 합쳐놓음.

 

그럼 저 __IO는 뭐냐,

 

volatile랑 같은거임.

이거는 전처리문이라 걍 치환시켜주는거라.. 

일단 volatile같은 경우 const같은 한정자 같은 거임.

즉.. 타입 앞에 같이 쓰는 그런거임..

 

그래서 volatile가 무슨 역할을 하냐, 최적화 금지.

이게 무슨소리냐면, 컴파일러가 똑똑해서 최적화를 함.

 

예를 들어,

int a = 3;
a = 7;
a = 8;
a = 12;

printf("%d\n", a);

이렇게 했을 경우, 컴파일러가 보기에는 3, 7,8은 사용하지가 않음.

그래서, 

int a = 12;

printf("%d\n", a);

컴파일하면서 이렇게 고칠 수도 있음. 아마 2진수로 고칠 때?

 

 

근데 임베디드는 a가 어떤 핀의 상태를 바꾸는 것 처럼, 

ACR을 버퍼 미리 읽기 기능을 키는 것 처럼, 프로그래밍 내에서 저걸 활용하는 게 아니라 값만 바꾸는 걸 수도 있음.

 

그러면 내가 암만 코드로 저것의 상태값을 바꿔도 컴파일러가 최적화를 한다고 결국 마지막인 12로 옴.

 

그래서 그런 최적화 하지 말고, 그냥 곧이 곧대로 하라고 하는 거임.

 

*a = 0x03;
while(){
    *a |= 1;
    *a |= 0;
}

printf("%d", a);

저 while문 안에 있는 게 제대로 안먹힐 수 있다는 이야기.

프로그래밍 상에서는 활용을 안하니, 컴파일러는 필요없는 값으로 인식할 수 있으니.

 

 

또,

a = 3
while(){
    if(a){
    	~~~~~
    }
}

이럴 경우 a를 굉장히 자주쓰니까,

최적화 한다고 저 값을 빨리빨리 반영하기 위해 메모리가 아닌 CPU가 자기 레지스터에 넣고 활용할 수 있음.

그러면 메모리가 아니라 CPU의 레지스터에서 값이 바뀜.

 

그럼 ACR의 상태라던가 그런 걸 메모리를 통해서 접근할 텐데 CPU레지스터에서만 값이 바뀌니 접근을 못함.

 

그런 것도 최적화 하지 말고, 그냥 메모리에 정석대로 넣으라고 

volatile를 붙임.

 

 

'임베디드' 카테고리의 다른 글

18. GPIO 옵션 (출력)  (0) 2026.02.05
17. 데이터시트 보고 코드 확인  (0) 2026.02.04
15. HAL 드라이버 분석  (0) 2026.02.03
14. GPIO 제어  (0) 2026.02.03
13. 프로젝트 생성  (0) 2026.02.03