티스토리 뷰

embedded

Embedded Project - Modularizing

주먹불끈 2019. 1. 18. 22:18

개요

 

작은 기능들을 담은 Embedded Project 들의 소스를 보다보면

하나의 파일에 모든 기능들을 담아놓은 경우를 보게 된다.

 

초기화 설정, 인터럽트, 센서와의 연동, 통신 등등이 뒤섞여있다.

일정에 맞춰 빠른 기능구현을 하다보니 그렇게 되었으리라 싶다.

 

또한 여러 파일로 나눠 놓았음에도 서로간의 연결이 뒤죽박죽인 경우도 있다.

헤더파일과 전역변수, 함수의 선언 (declaration) 등이 일관성이 없거나 잘못된 경우들

 

그나마 일관성을 유지하며 개발하려 노력하였으나

제대로된 가이드 문서를 만나게 되어, 문서에 그 동안의 경험을 더하여 개인적인 기준을 정리해본다.

* 문서에 더해지는 의견은 의견 이라고 표시하겠음

 

문서링크: https://goo.gl/xSzyy2 웹페이지의 Modularizing C Code: Managing large projects

 

 

목차 간략 정리

 

Identify Common Routines

분류해서 파일로 나눠라

Adding the new files to your makefile

이건 생략

Naming the routines

함수명을 파일명으로  시작하여 연관성을 드러낸다.

Making functions static

함수가 Static 선언이 가능하다면 쓰자

Global variables

전역변수의 위치

Splitting the header files

각각의 c 파일에 쌍으로  헤더파일을 만들자

Renaming the macros

매크로 역시 파일명과 연관이 있게 만들자

Global variables revisited

전역변수를 헤더파일에 선언하여 다른 파일도 있게 해주자.

Including the header files

헤더파일들을 어떻게 #include 것인가

Header file protection

헤더파일들의 중복에 대한 해법

 

 

 

Identify Common Routines

 

기능, Peripherals, 통신방식 등등으로 구분하여 각각의 파일을 만들라는 것이다.

- 메인함수가 있는 main.c, main.h

- 모터를 다룬다면 motor.c, motor.h

- ADC 작업이 있다면 adc.c, adc.h

- UART 를 통한 작업이 많다면 uart.c, uart.h

- 특정 센서를 사용한다면 sensor.c, sensor.h

 

의견

- 너무 엄격할 필요는 없다. 적당한 분류로 적당한 덩어리씩 나누자

- 초기화 부분, 인터럽트 부분은 main.c 에 둔다.

- 파일명의 대소문자 형식도 통일해주자. 개인적으로는 소문자와 언더스코어(_) 사용한다.

 

Adding the new files to your makefile

 

- IDE 가 makefile 을 만들어주니 이 부분은 생략

 

 

Naming the routines

 

- 함수명은 파일명에서 유추할 수 있는 특성으로  시작하게 하자

- , CheckADCChannel() 보다는 ADCCheckChannel() 을 쓰자.

 

Speaker 관련 함수

UART 관련 함수

ADC 관련 함수

SpeakerSetup()

SpeakerBeep()

USARTSetup()

USARTEnable()

USARTGetByte()

USARTProcessByte()

ADCCheckChannel()

ADCCheckTempSensorVal()

 

의견

- 개인적으로는 예시처럼 대문자로 시작하는 CamelCase 형식으로 이름을 짓는다.

- 이것 역시 너무 강제성을 가지고 쓰지 말자.

- 예를 들어 speaker.c 파일에서만 쓰는 작은 소리를 내는 함수라면 Beep() 정도만 해줘도 되겠다.

 

 

Making functions static

 

- Static function 은 함수가 있는 파일 안에서만 쓰인다.

- 일종의 private 함수같은 느낌으로 보아도 좋다. 같은 파일안의 함수들만 호출할 수 있다.

- Static function 의 선언부 (Prototype) 은 헤더파일에 두지말고 c 파일의 시작부에 두자

외부에 노출될 함수가 아니다. 헤더에 두면 warning 이 뜨기도 한다.

 

예시

- uart.c 파일에 USARTEnable() 함수가 있다면

- void USARTEnable(void); 라고 되어 있는 것을

- static void USARTEnable(void); 이라고 해주면 Static function 이 된다.

 

장점

- 모듈 내부에서만 쓰이는 함수를 외부에서 접근하지 못하도록 해준다.

- 컴파일러가 최적화 하는데 도움이 된다.

 

의견

- 애초에 중요한 변수를 변경할 수 있는 기능을 특정 함수에게만 주고 static 으로 선언해준다.

- 혹은 개발 완료후 refactoring 시에 외부 호출이 있는지 여부를 하나씩 검사한 다음 static 으로 해준다.

- 함수의 위치에 크게  문제가 없다면 호출하는 함수 위쪽에 모아두면 굳이 선언부를 c 파일 시작부에 둘 필요가 없다.

 

Global variables

 

전역변수들은 보통 c 파일의 시작부에 위치한다.

전역변수가 관련있는 파일에다 두면 된다.

 

의견

- 전역변수가 다른 파일에서 쓰일 수 있는데

- 일단은 선언하지 말고, 컴파일 에러가 발생하면 그때 하나씩 헤더파일에 선언해주자

 

 

Splitting the header files

 

- 각각의 c 파일에는 쌍을 이루는 같은 이름의 헤더파일을 둔다.

- include 하는 헤더파일, 다른 파일에서 사용하는 전역변수, function prototype,

그리고 typedef, enum, macro 들을 각각의 헤더파일에 위치시킨다

- 프로젝트 전반에 관련한 것들은 defines.h 라는 헤더파일을 별도로 만들어 넣어둔다.

 

의견

- 이견이 조금 있으나 아래에 언급하겠음

 

Renaming the macros

 

Naming the routines 마찬가지로  관련이 있는 파일명을 넣어주자.

 

Global variables revisited

 

전역변수가 c 파일에 정의되었다면, 헤더파일에 extern 키워드를 넣어 선언해주자.

 

uart.c 파일에 아래와 같이 정의되었다면

unsigned char LastCommand = 0x00;

uart.h 파일에 아래와 같이 선언해주자.

extern unsigned char LastCommand;

 

의견

- 변수명은 소문자와 언더스코어(_)를 선호한다.

- 변수 타입은 uint8_t, int32_t 와 같이 몇비트인지 한 눈에 알 수 있는 방법을 선호한다.

중요한 것은 일관성이다.

 

Including the header files

 

* 부분이 개인적인 기준과 가장 다르다.

 

1) 각각의 c 파일은 본인의 헤더파일을 위에 선언한다.

2) 각각의 c 파일이 사용하는 라이브러리 헤더파일을 당 헤더파일에  추가한다.

- 예를 들어 speaker.h 파일에 #include <avr/io.h> 추가

3) 마지막으로 개발자가 생성한 헤더파일을 다른 c 파일에서 사용하는 경우 해당 헤더파일에 추가한다.

- 예를 들어 speaker.h 파일에 #include "main.h" 추가

 

의견

1) 은 동의

2) 는 각각의 c 파일이 필요로 하는 라이브러리가 무엇인지 아는 효과는 있으나

- 개인적으로는 main.h 파일에 모아둔다.

3) 은 어느쪽에 일관성을 가지는가 하는 문제는 있으나

- 개인적으로는 c 파일에 자신의 헤더파일을 선언한 곳에 개발자가 생성한 헤더파일을 함께 #include 해서 모아둔다.

 

Header file protection

 

위와 같이 해두면 많은 헤더파일들이 서로가 서로를 #include 하게 된다.

그렇다면 중복 선언의 문제가 생길 수 있다.

 

요즘 IDE 들은 헤더파일을 만들면 기본적으로 아래와 같은 구조를 생성해준다.

헤더파일들이 중복되지 않도록 해준다.

 

- main.h 라면 MAIN_H

- uart.h 라면 UART_H 정도로 define 명을 만들어준다.

# ifndef MAIN_H

# define MAIN_H

// Header file contents

# endif

 

Voila! 브알라! 어때? 끝내주지?


반응형
반응형
잡학툰 뱃지
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/04   »
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
글 보관함