• 컴파일 과정
- 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 |