함수의 이름 : Symbol > Physical 주소 점유
실제 함수의 이름 > 함수의 시작주소를 의미
1. 함수포인터의 선언
자료형 (* 함수포인터 이름) (인자목록)
> character형을 가르키는 pointer
char * cdata;
포인터 함수
EX)
integer형을 return
integer형 argument를 하나 받는 포인터함수
int (*function)(int a);
<>
int * function (int a);
function 함수 > integer형 포인터를 return받음
포인터 함수 선언
pointer함수 > int recipe(int a)라는 함수 엮으려면
function = recipe;
또는
function = &recipe;
주의) 함수의 이름 : 시작주소를 의미
function = recipe(); > x
> recipe() 함수의 값을 넣으라는 뜻 > 다른의미
2. 함수포인터 Array
(plus(), minus(), multiply(), divide() 함수가 우리가 아는 그 사칙연산을 해주는 함수라고 가정했을 때. )
int (* functions[3][4]) (int, int) = { plus, minus, multiply, divide }
// {plus, minus, multiply, divide},
// {plus, minus, multiply, divide},
// {plus, minus, multiply, divide}
>
function[2][0](1, 3) 의 값은?
> multiply (1,3) 호출 > return값: 3
typedef enum // 이 함수의 특징
{
PLUS = 0, // 0 이라고 해두면
MINUS, // 1
MULTIPLY, // 2
DIVIDE // 3
NUM_MAX; // 4 라고 자동 정의
} cal_type;
int Calculation (cal_type how, int a, int b)
{
if (how >= NUM_MAX){
return NULL;
}
else{
return function[0][how](a, b);
}
}
calculation (PLUS, 3, 4) > plus (3, 4) > 7
또는 4칙 연산을 자동으로 모두 시행하려면
void Calculation_All (int a, int b)
{
int loop;
for (loop =0; loop<4; loop++)
{
printf ( "%d \n", function[0][loop] (a, b);
}
return;
}
3. 함수 포인터의 응용 → Device Drivers
함수 포인터 > Device Driver들을 그때그때 다르게 쓰고 싶을 때 사용
ex)
주변 Device들 중에 같은 기능을 하지만 여러 가지 Vendor의 Device들을 한꺼번에 지원하고 싶을 때
ex)
어떤 device가 read, write의 기능 >
typedef struct {
const char *name;
void (*read) (byte *buffer, int count);
void(*write) (byte *buffer, int count);
} device_type;
device driver들을 선언
device_type device =
{
"It's me",
device_read, // device_read 함수 포인터를 가짐
device_write
}
Device driver를 끼워 넣을 수 있음
device_type *device_target;
device_target = &device
>> device driver를 사용하는 사용자 입장
(*device_target->read)(buffer, count)
이런 식으로 호출 > 그때그때 Driver가 바뀌는 효과
// read 에 devie_read 의 주소가 들어감
// device_target 에는 device 구조체의 주소가 들어감
// *device_target : devie 구조체에
> ->read : devie_read > buffer, count 대입
이때 drivce_read (buffer, count)가 불림!
device2 선언 > device_target = &device2 라고 선언
device2에 엮인 driver들이 불림
4. 함수포인터와 typedef
typedef int (funtion)(void) 로 선언하면?
> function : int return값 + void 인자를 받는 함수
유식하게는 int ()(void)라는 뜻
ex)
typedef int (funtion)(void);
int example_function(void) {
return 42;
}
funtion *func_ptr = example_function;
// function type : void를 인자로 받고 return이 int형인 함수
int result = func_ptr(); // result는 42
*/
function *temp = hello;
helllo() : int형 return, (void) 인자를 갖는 함수
> temp() 를 호출 == hello()를 호출
5. 함수 포인터의 완전 응용 → 원하는 주소로 억지로 branch
Embedded System을 만들다 특정 주소로 branch해야 할 경우
ex) 뭔가 하다가 꼭 0x7777 주소로 branch해야함.
> 0x7777주소를 일단 void형의 함수 pointer임을 알려주는 casting
> () : 함수라는 표현 >( void (*)() )이용 ( void형 포인터 함수라는 뜻 )
/*
주소를 넣을 때 이걸 붙여줘야 안전함
// ( void *) :void 를 반환하는 포인터
// ( void (*)() ) void 반환 , void를 인자로 받는 포인터 함수
*/
>>
void (*example) (void);
example = (void (*)())0x7777; // example : void를 반환 포인터함수(void를 인자로받는) > 0x7777 을 넣음
(*example)(); // example == 0x7777 에 해당하는 값으로 jump
// 함수 이름은 시작주소
> 억지로 pc : 0x7777로 만들어줌
(*(void(*)())0x7777)(); // 한줄요약
NOR flash : NOR flash를 probing하기 위해 command set
> NOR 영역 모두 status를 return >너 누구냐 하고 묻는 순간 > NOR flash에서 software 실행
> Undefined Exception이 나는 현상.
> 해결
static unsigned int32 find_id[] = { // 명령어를 배열에 저장
// id_code PROC
// In values: R0 = base of code section
0x1c01, // MOV r1, r0
// unsigned int32 codes;
// *base = (word)0x90;
0x2090, // MOV r0, #0x90
......
// return codes;
0x4770 // BX r14
// out values, mfg id in top 16 bits R0
// part id in bottom 16 bits R0
// ENDP
};
미리 nmemonic : 32bit array에 넣어둠 > PSRAM에 올려놓고 > 실행
id = ((unsigned int32(*)()) ((unsigned char *) find_id)) (base);
// (unsigned char *) find_id) : 배열을 포인터 형으로 바꿈
// (unsigned int32(*)()) : int 를 반환하는 포인터함수 선언
// base : 인자
id 명령어 > char형으로 align, unsigned int32형을 return해주는 함수 포인터형으로 casting
> id_code의 시작 주소를 함수처럼 실행
그러면 맨 처음에 했던 선언을 기준으로 다음의 선언을 해석해 보세요.
ⓐ int (*ifunc)(int a);
ⓑ char *(*cfunc)(char *p[]);
ⓒ void (*vfunc)(void);
ⓐ int 형의 return값을 갖고, int a의 인자를 갖는 ifunc 라는 함수 포인터
ⓑ char 포인터형의 return값을 갖고, char형의 포인터 배열을 인자로 갖는 cfunc 이라는 함수 포인터
ⓒ return값이 없고, 인자값도 없는 vfunc라는 함수 포인터
// 포인터 함수의 연산은 허용하지 않음
'임베디드 > 임베디드 레시피' 카테고리의 다른 글
6장) RTOS, Kernel (0) | 2024.12.11 |
---|---|
linked list, Queue (0) | 2024.12.11 |
Stack의 Size (0) | 2024.12.07 |
stack 메모리 dump (0) | 2024.12.07 |
stack : 함수를 불렀을때 (1) | 2024.12.06 |