HW개발자를 위한 Software 워크숍
박동희
시간표

첫날 일정
- 8시 - 워크숍 소개. 개인소개
- 9시 - 컴퓨터 구조: 소프트웨어에서 하드웨어
- 10시 - 개발 환경 소개 (mbed, gcc, make)
- 11시 - 에러로 배우는 C 프로그래밍 언어 (탐험-> 이해)
- 12시: 점심
- 13–15시 - 에러로 배우는 C 프로그래밍 언어 (탐험-> 이해)
- 15–17시 - 에러로 배우는 C 프로그래밍 언어 + 퀴즈
첫날 워크숍 노트
HW개발자를 위한 Software 워크숍 노트: 첫날
http://dh8.kr/workshop/swworkshop/note/day1.html
자기소개
좋아하는것 또는 취미?
최근에 배운것 ?!
프로그래밍 경험?
이 워크숍에서 원하는것 ?
원하는 것 공유
- 짝과 공유
임베디드 하드웨어/소프트웨어 개발 시작하기
처음 시작할때는 취미 플래폼 체크: Rpi, Arduino, Particle, Mbed
- C언어 배우기
- 기초 전자이론(전압, 전류, 파워, 저항, 옴의법칙)
- 납땜, 멀티미터, 디버거, 오실로스코프(또는 로직 애널라이져)
- 마이크로컨트롤러와 툴체인 선택. 개발보드
- 부품 선택 구매(digikey, mouser), 그리고 데이터 쉬트 읽기.
컴퓨터의 역사
목표: 컴퓨터가 어떻게 동작하는지 알 수 있다.
자코드 방직기 (Jacquard loom) 1804
- 자코드 방직기
- 섬유패턴 자동화
- 천공카드 (프로그램)
- 자코드 방직기 동작영상
- 자코드 방직기 동작원리
배비지 머신 1833
- 해석 엔진(Analytical Engine): 기계식 컴퓨터 (기억:톱니, 연산:톱니, 입출력:천공카드,인쇄프린터)
- 로그표를 만들기 위해 만든 차분 엔진 을 만들고, 좀 더 유니버설한 기계를 만들려고 했다.
- Ada Lovelace : 최초의 프로그래머. 프로그래밍 언어(순차/반복/분기)
- 최초의 컴퓨터 프로그램(Ada Lovelace’s note G1942): Numbers of Bernoulli 1, –1/2, 1/6, –1/30, 1/4, –1/30 … 합을 적분 증명에 사용. 확률에 사용.
- 존 그레이엄-커밍: 제작되지 못한 최고의 기계
- 요즘 프로그램 언어로 푼 베르누이 숫자 http://rosettacode.org/wiki/Bernoulli_numbers
기계식 컨트롤러(컴퓨터)

출처: http://www.flickr.com/photos/28556101@N00/8837851912/
폰노인만 구조
- 수학적 모델: 튜링머신
- 전자식 컴퓨터, 프로그램 내장형 컴퓨터
- 메모리에 프로그램을 저장. 메모리에 저장된 프로그램을 실행
참고: 폰노인만 구조 –위키페디아
CPU 프로그래밍의 원리
소프트웨어는 어떻게 하드웨어를 동작 시키는가? 기계는 프로그램을 어떻게 해석 할까?
- CPU에 대해서 알아보고
- CPU가 코드를 실행하는 것을 시뮬레이션 해보자.
- 컴파일 과정을 알아보자.
CPU: Central processing unit
컴퓨터안에 있는 하드웨어로, 기본연산, 논리, 입출력을 계산하는 프로그램의 명령에 따라 일을 하는 하드웨어

참고: AVR(atmega128기준) 프로그램 접근은 16비트 버스, 데이터 접근은 8비트 참고: images/wXcJN0V.png
AVR Block Diagram
CPU 용어
레지스터: 특수 목적으로 저장하는 메모리
- Program Counter: CPU가 현재 실행하고 있는 명령어의 주소.
- Instruction Register: PC가 가르치 키는 명령의 주소에서 얻어온 명령어를 가지고 있다.
- Address Register: 억세스 할려고 하는 데이터 주소를 가지고 있다.
- Data Register: Address Register 가 메모리에서 패치해서 가져온 실제 값
- Accumulator: 연산의 결과값을 저장.
CPU 용어2
CPU 내부에 있는 모듈
- Decoder: IR에서 가져온 명령어를 해석
- Central Unit(CU) : 디코더에서 해석된 명령어의 신호를 받아 주변장치를 제어하는 신호를 만든다.
- ALU(Arithmetic Logic Unit): 숫자 계산, 논리식 계산, Program Status Register Update
하드웨어(CPU)에서 코드(Instruction) 실행
- 명령어 패치 -> 디코드 -> 실행
CPU가 어떻게 코드를 실행는가? 컴파일
byte a = 1;
byte b = 2;
byte c;
void add(void)
{
c = a+b;
return
}
C코드 (c = a+b;) 컴파일 결과: 어셈블리
0x1000 LOAD 0x2000
0x1002 ADD 0x2002
0x1004 STORE 0x2004
AVR은 8비트 CPU지만 opcode의 크기는 16비트 이다. PC도 16비트

LOAD 0x2000

ADD 0x2002

STORE 0x2004

컴파일
코드가 메모리에 올라가기전에 어떤일이 일어나나?
컴파일: 프로그래밍 언어를 CPU 명령어(Instruction)의 나열(코드)로 바꾼다.

컴파일: C->Assembly->기계어
c = a + b; // C언어
ADD R2, R1, R0 // R2 = R1 + R0; 어셈블리
0xEB010200 // ARM 기계어 코드, 32bits
링킹: 컴파일된 여러개의 파일을 하나의 코드로 합친다. (예: startup.s + main.c -> main.out )
>

로딩: 컴파일된 코드를 CPU에 적재!
참고: 컴파일/링킹: http://blog.feabhas.com/2012/06/the-c-build-process/
임베디드 소프트웨어의 컴파일, 펌웨어 업로드
- PC에서 컴파일 하여, 타겟 보드의 명령어 집합(instruction set)인 펌웨어를 생성한다.
- 타겟보드에 Debug interface를 통해서 펌웨어를 업로드 한다.

프로그램 (소프트웨어)
- 명령어의 나열
MCU (microcontroller unit)

한칩에 연산을 하는 코어, 메모리, 그리고 프로그래밍 가능한 입출력 주변기기를 가지고 있는 작은 컴퓨터
폰노인만 구조: 내장 메모리 순차 방식!
임베디드 소프트웨어?
- 역활: MCU를 제어하여 주변장치 제어.
- MCU를 제어하여 다양한 주변기기를 제어하는 방법을 학습.
임베디드 소프트웨어 어떻게 시작하는게 좋을까?
- 기계는 어떻게 해석하는지 ARM 프로세서가 C 코드를 어떻게 해석하는지 알 수 있다. (왜? 자신감!)
- 기존의 시스템 분석!
임베디드 소프트웨어는 왜 C? 인가?
- 프로그래밍 언어 사용 빈도 랭킹: C 프로그래밍 언어 18%
- MCU와 주변장치 제어: Embedded I/O -> C로 하드웨어 메모리 제어하기 편리함. (포인터)
mbed : http://mbed.org/

http://developer.mbed.org/platforms/mbed-LPC1768/
lpc1768 memory map
MCU에서 소프트웨어는 메모리를 제어 하여 주변장치를 제어하고, 연결한다.
그러니깐 메모리 맵이 …

메모리 용어 정리: Stack, Heap
Flash, Sram, 레지스터

Stack과 Heap은 Sram의 영역을 나누어서 사용 한다.
.bss 초기화 되지 않은 전역 변수 .data 초기화된 전역변수값 저장 .rodata 초기화된 const 전역변수값 저장
lpc1768 instruction set

설치
다운로드
다음 주소에 있는 파일을 다운로드 받는다.
- 다운로드 링크
http://okin.cc/~donghee/sw
컴파일/실행
- mbed_nxp1768 폴더로 이동
- BuildShell.cmd 명령을 실행. (환경변수 설정)
- 명령어 창이 뜨면 samples\HelloWorld 폴더로 이동 (cd samples\HelloWorld)
- makefile 수정
- make (컴파일)
- make upload
- 보드의 reset 버튼 누르기
표준 입출력 Standard Input Output
- mbed uart 드라이버 설치: mbedWinSerial_16466.exe
- teraterm–4.76 실행: ttermpro.exe
- teraterm 으로 mbed 연결 : File -> New Connection -> Serial -> mbed Serial Port
- teraterm 설정: Setup -> Terminal -> Under “New-line”, set Receive to “LF”
C 프로그래밍 언어!
- 구조
- 데이터 타입과 데이터 표현
- 변수
- 입/출력
- 조건문
- 함수
- 스코프
- 반복문
- 배열
- 포인터
github.com 가입 (구글 크롬에서만 가능)
구조: 나는 살아 있어!
#include <stdio.h>
int main()
{
printf( "I am alive! Beware.\n" );
return 0;
}
C언어 기본 구조 설명
- 전처리자(include), 함수의 구조, 함수(printf) 빌려 쓰기.
- 코멘트
- return 0
디버깅: 에러로 배우는 프로그래밍
- 의도적으로 에러 만들기.
- 에러 나는 이유 찾기.
- 기록하기 http://pad.dh8.kr/p/lgswws (가정, 관찰, 다음 행동)
- 기록한 내용 공유
참고:
C언어의 데이터 타입
int(정수), float(실수), char(문자)
int:3,-12,0x23a,023float:2.3f,4.0char:'b'
질문: 왜 타입을 쓰나?
C언어의 데이터 표현
정수(음수),실수(소수), 문자를 메모리에 저장하는 형식.
정수의 표현: 2의 보수 표현법. 비트 반전 후 결과값에 1 더하기. 왜?

- 실수의 표현: IEEE 754–1985: 현재 가장 많이 쓰는 실수표현.
- 부호/2^n제곱의 지수/가수(소수점 아래수)
- 10진수: 0.15625 -> 2진수: 0.00101 (1/8+1/32)

- 부호: 0, 지수: –3 + bias(단정도:127, 배전도: 1023), 가수: .01
- 문자 표현: ASCII(American Standard Code for Information Interchange)
- ’a’의 숫자값은?
변수
Code:
type varName = data;
Example:
int age = 3;float length = 2.4;char alphabet = 'c';
출력
printf("age = %d\n", age)printf("length = %f\n", length)printf("length = %d\n", (int)length)printf("alphabet = %c\n", alphabet)
실습해보기
- 선언된 변수와 다른 data type으로 화면에 출력
- 16진수를 10진수로 출력
- 8진수를 10진수로 출력
C언어에서 변수, 연산자

비교연산(*)
>,<>=,<===!=
논리 연산
- 1 && 1 == 1
- 1 || 0 == 1
- 1 && 0 == 0
조건문
if (condition1)
{
// if condition1 is true
// do this code
}
else if (condition2)
{
// if condition2 is true
// do this code
}
else
{
// do this code instead
}
실습해보기
Good morning!, Good afternoon!, Good evening!, Good night!
int time;
printf("What time is it now?\n");
scanf("%d", &time);
printf("%d\n",time);
if ( )
{
}
else if ( )
{
}
else
{
}
함수 function
함수를 이용하여 나만의 명령어를 만든다.
정의문법:
결과값의타입 함수이름(입력값의타입 입력값) {
return 결과값;
}
- Return type(결과값의 타입)
- 함수이름
- Parameter(입력값)
- Code block
- Return
함수 예제
int add(int x, int y) {
int result;
result = x + y;
printf("%d + %d = %d", x, y, result);
return result;
}
사용:
y = add(2,3);
printf("%d",y); // 5
해보기
- add 함수를 참고하여, 두개의 숫자를 입력하여 곱하는 결과는 출력하는 함수를 만들어 보자.
힌트: multiply(x,y) - multiply(100, 200)의 결과를 화면에 출력해 보자.
- multiply(100, 200)가 실행되는 순서를 말해보자.
C언어의 지역변수, 전역변수: Scope
함수 내부에 있느냐 함수 밖에 있느냐로 지역변수, 전역 변수를 구분.
지역변수
- 함수 내부에 있는 변수 (CPU 레지스터에 저장)
- 변수가 위치한 함수 내부에서만 유효
```
int multiply(int x, int y) {
int result;
result = x * y;
return result;
}
```
전역변수
- 함수 밖에 있는 변수 (SRAM에 .bss나 .data 영역 저장)
- 여러함수에서 접근할 수 있다.
```
int result;
int multiply(int x, int y) {
result = x*y;
return result;
}
int main()
{
printf(“result: %d”, result);
}
```
http://assembly.ynh.io 온라인 C->assembly 컴파일러
함수: 퀴즈
isLeapYear() 함수의 내용을 채우시오.
윤년: 1년이 366일이 되는 해가 윤년이다.
그레고리력의 윤년 규칙
- 연수가 4로 떨어지는 해는 윤년 (2004, 2008, 2012)
- 이중에 100으로 떨어지는 해는 평년(2100, 2200, 2300)
- 그중 400으로 나누어 떨어지는 해는 윤년(1600, 2000, 2400)
1태양년 = 365일 5시간 48분 46초
조건문: 윤년
10분, github.com에 가입한 후 gist.github.com에 풀이 코드 올리기. 짝 공유. ‘gist 사용하기 위해서는 구글 크롬 필수’
- 함수의 이름은 isLeapYear 이다.
- 입력: 타입은 정수형 이름은 year 이다.
- 출력: 윤년이면 정수 1을 출력, 아니면 정수 0을 출력한다.
#include "stdio.h"
int main()
{
int year;
printf("Enter any year: ");
scanf("%d", &year);
if(isLeapYear(year)) {
printf("%d is leap year!\n", year);
} else {
printf("%d is not leap year!\n", year);
}
return 0;
}
알고리즘 퀴즈 FizzBuzz
FizzBuzz 수열규칙을 읽고, fizzbuzz() 함수의 내용을 채우시오. 확인 힌트: 손코딩. 시간: 15분
- 1 부터 100 까지의 숫자를 화면(터미널)에 출력한다.
- 그러나, 3의 배수인 수 대신 “Fizz” 출력
- 또한, 5의 배수인 수 대신 “Buzz” 출력
- 그리고, 3과 5의 배수인 수 대신 “FizzBuzz” 를 출력.
..
#include <stdio.h>
void fizzbuzz(int n) {
// 아래 코드를 고쳐서 fizzbuzz 수열을 출력하시오.
print("%d\n", 1);
}
int main (void)
{
int i;
fizzbuzz(100);
return 0;
}
알고리즘 퀴즈: Prime Factor (소인수 분해)
Prime Factor 소인수 분해 참고: http://mathbang.net/200 (소인수분해 정의)
자연수 n 을 입력 받았을때 , n 의 소인수 분해 숫자(소수)를 출력하는 함수 void prime_factor (int n) 를 만들어 봅시다. 예를 들어
- prime_factor(1)을 실행하면 `` (빈칸)출력
- prime_factor(2) 을 실행하면
2을 출력 - prime_factor(30)을 실행하면
2 3 5출력 - prime_factor(75)을 실행하면
3 5 5출력
하도록 만들어 봅시다.
#include <stdio.h>
void primefactor(int number) {
// 아래 코드를 추가 하여 prime factor가 출력하시오.
}
int main (void)
{
int i;
primefactor(1);
primefactor(2);
primefactor(30);
primefactor(75);
return 0;
}