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 |