본문 바로가기
대외활동/시스템프로그래밍

임베디드 C

by hoshi03 2024. 7. 22.

• 컴파일 과정

- gcc 명령어 옵션

• 컴파일 후 실행

터미널에서 

gcc -S ptrNarray1 ptrNarray1.c <- 어셈블리 파일 생성

gcc -S  v1.s volatileBasic1.c

gcc -o ptrNarray1 ptrNarray1.c  <- 컴파일 후 실행파일 생성

./ptrNarray1 <- 실행

 

-memcpy를 이용한 데이터 복사

int swap(void *dest, void *src, int size){
	void* tmp = malloc(size);
	if (tmp == NULL) return -1;
	memcpy(tmp,dest,size);
	memcpy(dest,src,size);
	memcpy(src,tmp,size);
	free(tmp);
}

 

- 비트 연산자 계산기

bitSet 해당 위치 비트를 1로 만들기

bitReset 해당 위치 비트를 0으로 만들기

bitToggle 해다 위치 비트 뒤집기

#define bitSet(data, pos) ((data) |= (1 << (pos)))
#define bitReset(data, pos) ((data) &= ~(1 << (pos)))
#define bitToggle(data, pos) ((data) ^= (1 << (pos)))
#include <stdio.h>

#define bitSet(data, pos) ((data) |= (1 << (pos)))
#define bitReset(data, pos) ((data) &= ~(1 << (pos)))
#define bitToggle(data, pos) ((data) ^= (1 << (pos)))

int main(void)
{
    unsigned short data;
    int pos, menu;
    
    printf("Input a short integer data => ");
    scanf("%hd", &data);
    
    while (1) {
        // 메뉴 입력 받기
        do {
            printf("Bit Test(1.Bit Set, 2.Bit Clear, 3.Bit Toggle, 4:Quit) => ");
            scanf("%d", &menu);
        } while (menu < 1 || menu > 4);

        if (menu == 4) break;

        // 비트 위치 입력 받기
        do {
            printf("Bit Position(0~15, -1:Quit) => ");
            scanf("%d", &pos);
        } while (pos < -1 || pos > 15);

        if (pos == -1) continue;

        switch (menu) {
            case 1:
                bitSet(data, pos);
                printf("Bit_%d Set of 0x%04X => 0x%04X\n", pos, data, data);
                break;
            case 2:
                bitReset(data, pos);
                printf("Bit_%d Reset of 0x%04X => 0x%04X\n", pos, data, data);
                break;
            case 3:
                bitToggle(data, pos);
                printf("Bit_%d Toggle of 0x%04X => 0x%04X\n", pos, data, data);
                break;
        }
    }

    return 0;
}

 

• 7 Segment (FND)

char my_getchar(void);
void my_putchar(char);
void my_gets(char *);
void my_puts(char *);

#define FND00	(*((volatile unsigned short *)(0x14000000)))   
#define FND01	(*((volatile unsigned short *)(0x14100000))) 
#define FND02	(*((volatile unsigned short *)(0x14200000)))
#define FND03	(*((volatile unsigned short *)(0x14300000)))

#define FND_LED_0	0x3f // 0111 1111
#define FND_LED_1	0x06 // 0000 0110
#define FND_LED_2	0x5b // 0101 1011
#define FND_LED_3	0x4f
#define FND_LED_4	0x66
#define FND_LED_5	0x6d
#define FND_LED_6	0x7d
#define FND_LED_7	0x27
#define FND_LED_8	0x7f
#define FND_LED_9	0x6f


void FndTest(void)
{
	unsigned char fnd_val[10]={FND_LED_0, FND_LED_1, FND_LED_2, FND_LED_3,
	  FND_LED_4, FND_LED_5, FND_LED_6, FND_LED_7, FND_LED_8, FND_LED_9}; 
	char fnd_no, pos;
	
	while(1) {
		my_puts("\nSelect FND Number(0~7, Quit:9) => ");
		fnd_no = my_getchar();
		if(fnd == '9') break;
		fnd_no -= '0';
		my_puts("\nSelect Display Number(0-9) => "); 
		dis_no = my_getchar();
		dis_no -= '0';
		switch(fnd_no/4) {
			case 0 : 
				if(fnd%2) FND00 = fnd_val[dis_no]<<8;
				else FND00 = fnd_val[dis_no];
				break;
			case 1 :
				if(fnd%2) FND00 = fnd_val[dis_no]<<8;
				else FND00 = fnd_val[dis_no];
				break;
			case 2 : 
				if(fnd%2) FND00 = fnd_val[dis_no]<<8;
				else FND00 = fnd_val[dis_no];
				break;
			case 3 :
				if(fnd%2) FND00 = fnd_val[dis_no]<<8;
				else FND00 = fnd_val[dis_no];
				break;
			default :
				FND00 = fnd_val[dis_no];
		} 
	}
}

void c_main()
{
	char name[80];

	my_puts("\nMain Start...\n");
	my_puts("\nLED Test Start!!\n");
	FndTest();
	my_puts("\nLED Test Done...\n");
	while(1) {
		my_putchar(my_getchar());
	}
}

 

• const 키워드

const 키워드의 위치에 따라 값이 상수가 될수도 있고, 주소가 상수가 될 수도 있다

void constArgTest1(int * p) {
	printf("p:%p, *p:%d\n", p, *p);
	(*p)++;
	printf("p:%p, *p:%d\n", p, *p);
	p++;
	printf("p:%p, *p:%d\n", p, *p);
}
void constArgTest2(const int * p) { // p가 가리키는 값을 상수로
	printf("p:%p, *p:%d\n", p, *p);
	(*p)++;
	printf("p:%p, *p:%d\n", p, *p);
	p++;
	printf("p:%p, *p:%d\n", p, *p);
}
void constArgTest3(int * const p) { // p의 주소를 상수로
	printf("p:%p, *p:%d\n", p, *p);
	(*p)++;
	printf("p:%p, *p:%d\n", p, *p);
	p++;
	printf("p:%p, *p:%d\n", p, *p);
}
#include <stdio.h>

int main(void) {
	int n1=10, n2=20, n3=30;
	int * p1=&n1;
	const int * p2=&n1;
	int * const p3=&n1;

	(*p1)++;
	// (*p2)++; //값 변경 불가
	(*p3)++;

	p1 = &n2;
	p2 = &n2;
	// p3 = &n2; // 주소 변경 불가
	
	return 0;
}

 

• 일괄 컴파일

gcc -o extern_main  *.c


모든 .c 파일을 컴파일해서 extern_main 실행 파일을 생성하기

 

• 전역 변수

 

-main의 전역 변수는 다른 곳에서 다시 초기화 하는 방식으로 사용 하지 말자

int gIntData = 10;
int gArrData[3] = {1, 2, 3};
char gStrData[] = "apple";

 

위의 전역 변수를 아래처럼 다른 코드에서 다시 재할당 하는건 불가능, 컴파일 에러가 발생한다 

#include <stdio.h>

#ifdef TEST1
extern int gIntData = 10;
extern int gArrData[3] = {1, 2, 3};
extern char gStrData[50] = "apple";
#else
extern int gIntData;
extern int gArrData[];
extern char gStrData[];
#endif

 

형 변환

 

dataCopy 메서드는 보이드 포인터를 이용해서 해당 인덱스의 값을 복사한다

char* 타입으로 캐스팅해서 바이트 단위로 값을 복사해올 수 있다

void dataCopy(void *dest, const void *src_base, int size, int pos)
{
    memcpy(dest, (char*)src_base+(size*pos), size);
	return;
}

 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define	NAME_SIZE	20

void dataCopy(void *dest, const void *src_base, int size, int pos);

int main(void)
{
	short s, sdata[] = {1, 2, 3, 4};
	int i, idata[] = {10, 20, 30, 40};
	float f, fdata[] = {100.1F, 200.2F, 300.3F, 400.4F};
	char str[NAME_SIZE], name[][NAME_SIZE] = {"kim", "park", "choi", "lee"};
	
	dataCopy(&s, sdata, sizeof(short), 2);
	dataCopy(&i, idata, sizeof(int), 2);
	dataCopy(&f, fdata, sizeof(float), 2);
	dataCopy(str, &name[0][0], NAME_SIZE, 2);
	
	printf("s   : %d\n", s);
	printf("i   : %d\n", i);
	printf("f   : %.1f\n", f);
	printf("str : %s\n", str);
	
	return 0;
}

void dataCopy(void *dest, const void *src_base, int size, int pos)
{
    memcpy(dest, (char*)src_base+(size*pos), size);
	return;
}

 

• volatile

컴파일러 최적화를 방지

임베디드 시스템에서 volatile 변수는 항상  메모리에서  해당  값을  가져와  외부변경사항을  즉시  반영할  수  있음

변수에 대한 모든 액세스가 실제 메모리 액세스와 일치하도록 보장한다

멀티스레드 환경에서 공유 변수를 나타내는데 사용한다

 

 

gcc -S -O0 -o v1O0.s volatileBasic1.c <- O0 수준으로 최적화하고 v1O0.s 어셈블리 파일 생성

 

최적화를 적용해도 volatile 변수는 최적화 수준에 관계없이 항상 메모리 접근을 보장한다

 

최적화가 적용되면 아래의 int* 는 한번만, 최적화가 적용되지 않으면 5번 쓰기 작업

*(int *)a = 1;
*(int *)a = 1;
*(int *)a = 1;
*(int *)a = 1;
*(int *)a = 1;

 

최적화가 적용되지 않으면 5번, 최적화가 적용되어도 volatile 변수는 5번 쓰기 작업을 동일하게 수행한다

*(volatile int *)a = 1;
*(volatile int *)a = 1;
*(volatile int *)a = 1;
*(volatile int *)a = 1;
*(volatile int *)a = 1;

'대외활동 > 시스템프로그래밍' 카테고리의 다른 글

부트로더  (0) 2024.07.23
함수 포인터, 구조체 포인터 예제  (0) 2024.07.23
리눅스 C 환경설정  (0) 2024.07.22
volatile 지시자  (0) 2024.07.19
1주차 C 전처리, 매크로, 조건부 컴파일  (1) 2024.07.19