Macro : 자주 쓰는걸 한개로 묶을 수 있음
argument 를 받을 수 있음
Register 설정 같은걸 관리하기 용이
ex) 반복
critical_section_in(current);
ret = io_read (io_num);
critical_section_out(previous);
>
#define CRITICAL_IO_IN (current, io_num, previous) \
critical_section_in(current); \
ret = io_read (io_num); \
critical_section_out(previous); \
>> " \ " 로 연결
CRITICAL_IO_IN (1, 2, 3);
>>>
critical_section_in(1);
ret = io_read (2);
critical_section_out(3);
## : Define 설정된 이름들도 Argument 로 넣어줄 수 있음
ex)
#define CRITICAL_IO_IN (CURRENT, IO, PREVIOUS) \
critical_section_in(DEVICE_##CURRENT##_BUFFER); \
ret = io_read (IO_##IO##_NUM); \
critical_section_out(DEVICE_##PREVIOUS##_BUFFER);
// 선언
// 어딘가에 define 되어있는 CURRENT, IO, PREVIOUS 의 값이 아닌
// 그 이름 자체를 넣어 줄 수 있음
CRITICAL_IO_IN (BOOTUP, USB, STARTUP); // 호출
#define DEVICE_BOOTUP_BUFFER 1
#define DEVICE_STARTUP_BUFFER 3
#define IO_USB_NUM 2
critical_section_in(DEVICE_BOOTUP_BUFFER);
ret = io_read (IO_USB_NUM);
critical_section_out(DEVICE_STARTUP_BUFFER);
// 결과
>>
critical_section_in(1);
ret = io_read (2);
critical_section_out(3);
>>>
Register control
ex) clock configuration 할 수 있는 주소와 값들을 Macro로 정함
: IO_OUT(io_num, mask, val)
주소 : 0xC000CB00
32bit register
LSB bit 2,3 > MCU의 Data
Read, Write가 모두 가능한 Register
LSB 2,3bit가
0x0 : Clock disable
0x1 : Clock enable 하는 거고,
0x2 : enable된 Clock의 주기를 반으로
0x3 : enable된 Clock의 주기를 두 배로 up
>
define
이름 : HWCTIO_
주소 : _ADDR
Mask : _MSK
값 : _VALUE
#define HWCIO_MCU_CLK_ADDR 0xC000CB00
#define HWCIO_MCU_CLK_MSK 0x3
// 0x3 = 0b11 : 2bit를 mask 할 수 있음
#define HWCIO_MCU_CLK_SHIFT 0x2
// LSB bit2,3 이므로 2칸 shift 해줘야함
#define HWCIO_MCU_CLK_DIS_VALUE 0x0
#define HWCIO_MCU_CLK_EN_VALUE 0x1
#define HWCIO_MCU_CLK_TWICE_VALUE 0x3
#define HWCIO_MCU_CLK_HALF_VALUE 0x2
>>
활용
Clock 을 살리고 2배로 뻥튀기 하고 싶음
IO_OUT (MCU_CLK, MCU_CLK_TWICE);
#define IO_OUT (target, val) \
(*((volatile dword *) (HWCIO_##target##_ADDR)) =\
((dword) (HWCIO_##target##_##val##_VALUE & HWCIO_##target##_MSK\
)<<HWCIO_##target##_SHIFT));
// target 자리에 MCU_CLK, val 자리에 MCU_CLK_TWICE가 치환
>>
클락 주소 = ( 하고싶은 값 & MSK )<< SHIFT
(*volatile dword *)(0xC000CB00) = ((dword)(0x3 & 0x3)<<0x2))
>> 그 주소의 값에 0x1100 ( 0xC) 를 넣어줌
BUT) Register의 특정 bit만 쓸 수 없음
0xC000CB00에 있는 값 > MCU_CLK_Shadow라는 32bit 전역변수에 backup
(*((volatile dword *) (HWCIO_MCU_CLK_ADDR)) =\
MCU_CLK_shadow || \
((dword) (HWCIO_MCU_CLK_TWICE_VALUE & HWCIO_MCU_CLK_MSK\
)<<HWCIO_##target##_SHIFT));
: 원하는 bit 만 다시 넣어주고 나머지는 원래 있던대로 해줌
> 기존 값을 유지하면서 새로운 값을 추가
>>
(*((volatile dword *)0xC000CB00 = 0xC000CB00 || 0xC
do while 이용
if (dstlen>page_size_in_word) { \
write_and_set_curr_page((void *)dst, &dstlen, &total_rle_length); \
memset ((void *) dst, 0x0, FLASH_NAND_PAGE_NUM_BYTES);} \
>
#define write_and_foward_page() \
do { \
if (dstlen>page_size_in_word) { \
write_and_set_curr_page((void *)dst, &dstlen, &total_rle_length); \
memset ((void *) dst, 0x0, FLASH_NAND_PAGE_NUM_BYTES);} \
} while (0)
>> write_and_foward_page() 만 해주면됨
: Linux Kernel 에서 이용
do~while(0) 기법 :
{} 로 묶여있으니 local variable 을 선언해서 사용 가능
불확실한 if문의 사용을 확실하게 해줌
> if 여야 실행되는걸
> 무조건 한번은 실행하게 해줌
어떤 pointer에 직접 주소를 assign 하는 방법
volatile unsigned dword * io = (unsigned word *) 0xC0008000;
> io에 값을 쓸 때마다 0xC0008000에 32bit의 값을 쓸 수 있음
ex)
*io = 0x12345678
> 0xC0008000 이 주소에 0x12345678 값을 넣음
'임베디드 > 임베디드 레시피' 카테고리의 다른 글
Wait State (0) | 2025.01.15 |
---|---|
Synchronous ,Asynchronous (0) | 2025.01.15 |
shadow, Bit operation (0) | 2025.01.14 |
Device Interface의 CS, address 이용 - LCD (0) | 2025.01.14 |
MCU의 외부통신, 컨트롤 (0) | 2025.01.14 |