HAL 레이어 구현

EEEFFEE·2023년 12월 3일
0

kdt system-project note

목록 보기
5/15

최초 작성

  • c로만 이루어진 코드에 cpp로 작성한 코드를 적용

  • ./Makefile, ./Makefile.inc : cpp코드와 같이 컴파일 할 수 있도록 수정

include Makefile.inc

DIRS = system \ ui \ web_server
DIRS = system \ ui \ web_server \ hal
BUILD_DIRS = ${DIRS}

SYSTEM = ./system

TARGET = toy_system
CC = gcc
CPP = g++


FILENAME = main
MAINo = $(FILENAME).o
@@ -16,12 +18,13 @@ MAINh = $(SYSTEM)/system_server.h $(UI)/gui.h $(UI)/input.h $(WEB_SERVER)/web_se
MAINf = -I$(SYSTEM) -I$(UI) -I$(WEB_SERVER) -c -g -o

DIROBJ = ./system/system_server.o ./ui/gui.o ./ui/input.o ./web_server/web_server.o
HALOBJ = ./hal/camera_HAL.o ./hal/ControlThread.o

$(TARGET): $(MAINo) 
	@ echo ${BUILD_DIRS}
	@ for dir in ${BUILD_DIRS}; do (cd $${dir}; ${MAKE}); \
		if test $$? -ne 0; then break; fi; done;	
	$(CC) -g -o $(TARGET) $(MAINo) $(DIROBJ)
	$(CPP) -o $(TARGET) $(MAINo) $(DIROBJ) $(HALOBJ) $(CPPLIBS)

$(MAINo): $(MAINh) $(MAINc)
	$(CC) $(MAINf) $(MAINo) $(MAINc)
    
-------------------------------------------------------------------------------------    
PL_CFLAGS = -I../$(SYSTEM) -I../$(UI) -I../$(WEB_SERVER) -I../$(HAL)  -g -o
PL_CPPFLAGS = -lpthread -lm -lrt

CPPLIBS = -lpthread -lm -lrt

SYSTEM = system
UI = ui
WEB_SERVER = web_server
HAL = hal

CC = gcc
CPP = g++

HEADERS =  ../$(SYSTEM)/system_server.h\
		../$(UI)/gui.h\
		../$(UI)/input.h\
		../$(WEB_SERVER)/web_server.h
		../$(WEB_SERVER)/web_server.h\
		../$(HAL)/ControlThread.h\
		../$(HAL)/camera_HAL.h\

CPPINCLUDES = -l${SYSTEM} -l${UI} -l${WEB_SERVER} -l${HAL}		

CFLAGS = ${IMPL_CFLAGS}
CFLAGS = ${PL_CFLAGS}
CPPFLAGS = ${CPPINCLUDESDIRS} -g -O0 -std=c++14

RM = rm -f

  • /hal/ControlThread.cpp, ./hal/camera_HAL.cpp : 카메라 객체와 카메라를 조작할 cpp 코드

#ifndef _CONTROL_THREAD_H_
#define _CONTROL_THREAD_H_

class ControlThread {

public:
    ControlThread();
    ~ControlThread();

public:
    // 사진 찍는 메소드
    int takePicture();

private:

}; // class ControlThread

#endif /* _CONTROL_THREAD_H_ */
--------------------------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <errno.h>
#include <iostream>
#include <cstdio>
#include <unistd.h>
#include "camera_HAL.h"
#include "ControlThread.h"

static ControlThread *control_thread;

using std::cout;
using std::endl;

int toy_camera_open(void)
{
    cout << "toy_camera_open" << endl;

    control_thread = new ControlThread();

    if (control_thread == NULL) {
        cout << "Memory allocation error!" << endl;
        return -ENOMEM;
    }

    return 0;
}

int toy_camera_take_picture(void)
{
    return control_thread->takePicture();
}

  • /hal/Makefile : cpp코드를 컴파일하기 위한 makefile

include ../Makefile.inc

FILENAME1 = ControlThread
FILENAME2 = camera_HAL
GEN_EXE1 = $(FILENAME1).o
GEN_EXE2 = $(FILENAME2).o
SRC1 = $(FILENAME1).cpp
SRC2 = $(FILENAME2).cpp

EXE = $(GEN_EXE1) $(GEN_EXE2)

all: $(EXE)

$(GEN_EXE1): $(HEADERS) $(SRC1)
	$(CPP) -g $(CPPINCLUDES) $(CPPFLAGS) -c  $(GEN_EXE1) $(SRC1)


$(GEN_EXE2): $(SRC2)
	$(CPP) -g $(CPPINCLUDES) $(CPPFLAGS) -c  $(GEN_EXE2) $(SRC2)

allgen : ${GEN_EXE}

clean:
	${RM} ${EXE} *.o

  • /system/system_server.c : cpp로 구현한 카메라 기능을 호출하고 일정 시간마다 시간을 출력하는 타이머 코드 추가

#include <camera_HAL.h>
#include <bits/sigevent-consts.h>

pthread_mutex_t system_loop_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t  system_loop_cond  = PTHREAD_COND_INITIALIZER;
bool            system_loop_exit = false;    ///< true if main loop should exit

static int toy_timer = 0;

...

int system_server()
{
	...
    
    signal(SIGALRM, timer_expire_signal_handler);
    
    ...
    
     if(pthread_mutex_lock(&system_loop_mutex) < 0){
        perror("System server mutex lock error");
        exit(0);
    }
    while (system_loop_exit == false) {
        int result = pthread_cond_wait(&system_loop_cond, &system_loop_mutex);
        if(result == ETIMEDOUT){
            printf("System exit timed out!\n");
        }
    }
    if(pthread_mutex_unlock(&system_loop_mutex) < 0){
        perror("System server mutex unlock error");
        exit(0);
    }
    while (system_loop_exit == false) {
        sleep(1);
    }
    
}

...

void timer_sighandler(){
    static int timer = 0;
    timer ++;
    printf("System timer : %d sec\n", timer );
    toy_timer ++;
    signal_exit();
    //printf("System timer : %d sec\n", timer );
}   

...

void signal_exit(void)
{
    if(pthread_mutex_lock(&system_loop_mutex) < 0){
        perror("Signal exit mutex lock error");
        exit(0);    
    }
    system_loop_exit = true;
    pthread_cond_signal(&system_loop_cond);
    if(pthread_mutex_unlock(&system_loop_mutex) < 0){
        perror("Signal exit mutex unlock error");
        exit(0);    
    }
}

static void timer_expire_signal_handler()
{
    toy_timer++;
    signal_exit();
}

  • /ui/input.c : 메시지를 번갈아가며 한 글자 씩 번갈아가며 출력하는 코드

#define TOY_TOK_BUFSIZE 64
#define TOY_TOK_DELIM " \t\r\n\a"
#define TOY_BUFFSIZE 1024


#define MAX 30
#define NUMTHREAD 3 /* number of threads */

static pthread_mutex_t global_message_mutex  = PTHREAD_MUTEX_INITIALIZER;
static char global_message[TOY_BUFFSIZE];

char buffer[TOY_BUFFSIZE];
int read_count = 0, write_count = 0;
int buflen;
pthread_mutex_t count_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t empty = PTHREAD_COND_INITIALIZER;
int thread_id[NUMTHREAD] = {0, 1, 2};
int producer_count = 0, consumer_count = 0;

int toy_mutex(char **args);

char *builtin_str[] = {
    "send",
    "mu",
    "sh",
    "exit"
};

int (*builtin_func[]) (char **) = {
    &toy_send,
    &toy_mutex,
    &toy_shell,
    &toy_exit
};

int input()
{
	...
    
    int i;
    pthread_t thread[NUMTHREAD];
    
    pthread_mutex_lock(&global_message_mutex);
    strcpy(global_message, "hello world!");
    buflen = strlen(global_message);
    pthread_mutex_unlock(&global_message_mutex);
    pthread_create(&thread[0], NULL, (void *)toy_consumer, &thread_id[0]);
    pthread_create(&thread[1], NULL, (void *)toy_producer, &thread_id[1]);
    pthread_create(&thread[2], NULL, (void *)toy_producer, &thread_id[2]);


    for (i = 0; i < NUMTHREAD; i++) {
        pthread_join(thread[i], NULL);
    }
	...
}

int toy_mutex(char **args)
{
    if (args[1] == NULL) {
        return 1;
    }

    printf("save message: %s\n", args[1]);
    pthread_mutex_lock(&global_message_mutex);
    strcpy(global_message, args[1]);
    pthread_mutex_unlock(&global_message_mutex);
    return 1;
}

/*  consumer & producer */

void *toy_consumer(int *id)
{
    pthread_mutex_lock(&count_mutex);
    while (consumer_count < MAX) {
        pthread_cond_wait(&empty, &count_mutex);
        // get from queue
        printf("                           소비자[%d]: %c\n", *id, buffer[read_count]);
        read_count = (read_count + 1) % TOY_BUFFSIZE;
        fflush(stdout);
        consumer_count++;
    }
    pthread_mutex_unlock(&count_mutex);
}

void *toy_producer(int *id)
{
    while (producer_count < MAX) {
        pthread_mutex_lock(&count_mutex);
        strcpy(buffer, "");
        buffer[write_count] = global_message[write_count % buflen];
        // push at queue
        printf("%d - 생산자[%d]: %c \n", producer_count, *id, buffer[write_count]);
        fflush(stdout);
        write_count = (write_count + 1) % TOY_BUFFSIZE;
        producer_count++;
        pthread_cond_signal(&empty);
        pthread_mutex_unlock(&count_mutex);
        sleep(rand() % 3);
    }
}

0개의 댓글

관련 채용 정보