임베디드/임베디드 레시피

MACRO Technics

twoweeks-within 2025. 1. 14. 14:23

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