Project 카테고리에 있는 OS에 들어있는 내용은 "IT EXPERT, 64비트 멀티코어 OS 원리와 구조 - 저자: 한승훈" 책을 보면서 만든 것입니다.

1. ubuntu 18.04.2 LTS 개발환경 세팅

필수적으로 설치해야하는 패키지

  • GNU binutils: 여러 종류의 오브젝트 파일들을 핸들링하기 위한 바이너리들. 주로 make, gcc, gdb등과 함께 사용한다.
  • GNU bison: Parser의 일종으로 LARLR로 이루어진 문법을 해석하여 C코드로 작성하여 준다.
  • gcc-multilib: c의 크로스 컴파일을 위해 설치한다.
  • g++-multilib: C++의 크로스 컴파일을 위해 설치한다.
  • libc6-dev: libiconv(인코딩 변환 라이브러리)를 사용하기 위해 설치한다.
  • libtool: Portable library를 만들기 위한 도구이다.
  • make: 프로그램 그룹 유지를 위한 유틸리티로, 새롭게 컴파일 되어야 하는 부분을 판단하여 gcc를 이용해 재컴파일 한다.
  • patchutils:패치 파일을 핸들링하기 위한 유틸리티
  • libgmp-dev: GNU MP라이브러리를 사용하기 위해 설치
  • libmpfr-dev: MPFR라이브러리를 사용하기 위해 설치한다
  • libmpc-dev: MPC라이브러리를 사용하기 위해 설치

쉘명령어 입력

$ sudo apt-get update
$ sudo apt-get upgrade
$ sudo apt-get install gcc-multilib g++-multilib binutils bison flex libc6-dev libtool make patchutils libgmp-dev libmpfr-dev libmpc-dev

NASM 설치

어셈블리 빌드를 위해서 설치

$ sudo apt-get install nasm

QEMU 설치

emulator를 이용하기 위해서 설치

$ sudo apt-get install qemu-kvm

'Project > OS' 카테고리의 다른 글

6. Bootloader 만들기  (0) 2019.07.11
5. 부팅과 부트로더  (0) 2019.07.11
4. 운영모드와 메모리 관리기법  (0) 2019.07.11
3. 운영모드와 레지스터  (0) 2019.07.11
2. 운영모드  (0) 2019.07.11

Arduino Uno - Arduino M0(SAMD21G) serial 통신

참고: https://learn.adafruit.com/using-atsamd21-sercom-to-add-more-spi-i2c-serial-ports/creating-a-new-serial

참고: https://learn.adafruit.com/using-atsamd21-sercom-to-add-more-spi-i2c-serial-ports/muxing-it-up


*Uno

rx pin - D2

tx pin - D3


코드


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
#include <SoftwareSerial.h>
 
 
 
SoftwareSerial ser(2,3);
 
 
 
void setup() {
 
  // put your setup code here, to run once:
 
  Serial.begin(9600);
 
  ser.begin(9600);
 
  Serial.println("hi im uno");
 
}
 
 
 
void loop() {
 
  ser.write('c');
 
  while(ser.available() > 0){
 
    char temp = ser.read();
 
    Serial.println(temp);
 
    
 
  }
 
  delay(1000);
 
}
cs



*M0(SAMD21G)

rx pin - 30(PB03)

tx pin - A5(PB02)


코드


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
#include <Arduino.h>
 
#include "wiring_private.h"
 
#include <LiquidCrystal_I2C.h>
 
 
 
Uart SerialX(&sercom5, 30, A5, SERCOM_RX_PAD_1, UART_TX_PAD_0); // rx, tx
 
LiquidCrystal_I2C lcd(0x38204);
 
 
 
void SERCOM5_Handler(){
 
//  SerialUSB.println("irq");
 
  SerialX.IrqHandler();
 
}
 
 
 
void setup() {
 
  lcd.init();
 
  lcd.backlight();
 
  lcd.clear();
 
  SerialUSB.begin(9600);
 
  SerialX.begin(9600);
 
  pinPeripheral(30, PIO_SERCOM_ALT);
 
  pinPeripheral(A5, PIO_SERCOM_ALT);
 
  SerialUSB.println("hi im m0_serialUSB");
 
  lcd.setCursor(0,0);
 
  lcd.print("hi");
 
  
 
}
 
 
 
uint8_t i = 0;
 
 
 
void loop() {
 
//  SerialUSB.println(i);
 
  SerialX.write('a');
 
//  delay(5);
 
  while(SerialX.available()){
 
//    SerialUSB.print(" - > 0x");
 
    lcd.setCursor(0,0);
 
    char temp = SerialX.read();
 
    lcd.print(temp);
 
    SerialUSB.println(temp);
 
  }
 
  delay(1000);
 
}
cs


SerialX라는 이름의 Uart객체를 생성한다. sercom은 5를 사용한다.

Arduino M0(SAMD21G)는 총 6개의 sercom을 가지고 있으며 chip(SAMD21G)만 따로 떼어내서 사용하는 것이 아니라면 각각의 sercom은 용도에 맞게 예약되어 있다.

sercomN의 각각의 자주쓰는(chip만 떼어서 쓴다고하면 다른용도로도 사용할 수 있다는 것을 명심) 용도는 다음과 같다.

출처: https://forum.arduino.cc/index.php?topic=341054.0 에서 MartinL의 글

참고: variant.cpp 

참고: variant.h


sercom0 - Uart Serial (variant.cpp (링크)에서 Serial1 그리고 Serial5으로 선언이 되어있다.)

sercom1 - Uart Serial

sercom2 - Uart Serial

sercom3 - I2C Wire

sercom4 - SPI

sercom5 - EDGB (variant.cpp (링크)에서 Serial로 선언이 되어있다.


M0에서  uart serial 생성에서 기억해야 할 코드는 다음과 같다.


Uart SerialX(&sercom5, 30, A5, SERCOM_RX_PAD_1, UART_TX_PAD_0);


void SERCOM5_Handler(){

SerialX.IrqHandler();

}


SerialX.begin(9600);


pinPeripheral(30, PIO_SERCOM_ALT);

pinPeripheral(A5, PIO_SERCPM_ALT);


각각 설명을 해주면

------------------------------------------------------------------------------------------------------------------------

Uart SerialX(&sercom5, 30, A5, SERCOM_RX_PAD_1, UART_TX_PAD_0);


SerialX라는 이름의 serial 핸들링 객체를 하나 만든다.


파라미터는

Serial( sercomN의 주소값, RX pin number, TX pin number, RX_PAD number, TX_PAD number)

로 구성되어있다.


나는 sercom5를 사용했다.

sercom은 runtime시에 하나만 사용할 수 있다.

------------------------------------------------------------------------------------------------------------------------

RX는 현재 PB03를 사용하고 있다.

TX는 현재 PB02을 사용하고 있다.


windows의 경우 

C:\Users\user\AppData\Local\arduino15\packages\arduino\hardware\samd\1.6.20\variants\arduino_mzero

경로에서 variant.cpp를 보면 코드에서 사용할 수 있는 pin 번호가 적혀 있다.




위의 캡처한 사진을 보면

PB03는 30번 핀을 사용하고 있고


PB02은 A5번 핀을 사용하고 있다.


따라서 2번째 3번째 파라미터는 


 30, A5이 되는 것이다.


Uart SerialX(&sercom5, 30, A5, SERCOM_RX_PAD_1, UART_TX_PAD_0);

------------------------------------------------------------------------------------------------------------------------

3번째 4번째 파라미터는

PAD인데 정확한 의미와 뜻은 잘모른다. mux로 되어있다는 것만 알 수 있다.

그러나 어떻게 사용해야하는지는 알겠다.

SERCOM_RX_PAD_N 형태로 RX_PAD를 설정하고

UART_TX_PAD_N 형태로 TX_PAD 형태로 설정한다.


위의 사진과 SAMD21G의 datasheet(링크)의 23페이지를 살펴보면

PB02과 PB03을 사용하려면 sercom5와 PAD[0] PAD[1]을 사용해야한다.

PB02를 sercom5를 이용해 사용하려면 PAD[0]를 사용해야 한다는 것을 유추할 수 있다.

PB03은 datasheet에서 PAD[1]을 사용하라고 나와있다.



Uart SerialX(&sercom5, 30, A5, SERCOM_RX_PAD_1, UART_TX_PAD_0);

------------------------------------------------------------------------------------------------------------------------


void SERCOM5_Handler(){

SerialX.IrqHandler();

}


는 SerialX의 핸들러를 가져오겟다는 뜻이다. sercom을 사용하기 위해서는 반드시 정의해줘야한다. 함수명이 SERCOMN_Handler 형태로 되어있는 것에 주목하도록하자 우리는 sercom5를 쓰기때문에 SERCOMN_Handler에서 N에 5가 들어갔다.

이 함수는 콜백메소드이다.

------------------------------------------------------------------------------------------------------------------------

SerialX.begin(9600);


따로 설명하지 않겠다.

------------------------------------------------------------------------------------------------------------------------

pinPeripheral(30, PIO_SERCOM_ALT);

pinPeripheral(A5, PIO_SERCPM_ALT);


아까 선택했던 rx pin과 tx pin을 사용해줘야 한다.


pinPeripheral함수를 이용한다.

30번 핀을 PIO_SERCOM_ALT로 사용하겠다는 의미이다.

아까 데이터시트를 보면 D항목의 SERCOM5-ALT항목의 

위의 데이터시트 캡처화면의 PB03와 PB02에서 SERCOM5/PAD[0] 열따라 쭉 올라가보면 SERCOM5-ALT가 보인다.

pinPeripheral의 두번째 파라미터는

PAD가 ALT인지 아닌지에 따라 달라질 수 있다.

여기서는 ALT이므로 PIO_SERCOM_ALT 를 사용한다.

ALT가 아닐 시에는 PIO_SERCOM을 사용한다.


------------------------------------------------------------------------------------------------------------------------


*결과


M0 serial monitor


Uno serial monitor




'개발 tip > Arduino' 카테고리의 다른 글

[아두이노] MAC OS X에서 VS Code 개발 환경 세팅  (0) 2019.01.19

Node.js REST API - environment split


*환경의 분리

서버가 실행되는 모드를 정의해야 한다. 이건 테스트 때문이다. 아직 테스트에 db 붙이지는 않았지만 테스트에 디비를 붙일 것이다. 하지만 테스트 디비를 붙이게 되면 데이터베이스 테스트에서 사용한 데이터들이 쌓이게 된다. 따라서 테스트용 데이터 베이스가 따로 있어야하는데 이것을 위해 서버 환경을 분리할 것이다.


우리는 세가지 모드를 사용할 것이다.

-development

-test

-production

“development” 개발 모드이다. 우리가 지금까지 사용했던 환경이다.

“test” 테스트 환경을 의미한다.

“production” 운영모드이다. 실제로 코드가 서버로 배포되어 동작하는 환경을 의미한다.


이러한 환경 정보는 NODE_ENV라는 환경변수에 설정하여 사용할 수있다. 노드 코드에서는 process.env.NODE_ENV 라는 변수를 통해 접근할 있다.


테스트 환경과 개발환경을 분리하기 위해서 app/config/environment.js파일을 만들자.


environments 라는 변수를 두어 환경 이름에 해당하는 키를 만들었다. 그리고  nodeEnv라는 상수에 노드 환경변수 값을 할당했다. 

노드를 실행하기 전에 “Node_ENV = test”라고 실행하면 이값에 “test”라는 문자열이 들어간. 만약 아무것도 설정하지 않으면 “development”문자열이 들어가게 될것이다.

마지막으로 environments 객체에서 노드 환경변수에 해당하는 부분의 객체를 반환하는 모듈로 만들었다.


*테스트에 데이터베이스 연동하기

environment 모듈을 사용하여 기존코드를 변경해야한다.

environment에는 데이터베이스 접속정보가 있는데 부분은 models.js 수정하면 된다.

아래 코드처럼 말이다.



 environments 모듈은 NODE_ENV 환경변수 값에 따라 각각 다른 데이터베이스로 연결한다.


그럼  api/users/user.spec.js 테스트 코드로 돌아가 보자. 모카에는 before() / after() 함수가 있다.

이것은 테스트가 실행되기 /후에 각각 한번씩 실행되는 함수이다. before() 함수를 이용해 테스트 데이터베이스를 초기화하는 등의 테스트 환경을 만들어 있다. 아래 코드를 한번 보자


it()함수가 실행되기 직전 before() 함수가 먼저 실행된다. before() 함수에서는 데이터베이스를 초기화 수있는 sync({force: true}) 함수를 실행하면 된다.



*sync-database 모듈

한편 app.js에서 sync() 함수를 사용하고 있는데 이것을 테스트에서도 따로 떼어 내기 위해서는 데이터를 싱크할 있는 별도의 모듈로 떼어내는 것이 편리하다.


app/config/environment.js 다시 수정한다.


test mode에서는 sequelize force true이지만 development production에서는 false이어야만 한다.


 bin/sync-databse.js 파일로 만들어 보자


모듈은 데이터베이스를 싱크하는 매우 간단한 코드이다.

실행 모드가 test이냐 아니냐에 따라서force 값이 달라질것이다.


*www.js

이참에 서버 구동하는 모듈도 별도로 만들어 보자 bin/www.js 파일을 만든다.



서버 구동로직을 옮겨왔으니 app.js에서도 이부분을 제거해야하한다. app.js 남은 부분은 아래와 같다.


이제는 app.js 아니라 bin/www.js 파일로 서버를 구동할 있다. package.json start 스크립트도 변경해야한다.



*테스트 데이터 구성

이제 테스트 코드의 before() 함수에서 데이터베이스 싱크 모듈을 불러와 실행해 보자

user.spec.js  describe()함수의 before()


이제 실제 데이터베이스에 샘플데이터를 넣고 “GET /users” 테스트 해보자 먼저 before()함수에서 데이터베이스에 데이터 3개를 넣는 코드를 작성한다.


before()함수는 여러개 실행할 있다. 전부 it() 함수가 호출되기 전에 실행이 완료 된다.


두번째 before() 함수에서는 데이터베이스에 users  테이블에 있는 유저를 추가하는 역할을 한다.

sequelize 모델에는 create() 말고도 bulkCreate() 함수가 있다. create()  함수가 하나의 row 생성한다면 blukCreate()  함수는 여러개 데이터를 배열로 받아 여러개 row 생성하는 함수이다. 이렇게 샘플데이터를 테이블에 넣은 it()으로 api테스트를 진행 있다.


*테스트 데이터 삭제

마지막으로 after() 함수를 이용해 데이터베이스를 초기화 한다. 유저 데이터를 넣었기 때문에 다시 삭제하는 것이다. 여기서는 간단히 drop 데이터베이스 싱크를 돌리자.


after(‘clear up database’, (done) => {

models.User.drop();

syncDatabase().then( () => done());

});


*테스트 코드 실행

마지막으로 테스트를 실행해야한다. 이번에는 NODE_ENV 환경변수를 설정해 주어야 한다. 우리는 테스트 데이터베이스와 개발 데이터베이스를 분리했으니까 테스트시에는 테스트 데이터베이스로 접속해야한다.

테스트 실행시  “NODE_ENV=test” 추가해주면 된다.

package.json


그리고 명령문에서 npm test 테스트를 진행한다.


$ npm test


*나머지 테스트코드에서도 데이터베이스를 연결해보자

  • Create(POST)


  • Destroy(DELETE)

*폴더정리

다시 한번리펙토링을 해야할 같다. 리펙토링은 많이 할수록 좋음!

bin이라는 폴더를 만들게 되면서 서버 어플리케이션 코드와 섞이게 되었다.


bin폴더에는 두개의 파일이 있는데 데이터베이스를 싱크하는 sync-database.js 서버를 실제로 구동하는 www.js 있다. 엄밀히 말하는 어플리케이션 로직은 아닌셈이다.


한편 api 폴더에는 라우팅 로직들과 models.js 정의된 모델링 코드들은 어플리케이션으로 분리할 있다.


아래와 같이 파일들을 옮기자

/app: 서버 기능

/api: api로직을 담당

/config: 서버가 구동하기 위한 환경 변수 정의 (상수)

/models: 데이터베이스 모델링

/bin: 서버 구동을 위한 코드

/www.js: 서버 구동

/sync-database: db 싱크

파일에서 사용하는 모듈의 상대 경로도 변경하는 것을 잊지말자.

코드는 https://github.com/kiryun/NodeJS_REST-API_tutorial/commits/master 에서 볼 수 있다.



+ Recent posts