최적화방지!
//16bit 짜리 타이머
uint8 *TIMER = (uint8_t *)0x8020;
// 8bit 씩 쪼갬
1. (uint8_t *) 로 형변환 하는이유
: 0x8020 자체는 숫자임
> 포인터 형태로 바꾸어줘야 해당 주소로 접근 가능
> 0x8020란 주소는 이제 8bit 씩 값을 가르킴
/*
uint8_t value[2] = {0x0, 0x1};
// 각 요소를 8bit 씩 저장
&value[0] = 0000 0000
&value[1] = 0000 0001
//
cpu는 메모리를 1byte 씩 접근
>
uint16_t val = 0x0001;
>> (Little Endian)
&val = 0x01
&val+1 = 0x00
>>>
uint16_t *ptr16 = (uint16_t *)&val; 로 할경우
> 0x01 , 0x00 : 한번에 2개의 주소를 가져옴
// 그럼에도 ptr16 은 메모리 1byte 씩 저장
// <> 읽을때만 16 bit 씩 읽음
*/
> 메모리 주소를 가진 I/O는 volatile 로 선언!
>>
1.
uint8_t volatile *TIMER = (uint8_t volatile *)0x8020;
>
어셈블리 코드 변경시 메모리 주소 읽도록 // 컴파일러는 이때 최적화 진행
2.
a. Interrupt_Handler() 와 main() 내의 해당 함수를 공유하는 변수는 전역변수로 선언
b. 캐싱 (regi 에 넣어두고 빠르게 꺼내씀) 때문에 메모리에서 한번 참조 후에는 재확인x
c. (문제발생)
Interrupt / main 에서의 register 가 다름 by Context Changing
> 각각 함수 내에서 변수의 값이 바뀌더라도 공유가 안됨
>>
d. (해결)
항상 메모리를 참조 하도록 Volatile 로 선언!
3. 멀티 쓰레드
이때도 Context_Changing 발생 ! > 다른 레지스터 사용
4. 예외의 상황
void delay(){ 카운트 증가하는 for문~ }
int main(){
PORTA = 0x00;
delay(100);
PORTA = 0xff;
}
> 컴파일러 입장에서는 0x00 > delay(100) 동안에 값 바뀐게 X
> PORTA = 0xff 만 하도록 최적화 할 수 있음
> 이를 방지: Volatile
총정리)
1. 메모리 > 레지스터 > cpu
2. 이때 컴파일러는 캐싱, 최적화 진행 // 자주 쓰는건 regi 유지
3. 메모리의 값 변경 확인 놓칠 수 있음
4. voliatile 로 선언 > 계속 메모리에서 확인하도록함
'임베디드' 카테고리의 다른 글
게획) SBC, MCU, FPGA (0) | 2025.01.29 |
---|