모든 윈도우CE 기반 장치들은 Windows 폴더 아래에 CEConfig.h 파일을 가집니다.
이 파일은 각기 다른 프로젝트나 SDK에서 선택적인 컴파일 시에 사용됩니다.
그리고 해당 장치의 윈도우CE OS 라이센스 단계를 판별하는데 쓰입니다.
(ex 5.0 core, 5.0 pro, 5.0 pro plus )

CEConfig.h파일은 플랫폼 빌더를 이용하여 윈도우 CE OS프로젝트를 빌드 하거나
시스템을 생성(sysgen)할 때 만들어지며,
이 파일은 프로젝트에 포함된 OS 컴포넌트를 매크로 형태로 정의하고 있습니다.

예를 들어 런타임 정보등을 수집하는 ToolHelp API를 포함하는 윈도우 CE OS 존재할 수 있는데, 만약 사용자가 응용프로그램 작성시 해당 API에 종속된 프로그램을 만들 경우에는 ToolHelpAPI를 포함하지 않는 윈도우 CE OS에서는 오류를 발생합니다.
만약에 OS가 ToolHelp API를 포함하고 있다면
CEConfig.h 파일은
#define CE_MODULES_TOOLHELP 1 
을 포함하고 있을 겁니다.

그러면 아래와 같이 체크하는 루틴을 추가해서 해당 API로 부터 독립된 빌드 형태의 응용 프로그램을 작성할 수 있습니다. 
#include <ceconfig.h>

#ifdef CE_MODULES_TOOLHELP
#include "tlhelp32.h"
#endif

* OS 라이센스 단계를 검출해 낼수 있는 툴은 아래 링크에서 다운 받을 수 있습니다.
Microsoft® Windows® CE 5.0 Run-time Assessment Tool

- 원문출처 -

Windows CE 5.0: Standard Software Development Kit (SDK)

의외로 찾기가 힘들었음..;;
EVC 서비스팩 4 상태에서는 5.0용 armv4i 가 없음.
wce400\STANDARDSDK 만 존재.


if(dwFlags==0)
       {
           HWND hWndTaskBar = FindWindow(_T("HHTaskBar"),NULL);
           ShowWindow(hWndTaskBar, SW_SHOWNORMAL);
           Sleep(200);
       }
       keybd_event(VK_LWIN, 0, dwFlags, 0);

virtual keyboard event 사용~
H/W 버튼을 가진 WinCE 단말기에서 윈도우 키 + 태스크바 나타내기 기능을 달아주는 것.

BUILD: [00:0000000568:PROG  ] 'NMAKE.EXE   -i -c BUILDMSG=Stop.  NOLINK=1 PASS0ONLY=1 CLEANBUILD=1'
BUILD: [01:0000000569:INFO  ] makefile.def: BUILDROOT is D:\WINCE500\PLATFORM\DM644X

BUILD: [01:0000000570:INFO  ] makefile.def: Including D:\WINCE500\PLATFORM\DM644X\sources.cmn

BUILD: [01:0000000571:INFO  ] Directory: D:\WINCE500\PLATFORM\DM644X\SRC\COMMON\BMPLIB\800x480

BUILD: [01:0000000572:INFO  ] TARGETNAME: bmplib_800X480

BUILD: [01:0000000573:INFO  ] makefile.def: Including D:\WINCE500\public\common\oak\misc\sources.ReleaseType_PLATFORM

BUILD: [01:0000000574:ERRORE] makefile(16) :  U1020: end-of-file found before next directive



-> source.cmn 에서 #IF 가 제대로 닫히지 않았을 때..


참조하는 프로그램에 정적 라이브러리가 아닌 동적 링크를 사용하게 해준다.
기존의 정적 라이브러리와는 달리 컴파일 시에 참조하는 함수의 코드가 실행 파일로
복사되는 것이 아니라 실행 중에 라이브러리에 있는 함수를 호출 하게된다.

단점 : 만들는 과정이 복잡하며,(DLL 까지 만들어줘야 하는경우)
         프로그램 자체가 DLL에 의지하여 실행하는 독립적이지 못한 상태가 되고,
         DLL 이 없거나 손상될 경우 프로그램 실행이 불가능하다.

장점 : 여러 프로그램에서 한 DLL을 동시 사용하기에 메모리가 절약된다.
         같은 DLL을 사용하는 여러 프로그램이 동시에 실행되도 DLL은 딱 한번만 실행되면 되며,
         DLL을 사용하는 프로그램 자체의 크기가 작아진다.
         참조하는 DLL 내의 알고리즘이 개선되면 각각의 프로그램의 성능 또한 같이 개선된다.
         다국어 지원 리소스로 쉽게 교체도 가능하다.

* DLL 내부의 코드의 경우는 최초 호출시에 한번만 실행된다.
  단, DLL 내의 고유 변수 등은 사용하는 프로그램이 호출시에 다시 메모리를 할당받는다.
  ! 각 프로그램간 DLL 내부의 값 자체를 공유하지는 못한다.

-DLL의 연결방법-
1. 묵시적(Implicit)연결 : 프로그램이 실행될 때 DLL이 로드됨 (Load time Linking - 실행시 연결)
                                  함수가 어느 DLL에 있는지 밝히지 않고 사용.
                                  윈도우가 알아서 DLL을 로딩해주고 사용하는 모든 프로그램이 종료가 되어
                                  사용 카운트가 0이되면 알아서 DLL을 언로딩해준다.
                                  프로젝트내에서 임포트 라이브러리 해줘야한다.

2. 명시적(Explicit)연결 : 프로그램이 실행될 때 DLL이 로드되지않고
                                  사용자가 DLL을 로드 하라는 명령을 했을 때 로드된다.
                                  (Run time Linking - 실행중 연결)
                                  다국어 같은 다양한 리소스를 사용할 때 선택적으로 같은 리소스를 가지고 있으나
                                  언어 설정이 다른 DLL을 실시간으로 교체 하는 방법에 응용이 가능할 듯하다.
 
                                  프로젝트 내에서 임포트 라이브러리를 해주지 않아도 된다.

* HINSTANCE LoadLibrary(LPCTSTR lpLibFileName);
* FARPROC GetProcAddress(HMODULE hModule, LPCSTR lpProcName);
  ( DLL에서 export한 함수의 번지를 찾아 그 함수의 함수 포인터를 리턴해 준다. )
* BOOL FreeLibrary(HMODULE hLibModule);
  ( DLL의 사용 카운트를 -1 해주고 카운트가 0이 되면 DLL을 메모리에서 삭제한다. )
The ROMHDR and pTOC are created and fixed up by romimage.exe. 
 
Most of the member in ROMHDR are quite stright forwad, search keywork ROMHDR 
 
in Windows CE's on-line help will get some info.

-startup code--------------------------------------------------------------------------
STARTUPTEXT
LEAF_ENTRY StartUp 

-중략-

LTORG
ALIGN 32
Reset_Handler
-분석----------------------------------------------------------------------------------

STARTUPTEXT - 코드가 시작되는 텍스트 세그먼트 영역
이 매크로는 현재 지정된 섹션을 '.astart'에 설정한다.
kxarm.h에 아래와 같이 선언되어 있다.

MACRO
STARTUPTEXT
AREA |.astart|,ALIGN=2,CODE
AreaName SETS "|.astart|"
 MEND

AreaName - 지정된 '.astart'가 되는 area의 name 또는 section
ALIGN - section boundary를 정의한다. pression은 ELF 섹션을 2expression -byte만큼 정렬한다. 
0에서 31까지의 integer를 가질 수 있다. code section에서sms ALIGNE=0, ALIGN=1을 사용하지 않는다. ALIGN attribute는 ALIGN directive와 같지않다.

LEAF_ENTRY - prolog code에서 요구되지 않는 routine의 시작을 선언하는 매크로이다.
LEAF_ENTRY Name[,
[Section=]SectionName]
name - routine name
SectionName - 옵션. entry에 나타나는 section의 이름으로 디폴트는 '.text'이다.
Remarks
Name는 global name space에 있다. LEAF_ENTRY는 반드시 ENTRY_END와 같이 써야 한다.

ALIGN - ALIGN {<expression>, {<offset>}}
다음 명령어의 주소를 q*<expression>+<offset>으로 정렬한다. 이 정렬은 ELF 섹션의 시작에 대해 상대적이므로, 적절하게 정렬되어 있어야 한다. <expression>은 2의 배수이어야 하고, 디폴트 값은 4이다. <offset>은 별도로 지정하지 않으면 0이다.

LTORG - 리터럴 풀을 삽입하기위해 사용. 어셈블러는 LDR Rd, =<value> 명령어에 나와 있는 상수를 저장하기 위해 리터럴 풀을 사용한다. 보통 어셈블러는 각 영역의  끝에 리터럴 풀을 자동으로 삽입한다. 하지만 영역이 너무 크다면 LDR 명령어는 pc-상태 주소를 사용하여 이 리터럴 풀에 도달할 수 없다. 그런 경우에는 LDR 명령어 근처에 직접 리터럴 풀을 삽입해야한다.

-용어정리------------------------------------------------------------------------------

Literral Pool - 프로그램에서 사용되는 대부분의 데이터는 코드의 마지막에 위치한다. 하지만 pc-relative에서 사용되는 경우 실제 명령이 있는 PC의 위치에서 4K바이드 이내에는 아주 작은 프로그램을 제외하면 대부분 코드가 있기 때문에 데이터는 코드 내의 중간에 삽입된다. 이와 같은 영역을 리터럴 풀(literal pool)영역이라고 한다.

ELF - Excutable and Linking Format

.astart

다음은 eboot.map파일의 일부이다.

 EBOOT

 Timestamp is 46e4a9fa (Mon Sep 10 11:20:42 2007)

 Preferred load address is 00010000

 Start         Length     Name                   Class
 0001:00000000 000014c4H .astart                 CODE
 0001:000014d0 00006c13H .rdata                  CODE
 0001:000080e4 00000055H .rdata$debug            CODE
 0001:0000813c 000166b0H .text                   CODE
 0001:0001e7ec 00000000H .edata                  CODE
 0002:00000000 0000010cH .data                   DATA
 0002:00000120 00010714H .bss                    DATA
 0003:00000000 000009a8H .pdata                  DATA

section 001 - 프로그램 실행 코드

section 002 - 읽기 전용 정적 데이터

section 003 - 읽기/쓰기 정적 데이터

section 004 - 다른 DLL을 호출하는 데 필요한 재배치 테이블(fix-up table)

section 005 - 리소스 섹션, 메뉴와 대화 상자 템플리트 같은 응용프로그램 리소스

.data 섹션 - 초기화된 읽기/쓰기 데이터가 들어간다.(세그먼트와 섹션은 혼용하여 사용하는것 같다.)

                 static HINST g_hLoadlib = NULL;

.bss 섹션 - 초기화되지 않은 읽기/쓰기 데이터가 들어간다.

                 static BYTE g_ucItems[256];

.rdata - 읽기전용 데이터가 들어가는 세그먼트

                 const struct decodeUINT MainMessage[] = {

                      WM_CREATE, DoCreateMain,

                      WM_SIZE, DoSizeMain,

                      WM_COMMAND, DoCommandMain,

                      WM_DESTROY, DoDestroyMain,

                 };

.map파일 - 디버깅을 위해 함수와 데이터의 위치를 파악하는데 사용된다. 텍스트 파일로서 program에 link되는 정보를 포함한다.

- 파일의 이름에 기초한 모듈이름

- 프로그램 파일 헤더로 부터의 timestamp(file system이 아니다.)

- 각 그룹의 start address, length, group name, class를 포함한 프로그램내의 그룹 리스트

- 각 어드레스, symbol name, flat address, symbol에 정의된 .obj file을 포함한 public symbol 리스트
- entry point


-참고----------------------------------------------------------------------------------

MSDN, Google

ARM System Developer's Guide

ARM으로 배우는 임베디드 시스템

PROGRAMMING MICROSOFT WINDOWS CE .NET


요약 : WinCE 어플리케이션에서 실행 중 특정 동작에서 aborting에러가 날 경우 해당 address를 가지고 map파일 내의 function을 찾아가서 정확한 에러 위치를 검출해 내는 방법



릴리즈 모드로 컴파일 하였거나 디버깅이 불가능 한 상황에서 Data Abort로 프로그램이 죽었을 경우 그 위치를 찾아 낼 수 있다. 
간단한 세팅이 필요하다. 
Project Setting -> Link 에서 Category : Debug 으로 설정
Generate mapfile 체크한다.
Project Option : /MAPINFO:EXPORTS /MAPINFO:LINES 추가하고 /incremental:no Setting
Project Setting -> C/C++ 에서 Debug Info : Line Number Only 로 설정
Data Abort 발생

Data Abort: Thread=87333b28 Proc=843bcf70 'DATA_ABORT.EXE'
AKY=00040001 PC=00011014 RA=00011034 BVA=26000000 FSR=00000007
Crash Address ? Preferred Load Address ? 0x1000
Crash Address (PC) : 0x00011014
Preferred Load Address : 0x00010000
Preferred Load Address map file을 오픈하여 찾을 것!!!
공식으로 계산을 하면
0x00011014 - 0x00010000 - 0x1000 = 0x14 이 나오게 되고
0x14 값을 가지고
map 을 살펴 보면 

Line numbers for .ARMV4IDbgDataAbort.obj(C:Documents and SettingsAdministrator바탕 화면DataAbortDataAbort.cpp) segment .text

7 0001:00000000 8 0001:00000004 9 0001:0000000c 10 0001:00000018
16 0001:00000020 18 0001:00000028 19 0001:0000002c 20 0001:00000038
9 0001:0000000c 10 0001:00000018 이 부분 사이에 값이 들어가게 된다.

그러므로 9, 10 라인에서 Crash가 발생된 걸 알 수 있다.



요약 : WinCE 개발 절차 중 첫번째 단계인 부트로더 포팅 부분을 분석한다. 
(두번째 단계는 OAL포팅)
ARM 기반 WinCE 포팅된 시스템을 startup.s 부터 시작해서 low level -> kernel 까지 분석
ARM9TDMI, WINCE5.0core, DDR ram, NAND flash, UDMA HDD, 800x480 4.3 LCD, ,,,

NOR 장착 시스템
 해당 위치에서 직접 실행이 가능
  - 부트로더가 nk.nb0를 불러 ROM에서 실행 가능
  - eboot.nb0 + nk.nb0 형태
NAND 장착 시스텝
  해당 위치에서 직접 실행이 불가능
  * 부트로더가 올려졌을 때 file이 쪼개져서 올라갈 수 있음.
  - loader.bin (여러 이름) + eboot.nb0 + nk.nb0 형태나
  - loader.bin + nk.bin 형태

...........................................................................

XIP 지원 시스템
 부트로더 = EBOOT

NAND Flash Booting 지원 시스템
부트로더 = ILP + SPL

ILP(Initial Program Loader)
- 2KB 내외의 작은 프로그램
- NAND Flash의 특정영역에 저장되어 있는 EBOOT Code를 DRAM에 Load시켜 RUN하는 역할
SPL(Secondary Program Loader)
- EBOOT와 동일

XIP(eXcute In Place)
- ROM에서 실행
- RAM으로 NK.bin을 복사하지 않음
- RAM 용량 절약이 가능

.............................................................................

nk.nb0 - ROM 실행파일 형태

bin 파일
  - 헤더를 비롯한 여러가지 섹션을 갖고 있는 이미지
nb0 파일
  - plain binary (memory dump를 해서 얻어지는 nb0)

참고로
NK.bin은
Sync bytes(7bytes) + Image address(4bytes) + Image length(4bytes) + Record Address(4bytes) + Record length(4bytes) + Record checksum(4bytes)

nb0 는
첫 4kb 는 ResetHandler에 해당하는 Instruction code
그리고, 설정한 크기대로 생성 되면서 이외의 뒷부분은 0으로 채운다.

..............................................................................
startup.s파일에서 주요 수정 부분 / 기존 작성된 BSP 수정시~
1. sdram에 관한 클럭 및 뱅크에 해당하는 용량 부분
2. 부트로더에 대한 변경 사항 내용 (boot.bib와 같이 수정)

...............................................................................

RTC 초기화 문제 부분 수정 point
- platform/common/src/arm/samsung/s3c2440a/rtc의 rtc.c에서 OALIoCtlHalInitRTC함수에서
rc = OEMSetRealTime(pTime);

+ Recent posts