펌웨어 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를 연결하는 동작이 제대로 되지 않아 문의 드렸습니다..

나빌레라의 이미지

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

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

아ㅏㅏㅏㅏㅏㅏㅏ의 이미지

qemu-system-arm -M realview-pb-a8 -kernel build/navilos.axf -S -gdb tcp::1234,ipv4 -nographic
로 실행하면 실행됩니다.
이유는 모르겠는데 저는 CPU를 RYZEN을 써서가 아닐까 생각됩니다.
이것때문에 20시간은 보낸듯

mcpark의 이미지

저도 nographic 옵션 사용하여 해결했네요.

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를 만들어보니 지겨웠던 업무가 재밌어지고, 저도 나빌로스 작가님처럼 되고 싶다는 생각이 요새 많이 드네요. 너무 친절하게 자세히 책을 써주셔서 이보다 더 좋은 책은 없을 듯 합니다. 한줄기 빛이 되어주셔서 너무나 감사드립니다ㅠㅠㅠ

나빌레라의 이미지

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

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

09의 이미지

아두이노나 라즈베리파이에 업로드 하는 방법은 없습니까?아신다면 좀알려주세요
ez-x5는 초록책에 있던데 ez-x5하드웨어는 못구했고요 라즈베리파이b+와 아두이노(nodemcu와 ttgo)는 있는데 navilos를 올리는 방법을 찾고있습니다..
infocenter.arm.com에 가보니 realviewpb 데이터시트가 없습니다 DUI0417D_realview_platform_baseboard_for_cortex_a8_ug.pdf는 다운이 되는데 내용이 보드에 대한내용은 없습니다

나빌레라의 이미지

아두이노는 제가 알기로 atmega를 쓰는 보드로 알고 있습니다. ARM 기반인 navilos를 쓰려면 포팅작업을 해야 합니다.
마찬가지로 라즈베리파이의 컨트롤러와 제가 책에 레퍼런스로 쓴 realviewpb는 다른 컨트롤로입니다. 그러나 같은 ARM이기 때문에 UART나 타이머, 인터럽트 정도만 포팅하면 아마 올려서 실습해 볼 수 있을 것입니다.

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

09의 이미지

이책도 dtk4412라는 하드웨어를 사용하는데 cortex-A9쿼드코어계열의 exynos441 사용한다고 나와있습니다.그런데 qemu로돌리려면 어떻게하는지 알고싶습니다.주황책과 qemu를 돌리는 방법이 비슷할꺼 같은데..

나빌레라의 이미지

qemu에서 dtk4412를 지원안하면 못 씁니다. 같은 보드 구성을 하는 호환 보드를 qemu가 지원하는지 찾아보세요.

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

뒤뜰정원사의 이미지

나빌레라님! 좋은 책 써주셔서 감사합니다.
덕분에 많은 도움이 되고 있습니다.
여쭤보고 싶은 것이 있는데요, 이 책을 보고난 이후의 과정에 관한 것입니다.

- RTOS 개발에 관한 조금 더 깊은 공부를 하고 싶은데 추천해 주실만한 도서나 자료가 있을까요?
- 이전에 쓰신 '초록색 책'이 그런 자료에 해당이 될까요? 목차를 보니 큼지막한 내용은 비슷하지만 조금 더 세부적인 내용이 있어 보입니다.

나빌레라의 이미지

두 책의 난이도는 비슷합니다. 나중에 쓴 책에 불필요하다고 생각했던 내용을 뺐지요.
RTOS를 더 알고 싶으면 주제를 하나 정해서 뭔가를 만들어보는 것을 추천합니다.

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

뒤뜰정원사의 이미지

답변 감사합니다. :)

yosi의 이미지

안녕하세요. 우선 좋은 책 잘 보고있습니다. 감사합니다.

3장 챕터 진행중에 몇일동안 구글링 해도 해결이 안되어 질문을 남기게 되었습니다.

< 질문 내용 >

1. QEMU를 킨뒤에 gdb서버를 연결한뒤에 0번 메모리를 참고하였는데
'Cannot access memory at address 0x0'
이런 문구가 계속 뜹니다.

그냥 넘어가려해도 이후 챕터에서 바로 이문제로 인해 진행이 안되는데 왜그럴까요..

위에 다른분들이 gui없이 QEMU를 켜보라고해서 그렇게 해보았는데 서버 접속은 잘되는데 계속 0번 address에 접근할 수 없다고 뜨네요.

리눅스 민트 깔아서 해보아도 동일합니다.

댓글 첨부 파일: 
첨부파일 크기
Image icon 캡처1.PNG1.36 MB
yosi의 이미지

책에는 $ arm-none-eabi-gdb 이렇게만 나와있어서 계속 gdb 만 했는데
$ gdb navilos.axf 이렇게 쳐야하는군요 ㅠㅠ 일주일을 고민했는데 ..
그래도 해결해서 이제 진도를 다시나가는게 더 기쁘네요 :)

이제우의 이미지

안녕하세요.
주황책 21페이지 QEMU 실행하고 gdb 동작하지 않아서 하루종일 해메다가 해결방법을 찾은거같아 다른사람이랑 공유 하고자 글을 작성합니다.(틀린부분있으면 알려주세요. 초보자입니다.)

21페이지
1.sudo apt install gdb-arm-none-eabi 설치 안될때
-->sudo apt install gdb-multiarch 입력후 의존성관련 오류가 뜰경우 예시)sudo apt install gdb=9.1 -o ubuntu1 입력시 설치됨

2.arm-none-eabi-gdb 실행안될때
-->gdb or gdb-multiarch 입력시 동작함

3.gdb 진입시 명령어 오류
-->target remote:1234 입력시 "warning: while parsing target description (at line 1): Target description specified unknown architecture "arm"" 날때
-->여기서 "gdb-multiarch" 해당 명령으로 진입히 오류가 해결된건지 확인이 안되기 때문에 입력했던 명령어를 다 적어보겠습니다.
-->sudo apt-get install gcc-aarch64-linux-gnu 설치-> gdb 진입후 "set arc arm"입력,"set arc aarch64"입력
-->쉘에서 gdb-multiarch 입력후 target remote:1234 입력시 책대로됨, gdb입력후 target remote:1234입력시 여전히 오류남 <-- 이부분은 뭐가 다른건지 모르겠습니다.

적고나니 별거 없네요.. 혹시나 위방법이 아니거나 잘못된내용있으면 알려주시면 감사드리겠습니다.
참고로 민트리눅스"linuxmint-20.1-cinnamon-64bit.iso" 설치 사용중입니다.

yosi의 이미지

제가 위에 적어놓은 방법은 통신을 통해서 들어간게 아니고 그냥 axf파일 그자체를 실행 한것이더라구요..
써주신대로 gdb-multiarch 명령어를 통해 실행해야만 제대로 작동하는 듯 보입니다.

제 생각으로는 위에 저자분께서 써주신대로 버젼이 바뀌면서 지원을안하게 되었고 그래서 저희가 설치할때 다른방식으로 설치를 했는데 그래서 명령어도 달라진게 아닌가... 저도 초보인지라 ㅠㅠ

여튼.. 감사드립니다 ㅠㅠ 엄청 오래 고생했는데 해결한줄알고 뒤로 넘어가다 또 막혀서 절망하고있었는데 다행히 해결되었네요 !!!

duty7351의 이미지

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;
}

나빌레라의 이미지

바이트 어드레스 포인터라서 그렇습니다.

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

ㅇㅇ의 이미지

책에 있는 UART는 0x10009000, TIMER는 0x10011000 메모리 주소를 접근 통해 제어하는데 어떻게 이게 가능한 것인가요? 10진수로 바꾸면 256MB 이상의 메모리 주소에 접근하는 것입니다. 책의 내용에는 QEMU이라서 메모리가 메가 단위로 사용하지만 실제 하드웨어는 몇십 KB 정도밖에 못 쓴다고 여러 차례 언급한 걸로 보면 실제 하드웨어에서는 이렇게 메모리가 256MB 이상씩이나 있는 것 같진 않는데 어떻게 메모리 주소를 접근이 가능한 건가요? 물론 데이터시트를 보면 그렇다고 하는 말 말고 원리를 알고 싶습니다. 가령 어떠한 장치가 있기 때문에 가능하다든가요. 실제 실무에서도 어떤식으로 하는지도 알려주시면 감사하겠습니다.

나빌레라의 이미지

HW 레지스터의 주소는 SoC에서 미리 map을 잡아 놓습니다. 메모리 256MB라는 것은 DRAM controller로 연결된 진짜 DRAM의 크기가 256MB라는 것이지요.

그래서 HW 레지스터 주소는 FW에서 포인팅 가능한 숫자면 아무거나 가능합니다. SoC에서 정해준 대로 쓰면 되는 거니까요.

후려쳐서 이해 하려면 CPU에서 메모리 어드래싱을 하는 신호선이 32개가 있는데 그중 MSB의 라인 하나를 HW 레지스터쪽으로 연결해 놓고 나머지는 DRAM으로 보내는 식으로 구성이 가능하다고 생각하고 그림을 그려 보세요.

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

ㅇㅇ의 이미지

KernelTcb_t 타입에서 stack_base의 변수를 포인터 변수로 한 이유에 대해서 알고 싶습니다. uint32_t가 안되는 이유를 알고 싶습니다. 별개의 질문으로 또 왜 하필 uint8_t 포인터 변수인가요? uint32_t 포인터 변수는 안되는 건가요?

컨텍스트 백업 코드를 포면 인라인 함수에 push {lr}이라고 적혀있습니다. lr은 r14이고 r14는 C언어에서 함수를 호출하면 복귀 주소를 명시하는 걸로 알고 있습니다. 백업을 할 때는 Kernel_task_scheduler -> Kernel_task_context_switching -> Save_context 함수 순으로 호출이 됩니다. 현재 3번째함수를 실행하기 때문에 lr은 보통 2번째 함수에서 표기되지만 인라인 어셈블리어 B 명령어로 호출했기 때문에 r14는 아무것도 안 적히고 함수 호출만 하는 걸로 알고 있습니다. 결국은 첫번째에서 두번째로 호출할 때 복귀 주소인 첫번째 쪽에서 enable_irq를 호출하는 쪽의 주소를 lr에 저장하고 있을 것 같습니다. 그렇다면 태스크를 세번을 돌면 결국은 태스크를 등록한 함수 주소가 다 사라지는 거 아닌가요?
왜 하필 PC가 아닌 LR로 한 것인지 정말 궁금합니다. 저의 생각으로는 현재의 PC 또는 아예 태스크 시작할 때 PC만 따로 저장해놓고 컨텍스트에 백업할 때 저장하는 걸로 생각했습니다.

나빌레라의 이미지

KernelTcb_t 타입에서 stack_base의 변수를 포인터 변수로 한 이유에 대해서 알고 싶습니다. uint32_t가 안되는 이유를 알고 싶습니다. 별개의 질문으로 또 왜 하필 uint8_t 포인터 변수인가요? uint32_t 포인터 변수는 안되는 건가요?

==> 메모리 어드래싱을 해야 해서 포인터 변수를 했고, uint8_t를 해야 1씩 더해서 메모리 어드래스를 계산하기 편하기 때문입니다. 아시다시피 uint32_t 포인터 변수를 쓰면 +1 할 때 실제 주소는 4씩 올라가니까요.

컨텍스트 백업 코드를 포면 인라인 함수에 push {lr}이라고 적혀있습니다. lr은 r14이고 r14는 C언어에서 함수를 호출하면 복귀 주소를 명시하는 걸로 알고 있습니다. 백업을 할 때는 Kernel_task_scheduler -> Kernel_task_context_switching -> Save_context 함수 순으로 호출이 됩니다. 현재 3번째함수를 실행하기 때문에 lr은 보통 2번째 함수에서 표기되지만 인라인 어셈블리어 B 명령어로 호출했기 때문에 r14는 아무것도 안 적히고 함수 호출만 하는 걸로 알고 있습니다. 결국은 첫번째에서 두번째로 호출할 때 복귀 주소인 첫번째 쪽에서 enable_irq를 호출하는 쪽의 주소를 lr에 저장하고 있을 것 같습니다. 그렇다면 태스크를 세번을 돌면 결국은 태스크를 등록한 함수 주소가 다 사라지는 거 아닌가요?
왜 하필 PC가 아닌 LR로 한 것인지 정말 궁금합니다. 저의 생각으로는 현재의 PC 또는 아예 태스크 시작할 때 PC만 따로 저장해놓고 컨텍스트에 백업할 때 저장하는 걸로 생각했습니다.

==> 질문이 이해가 잘 안되는데, LR도 복구를 해 줘야 컨택스트 스위칭 당한(?) 함수로 다시 복귀했을 때 얘가 정상적으로 리턴을 할 수 있기 때문입니다.

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

질문드립니다.의 이미지

안녕하세요 나빌레라님 답변해주신 댓글들을 읽어보니 ARM 기반 보드이면 실제 보드로 몇 가지 기능을 사용가능하다는 정보를 얻었습니다. 혹시 https://www.navimro.com/p/items/K28016982/?access_google_shopping&gclid=EAIaIQobChMIu_ntv9vY8gIVg1VgCh14zAtCEAQYASABEgIH_fD_BwE 와 같이 stm32 뉴클레오 개발 보드를 사용해도 실제 실습이 가능한지 여쭙고 싶습니다. 좋은 책 감사드립니다.

나빌레라의 이미지

책 내용만 가지고서는 stm32에 쓸 수 없습니다. stm32는 cortex-m0 (m3 였든가... (중요하지 않습니다..)) 라서 책에는 컨택스트 스위칭 구현을 cortex-a 아키텍쳐에 맞춰서 설명했거든요.
github에 최신 코드는 제가 stm32에 맞춰서 컨택스트 스위칭 코드를 추가한 코드가 있습니다.
저의 다른 연재물 보면 stm32 보드로 키보드 펌웨어를 만든 것이 있습니다. 해당 연재물과 책과 github의 코드를 가지고 공부하면 stm32에서 나빌로스와 펌웨어를 어떻게 구현하는지 알 수 있습니다.

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

dog_chobo의 이미지

블로그를 보니, WSL에서 QEMU를 동작시킨 분이 계셨습니다.
https://jakupsil.tistory.com/36?category=453560 을 참조해서 했는데,
저는 QEMU 창이 안뜹니다 ㅠㅠ
혹시 회사에서 보안에 막혀서 이럴수도 있나 싶기도 합니다 ....
혹시 해결 방법이 있을까요?

나빌레라의 이미지

그냥 될텐데요. 어차피 nographic 옵션 쓰는거라 창 뜨는건 안되도 상관없고요.
qemu는 이 책에서 그냥 쓰기만 할 뿐 관련 트러블 슈팅은 책의 범위가 아니라서 정확한 답은 저도 모르겠습니다.

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

holup의 이미지

Intel x86 기반에서는 세그먼트 레지스터와 오프셋의 개념으로 선형주소를 만들어 내는걸로 알고있습니다.
그런데 여기서 페이징 작업이 없는 리얼모드에서는 세그먼트 Base Address * 16 + offset(가상주소) 이렇게 해서 나오는 값이 곧 물리주소인것으로 알고있는데,

ARM 기반 레지스터를 보니 세그먼트 레지스터가 별도로 존재하지 않는거 같더라구요.
실습과정에서 보면 =0x10000000 이런식으로 주소를 직접 다루시는거 같은데...
기본적으로 페이징 기능이 비활성화되어 있다면 저 값이 곧 RAM의 물리적 주소를 가리키는게 맞는 것인지요?

그리고 링커 스크립터를 작성하시면서 . = 0x0; 이런 구문을 사용하셨는데
이게 물리적 메모리 0x00000000에 text 섹션을 할당하겠다는 것을 의미하는 것인지 궁금합니다..
정확하게 링커 스크립트가 해당 실행파일을 물리적 메모리 몇 번지부터 할당하겠다는 것을 정의하는게 맞는것인가요 ?

나빌레라의 이미지

로딩과 할당은 다릅니다.
또한 로딩과 relocation도 구분해서 개념을 이해 하셔야 합니다.
링크 스크립트는 relocation 정보를 기록하는 파일입니다. (링커가 리로케이션 작업할 때 참고하는 정보지요.)
로딩은 로더가 합니다.

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

yilee의 이미지

링커 스크립트 부분에서 궁금한점이 생겨 질문을 남기게 되었습니다.

링커 스크립트를 작성하는 부분에 . = 0x0; 이렇게해서 실제 실행하면 물리 메모리(RAM)의
0x0000_0000 번지에 text 섹션이 로드되어질텐데 ELF 실행 파일의 헤더 부분은 어디에 로드가 되어지는 건가요 ?

나빌레라의 이미지

로딩은 로더가 하는 겁니다.
링커 스크립트에 쓴 주소들은 바이너리 안에서 변수들의 relocation에 이용되는 정보들입니다.
링커 스크립트에 쓴 주소로 바이너리가 자동으로 들어가는게 아닙니다.
로더에서 해 줘야 하는 일이지요.

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

yilee의 이미지

감사합니다.
로더에 대한 개념은 생각도 안하고 있었습니다.

그래도 의문이 있는 부분은 결국에는 링커가 실행파일을 생성할 때 Image Base 주소를 할당해 준다고 하는데
로더가 해당 실행파일의 헤더 부분에서 Image Base 주소를 참고하여 물리 메모리에 올려주는 것이 아닌지요 ?

나빌레라의 이미지

로더에 대한 자세한 설명은 아마 책에 없을겁니다.
qemu에 elf 파일을 올리면 자동으로 elf의 섹션 정보을 읽어서 qemu가 메모리에 올려주거든요.
리얼보드에 올릴때는 그래서 약속이 필요합니다. 링커 스크립트에 적는 주소와 로더가 알아야 하는 주소가 일치해야 하거든요.
각각 같은 숫자를 쓰든, #define으로 해 놓고 스크립트와 로더가 같이 참조하든 하는 식으로요.

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

chlgus96의 이미지

안녕하세요. 제가 기본 문법은 구글링을 이용하려고 했지만, 찾기가 어려워 질문드립니다.
1. ./는 현재 파일을 의미하고, 쉘 명령어에서 실행을 위해 쓰는 것으로 알고 있습니다. 명령어를 쓸 때 일부는 ./를 쓰고 일부는 쓰지 않습니다. 그 기준이 궁금합니다.
○ ./를 쓰는 경우
p.17 코드3.2: ./Entry.S, p.20 코드3.4: ./navilos.ld
○ 안 쓰는 경우
p.17 코드3.2: Entry.o, p.20 코드3.4: boot/Entry.o

2. makefile에서 @rm의 @의 의미가 궁금합니다.

단어 같은 것이라면 구글링하면 웬만하면 찾을 수 있는데, ./나 @는 그 용도를 찾기 어려운 것 같습니다. 감사합니다.

나빌레라의 이미지

책의 주제와 관계없는 질문입니다.
이런 질문은 질문 게시판에 올려주세요.

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

세벌의 이미지

1. ./ 쓰는 경우 : 현재 디렉터리에 있는 명령 실행.
./ 안 쓰는 경우 : PATH 설정 되어 있는 디렉터리에 있는 명령 실행.

chlgus96의 이미지

A)p.105에 '마스크 한다'는 말은 쉽게 말해서 막아버린다는 뜻입니다.
B)p.111에 Interrupt Enable을 위해서 1을 write해줍니다. datasheet를 찾아보니 On a write of 1 to the particular bit, ikt set the corresponding mask of that interrupt. 라고 써져 있습니다!!
Mask 한다는 것은 막는다는 것일까요, 풀어준다는 것일까요?

페이지

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.