펌웨어 RTOS 책을 썼습니다.

나빌레라의 이미지

10년만에 책을 한 권 썼습니다.

10년전에 KLDP에 쓴 글을 바탕으로 책을 냈었습니다.

이 책이죠. 아직도 절판되지 않고 팔리고 있습니다. 10년동안 꾸준히 일정 권수만큼 매년 팔리는 것 보면 아마도 어딘가에서 교재로 쓰고 있지 않나 하는 합리적 의심을 하고 있습니다.

그러는 동안 꾸역꾸역 시간은 흘렀습니다. 저도 어느덧 10년 넘는 경력의 개발자가 되었고 책도 나온지 10년이나 된 오래된 책이 되어 버렸습니다. 물론 10년이 지나서 봐도 여전히 훌륭한 책입니다. 그래도 10년이나 지났으니 새 책을 써야 겠다는 생각이 들었습니다. 10년간 바뀐 개발 환경 그리고 제가 10년간 현업에서 얻은 경험을 살짝 녹여서 책을 썼습니다.

이 책입니다.

다 쓰고 보니 오히려 내용의 난이도는 전작보다 쉬워졌습니다. 역시 경력이 쌓이니 같은 내용도 더 쉽게 설명하는 방법을 터득했나봅니다. 그리고 전작에서 실물 하드웨어 개발보드를 타겟보드로 삼아 내용을 진행했던 것과 달리 이번책에서는 전부다 QEMU에서 작업합니다. (QEMU도 10년동안 프로젝트가 안망하고 계속 발전했더군요. 이제는 완전히 메이저 오픈소스 프로젝트중 하나가 된듯 합니다.) 그래서 책만 사서 열심히 따라하면 책의 내용을 모두 실습해 볼 수 있습니다. 맞습니다. 돈을 아낄 수 있습니다.

이 책도 앞으로 한 10년간 절판없이 생존하길 바라며..
그 10년후에 저도 계속 이 바닥에서 생존하길 바라며..

많이 사 주세요~

File attachments: 
첨부파일 크기
Image icon EmbeddedOSProjectBook.jpeg107.61 KB
Image icon L.jpg92.29 KB

댓글

세벌의 이미지

reistrem의 이미지

주문했는데요.
오늘 오겠네요!!!
야호!!!

나빌레라의 이미지

참! 이 게시물 댓글로 책 내용에 대한 질문을 직접 받고 답변 드립니다.
지난 책 냈을 때 보니 책 출간하고도 한 3년 정도까지 출판사 통해서 질문이 들어오더라구요.

<임베디드 OS 개발 프로젝트>를 읽으면서 궁금한점이 있으면 여기에 댓글 달아 주세요.

----------------------
얇은 사 하이얀 고깔은 고이 접어서 나빌레라

김진희(IDT)의 이미지

책을 구입을 하여 차근 차근 따려 하려고 합니다.(리눅스 계열은 처음입니다.)
리눅스 설치는 워낙에 많은 자료가 있어 문제 없이 진행이 되었습니다.

리눅스 계념이 예전에 DOS 처럼 터미널을 이용한 프로그램 인거 같습니다.

아직 생소한 명령어에 이해가 가지 않지만 그럭저럭 찾아보면서 하고 있습니다.

현재 3.3 QEMU에서 실행을 하고 있습니다. 우분투버전(18.04.3) 입니다.
arm-none-eabi-gdb 를 하려는대 에러가 납니다. 책에도 같은 내용입니다.

그래서 sudo apt install gdb-arm-none-eabi 를 터미널에 입력하면
패키지를 찾을수 없다고 합니다.

우분투 버젼이 높아서 그렇다고 하던데 그렇다고 우분투 버전을
내려서 할수도 없고 책에 우분투 버젼 관련 내용이 없어서 최선 버젼을 설치를 했는데
우분터 버젼을 제시해주시면 차레대로 나갈수 있을거 같습니다.

나빌레라의 이미지

저는 리눅스 민트를 쓰고 있습니다. 최신 버전이긴 한데 리눅스 민트가 아직 우분투 리눅스 최신버전을 적용하지 않았거나 gdb-arm-none-eabi 패키지는 여전히 지원하는 듯합니다. 왜냐면 제 시스템에서는 검색이 되거든요.

아무튼 구글로 검색해 보니

https://askubuntu.com/questions/1031103/how-to-install-gdb-arm-none-eabi-on-ubuntu-18-04

이런 게시물이 나옵니다. 내용을 보니

sudo apt install gdb-multiarch

명령으로 gdb-multiarch 패키지를 설치해서 그냥 gdb를 쓰면 되는 듯 합니다. gdb가 버전이 올라가면서 이제 자체적으로 여러 아키텍처를 지원하는 듯 하네요.

----------------------
얇은 사 하이얀 고깔은 고이 접어서 나빌레라

diet84의 이미지

확인한 내용 감사합니다.
제가 이해 한것은 이것 입니다.
현재 우분투 18.04.3 에서는 gdb-arm-none-eabi 설치 가 안된다.
그래서 그 대체인(상위버젼?) gdb-multiarch 설치를 한다.

그러면 책 내용의 모든 내용은 gdb-arm-none-eabi -> gdb-multiarch 이걸로 대체 가능하다 라는 결론을
얻었습니다.

우분트를 처음 접하는 거라 어려운게 많아 책은 초급자가 보기엔 어려운게 많은거 같습니다.

또한 책 내용중에

3장 28페이지 make -> 1회성 다시 빌드 하려면 clean 명령어 필수
make gdb -> makefile 파일 내용중 gdb-arm-none-eabi -> gdb-multiarch 교체로 해결

그래서 28장을 천천히 진행을 해보면 이렇습니다.
\ make -> 잘 됩니다.
\ make debug -> 잘됩니다. 그리고 창이 하나 뜹니다. 멈춤 검은색창
여기서 문제 입니다. 디버그 내용을 보면 타켓 보드를 띠어 놓는 현상 같은 걸로 보입니다.
그러면 터미널 창은 입력 하는 모양이 아니라 stop 영향으로

\ -> 아니라 그림처럼

\ make debug
생략
pulseaudio: Reason: Invalid argument
|(커서깜박 깜박)

즉 \ 명령어 입력 모드가 아닌 그냥 글자만 입력이 되는 형태가 진행이 되어서
다음 명령어인 make gdb 가 실행이 되지 않습니다. 그렇다고 창을 닫으면(검은색창)

\ 입력모드 가능
gdb 명령어 에서 targer remote:1234 는 연결시간 초과
gdb file build/navilos.axf -> 정상
gdb list -> 정상
gdb info register
The program has no regosters now.
라는 결과가 초래 됩니다. 아마 target remote 가 되면 해결이 될거 같은데 막히는 부분이 많은거 같습니다.

진행불가 jpg / 검은창 닫으면 가능2 / gdb 상황 그림파일 올려 봅니다.
감사합니다.

댓글 첨부 파일: 
첨부파일 크기
Image icon 진행불가.png121.65 KB
Image icon 검은창을 닫으면 가능2.png137.97 KB
Image icon gdb 상황.png138.83 KB
나빌레라의 이미지

터미널 두 개 띄워서 작업하세요.

사실 당연한 건데 터미널 환경(리눅스든 윈도우든) 처음 써 보는 분에겐 어려울 수도 있겠군요.

겪고 계신 문제는 구글 검색하면 쉽게 해결 가능합니다.
검색을 생활화 합시다..

----------------------
얇은 사 하이얀 고깔은 고이 접어서 나빌레라

choi7의 이미지

우선 너무나도 좋은 책 감사합니다. 마침 RTOS에 대하여 이론적으로 학교에서 공부하고 실제로 만져볼 수 있는 기회가 된다는게 너무나도 감사드립니다.
저는 우분투 16.04 LTS버전에서 편집기로 작업중입니다. 4.4절(p.51)에 stdint.h파일을 include디렉토리에 따로 만드셨는데 stdint.h파일을 어떻게 만드셨는지 궁금합니다. 리눅스에서 기본으로 제공하는 include 디렉토리에는 stdint.h을 복사하여 제가 작업중인 include 디렉토리에 추가했는데 stdint.h파일이 다른 헤더파일들을 include하고 있어서 오류가 나는 것 같은데 해결 방법을 잘 모르겠습니다.

댓글 첨부 파일: 
첨부파일 크기
Image icon 스크린샷, 2020-02-14 14-35-55.png237.17 KB
나빌레라의 이미지

arm-gcc에 있는 stdint.h 파일에서 필요한 내용만 가져다가 새로 만들었습니다.

가장 쉬운 방법은 책에 적어 놓은 github 저장소에서 나빌눅스 소스 코드 파일을 받아서 사용하시는 겁니다.

----------------------
얇은 사 하이얀 고깔은 고이 접어서 나빌레라

choi7의 이미지

https://github.com/navilera/Navilos 여기서 제가 stdint.h파일이 있는지 찾아 봤지만 찾지 못했습니다 ㅠ.ㅠ

그리고 4장 맨 앞에 공유해 놓으신 코드 링크 해놓으신 명령어도 stdint.h파일은 찾지 못했습니다.

혹시 가능하시면 선생님께서 새로 만드신 stdint.h파일을 공유 받을 수 있을까요??

나빌레라의 이미지

없을리가 있나요~ㅎㅎㅎ
자세히 찾아보세요. 100% 있습니다.
그냥 링크 달아드리고 싶으나,
이런것 찾아보는것도 공부라 생각되어
확신만 드립니다.
파일이 있으니 찾아보세요.

----------------------
얇은 사 하이얀 고깔은 고이 접어서 나빌레라

choi7의 이미지

말씀하신대로 제가 잘못 찾았던거였던군요.. stdint.h파일은 찾았습니다.

그러나 main 함수를 찾지 못하는 것 같습니다. undefined reference to main error가 뜹니다..

구글링 해본 결과 오타 혹은 gcc옵션실수 나 함수의 공개 범위문제라고 어떤문제일까요?

댓글 첨부 파일: 
첨부파일 크기
Image icon Makefile.png303.99 KB
Image icon Main.png188.54 KB
Image icon Entry.png289.45 KB
Image icon error.png233.54 KB
choi7의 이미지

제가 바보같은 오류를 범했더군요 ㅠㅠ 이제부터 더 깊게 생각해보겠습니다! (ㅡㅡ)

손혁준의 이미지

출판사로 내용을 보냈는데, 여기를 앞으로 이용하라고 해서 일단 다시 올립니다.

책을 사서 읽어 정리가 잘되어 책에 대해서 대단히 만족합니다.

몇가지 질문과 제가 찾은 오타 등 정리해서 올립니다.

일단 전체적으로 정리가 잘된 책이라고 생각합니다. 저자에게 진심으로 감사드립니다.

첫째, 모든 코드에서 struct, union, enum typedef할 때 보면
typedef struct queue_t {
....
....
} queue_t
같은 코딩스타일을 사용하는데, 저는 typedef struct queue_t queue_t 이런 코딩스타일을 처음 보아서 왜 이런 스타일을 일관되게 사용하시는지 궁금합니다.

P136

코드 8.1:태스크 컨트롤 블록과 관련 함수 정의 task.c -> task.h로 변경이 필요함.

P148

if (pNextTcb != pNextTcb) -> if (pNextTcb != sCurrent )

P163 상단에 문장 의미를 좀 더 명확하게 해주었으면 함.

지금까지의 컨텍스트는 모두 사라지고 태스크의 컨텍스트를 ARM 코어에 덮어 씁니다.

>> 지금까지의 (ARM Core에서의) 컨텍스트는 모두 사라지고 (스택에 있는) 태스크의 컨텍스를 ARM 코어에 덮어 씁니다.

p170 상단의 문장 의미를 좀 더 명확하게 해주었으면 함.

그리고 개별 프로그램의 버튼 클릭 이벤트 함수가 태스크에 있는 이벤트 핸들러 함수와 같은 역활을 한다.

>> 그리고 (MS윈도우즈에서의) 개별 프로그램의 버튼 클릭 이벤트 함수가 (우리가 애기하고 있는) 태스크에있는 이벤트 핸들러 함수와 같은 역할을 합니다.

p178 하단

만약 기다리는 이벤트가 커널에 없으면 Kernel_yield() 커널 API를 호출해서 다른 태스크로 컨텍스트를 넘깁니다.

>> 컨텍스트를 넘긴다는 말이 좀 모호하다. 컨텍스트를 넘긴다는 것이 문맥교환(컨텍스트 스위칭)이 이루어진 다는 말 또는 CPU를 넘긴다(양보한다)

"컨텍스트를 넘긴다"는 말이 여러 군데서 사용되는데 의미가 모호함

p184 상단

비트맵으로 설계되어 있으므로 논리 OR 연산자(|)로 원하는

>> 비트 OR 연산자(|)

p193 코드 12.2 7번째 라인

KernelCirQ_t sMsgQ[KernelMsgQ_Num];

>> 이 책에서 일관되게 사용한 코딩 스타일을 보면 변수에 s가 붙으면 static 변수 였는데 그렇다면

static KernelCirQ_t sMsgQ[KernelMsgQ_Num];

p208

이 페이지에 synch.h헤더 파일이 있어야 할 것 같은데, 바로 코드 13.1 세마포어 구현 synch.c가 나옴

p219 코드 11.3에 나오는 synch.h 파일 삽입이 필요해 보임

p209 하단

당연히 이 값이 2면 컨텍스트 두 개까지, 3이면 컨택스트 세 개까지 진입 가능합니다.

>> 여기서 컨텍스트가 태스크를 의미하는 건가요? 모호한 것 같아 보임

p210 하단

kernel_yield() 함수를 호출해야만 스케줄링이 동작하므로 동기화

>> 명확한 표현을 위해 kernel_yield() 함수를 명시적으로 호출해야만

p219 코드 13.9 첫번째 라인

KernelMutext_t sMutx;

>> 이 책에서 일관되게 사용한 코딩 스타일을 보면 변수에 s가 붙으면 static 변수 였는데 그렇다면

static KernelMutex_t sMutex;


다시 한번 훌륭한 책에 감사드립니다.

나빌레라의 이미지

책을 그야말로 정독해 주셔서 감사합니다.

그럼 아래 답변입니다..

첫째, 모든 코드에서 struct, union, enum typedef할 때 보면 typedef struct queue_t { .... .... } queue_t 같은 코딩스타일을 사용하는데, 저는 typedef struct queue_t queue_t 이런 코딩스타일을 처음 보아서 왜 이런 스타일을 일관되게 사용하시는지 궁금합니다.

해당 코딩 스타일은 매우 일반적이고 많이 사용하는 코딩스타일입니다. 대부분 타이핑 길게하기 싫어서 그렇죠

P136

코드 8.1:태스크 컨트롤 블록과 관련 함수 정의 task.c -> task.h로 변경이 필요함.

감사합니다. 출판사에 전달하겠습니다.

P148

if (pNextTcb != pNextTcb) -> if (pNextTcb != sCurrent )

감사합니다. 출판사에 전달하겠습니다.

P163 상단에 문장 의미를 좀 더 명확하게 해주었으면 함.

지금까지의 컨텍스트는 모두 사라지고 태스크의 컨텍스트를 ARM 코어에 덮어 씁니다.

지금까지의 (ARM Core에서의) 컨텍스트는 모두 사라지고 (스택에 있는) 태스크의 컨텍스를 ARM 코어에 덮어 씁니다.

감사합니다. 출판사에 전달하겠습니다.

p170 상단의 문장 의미를 좀 더 명확하게 해주었으면 함.

그리고 개별 프로그램의 버튼 클릭 이벤트 함수가 태스크에 있는 이벤트 핸들러 함수와 같은 역활을 한다.

그리고 (MS윈도우즈에서의) 개별 프로그램의 버튼 클릭 이벤트 함수가 (우리가 애기하고 있는) 태스크에있는 이벤트 핸들러 함수와 같은 역할을 합니다.

감사합니다. 제안해 주신 문장을 참고해서 해당 문장은 새로 쓰는게 나을것 같습니다.

p178 하단

만약 기다리는 이벤트가 커널에 없으면 Kernel_yield() 커널 API를 호출해서 다른 태스크로 컨텍스트를 넘깁니다.

컨텍스트를 넘긴다는 말이 좀 모호하다. 컨텍스트를 넘긴다는 것이 문맥교환(컨텍스트 스위칭)이 이루어진 다는 말 또는 CPU를 넘긴다(양보한다)

"컨텍스트를 넘긴다"는 말이 여러 군데서 사용되는데 의미가 모호함

모호하지 않습니다. 정말 컨택스트를 넘기는 것이니까요.

p184 상단

비트맵으로 설계되어 있으므로 논리 OR 연산자(|)로 원하는

비트 OR 연산자(|)

감사합니다. 출판사에 전달하겠습니다.

p193 코드 12.2 7번째 라인

KernelCirQ_t sMsgQ[KernelMsgQ_Num];

이 책에서 일관되게 사용한 코딩 스타일을 보면 변수에 s가 붙으면 static 변수 였는데 그렇다면

static KernelCirQ_t sMsgQ[KernelMsgQ_Num];

감사합니다. 출판사에 전달하겠습니다. 깃헙에 올린 코드는 static인데 책에는 누락되어 있네요.

p208

이 페이지에 synch.h헤더 파일이 있어야 할 것 같은데, 바로 코드 13.1 세마포어 구현 synch.c가 나옴

p219 코드 11.3에 나오는 synch.h 파일 삽입이 필요해 보임

해당 설명을 하는 시점에 너무 뻔한 코드는 넣지 않았습니다. 불필요한 설명이니까요. p219에는 뻔하지 않은 KernelMutex_t 구조체에 대한 선언을 설명하기 때문에 synch.h가 필요한 것입니다.

p209 하단

당연히 이 값이 2면 컨텍스트 두 개까지, 3이면 컨택스트 세 개까지 진입 가능합니다.

여기서 컨텍스트가 태스크를 의미하는 건가요? 모호한 것 같아 보임

세마포어는 일반적 개념입니다. 나빌로스에는 없지만 태스크가 여러개의 컨택스트를 가질 수 있지요(쓰레드). 그래서 컨택스트라는 용어를 사용한것입니다.

p210 하단

kernel_yield() 함수를 호출해야만 스케줄링이 동작하므로 동기화

명확한 표현을 위해 kernel_yield() 함수를 명시적으로 호출해야만

C언어에서 모든 호출은 명시적입니다. 굳이 '명시적'이라는 용어를 쓸 필요없습니다.

p219 코드 13.9 첫번째 라인

KernelMutext_t sMutx;

이 책에서 일관되게 사용한 코딩 스타일을 보면 변수에 s가 붙으면 static 변수 였는데 그렇다면

static KernelMutex_t sMutex;

감사합니다. 출판사에 전달하겠습니다. 그러고 보니 저거 오타네요.. 깃헙 코드에도 오타가 있네요..헐...

----------------------
얇은 사 하이얀 고깔은 고이 접어서 나빌레라

hjs1543의 이미지

struct, union, enum typedef할 때 보면 typedef struct queue_t { .... .... } queue_t 에서 제가 문의한 것은
typedef struct queue_t queue_t가 좀 의아하다는 것입니다. 보통 typdef struct queue queue_t라고 사용하는데.. 특이해 보여서 여쭤 보았습니다. 혹시 self-referential pointer를 일관되게 사용하기 위해서 인지...

나빌레라의 이미지

딱히 대단한 이유는 없습니다.
평소에는 typedef struct _name_t_ {....} name_t; 이런식으로 많이하는데 나빌로스의 첫 번째 구조체를 작성하던 날 기분이 typedef struct name_t {....} name_t;로 하고 싶어서 그렇게 썼고 그 이후로는 그냥 일관성 유지하려고 똑같은 스타일로 쓴 것 뿐입니다.

----------------------
얇은 사 하이얀 고깔은 고이 접어서 나빌레라

choi7의 이미지

UART 베이스 주소와 인터럽트 컨트롤러 베이스 주소를 지정 할때 특정한 주소를 지정해야 하나요?

그리고 베이스 주소를 지정하는 이유가 있을까요??

제 생각에는 베이스 주소가 없으면 어디에서 시작해야하는 지 몰라서 지정하는 것 같은데...

나빌레라의 이미지

네, 특정한 주소를 지정해야 합니다. 그 주소는 HW마다 다릅니다. 정해진 주소를 데이터시트에서 찾아서 써야 합니다.
베이스 주소가 해당 HW의 레지스터가 매핑된 주소입니다.

----------------------
얇은 사 하이얀 고깔은 고이 접어서 나빌레라

양희웅의 이미지

책으로 열심히 공부하고있는 사람입니다.
우선 이 책을 통해서 ‘펌웨어 개발’이라는 부분을 학교에서 이론으로만 배워서 답답한 상태였던 컴퓨터구조, 운영체제와 직접 접목시키면서 실습하고, 복습할 수 있는 기회를 얻은 것 같아 정말 감사하다는 말씀을 드리고 싶습니다.
공부하다가 의문이 드는 부분을 몇개 발견해서 댓글을 작성합니다.

1. 39페이지의 5번째 줄의
‘이중 USR 모드와 SYS 모드는 레지스터를 공유하므로 SP 레지스터는 총 6개의 뱅크드 레지스터로 제공됩니다.’
부분입니다.
책의 A.1.5 부분(p.244)과 ARM 홈페이지에 있는 정보에 의하면 USR과 SYS모드에서는 banked register를 사용하지 않는 것으로 나옵니다.
그러면 ‘banked register’로서 제공되는 SP 레지스터는 5개가 되어야 하지 않나? 라는 의문이 들었습니다.

2. 238페이지의
‘3. CPSR의 동작 모드 비트와 I, T 비트의 값을 각 익셉션과 동작 모드에 맞게 변경합니다.’
부분입니다.
T비트의 값은 ‘5. SCTLR의 TE 비트 값에 따라 T 비트를 설정합니다’ 부분에서 설정되는 것으로 나옵니다.
혹시 T비트가 2번 설정되나요?
아니면 I비트는 IRQ를 의미하니 FIQ를 의미하는 F비트대신, T비트로 잘못 작성하신 건지 궁금합니다.

3. 244페이지의 그림 A.1 부분입니다.
레지스터의 여러 동작 모드가 나오는데, 맨 오른쪽에 앞의 부분에서는 설명되지 않은 ‘MON’모드가 추가되어 있습니다.
ARM에서는 37개의 작업 레지스터를 사용한다고 하셨지만, MON모드의 banked register까지 추가하면 40개의 레지스터가 되어버립니다.
MON모드의 banked register를 레지스터의 개수를 셀 때 포함하지 않는 이유도 추가해 주셨으면 좋을 것 같습니다.

감사합니다!

양희웅의 이미지

파트 5.4 printf 파트에서

debug_printf()함수에서 쓰이는 printf_buf(코드 5.16의 5번째, 8번째 줄)
vsprintf()함수에서 쓰이는 PRINTF_BUF_LEN(코드 5.19의 48번째 줄)

두 개가 책에는 정의되어 있지 않습니다.
깃헙에 올리신 코드를 보면 정의가 되어있는데 책에는 쓰여있지 않습니다.
그리고 책에서는 printf_buf이지만, 깃헙에서는 sPrintf_buf로 다른 이름으로 정의되어 있습니다.
감사합니다!

나빌레라의 이미지

Quote:

깃헙에 올리신 코드를 보면 정의가 되어있는데 책에는 쓰여있지 않습니다.

원고를 다 쓴 다음 코드를 수정해서 그렇습니다.
원고에 있는 코드와 깃헙의 코드가 100% 일치하진 않습니다.

----------------------
얇은 사 하이얀 고깔은 고이 접어서 나빌레라

나빌레라의 이미지

감사합니다.

1. 그림만 보면 덮어 버리는 (뱅크드하는) 레지스터만 뱅크드 레지스터로 볼 수도 있겠네요. 저는 뱅크드 대상이 되는 레지스터를 모두 뱅크드 레지스터라고 생각합니다. 그래서 6개라고 했고요. 실제로 개발 할 때도 동작 모드에 따라 뱅크드되는 레지스터를 모두 뱅크드 레지스터라고 이해 하는게 더 쉽습니다.

2. 두 번 설정됩니다.

3. MON 모드는 ARM 아키텍처 버전에 따라 지원하기도 하고 안 하기도 하기 때문입니다.

----------------------
얇은 사 하이얀 고깔은 고이 접어서 나빌레라

홍경호의 이미지

책 내용이 너무 좋습니다. 감사합니다.
많은 도음이 되고 있고 질문사항이 있어 문의드립니다.

void Kernel_task_init(void)
{
sAllocated_tcb_index = 0;
sCurrent_tcb_index = 0;

for(uint32_t i = 0 ; i < MAX_TASK_NUM ; i++)
{
sTask_list[i].stack_base = (uint8_t*)(TASK_STACK_START + (i * USR_TASK_STACK_SIZE));
sTask_list[i].sp = (uint32_t)sTask_list[i].stack_base + USR_TASK_STACK_SIZE - 4;

sTask_list[i].sp -= sizeof(KernelTaskContext_t);
KernelTaskContext_t* ctx = (KernelTaskContext_t*)sTask_list[i].sp;

ctx->pc = 0;
ctx->spsr = PSR_INIT;
}
}
Github에 있는 코드 중 Kernel_task_init 함수의 마지막 줄이 ctx->spsr = PSR_INIT;으로 되어 있어 해당 코드에 대해 문의드립니다.

해당os를 stm32 mcu에서 연습을 하고 있어서 해당 코드를 보니
결국 다음과 같이 표현이 되더군요
ctx->spsr = 0x21000000;
psr register 를 보니 Thumb 모드 1, Carry flag 1 로 setting 하는 것 같은데 cortex-m 은 arm mode를 지원하지 않기 때문에 thumb 모드로 한것 같은데 Carry flag는 이유를 잘 모르겠습니다.

혹시 알려주실 수 있을 까요??

나빌레라의 이미지

STM32 BSP에 기본값이 그렇게 설정되 있어서 그대로 썼습니다.

----------------------
얇은 사 하이얀 고깔은 고이 접어서 나빌레라

홍경호의 이미지

안녕하세요 질문 사항이 또 있습니다
제가 이해 한 것이 맞는지 궁금해서요..
github에 있는 프로젝트의 stm32f103용 ld 파일을 보면 다음과 같이 메모링 영역이 설정 되어 있는데요.
/* Uninitialized data section */
. = ALIGN(4);
.bss :
{
/* This is used by the startup in order to initialize the .bss secion */
_sbss = .; /* define a global symbol at bss start */
__bss_start__ = _sbss;
*(.bss)
*(.bss*)
*(COMMON)

. = ALIGN(4);
_ebss = .; /* define a global symbol at bss end */
__bss_end__ = _ebss;
} >RAM

/* User_heap_stack section, used to check that there is enough RAM left */
._user_heap_stack :
{
. = ALIGN(8);
PROVIDE ( end = . );
PROVIDE ( _end = . );
. = . + _Min_Heap_Size;
. = . + _Min_Stack_Size;
. = ALIGN(8);
} >RAM

bss 내용을 RAM에 할당하고 그 다음 heap 영역이 설정되어 있습니다. 그런데 github의 MemoryMap.h를 보면

extern uint32_t __bss_end__;

#define TASK_STACK_START ((uint32_t)&__bss_end__)
#define USR_TASK_STACK_SIZE (2 * 1024)
#define TASK_STACK_SIZE (USR_TASK_STACK_SIZE * 3)

#define EFLASH_TOTALNUM 64
#define EFLASH_START 0x08000000
#define EFLASH_PAGESIZE 0x400
#define EFLASH_BADDR(X) (EFLASH_START + EFLASH_PAGESIZE * (X))

#define MAIN_FW_PAGENUM 20
#define MAIN_FW_FLASH_SIZE 43
#define MAIN_FW_ENTRY_OFFSET (MAIN_FW_PAGENUM * EFLASH_PAGESIZE)
#define MAIN_FW_BADDR EFLASH_BADDR(MAIN_FW_PAGENUM)

#define KEYMAP_PAGENUM (EFLASH_TOTALNUM - 1) /* last page of eFlash */
#define KEYMAP_BADDR EFLASH_BADDR(KEYMAP_PAGENUM)

위와 같이 __bss_end__ 가 끝난 영역부터 Task 의 Stack 사이즈로 설정 되어 있는데요. 이렇게 하게 될 경우 Task 영역으로 설정된 부분과 Heap 영역이 겹치게 될것 같은데, 혹시 제가 잘못 이해하고 있는 것인가요?

처음 메모리맵과 OS를 접하다보니 부족한 부분이 많네요...

답변 주시면 정말 감사하겠습니다~!

나빌레라의 이미지

질문이 이해가 안됩니다.

heap과 stack은 사용하는 방향이 반대입니다. 그래서 정한 크기를 넘기지 않는한 겹치지 않습니다. 크기를 넘겨서 사용하면 겹치죠. 그런데 크기를 넘었다는 것부터 오류입니다. 그래서 그런 상황이 생기면 크기를 조정해야 하죠.

----------------------
얇은 사 하이얀 고깔은 고이 접어서 나빌레라

지옥참새의 이미지

cc1: warning: switch '-mcpu=cortex-a8' conflicts with '-march=armv7-a' switch
위와 같은 warning을 뱉는데 어떻게 제 능력으로 해석이 안됩니다.

4장 내용까지는 어떻게 진행이 되기는 되고 디버그 단계에서 step이 안먹네요

의견 부탁드립니다.

댓글 첨부 파일: 
첨부파일 크기
Image icon warning.png96.33 KB
나빌레라의 이미지

-marm

옵션을 추가 해 보세요.

----------------------
얇은 사 하이얀 고깔은 고이 접어서 나빌레라

써니의 이미지

우선 책내용이 정말 도움이 됩니다. 감사합니다.
22P gdb x/4x 0입력하면 책에는 0x0 : 0x01 0x00 0xa0 0xe1되어있지만
저는 0x0: 0xe3a00201 0xe5901000 0x00000000 0x00000000 이렇게 출력됩니다.
저의 터미널 창에는 왜 가 표시되지 않으까요?
gdb-multiarch 사용중이며 혹시 이게 문제인가 싶어서 우분투 16버전으로 gdb 설치하여 진행해봤으나 동일합니다.
그리고 책의 출력처럼 바이트단위로 출력이 되려면 혹시 x/4bx 0 이렇게 입력해야하지 않나요 오타인가요?

써니의 이미지

표시가 안되어 해당 부분만 다시 적습니다.
22P gdb x/4x 0입력하면 책에는 0x0 vector_start: 0x01 0x00 0xa0 0xe1되어있지만
저는 0x0: 0xe3a00201 0xe5901000 0x00000000 0x00000000 이렇게 출력됩니다.
저의 터미널 창에는 왜 vector_start 가 표시되지 않으까요?

나빌레라의 이미지

x/4bx 일땐 제대로 나오나요? 제가 알기로도 x/4bx가 맞는데.. 책에 x/4x로 나왔다면 오타 맞습니다..

----------------------
얇은 사 하이얀 고깔은 고이 접어서 나빌레라

써니의 이미지

위에 다른 질문도 확인 가능하실까요?^^

나빌레라의 이미지

출력 포멧의 차이일 뿐이니 값이 같다면 문제 없습니다.

----------------------
얇은 사 하이얀 고깔은 고이 접어서 나빌레라

써니의 이미지

x/b4x 와 x/4x의 차이는 출력 포멧의 차이라 상관없는데
제가 궁금한건 vector_start라는 symbol? 표시가 안되는 이유입니다.
gdb 창에 list 명령어 입력하면 No symbol table is loaded 라고 뜨던데 symbol 인식에 문제가 있다는 말일까요?
오브젝트 파일 추출할때 -g 옵션추가로 해줬는데 안되네요. 책에는 vector_start라는 표시 이후에 Data값이 출력되던데 제껀 안되고 있어 영 찝찝합니다..

나빌레라의 이미지

보통 -g 옵션을 넣으면 심볼 정보가 있어야 합니다.. 음.. 그러면 objdump나 readelf 등의 툴로 심볼 정보만 뽑아서 확인해 보실래요? 이게 가끔 gdb가 이상하면 저럴 때도 있거든요.

----------------------
얇은 사 하이얀 고깔은 고이 접어서 나빌레라

써니의 이미지

navilos.axf: file format elf32-littlearm
Disassembly of section .text:
00000000 :
0: e1a00001 mov r0, r1
00000004 :
...
~~(생략)
GDB multiarch, GDB 둘다 동일증상인데 설치 문제라고 생각하면 될까요?

나빌레라의 이미지

설치문제는 아닌것 같고요. Github에 있는 소스 코드 그대로 받아서 빌드해도 GDB에서 vector_start가 안나오나요?

----------------------
얇은 사 하이얀 고깔은 고이 접어서 나빌레라

완전초보자의 이미지

안녕하세요.
10장을 따라서 실행했는데, 태스크 전환이 안됩니다.
void Kernel_task_start(void){}함수에서 Restore_context()함수를 호출하기 직전에 리셋이 되는 것 같습니다.
계속해서 예제로 출력했던 문자들(NNNNNN....)이 반복적으로 나옵니다.

혹시 github에서 .cproject 와 .settings/.gitignore 도 적용해줘야 되는 건가요? (이 둘을 어떻게 파일을 만들거나 적용해야 할지 몰라서 뺐었습니다)

나빌레라의 이미지

cproject 와 .settings/.gitignore 는 상관없습니다.
질문 내용만 가지고는 무슨 이유로 태스크 전환이 안되는지 정보가 부족합니다.
github의 코드를 그대로 가져다가 빌드해서 테스트해보고 본인이 작성한 코드와 차이를 비교해 보기 바랍니다.

----------------------
얇은 사 하이얀 고깔은 고이 접어서 나빌레라

완전초보자의 이미지

책과 소스코드 보면서 타이핑하다가 한 줄 빠뜨렸었네요.
감사합니다.

오미눅1의 이미지

"3.3 QEMU에서 실행해보기"에서 두가지 문제점이 있습니다.
1. qemu-system-arm -M realview-pb-a8 -kernel navilos.axf -S -gdb tcp::1234,ipv4 명령어를 칠 경우 교재와는 다른 error 문구가 표시됩니다. ( 사진 1 첨부 )
2. 그래서 인지 arm-none-eabi-gdb 명령어 입력 후 target remote:1234를 칠 경우 Connection timed out이 출력되네요..

상기 문제점은 UBUNTU 20.04 / 18.04 / 16.04에서도 동일하게 발생되네요..
방화벽 해제 등 여러 방법을 찾아서 수행해봤는데, 해결이 안되서 도움 요청합니다.
의심 갈만한 부분이 있으면 코멘트 부탁드립니다 !

댓글 첨부 파일: 
첨부파일 크기
Image icon 사진1.png53.38 KB
나빌레라의 이미지

연관없어 보이는 에러는 무시하면 됩니다.

----------------------
얇은 사 하이얀 고깔은 고이 접어서 나빌레라

오미눅1의 이미지

에러와 더불어서 의도한 출력이 나오지 않습니다.
코드 3.6의 gdb와 QEMU를 연결하는 동작이 제대로 되지 않아 문의 드렸습니다..

나빌레라의 이미지

에러 메시지에서는 이상한 내용이 없습니다. 주어진 정보 만으로는 제가 도와 드릴 수 있는 내용이 없네요.

----------------------
얇은 사 하이얀 고깔은 고이 접어서 나빌레라

09의 이미지

초록색 책인데 질문이 잇이어요
책에서 있는데로 make를 하니 이런 에러가나오네요
어디를 고쳐야할지 알려주세요..
리눅스 버전은 5.4.0-47-generic #51~18.04.1-Ubuntu SMP Sat Sep 5 14:35:50 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
$ make
arm-linux-gcc -c -nostdinc -I. -I./include -I fs/include -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fno-strict-aliasing -fno-common -pipe -mapcs-32 -mcpu=xscale -mshort-load-bytes -msoft-float -fno-builtin -o entry.o entry.S
arm-linux-gcc -c -nostdinc -I. -I./include -I fs/include -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fno-strict-aliasing -fno-common -pipe -mapcs-32 -mcpu=xscale -mshort-load-bytes -msoft-float -fno-builtin -o gpio.o gpio.c
arm-linux-gcc -c -nostdinc -I. -I./include -I fs/include -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fno-strict-aliasing -fno-common -pipe -mapcs-32 -mcpu=xscale -mshort-load-bytes -msoft-float -fno-builtin -o time.o time.c
arm-linux-gcc -c -nostdinc -I. -I./include -I fs/include -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fno-strict-aliasing -fno-common -pipe -mapcs-32 -mcpu=xscale -mshort-load-bytes -msoft-float -fno-builtin -o vsprintf.o vsprintf.c
arm-linux-gcc -c -nostdinc -I. -I./include -I fs/include -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fno-strict-aliasing -fno-common -pipe -mapcs-32 -mcpu=xscale -mshort-load-bytes -msoft-float -fno-builtin -o printf.o printf.c
arm-linux-gcc -c -nostdinc -I. -I./include -I fs/include -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fno-strict-aliasing -fno-common -pipe -mapcs-32 -mcpu=xscale -mshort-load-bytes -msoft-float -fno-builtin -o string.o string.c
arm-linux-gcc -c -nostdinc -I. -I./include -I fs/include -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fno-strict-aliasing -fno-common -pipe -mapcs-32 -mcpu=xscale -mshort-load-bytes -msoft-float -fno-builtin -o serial.o serial.c
serial.c:1: error: stray '\357' in program
serial.c:1: error: stray '\273' in program
serial.c:1: error: stray '\277' in program
serial.c:1: error: syntax error at '#' token
serial.c:1: error: parse error before '<' token
In file included from serial.c:2:
include/serial.h:30: warning: type defaults to `int' in declaration of `eBauds'
include/serial.h:30: warning: data definition has no type or storage class
include/serial.h:32: error: parse error before "baudrate"
include/serial.h:32: warning: function declaration isn't a prototype
serial.c:11: error: parse error before "FFUART"
serial.c:11: warning: type defaults to `int' in declaration of `FFUART'
serial.c:11: error: parse error before "Word"
serial.c: In function `SerialOutChar':
serial.c:31: error: parse error before "Word"
serial.c:31: error: `LSR_TDRQ' undeclared (first use in this function)
serial.c:31: error: (Each undeclared identifier is reported only once
serial.c:31: error: for each function it appears in.)
serial.c:34: error: parse error before "Word"
serial.c: In function `SerialIsReadyChar':
serial.c:85: error: parse error before "Word"
serial.c:85: error: `LSR_DR' undeclared (first use in this function)
serial.c: In function `SeriallGet_LSR':
serial.c:97: error: parse error before "Word"
serial.c: In function `SerialIsGetChar':
serial.c:108: error: parse error before "Word"
serial.c:108: error: `LSR_PE' undeclared (first use in this function)
serial.c:108: error: `LSR_FE' undeclared (first use in this function)
serial.c:108: error: `LSR_OE' undeclared (first use in this function)
serial.c:111: error: parse error before "Word"
Makefile:16: recipe for target 'all' failed
make: *** [all] Error 1

-----------------------------------------------------makefile
CC = arm-linux-gcc
LD = arm-linux-ld
OC = arm-linux-objcopy

CFLAGS = -nostdinc -I. -I./include -I fs/include
CFLAGS += -Wall -Wstrict-prototypes -Wno-trigraphs -O2
CFLAGS += -fno-strict-aliasing -fno-common -pipe -mapcs-32
CFLAGS += -mcpu=xscale -mshort-load-bytes -msoft-float -fno-builtin

LDFLAGS = -static -nostdlib -nostartfiles -nodefaultlibs -p -X -T ./main-ld-script

OCFLAGS = -O binary -R .note -R .comment -S
all: navilnux.c
$(CC) -c $(CFLAGS) -o entry.o entry.S
$(CC) -c $(CFLAGS) -o gpio.o gpio.c
$(CC) -c $(CFLAGS) -o time.o time.c
$(CC) -c $(CFLAGS) -o vsprintf.o vsprintf.c
$(CC) -c $(CFLAGS) -o printf.o printf.c
$(CC) -c $(CFLAGS) -o string.o string.c
$(CC) -c $(CFLAGS) -o serial.o serial.c
$(CC) -c $(CFLAGS) -o lib1funcs.o lib1funcs.S
$(CC) -c $(CFLAGS) -o navilnux.o navilnux.c
$(LD) $(LDFLAGS) -o navilnux_elf entry.o gpio.o time.o vsprintf.o printf.o string.o serial.o lib1funcs.o navilnux.o
$(OC) $(OCFLAGS) navilnux_elf navilnux_img
$(CC) -c $(CFLAGES) -o serial.o serial.c -D IN_GUMSTIX
$(LD) $(LDFLAGS) -o navilnux_gum_elf entry.o gpio.o time.o vsprintf.o printf.o string.o serial.o lib1funcs.o navilnux.o
$(OC) $(OCFLAGS) navilnux_gum_elf navilnux_gum_img
clean:
rm *.o
rm navilnux_elf
rm navilnux_img
rm navilnux_gum_elf
rm navilnux_gum_img

나빌레라의 이미지

소스 코드에 오타가 있는가 봅니다.

serial.c:1: error: stray '\357' in program
serial.c:1: error: stray '\273' in program
serial.c:1: error: stray '\277' in program
serial.c:1: error: syntax error at '#' token
serial.c:1: error: parse error before '<' token

컴파일러 에러메시지를 바탕으로 찾아보세요.

----------------------
얇은 사 하이얀 고깔은 고이 접어서 나빌레라

09의 이미지

위에 질문은 마우스패드 텍스트편집기에서 인코딩을 잘못해서 그렇게 되었네요.
이번엔 qemu로 실행하면 윈도우와 리눅스에서 이렇게 나옵니다. 어떻게 해야하나요?
C:\>"C:\Program Files\qemu\qemu-system-arm.exe" -M connex -pflash navilnuximg -nographic
WARNING: Image format was not specified for 'navilnuximg' and probing guessed raw.
Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
Specify the 'raw' format explicitly to remove the restrictions.
C:\Program Files\qemu\qemu-system-arm.exe: device requires 16777216 bytes, block backend provides 315392 bytes

나빌레라의 이미지

QEMU가 버전업 하면서 뭘 막았나보네요.
책에 명시한 QEMU 버전을 쓰거나,

최근에 나온 "임베디드 OS 개발 프로젝트" (주황색책) 으로 공부하는걸 추천드립니다.

----------------------
얇은 사 하이얀 고깔은 고이 접어서 나빌레라

09의 이미지

ez-x5보드 대신에 라즈베리파이에서나 아두이노에서도 os를 포팅할수 있을꺼 같은데 나빌눅스를 포팅할수 있을지알고싶습니다.그리고 어셈으로 제작된 kolibri os나 menuet os를 어셈블하는 방법도 알고싶은데 알고계신다면
알려주세요

나빌레라의 이미지

ARM 기반이면 포팅가능합니다.

----------------------
얇은 사 하이얀 고깔은 고이 접어서 나빌레라

나태의 이미지

P.123 에서 SYSCTRL0 의 값이 0이기 때문에 타이머의 클럭은 1MHz라고 되어있습니다.
그런데 데이터시트에는
TIMCLK is 1MHz. REFCLK is 32.768kHz.
Timer 0 enable/ Timer Reference Select. If 0, the timing reference is REFCLK. If 1, the timing reference is TIMCLK.
다음과 같이 나와있는데, 이러면 0일때 REFCLK이기때문에 32.768kHz 가 맞는거 아닌가요?

나빌레라의 이미지

맞습니다. 서술 오류입니다. 글 쓸 때는 왜 반대로 이해 했는지 모르겠네요.
그리고 이해를 반대로 하고 코딩했으므로 코드가 동작 안해야 하는데 맞게 동작하는것도 이상합니다.. 미스테리네요.

----------------------
얇은 사 하이얀 고깔은 고이 접어서 나빌레라

나태의 이미지

[15bit]Timer 0 enable/ Timer Reference Select. If 0, the timing reference is REFCLK. If 1, the timing reference is TIMCLK.
이므로 15째 bit를 1로 바꾸는것으로 REFCLK으로 해서 1MHz로 하려고 아래와 같은 코드를 사용했습니다.

uint32_t* sysctrl0 = (uint32_t*)0x10001000;
(*sysctrl0) |= (uint32_t)0x00008000;

그런데 했는데도 0으로 출력됩니다.

나빌레라의 이미지

서술 오류와는 별개로 qemu 자체에도 버그가 있는가 봅니다...

----------------------
얇은 사 하이얀 고깔은 고이 접어서 나빌레라

purakong의 이미지

평소, RTOS에 관심이 많았고, 현재 0년차이며, Base Software 개발을 맡고 있습니다. 이것저것 만들어보는 것을 좋아하는데 항상 어딘가에 막히고, 포기하기를 반복했습니다. 임베디드 기본지식이 없으니 배워도 배워도 밑빠진 독에 물을 붓는것 같았죠. 현업과 이책을 번갈아보면서 실무에서는 어떻게 적용되고 있는지를 파악하고, 직접 RTOS를 만들어보니 지겨웠던 업무가 재밌어지고, 저도 나빌로스 작가님처럼 되고 싶다는 생각이 요새 많이 드네요. 너무 친절하게 자세히 책을 써주셔서 이보다 더 좋은 책은 없을 듯 합니다. 한줄기 빛이 되어주셔서 너무나 감사드립니다ㅠㅠㅠ

나빌레라의 이미지

도움이 되었다니 저도 기쁩니다.
자! 이제 이 책을 널리 퍼뜨려 주변 사람들에게 강매 부탁드립니다. :)
공부할 생각 없는 사람에게도 라면받침으로 적당히 얇은 두께로 좋다고 해 주세요..

----------------------
얇은 사 하이얀 고깔은 고이 접어서 나빌레라

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.