■임베디드 시스템의 정의■


특정한 기능을 수행하도록 설계된 내장형 컴퓨팅 시스템.


======H/W===========S/W===========

=                                                                =

=    프로세서                    응용 소프트웨어        =

=                                                                =

=    메모리 장치        +      시스템 소프트웨어     =   시스템 소프트웨어 : 함수를 쓸때 함수원형이 OS커널안에 있다.

=                                                                =

=    입출력 장치                OS 커널                  =

=                                                                =

==================================

#MCU(=MPU)


CPU와 각종 Peripheral Controller들의 결합(=>프로세서를 내장하고 있는 SoC를 말한다.)


SoC(System on Chip) : 여러 개의 반도체 부품이 하나로 집적되느 기술 및 제품, 단일 칩으로 구현. 


<구성>

1. CPU Core : ALU, CU, Register로만 구성된 CPU의 핵심

2. ALU(Arithmetic and Logical Unit) : 산술/논리 연산을 위한 장치

3. CU(Control Unit) : 기계어를 분석하고 실행하기 위해 제어 신호를 순차적으로 발생시킴

4. Register : 연산이나 기타 목적으로 사용될 저장 공간, 메모리 계층에서 가장 빠르다(Flip-Flop으로 구성)

(=>1.제어 2.임시 기억 장소)<<범용 레지스터 :GFR, 제어용 레지스터 : CPSR, 상태 레지스터 : Status>>

5. Cache : 프로세서가 최근에 액세스한 메모리의 내용을 보관, 재요철시 메모리 액세스 없이 전달

6. MMU(Memory Management Unit) : 운영체제를 위해 가상메모리 지원

(=>Virtual address와 Physical address를 연결시켜주기 위해서 매핑을 해주는 역할을 한다.)

7.Bus : 1. 공유 2. 공통된 선들의 집합


ARM Processor에서 개발환경을 구성하기 힘들기 때문에 교차 개발을 한다.

교차 개발이란 Host System(PC)에서 개발환경을 구성하고 타켓(ARM Processor) 시스템 전용의 실행 파일을 생성하여 타켓 시스템이

다운로드한다. PC에서 크로스 툴체인을 이용한다.


#컴파일

<컴파일 단계>

전처리 -> 컴파일 -> 어셈블 -> 링크 과정을 거쳐 최종적으로 실행 이미지 생성.


1.전처리

컴파일 전에 전처리기(Preprocessor)에 의해 수행된다.

헤더 내용(.h)과 define 매크로/상수를 소스파일(.c)에 복사하는 작업.

.i 형태로 임시 저장되었다가 삭제된(-E option 컴파일 전에 멈춤)


2.컴파일

C코드를 해당 Machine의 어셈블리로 번역, 코드의 에러 경고 발생, .i -> .S


3.어셈블

어셈블리 코드를 Binary형태의 기계어로 변환하는 작업

어셈블러를 통과시킨 결과물을 Object File이라고 한다.

.S ->.o

<어셈블러가 어셈블리어를 어셈블한다.>


4.링크

오브젝트 파일 단독으로는 실행될 수 없어서 여러 개의 오브젝트 파일들과 라이브러리 파일들의 모든 코드롸 데이터를 포함하여 새로운 오브젝트 생성하는데 Section 단위로 묶여져 1개의 실행 파일(.exe)이 생성된다. 




#메모리 맵

-메모리에 적재되어 실행 가능한 오브젝트 파일


오브젝트 파일은 링커에 의해 해석될 수 있도로 여러가지 섹션들로 구성


대표적 섹션들 : text(code), data(RO),data(RW),bss(ZI),HEAP,STACK .....



1
2
3
4
5
6
7
8
9
10
11
#include<stdio.h>
int g_a = 20;                //DATA(RW)
int g_b;                    //BSS
const double PI = 3.14;        //DATA(RO)
 
void Func(int x)            //STACK
{
    static int cnt;            //BSS
    static int life = 5;    //DATA(RW)
    int result = -1;        //STACK
}
cs


1. DATA(RW) : read-write 로서 초기값이 있는 전역변수

2. ZI(Zero-initialized) BSS : 초기값이 0인 전역변수

3. DATA(RO) : read-only 로서 수정이 불가능한 const 전역변수 text인 code 의미,(단, const붙은 전역변수도 포함) 








■Uart_Print■

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#include "2450addr.h"
#include <stdarg.h>
#include "libc.h"
#include "option.h"
 
#define rUTXH1 (*(volatile unsigned *)0x50004020)
#define rURXH1 (*(volatile unsigned *)0x50004024)
#define rUTRSTAT1 (*(volatile unsigned *)0x50004010)
#define rUDIVSLOT1    (*(volatile unsigned *)0x5000402C)
 
// Function Declaration
void Uart_Init(int baud);
void Uart_Printf(char *fmt,...);
void Uart_Send_String(char *pt);
void Uart_Send_Byte(int data);
char Uart_Get_Char();
void Uart_get_String(char* str);
 
extern int vsprintf(char *const char *, va_list);
 
 
void Main()
{
 
    char str[]="";
    //Uart_Init(NULL);
    while(1)
    {
    Uart_get_String(str);
    Uart_Send_String(str);
    }
}
 
 
 
void Uart_Init(int baud)
{
    int pclk;
    pclk = PCLK;
    
    // PORT GPIO initial
    rGPHCON &= ~(0xf<<4);
    rGPHCON |= (0xa<<4);    
 
    
    rUFCON1 = 0x0;
    rUMCON1 = 0x0;
    
    /* TODO : Line Control(Normal mode, No parity, One stop bit, 8bit Word length */
    rULCON1 = 0x03;
 
    /* TODO : Transmit & Receive Mode is polling mode  */
    rUCON1 = 0x05;
 
    /* TODO : Baud rate 설정  */        
    rUBRDIV1=0x22;
    rUDIVSLOT1=0xDFDD;
}
#if 0
void Uart_Printf(char *fmt,...)
{
    va_list ap;
    char string[256];
 
    va_start(ap,fmt);
    vsprintf(string,fmt,ap);
    Uart_Send_String(string);
    va_end(ap);        
}
#endif
void Uart_Send_String(char *pt)
{
    while(*pt)
    {
        /* TODO : 문자 하나씩 증가시키면서 문자열 출력  */
        /*YOUR CODE HERE*/
        Uart_Send_Byte(*pt++);
    }
}
 
void Uart_Send_Byte(int data)
{
    while(!(rUTRSTAT1 & 0x2));//tx버퍼가 비어있으면 출력(while문 끝나지 x)
                        //비어있다 1 -> while(0)
                        //비어있지 않다 0 ->while(1)
    rUTXH1 = (char)data;
    if(data=='\r')
    {
        //while(!(rUTRSTAT1 & 0x2));
        rUTXH1 = '\r';
        //while(!(rUTRSTAT1 & 0x2));
        rUTXH1 = '\n';
    }
    /* TODO : UTRSTAT1의 값을 확인하여 TX 버퍼가 비어있으면 문자 출력   */    
    /*YOUR CODE HERE*/
}
 
char Uart_Get_Char()
{
    /* TODO : UTRSTAT1의 값을 확인하여 문자열 입력   */        
    /*YOUR CODE HERE*/
    
    while(!(rUTRSTAT1 & 0x1));
    return rURXH1;
 
}
 
void Uart_get_String(char* str)
{    
    unsigned char data;
    while(1)
    {
        data = Uart_Get_Char();
        *str++ = data;
        Uart_Send_Byte(data);    
        if(data == '\r')
        {
        break;
        }
    }
    *str = '\0';
}
 
cs

#Uart_Get_Char에서 폴링 방식으로 TX버퍼가 0인지 1인지 검사를 계속한다.


#결과(Tera Term)




■Volatile■

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include<stdio.h>
 
int main(void)
{
    volatile unsigned int i;
//  unsigned int i;
    for(i=0;i<0x10000000;i++);
    //Dead Code 
    
    /************************
    1.vlatile 없이 
    gcc -o test test.c
    ./test.c
    =>delay가 생김. 
    
    2. gcc -o test test.c -O3
    =>최적화(delay x)
    
    3.volatile 작성
    gcc -o test test.c -O3
    =>delay가 생김 
    **************************/ 
printf("\n");
printf("end...");
}
cs

<Volatile의 역할>
1.컴파일러의 최적화를 막아준다.
위 코드를 보면 dead code같은 코드를 보면 컴파일러가 최적화 레벨에 따라
생략해서 컴파일하게 된다.

2.캐시를 거치지 않는다.
임베디드에서 프로세서의 레지스터를 직접 제어하는 경우가 많은데 캐시에 저장되어 있으면
레지스터 제어가 잘 되지않기 때문에 써주는 것이 좋다.



■LED + keypad 회로도 (비트필드 구조체 사용)■

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
#include "2450addr.h"
typedef struct    
{
    unsigned gpg0 : 2;
    unsigned gpg1 : 2;
    unsigned gpg2 : 2;
    unsigned gpg3 : 2;
    unsigned gpg4 : 2;
    unsigned gpg5 : 2;
    unsigned gpg6 : 2;
    unsigned gpg7 : 2;
 
}gpgcon_t;
typedef struct 
{
    unsigned gpg0 : 1;
    unsigned gpg1 : 1;
    unsigned gpg2 : 1;
    unsigned gpg3 : 1;
    unsigned gpg4 : 1;
    unsigned gpg5 : 1;
    unsigned gpg6 : 1;
    unsigned gpg7 : 1;
}gpgdat_t;
 
typedef struct 
{
    unsigned gpf0 : 2;
    unsigned gpf1 : 2;
    unsigned gpf2 : 2;
    unsigned gpf3 : 2;
    unsigned gpf4 : 2;
    unsigned gpf5 : 2;
    unsigned gpf6 : 2;
    unsigned gpf7 : 2;
}gpfcon_t;
typedef struct 
{
    unsigned gpf0 : 1;
    unsigned gpf1 : 1;
    unsigned gpf2 : 1;
    unsigned gpf3 : 1;
    unsigned gpf4 : 1;
    unsigned gpf5 : 1;
    unsigned gpf6 : 1;
    unsigned gpf7 : 1;
}gpfdat_t;
 
#define GPGCON  (*(volatile gpgcon_t *)0x56000060)
#define GPGDAT  (*(volatile gpgdat_t *)0x56000064)
#define GPFCON  (*(volatile gpfcon_t *)0x56000050)
#define GPFDAT  (*(volatile gpfdat_t *)0x56000054)
void LED_Port_Init(void);
void LED_ON_Off(int num);
int Get_Key_byPolling(void);
 
void Main()
{
    int key;
    LED_Port_Init();
    while(1)
    {
 
    GPGDAT.gpg0 = 0x1;
    GPFDAT.gpf7 = 0x0;
    key = Get_Key_byPolling();    
    LED_ON_Off(key);
 
    GPGDAT.gpg0 =0x0;
    GPFDAT.gpf7 = 0x1;
    key = Get_Key_byPolling();    
    LED_ON_Off(key+1);
 
    }
}
 
void LED_Port_Init() 
{    
    GPGCON.gpg0 = 0x1;
    GPGCON.gpg4 = 0x1;
    GPGCON.gpg5 = 0x1;
    GPGCON.gpg6 = 0x1;
    GPGCON.gpg7 = 0x1;
 
    GPGDAT.gpg4 = 0x1;
    GPGDAT.gpg5 = 0x1;
    GPGDAT.gpg6 = 0x1;
    GPGDAT.gpg7 = 0x1;
    
    GPFCON.gpf2 = 0x0;
    GPFCON.gpf3 = 0x0;
    GPFCON.gpf4 = 0x0;
    GPFCON.gpf5 = 0x0;
    GPFCON.gpf6 = 0x0
    GPFCON.gpf7 = 0x1;
    
 
    GPFDAT.gpf0= 0x0;
    GPFDAT.gpf1= 0x0;
    GPFDAT.gpf2= 0x0;
    GPFDAT.gpf3= 0x0;
    GPFDAT.gpf4= 0x0;
    GPFDAT.gpf5= 0x0;
    GPFDAT.gpf6= 0x0;
    GPFDAT.gpf7= 0x0;
}
 
 
void LED_ON_Off(int num)
{
    switch(num)
    {
    case 0:
    GPGDAT.gpg4 = 0x1;
    GPGDAT.gpg5 = 0x1;
    GPGDAT.gpg6 = 0x1;
    GPGDAT.gpg7 = 0x1;
    break;
    case 1:
    GPGDAT.gpg4 = 0x0;
    GPGDAT.gpg5 = 0x1;
    GPGDAT.gpg6 = 0x1;
    GPGDAT.gpg7 = 0x1;
    break;
    case 2:
    GPGDAT.gpg4 = 0x1;
    GPGDAT.gpg5 = 0x0;
    GPGDAT.gpg6 = 0x1;
    GPGDAT.gpg7 = 0x1;
    break;
    case 3:
    GPGDAT.gpg4 = 0x1;
    GPGDAT.gpg5 = 0x1;
    GPGDAT.gpg6 = 0x0;
    GPGDAT.gpg7 = 0x1;
    break;
    case 4:
    GPGDAT.gpg4 = 0x1;
    GPGDAT.gpg5 = 0x1;
    GPGDAT.gpg6 = 0x1;
    GPGDAT.gpg7 = 0x0;
    break;
    case 5:
    GPGDAT.gpg4 = 0x1;
    GPGDAT.gpg5 = 0x1;
    GPGDAT.gpg6 = 0x0;
    GPGDAT.gpg7 = 0x0;
    break;
    case 6:
    GPGDAT.gpg4 = 0x0;
    GPGDAT.gpg5 = 0x0;
    GPGDAT.gpg6 = 0x1;
    GPGDAT.gpg7 = 0x1;
    break;
    }
}
 
int Get_Key_byPolling(void)
{        
    unsigned char key=(GPFDAT.gpf2)|(GPFDAT.gpf3<<1)|(GPFDAT.gpf4<<2)|(GPFDAT.gpf5<<3)|(GPFDAT.gpf6<<4);
    if(key==0x1e)     
        {return 1;}
    if(key==0x1d)
        {return 2;}
    if(key==0x1b)
        {return 3;}
    if(key==0x17)
        {return 4;}
    if(key==0xf)
        {return 5;}
}
cs


■CallBack 함수■

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
void LibFunc(void (*pFunc(void))
{
    //...
    pFunc();
}
void MyEvent()
{
    Uart_Printf("call me..");
}
void User_Main()
{
    LibFunc(MyEvent);
}
cs
#CallBack 함수란 간단히 말하자면 LibFunc라는 CallBack 함수를 정해두고 거기서 함수를 불러서 사용하는 것입니다.

즉, Main에서는 LibFunc라는 CallBack함수만 사용하면 되는 것입니다.


리눅스 임베디드에서 CallBack은 중요한데 리눅스 커널을 디버깅 하는데 많은 시간이 필요하고 양도 방대합니다.

그래서 디버깅중에 모듈을 넣고 빼고 하는데에 CallBack을 사용합니다.


그래서 디바이스 드라이버를 형태(틀)만 짜서(CallBack함수를 이용해) User1든 User2든 자신만의 각각 필요한 기능을

구현해서 개발하기가 수월합니다.


CallBack함수에 대한 자세한 설명이 링크에 있어서 참고합니다.

http://lab.gamecodi.com/board/zboard.php?id=GAMECODILAB_QnA_etc&page=1&sn1=&divpage=1&sn=off&ss=on&sc=on&select_arrange=headnum&desc=asc&no=3059

LED + Keypad 회로도■

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#include "2450addr.h"
#define GPGCON (*(volatile unsigned int *)0x56000060)
#define GPGDAT (*(volatile unsigned int *)0x56000064)
#define GPFCON (*(volatile unsigned int *)0x56000050)
#define GPFDAT (*(volatile unsigned int *)0x56000054)
void Init(void);
void LED_ON_Off(int num);
int Get_Key_byPolling(void);
 
void Main()
{
    int key;
    Init();
    
    while(1)
    {
    GPFDAT &= ~(0x1 <<7);
    GPGDAT |= 0x1;
    key = Get_Key_byPolling();    
    LED_ON_Off(key);
 
    GPFDAT |= (0x1 <<7);
    GPGDAT &= ~(0x1);
    key = Get_Key_byPolling();    
    LED_ON_Off(key+1);
    }
}
 
void Init() 
{    
 
    GPGCON |= 0x5500;
    GPGDAT |=0xf0;
    
    GPFCON |=0xffff;
    GPFCON &= ~(0x3ff << 4);
 
    GPFCON &= ~(0x2 <<14);
    GPGCON |= 0x1;
 
    GPFDAT &= ~(0xff);
}
 
 
void LED_ON_Off(int num)
{
    GPGDAT |=0xf0;
    switch(num)
    {
    case 0:
    GPGDAT &=(0xf0);
    break;
    case 1:
    GPGDAT &=(0xe0);
    break;
    case 2:
    GPGDAT &=(0xd0);
    break;
    case 3:
    GPGDAT &=(0xb0);
    break;
    case 4:
    GPGDAT &=(0x70);
    break;
    case 5:
    GPGDAT &= (0x30);
    break;
    case 6:
    GPGDAT &=0xc0;
    break;
    }
}
 
int Get_Key_byPolling(void)
{        
        if((GPFDAT & 0x7)==0x3)
        return 1;
        if((GPFDAT & 0xf)==0x7)
        return 2;
        if((GPFDAT & 0x1f)==0xf)
        return 3;
        if((GPFDAT & 0x3f)==0x1f)
        return 4;
        if((GPFDAT & 0x7f)==0x3f)
        return 5;    
}
cs
<스위치 작동원리>


스위치를 누르지 않은 상태일때는 스위치에 해당하는 핀의 전압이 VDD이므로 1(HIGH) 상태이다.


스위치를 누를경우 스위치에 해당하는 핀이 4~8번일경우 GPF7과, 9~13번일경우 GPG0 과 연결되는데,


GPF7, GPG0의 값이 0(LOW)이면, 연결된 핀의 전압이 0V가 되므로 0(LOW)상태가 된다.


GPFDAT7, GPGDAT0을 1(HIGH)상태로 둘경우 연결된 핀의 전압은 여전히 VDD이므로 핀의 상태는 HIGH(1)가 된다.



ex)

4번 스위치가 열린상태 : GPF2에 걸리는 전압이 VDD 이므로 1(HIGH)


4번스위치 닫힘, GPF7의 상태가 LOW : GPF2에 걸리는 전압이 0V 이므로 0(LOW)


4번스위치 닫힘, GPF7의 상태가 HIGH : GPF2에 걸리는 전압이 VDD 이므로 1(HIGH)



1. LED 설정


GPGCON4~GPGCON7 을 01(output mode) 로 초기화


GPGDAT의 4~7번 비트를 1(HIGH)로 초기화



2. keypad 설정


GPFCON2 ~ GPFCON6 을 00(input mode)로 초기화


GPFDAT의 2~6번 비트는 회로상 이미 1(HIGH)상태




GPFCON7, GPGCON0 을 00(output mode) 로 초기화


GPFDAT의 7번비트를 0으로 할 경우 4~8번 스위치가 작동


GPGDAT의 0번비트를 0으로 할 경우 9~13번 스위치가 작동




3. GPFDAT


회로상 GPFDAT의 2~6번비트는 기본상태가 1(HIGH)이다.


각 핀에 해당하는 스위치를 누를 경우 해당 비트가 0(LOW)가 된다.


ex)5번 스위치를 누를경우 GPFDAT의 3번비트만 0이 된다.



while문을 통해서 

GPFCON7, GPGCON0 을 01

GPFCON7, GPGCON0 을 10

인 상태에서 key값을 받아서


조건문을 통해 각 스위치에 맞게 LED를 설정한다.



#환경 설정


Ubuntu10 압출 풀기 -> 새로만들기 -> 이름 버전 입력(32bit linux)-> 메모리 4G -> 하드 디스크(기존 가상 하드 디스크 파일 사용)

-> virtualBox 실행


(Ubuntu)

장치 -> 게스트 확장 클릭 -> 바탕화면의 CD 더블클릭 ->autorun.sh 터미널에서 실행


(virtualBox)

virtualBox의 설정 ->네트워크 -> 브리지 어댑터 ->ASIX 설정

/*

이전에 드라이버가 설치 되어 있는지 확인(windows의 장치 관리자 확인)

*/

장치 ->공유 폴더 ->추가 ->(window 폴더 설정)->자동마운트,항상사용하기 선택


(Windows)

Tera Term 설치 -> Serial 클릭 -> setup Serial prot 115200으로 설정 

S3c2450 전원 키기


(Ubuntu)

# cd /etc/xinetd.d/

# gedit tftpd 


service tftp


{


protocol = udp


port = 69


socket_type = dgram


wait = yes


user = nobody


server = /usr/sbin/in.tftpd


server_args = /tftpboot


disable = no


}



# mkdir /tftpboot/

# chmod 777 /tftpboot/

# /etc/init.d/xinetd restart


 * Stopping internet superserver xinetd                                  [ OK ] 


 * Starting internet superserver xinetd                                  [ OK ]




# netstat -au


#halt =>종료

(reboot 할것)


(bootroad) =>보드의 reset 버튼 누르고 enter해서 진입(명령대기 상태)

/*

bootroad의 부팅은 2가지 1.자동부팅 2.명령대기 상태(프롬프트 상태)

*/


#printenv

#setenv serverip 192.168.10.107

#setenv ipaddr 192.168.10.117


#saveenv

/*

ip를 직접 잡아줍니다.

*/


(Ubuntu)

# ifconfig eth0 192.168.10.107 up

# ifconfig

# cd /media/sf_D_DRIVE/

# ls


MDS2450.bin ==>(윈도우의 공유파일에 직접 넣어준 파일)



# cp MDS2450.bin /tftpboot/

# chmod 777 /tftpboot/MDS2450.bin ‬ ==>Access violation오류시



(bootroad)

#tftp 30000000 MDS2450.bin //PC로 부터 다운로드

#go 30000000 //실행





led.zip와 arm-2011.03-42-arm-none-eabi-i686-pc-linux-gnu.tar.bz2를 리눅스에 생성된 공유파일(sf_D_DRIVE)에 넣는다.


(Ubuntu)

#cd /media/sf_D_DRIVE

#cp led.zip /root


# cp arm-2011.03-42-arm-none-eabi-i686-pc-linux-gnu.tar.bz2 /root


#cdtar  /root


#tar xvjf arm-2011.03-42-arm-none-eabi-i686-pc-linux-gnu.tar.bz2


/*


tar.bz2 ->xvjf


tar.bz  ->xvzf


*/


#cd /etc


#gedit environment



PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/root/arm-2011.03/bin"


/*

수정

*/




#source /etc/environment


#arm-none-eabi-gcc




#cd /root



#unzip led.zip


#cd led


#cd SOURCE




#ls -al

#gedit Main.c

/*

소스 입력

*/



#make clean


#make


/*

Makefile : 컴파일 자동화 유티리티

clean후 컴파일

*/


#cp MDS2450.bin /tftpboot



/*

tftp(file transfer protocol)를 통해 board에 보내어 board에서 실행한다


PC(host)/ TFTP server  || targetboard()/client

*/



(bootroad)




#tftp 30000000 MDS2450.bin

/*

다운로드

*/


#go 30000000





<Main.c>작성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include "2450addr.h"    //S3c2450의 모든 register주소가 들어있는 헤더파일
#define GPGCON (*(volatile unsigned int *)0x56000060)
#define GPGDAT (*(volatile unsigned int *)0x56000064)
 
void LED_Port_Init(void);
void LED_ON_Off(int num);
 
void Main()
{
    
    LED_Port_Init();
    while(1)
    {
        int i;
        LED_ON_Off(5);
        for(i=0; i<300000; i++);
        LED_ON_Off(6);
        for(i=0; i<300000; i++);
        LED_ON_Off(1);
        for(i=0; i<300000; i++);
        LED_ON_Off(2);
        for(i=0; i<300000; i++);
        LED_ON_Off(4);
        for(i=0; i<300000; i++);
        LED_ON_Off(3);
        for(i=0; i<300000; i++);
    }
}
void LED_Port_Init() 
{
    GPGDAT |= 0xf0;
    GPGCON |= 0x5500;
}
 
void LED_ON_Off(int num)
{    
    GPGDAT |= 0xf0;
    switch(num){
        case 1:
            GPGDAT &= (0xe0);
            break;
        case 2:
            GPGDAT &= (0xd0);
            break;
        case 3:
            GPGDAT &= (0xb0);
            break;
        case 4:
            GPGDAT &= (0x70);
            break;
        case 5:
            GPGDAT &= (0x30);
            break;
        case 6:
            GPGDAT &= (0xc0);
            break;
    }
}
 
cs





# 비트 set ,claer 연습

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include<stdio.h>
 
int main()
{
    unsigned char data1 = 0xad;
    unsigned char data2 = 'a';
    
    //B5로 만들기
    data1 &=~(0x7<<3); //3bit를 clear
    data1 |= 0x6 <<3;  //110 삽입
//clear를 하고 삽입한는 방식이 일반적
 
    //대문자 A로 만들기
    data2 ^= 0x1 <<5//a는 0x61,A는 0x41
                      //5번째 자리 반전 
    
    printf("%0x\n",data1);
    printf("%c\n",data2);
}
cs
<개념>

1.set

data = data | 0x20;    //data 5번 bit만 set
=> data = data | 0x1 << 5;
=> data |= 0x1 << 5;   (이런 표기법을 쓰도록 하자)

2.claer


data &= ~(0x1 <<5);


3.reverse


data ^= 0x1 <<5;



*응용

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//값을 입력하여 신호등을 표시합니다.//
 
#include <stdio.h>
void main()
{
    int i;
    unsigned char sign;
    unsigned char data;
    char str[4][9]={"녹색불""자회전불""노란불""빨간불"};
    printf("값을 입력하세요(1, 2, 3, 4, 8) : ");
    scanf("%d"&sign);
    for(i=3;i>=0;i--)
    {
        data=(sign&(1<<i))>>i;
        printf("%s : ", str[i]);
        data==1 ? printf("on\n"): printf("off\n");
    }
}
cs


+ Recent posts