앞의 글에서 설명한 CLI 구현 방식에는 조금 불편한 내용이 있다.새로운 명령을 추가하거나 삭제하기 위해서는 cli_command[] 배열을 수정해야 된다는 것이다. 이것이 크게 문제 되지 않기는 하겠지만 때로는 상당히 번거로운 일이 되기도 한다.이번 글에서는 좀 더 쉬운 방법을 통해서 CLI 처리 부분에 대한 소스 코드 수정없이 새로운 명령을 추가 하는 방법에 대해서 설명 하도록 하겠다.이 방법은 링커 프로그램을 이용하는 방법이다.따라서 이 기능을 위해서 링커 스크립트 파일을 수정하도록 하겠다. .text : { KEEP(*(.vectors.table)) KEEP(*(.vectors.code)) *(.text .text.*) __cli_start = .; KEEP(*(SORT(.cli.*))) __cl..
메뉴 방식 사용자 인터페이스는 직관적인 인터페이스를 가지므로 굳이 사용법을 배우지 않더라도 쉽게 사용할 수 있다.그러나, 원하는 기능을 수행하기 위해서는 여러 단계를 거쳐야 하고, 또다른 기능을 수행하기 위해서는 최상위 단계까지 나온 다음 새로운 단계로 들어가야 한다. 즉, 사용법은 쉽지만 절차가 복잡하다는 단점이 있다.이와 다르게 이번에 설명할 CLI 기능은 명령어 방식을 적용하여 필요한 기능을 즉시 수행할 수 있도록 해준다. 특히 임베디드 시스템의 개발 단계에서 필요한 기능을 시험할 때 유용하게 사용할 수 있으므로 알아두면 도움이 될것 같다.CLI의 단점은 자주 사용하는 명령어는 문제 없지만 가끔씩 사용하는 명령어는 사용법을 기억하지 못하여 문서를 만들어 두거나 소스를 분석해야 하는 경우가 있다. 이..
앞에서 설명한 글들에서는 사용자로부터 입력을 받는 방법에 대해서 설명하였다.이번 글에서는 앞의 내용들을 응용하여 사용자의 입력을 받아들이고, 사용자가 원하는 기능을 수행해 보는 방법중 하나인 메뉴 방식 사용자 입력에 대해서 설명하도록 하겠다. extern void root_menu(char *); void loop(void) { root_menu("Just4fun Online Market"); } loop() 함수에서 root_menu()를 불러 메뉴 방식 인터페이스를 시작하도록 한다. static int get_menu_num(void) { int num; char *cmd = wait_command(); num = strtol(cmd, NULL, 0); return num; } static void ..
일반적인 C 프로그램은 다음과 같은 코드로부터 시작 한다.C 프로그램은 반드시 main() 함수로부터 시작 되며, main() 함수의 argument는 int argc, char *argv[]를 가진다. 때로는 세번째 argument로 char *envp[]를 가질수도 있지만 대부분의 경우 사용하지 않는다.argc와 argv는 쉘에서 프로그램을 실행할 때 실행파일 뒤에 연달아 입력되는 문자열의 개수와 각각의 문자열에 대한 포인터값을 알려주기 위하여 사용된다. #include int main(int argc, char *argv[]) { int i; printf("Number of Arguments: %u\n", argc); for (i=0; i
이번 글에서는 실제로 사용자가 하나씩 입력하는 문자를 버퍼에 저장하였다가, 사용자가 엔터키를 누르게 되었을 때 저장해 둔 문자열을 리턴해 주는 코드를 만드는 방법에 대해서 설명하도록 하겠다.#define CTRL_B 2 #define CTRL_C 3 #define CTRL_F 6 #define EOL '\0' #define ENTER '\r' #define BS '\b' #define ESC 0x1B #define ESC2 '[' #define DELIMIT '~' #define DELETE 0x7F #define UP_ARROW 'A' #define DN_ARROW 'B' #define RI_ARROW 'C' #define LE_ARROW 'D' static char command_buf[BD_CMD_..
많은 임베디드 시스템은 사람의 개입없이 자동으로 미리 설정된 조건에 따라 동작되도록 만들어져 있다. 그러나, 또다른 많은 임베디드 시스템은 사람의 직접적인 조작을 필요로 하기도 한다.임베디드 시스템에 적용할 수 있는, 사용자의 입력을 받아 들이는 방법과 결과를 알려주는 방법은 셀 수 없이 많겠지만, 그 중에서도, 임베디드 시스템 개발 단계에서 가장 쉽고 유용하게 선택할 수 있는 기능인 UART를 통한 사용자 인터페이스에 대한 설명을 진행해 보도록 하겠다.지금까지는 주로 보드의 동작 상태를 확인하거나 디버거 메시지를 출력하기 위하여 UART를 사용하였다면, 앞으로 설명할 내용들은 사용자의 입력을 어떤 방식으로 처리할 것인지에 대한 내용을 다룰 것이므로 알아두면 유용하게 활용할 수 있을 것이다.먼저 확인할 ..
이번 글에서는 mailbox에 대해서 설명하도록 하겠다. 앞의 글에서 설명한 semaphore나 flag는 이벤트가 발생했다는 것만을 알려주는것이었다면, mailbox는 어떤 이벤트가 발생했는지 그 내용을 전달해주는 기능을 제공한다. 자세한 내용은 소스를 구현해 나가면서 설명하도록 하겠다. 역시 mailbox를 구현하기 위하여 os.h에 mailbox를 위한 구조체를 선언하여야 한다. struct os_mbox { uint8_t size; uint8_t base; uint8_t count; struct list get_list; struct list put_list; void **item; }; 위의 구조체에서 item이라는 항목이 이벤트의 내용을 저장하기 위한 포인터 배열이다. size는 mailbox..
앞의 글에서 설명한 Semaphore는 단순히 이벤트가 발생했다는 것만을 알려주기 위하여 사용된다면, 이번 글에서 다룰 flag는 이벤트의 종류를 세분화 하여 알려줄수 있는 기능을 지원한다. 예를 들어 다음과 같은 상황을 상상해 보자. 몇만톤급의 호화유람선의 진수식이 조선소에서 진행되고 있다. 유람선을 구매한 선사에서 사장, 부사장, 선장, 승무원 대표 이렇게 네명과, 배를 만든 조선회사의 사장, 부사장, 공장장, 사원대표 이렇게 네명을 포함하여 모두 여덟명의 주요 인사들 앞에 스위치가 하나씩 설치되어 있다. 이제 사회자의 진행에 따라 배를 바다에 띄우기 위하여 스위치를 누르라는 얘기를 하면 각자 스위치를 누를 것이다. 이러한 상황에서 양쪽 회사의 사장과 부사장들 네명 모두 스위치를 눌렀을 때 비로소 배..
간단한 임베디드 시스템이라면 앞에서 설명했던 counter만 가지고도 필요한 기능을 수행할 수 있겠지만, 일반적인 임베디드 시스템에서는 좀더 다양한 형태의 이벤트 처리 기능을 요구하게 된다. 인터럽트가 발생했을때 적절한 처리를 하도록 타스크에게 알려주기 위해서나, 타스크간의 정보 교환이 필요한 경우가 있는데 이를 동기화(Synchronization)라고 한다. megaOS에서는 동기화 기능중 semaphore, flag, mailbox를 만들어 보도록 하겠다. Synchronization을 지원하기 위해서 TCB 구조체에 sync_list를 추가하여야 한다. 당연히 os_task_create() 함수에서는 sync_list 초기화 코드도 추가하여야 한다. 이 부분은 이 글의 마지막 부분에 첨부되어 있는 ..
RTOS 뿐만 아니라 모든 OS는 커널에서 사용하기 위한 타이머가 있다. 그리고 OS에서 사용할 수 있도록 많은 CPU에는 전용의 타이머를 제공하기도 한다. 이번 글에서는 커널에서 사용하는 system timer에 대해서 설명하도록 하겠다. 먼저 os.h 파일에 필요한 내용을 추가해 보도록 하겠다. #ifdef BOARD_TICKS_PER_SEC #define OS_TICKS_PER_SEC BOARD_TICKS_PER_SEC #else #define OS_TICKS_PER_SEC 100 #endif #define OS_SCHED_TIMESLICE_TICKS (OS_TICKS_PER_SEC/10) OS_TICKS_PER_SEC은 1초에 몇번의 tick을 발생 시킬것인지 설정하는 역할을 한다. OS 타이머는..