1. SDRAM Configuration Register(MDCNFG)
The MDCNFG register contains control bits for configuring the SDRAM with parameters such as tRP, tRCD, tRAS, tRC. Both SDRAM chip selects must use the same parameters.
2. SDRAM Refresh Control Register(MDREFR)
The MDREFR register contains control bits for SDRAM refresh.
3. SDRAM Mode Register Set Configuration Register(MDMRS)
The MDMRS register is used to issue MRS and EMRS commands to SDRAM
4. DDR Hardware Calibration Register(DDR_HCAL)
This register allows hardware to calibrate and set the strobe delay lines.
5. DDR Write Strobe Calibration Register(DDR_WCAL)
This register lets hardware calibration set the write-strobe delay lines.
6. Dynamic Memory Controller Interrupt Enable Register(DMCIER)
The DMCIER is the Interrupt Enable register for all of the dynamic-memory controller interrupts.
7. Dynamic Memory Controller Interrupt Status Register(DMCISR)
The DMCISR is the Intrrrupt Status register for all of the dynamic-memory controller interrupts.
8. Delay Line Status Register(DDR_DLS)
The read-only Delay Line Status register monitors the delay-line values on strobes DQSx. DDR_DLS contains calibration information for controlling the external-bus delay lines and DQSx.
9. External Memory Pin Interface Control Register(EMPI)
The EMPI register controls the external-memory pin-interface(EMPI) module.
10. Rcomp Control Register(RCOMP)
The Rcomp Control register is similar in concept to the SDRAM Refresh Control register, MDREFR. Both registers use a counter clocked off of a 13-MHz clock to initiate events, and both registers contain an identical software mechanism for initiating their respective events.
2008년 6월 23일 월요일
2008년 6월 18일 수요일
VC.net과 VC 2005에서의 C Run-Time Libraries
VC 2005(visual c++ 8.0)의 경우 Run-Time Libray 함수를 사용하기 위해서 해당 함수의 확인이 필요하다. 이는 기존의 Run-Time Libray 함수들이 재정의 되면서 함수의 형태 및 필요 인수와 반환값의 형태가 바뀐 것들이 많기 때문이다.
VC 2005 Run-Time Library 목록
VC .net Run-Time Library 목록
VC 2005 Run-Time Library 목록
VC .net Run-Time Library 목록
2008년 6월 17일 화요일
Visula Studio 2005 단축키
Ctrl + Tab Edit하고 있는 Child Window 간의 이동
Ctrl + F4 현재 Edit하고 있는 Child Window를 닫기
Ctrl + I 문자열 입력 점진적으로 문자열 찾기 (Incremental Search)
Ctrl + F3 현재 커서에 있는 문자열 찾기 fowared (블록 지정 안 해도 됨)
Shift + F3 현재 커서에 있는 문자열 찾기 backward
F3 찾은 문자열에 대한 다음 문자열로 이동 (Next Search)
Ctrl + H 문자열 찾아 바꾸기 (Replace)
Ctrl + Left/Right Arrow 단어 단위로 이동
Ctrl + Delete 또는 Backspace 단어 단위로 삭제
Ctrl + F2 현재 라인에 북마크 지정/해제
F2 지정된 다음 북마크로 이동
Ctrl + Shift + F2 지정된 모든 북마크를 해제
F9 현재 라인에 Breakpoint를 지정/해제
Ctrl + Shift + F9 현재 Edit하고 있는 소스파일에 지정된 모든 Breakpoint 해제
Ctrl + ] 또는 E '{'괄호의 짝을 찾아줌 ('{'에 커서를 놓고 눌러야 함}
Ctrl + J, K #ifdef 와 #endif의 짝을 찾아줌
Ctrl + L 한 라인을 클립보드로 잘라내기 (Cut)
Ctrl + Shift + L 한 라인을 삭제
Alt + Mouse 블록 설정 세로로 블록 설정하기 (마우스d로)
Ctrl + Shift + F8 세로로 블록 설정하기 (키보드로), 취소할 때는 Esc키를 눌러야 함
블록 설정 -> Tab 선택된 블록의 문자열을 일괄적으로 들여쓰기(Tab) 적용
블록 설정 -> Shift + Tab 선택된 블록의 문자열을 일괄적으로 내어쓰기 적용
Alt + F8 -> Tab 또는 Shift + Tab 들여쓰기 자동 조정 (Tab:들여쓰기, Shift + Tab : 내어쓰기)
Ctrl + T 현재 커서에 있는 변수/함수에 대한 Type이 Tooltip 힌트 창에 나타남
Ctrl + Alt + T 멤버 변수/함수 목록에 대한 팝업 창이 나타남
Ctrl + Shift + T 공백/콤마/파이프/괄호 등을 기준으로 좌우 문자열을 Swap시킴
Ctrl + Shift + 8 문단기호 표시/감추기 : Tab은 ^, Space는 .으로 표시
Ctrl + D 툴바의 찾기 Editbox로 이동
Ctrl + Up/Down Arrow 커서는 고정시키고 화면만 스크롤 시키기
Tab 들여쓰기
Shift+Tab 내어쓰기
F4 다음 에러메세지로 이동
Alt+F8 들여쓰기 자동 조정
Ctrl+F 찾기
Ctrl+F3 현재 커서에 있는 단어로 찾기
Ctrl+H 찾아 바꾸기
F3 다음 단어 찾기
Ctrl+Shift+F3 이전 단어 찾기
Alt+E+I 프로젝트 내의 모든 파일에서 찾기
F2 설정된 북마크로 이동
F9 현재 커서위치에 BreakPoint를 설정/해제
Ctrl+B 브레이크 포인트 관리 메뉴
Ctrl+Spacebar 멤버목록 팝업창
Ctrl+T 현재 커서에 있는 단어의 툴팁정보 보기
Ctrl+U 모두 소문자로
Ctrl+Shift+U 모두 대문자로
Ctrl+Shift+8 Tab은 ^ 로 공백은 . 으로 보여줌
디버깅에 관련된 단축키 하나 더.
변수이름을 적어 놓고 브래이크 포인터의 위치 여부와 관계 없이 변수의 내용을 추적하는 기능이 Watch Window에 들어 있다. 디버그 모드에서 추가하고픈 변수나 등등 앞에 커서를 위치 시킨후 Shift + F9를 누르면 그냥 바로 추가된다.
▼ Browse Information file 이 필요한 단축키
(컴파일 되어야 함)
F12 현재 커서의 함수 정의 부분으로 이동
Shift+F12 현재 커서의 함수 참조 부분으로 이동
Ctrl+Num+ 다음 정의/참조 로 이동
Ctrl+Num- 이전 정의/참조 로 이동
▼ Visual Assist 6.0 설치시 가능한 단축키
Alt+O 현재 파일의 헤더(.h)/구현(.cpp) 파일로 이동
Alt+G 현재 커서의 함수 정의 부분으로 이동
Alt+M 현재 파일의 모든 함수 목록
Ctrl+Shift+V 선택해서 붙여넣기
Alt+← 이전 커서 위치로 이동
Alt+→ 다음 커서 위치로 이동
■ 디버그 단축키
변수이름을 적어 놓고 브래이크 포인터의 위치 여부와 관계 없이 변수의 내용을
추적하는 기능이 Watch Window에 들어 있죠...
그 때 디버그 모드에서 추가하고픈 변수나 등등 앞에 커서를 위치 시킨후
Shift + F9를 누르면 그냥 바로 추가됩니다
■ General Development Settings Default Shortcut Keys
http://msdn.microsoft.com/en-us/library/xte2hh6a(VS.80).aspx
Ctrl + F4 현재 Edit하고 있는 Child Window를 닫기
Ctrl + I 문자열 입력 점진적으로 문자열 찾기 (Incremental Search)
Ctrl + F3 현재 커서에 있는 문자열 찾기 fowared (블록 지정 안 해도 됨)
Shift + F3 현재 커서에 있는 문자열 찾기 backward
F3 찾은 문자열에 대한 다음 문자열로 이동 (Next Search)
Ctrl + H 문자열 찾아 바꾸기 (Replace)
Ctrl + Left/Right Arrow 단어 단위로 이동
Ctrl + Delete 또는 Backspace 단어 단위로 삭제
Ctrl + F2 현재 라인에 북마크 지정/해제
F2 지정된 다음 북마크로 이동
Ctrl + Shift + F2 지정된 모든 북마크를 해제
F9 현재 라인에 Breakpoint를 지정/해제
Ctrl + Shift + F9 현재 Edit하고 있는 소스파일에 지정된 모든 Breakpoint 해제
Ctrl + ] 또는 E '{'괄호의 짝을 찾아줌 ('{'에 커서를 놓고 눌러야 함}
Ctrl + J, K #ifdef 와 #endif의 짝을 찾아줌
Ctrl + L 한 라인을 클립보드로 잘라내기 (Cut)
Ctrl + Shift + L 한 라인을 삭제
Alt + Mouse 블록 설정 세로로 블록 설정하기 (마우스d로)
Ctrl + Shift + F8 세로로 블록 설정하기 (키보드로), 취소할 때는 Esc키를 눌러야 함
블록 설정 -> Tab 선택된 블록의 문자열을 일괄적으로 들여쓰기(Tab) 적용
블록 설정 -> Shift + Tab 선택된 블록의 문자열을 일괄적으로 내어쓰기 적용
Alt + F8 -> Tab 또는 Shift + Tab 들여쓰기 자동 조정 (Tab:들여쓰기, Shift + Tab : 내어쓰기)
Ctrl + T 현재 커서에 있는 변수/함수에 대한 Type이 Tooltip 힌트 창에 나타남
Ctrl + Alt + T 멤버 변수/함수 목록에 대한 팝업 창이 나타남
Ctrl + Shift + T 공백/콤마/파이프/괄호 등을 기준으로 좌우 문자열을 Swap시킴
Ctrl + Shift + 8 문단기호 표시/감추기 : Tab은 ^, Space는 .으로 표시
Ctrl + D 툴바의 찾기 Editbox로 이동
Ctrl + Up/Down Arrow 커서는 고정시키고 화면만 스크롤 시키기
Tab 들여쓰기
Shift+Tab 내어쓰기
F4 다음 에러메세지로 이동
Alt+F8 들여쓰기 자동 조정
Ctrl+F 찾기
Ctrl+F3 현재 커서에 있는 단어로 찾기
Ctrl+H 찾아 바꾸기
F3 다음 단어 찾기
Ctrl+Shift+F3 이전 단어 찾기
Alt+E+I 프로젝트 내의 모든 파일에서 찾기
F2 설정된 북마크로 이동
F9 현재 커서위치에 BreakPoint를 설정/해제
Ctrl+B 브레이크 포인트 관리 메뉴
Ctrl+Spacebar 멤버목록 팝업창
Ctrl+T 현재 커서에 있는 단어의 툴팁정보 보기
Ctrl+U 모두 소문자로
Ctrl+Shift+U 모두 대문자로
Ctrl+Shift+8 Tab은 ^ 로 공백은 . 으로 보여줌
디버깅에 관련된 단축키 하나 더.
변수이름을 적어 놓고 브래이크 포인터의 위치 여부와 관계 없이 변수의 내용을 추적하는 기능이 Watch Window에 들어 있다. 디버그 모드에서 추가하고픈 변수나 등등 앞에 커서를 위치 시킨후 Shift + F9를 누르면 그냥 바로 추가된다.
▼ Browse Information file 이 필요한 단축키
(컴파일 되어야 함)
F12 현재 커서의 함수 정의 부분으로 이동
Shift+F12 현재 커서의 함수 참조 부분으로 이동
Ctrl+Num+ 다음 정의/참조 로 이동
Ctrl+Num- 이전 정의/참조 로 이동
▼ Visual Assist 6.0 설치시 가능한 단축키
Alt+O 현재 파일의 헤더(.h)/구현(.cpp) 파일로 이동
Alt+G 현재 커서의 함수 정의 부분으로 이동
Alt+M 현재 파일의 모든 함수 목록
Ctrl+Shift+V 선택해서 붙여넣기
Alt+← 이전 커서 위치로 이동
Alt+→ 다음 커서 위치로 이동
■ 디버그 단축키
변수이름을 적어 놓고 브래이크 포인터의 위치 여부와 관계 없이 변수의 내용을
추적하는 기능이 Watch Window에 들어 있죠...
그 때 디버그 모드에서 추가하고픈 변수나 등등 앞에 커서를 위치 시킨후
Shift + F9를 누르면 그냥 바로 추가됩니다
■ General Development Settings Default Shortcut Keys
http://msdn.microsoft.com/en-us/library/xte2hh6a(VS.80).aspx
2008년 6월 16일 월요일
[Tip] RETAILMSG로 디버그메시지 출력하기 [펌]
디버깅 하고자하는 파일(*.cpp, *.c)에 다음 두줄을 선언하시고 빌더하시면 됩니다.
(대략 위치는 헤드 파일 선언 이후면 되겠네요.)
#undef DEBUGMSG
#define DEBUGMSG( a, b) RETAILMSG( 1, b)
그러면 해당 파일에 있는 DEBUGMSG의 메시지들이 릴리즈 모드에서도 출력됩니다.
※ 헤드파일(*.h)에는 선언하지 마시기 바랍니다. 여러 파일에 적용되어 메시지 홍수 납니다.
함수 내에 선언하셔서 함수만 적용되도록 하셔도 됩니다.
이런게 가능한 이유는 DEBUGMSG 가 함수가 아니라 define으로 되어 있기 때문입니다.
고수님들은 다 알고 계신 내용을 팁이겠지만 도움되시는 분들이 있으실까봐 올립니다.
역시나 적고 보니 조금 허접하네요. 단 두줄이라니.. ^^;;
--------------------------------------------------------------------------------------------------------------------------------------
참고로.. RETAILMSG의 사용법은 소스를 보시면 많이 있는데 보통 아래와 같습니다.
RETAILMSG( 1, (TEXT("Message \r\n") ));
RETAILMSG( 1, (TEXT("Message : %d \r\n"), count ));
메시지들은 KITL로 연결되면 PB에 출력되며, KITL 연결이 아니면 디버거 시리얼 포트로 출력됩니다.참 RETAILMSG의 첫 인자가 1일때 출력됩니다. ( 1이나 TRUE 일때 )
---------------------------------------------------------------------------------------------------------------------------------------
(대략 위치는 헤드 파일 선언 이후면 되겠네요.)
#undef DEBUGMSG
#define DEBUGMSG( a, b) RETAILMSG( 1, b)
그러면 해당 파일에 있는 DEBUGMSG의 메시지들이 릴리즈 모드에서도 출력됩니다.
※ 헤드파일(*.h)에는 선언하지 마시기 바랍니다. 여러 파일에 적용되어 메시지 홍수 납니다.
함수 내에 선언하셔서 함수만 적용되도록 하셔도 됩니다.
이런게 가능한 이유는 DEBUGMSG 가 함수가 아니라 define으로 되어 있기 때문입니다.
고수님들은 다 알고 계신 내용을 팁이겠지만 도움되시는 분들이 있으실까봐 올립니다.
역시나 적고 보니 조금 허접하네요. 단 두줄이라니.. ^^;;
--------------------------------------------------------------------------------------------------------------------------------------
참고로.. RETAILMSG의 사용법은 소스를 보시면 많이 있는데 보통 아래와 같습니다.
RETAILMSG( 1, (TEXT("Message \r\n") ));
RETAILMSG( 1, (TEXT("Message : %d \r\n"), count ));
메시지들은 KITL로 연결되면 PB에 출력되며, KITL 연결이 아니면 디버거 시리얼 포트로 출력됩니다.참 RETAILMSG의 첫 인자가 1일때 출력됩니다. ( 1이나 TRUE 일때 )
---------------------------------------------------------------------------------------------------------------------------------------
WinCE에서의 스트링 사용
WinCE에서 스트링을 처리할 때는 기존의 표준 ANSI C 함수(strcpy, strcmp 등)를 사용할 수 없다. WinCE가 유니코드를 사용하기 때문이다. 유니코드라고 해서 특별히 복잡한 것은 없는데 다만 1바이트로 처리하던 문자(ANSI의 경우 표준 아스키코드 128종류문자, 확장 특수문자까지 포함하면 256가지)를 2바이트로 대폭 확장했다는 차이만이 있을 뿐이다. 그렇지만 이 차이로 인해 PC상에서 주로 썼던 친숙한 스티링 함수 등은 전부 쓸 수 없게 되었다. 대신 한글처리나 기타 여러 언어의 문자를 처리함에 있어서 언어버전마다 다른 복잡한 PC윈도 프로그램 보단 통일성 있게 프로그래밍이 가능해졌다.
스트링의 선언
- ANSI의 경우(컴파일러 환경에 _MBCS라는 매크로가 정의된 경우)
char string[10];
- Unicode 의 경우(컴파일러 환경에 UNICODE나 _UNICODE라는 매크로가 정의된 경우)
wchar_t string[10];
두 가지를 통합하는 변수타입도 있는데 다음과 같이 선언해주면 ANSI든 Unicode든 상관없이 컴파일러 옵션에서 알아서 처리한다.
TCHAR string[10];
앞으로는 WinCE 의 스트링을 처리할 때는 꼭 'TCHAR'를 기억하자. 참고로 TCHAR는 다음과 같이 선언되어 있다.
#ifdef _UNICODE
#define TCHAR wchar_t
#endif
#ifdef _MBCS // ANSI의 Ascii 코드 방식일 때
#define TCHAR char
#endif
스트링을 선언과 함께 초기화할 때
- ANSI의 경우
char szString[20] = "I am a girl";
- Unicode의 경우
wchar_t szString[20] = L"I am a girl";
유니코드의 경우 쌍따옴표 앞에서 붙은 'L'이라는 매크로를 붙임으로 해서 쌍따옴표 부분이 유니코드로 변환된다. 하지만 실제로 가장 많이 쓰는 변수형은 다음과 같다.
TCHAR szString[20] = _T("I am a girl");
TCHAR szString[20] = TEXT("I am a girl");
_T()와 TEXT()는 사실 같은 역할을 하는 매크로로 컴파일러 환경이 ANSI로 정의되어 있으며 괄호안에 스트링을 그대로 두어 ANSI코드로 만들고 UNICODE로 되어 있으면 'L'이라는 매크로를 앞에 붙여서 괄호안의 스트링을 유니코드로 만드는 것과 같은 역할을 한다.
즉, 다음과 같은 역할을 하는 것이다.
- ANSI의 경우
TCHAR szString[20] = _T("I am a girl");
-> char szString[20] = "I am a gril";
-Unicode의 경우
TCHAR szString[20] = _T("I am a girl");
-> wchar_t szString[20] = L"I am a girl";
결론적으로 가장 중요하게 강조하고 싶은 저은 TCHAR와 _T("")/TEXT("") 매크로로 프로그램이나 모듈을 짜놓으면 개발환경이 ANSI인지 유니코드인지 상관없이 컴파일이 가능한 코드를 작성할 수 있다. 가급적으로 WinCE에서는 이 매크로들만 사용하기를 강하게 추천하는 바이다.
또 주의해야 할 점은 TCHAR와 _T(""), TEXT("") 같은 통합 매크로를 사용했으면 지속적으로 사용해야지 중간에 char, tchar나 'L' 매크로 등을 소스 중간 중간에 써넣으면 나중에 간혹 환경이 다른 상황에서 컴파일 할 때의 자잘한 수 백 개의 컴파일 에러들이 짜증날 가능성이 높다.
스트링 처리 함수
C 프로그램을 짜다가 보면 아마 가장 많이 사용하는 함수 중의 하나가 strcpy, strlen 등의 스트링 처리 함수일 것이다. 하지만 이런 함수들은 기본적으로 1바이트 차계의 스트링들을 처리하기 위한 함수들이므로 WinCE의 유니코드 환경에서 제대로 작동하지 않는다.
- ANSI에서 스트링 처리 함수
strcpy, strncpy, strlen, strcmp, strncmp 등
- Unicode에서 스트링 처리 함수
wcscpy, wcsncpy, wcsnlen, wcscmp 등
즉 str로 시작되는 접두사 부분을 wcs로 바꾸어 프로그램을 짜면 된다. 또 TCHAR형식처럼 ANSI와 유니코드를 동시에 지원하려면 다음 함수들을 사용하면 되며, 모두 'tchar.h'에 정의되어 있다.
_tcscpy, _tcsncpy, _tcsnlen, _tcscmp 등
스트링 입출력 함수
- ANSI : printf, sprintf, scanf
- Unicode : wprintf, swprintf, wscanf
- TCHAR : _tprintf, _stprintf, _tscanf
실제 사용 예제는 다음과 같다.
{
TCHAR szTemp1[100] = _T("You are my brother.");
TCHAR szTemp2[100] = _T(" And we are the world.");
TCHAR szTemp3[100] ;
_tcscat(szTemp1, szTemp2);
_stprintf(szTemp3, _T("%s -> Merge string"), szTemp1);
MessageBox(NULL, szTemp3, _T("Test"), MB_OK);
}
Win32에서는 sprintf를 쓸 수 없고 wsprintf를 써야만 되는 경우가 있어서 위 소스가 컴파일 에러를 낼 수 도 있다. 이 경우 다음의 사용자 정의 스트링 처리 함수 부분을 참조하자.
사용자 정의 스트링 처리 함수
아무리 TCHAR 형식 스트링이 ANSI/유니코드를 동시 지원한다고는 하지만 실제 프로그래밍을 들어가 보면 사용자 정의 형식의 함수가 필요할 때가 아주 많다. 예를 들어 위 스트링 처리 함수들을 응용하고 재조합하는 함수를 만들다가 보면 중간에 별도의 다른 내용의 함수가 필요할 때가 종종 있다.
예를 들어 다음과 같이 Sample이라는 스트링의 실제 문자 수를 알고 싶다면
TCHAR Sample[10] = _T("Test");
ANSI에서는 strlen()함수, 유니코드에서는 wcslen()함수 등을 쓰면 된다. 혹은 _tcslen함수를 써도 마찬가지다. 근데 만약 알고 싶은 것이 실제 문자수가 아니라 스트링이 몇 바이트인지 알고싶을 때는 _tcslen 함수를 사용해도 알 수 없다.
왜냐하면 _tcslen함수는 무조건 4라는 리턴값을 취할 것이기 때문이다. 유니코드 상태에서 Sample이라는 변수의 "Test"란 스트링이 차지하는 바이트 수는 8이다(4개의 문자 * 유니코드 기본바이트 2). 이 경우는 비교적 간단한 경우라서
_tcslen(Sample) * sizeof(TCHAR)
이런 식으로 리턴값을 얻어내면 되겠지만 모든 소스코드 라인에 이런 귀찮은 표현을 타이핑 하기에도 아주 번거로울 것이다. 이런 경우에 대비하여 아예 my_strbyte()란 함수를 만들어두고 필요할 때마다 사용하면 편할 것이다. 다음과 같이 사용자 정의 함수를 만들면 된다.
inline int my_strbyte( TCHAR *szString )
{
#ifdef _MBCS // ANSI
return strlen(szString);
#endif
#ifdef _UNICODE // Unicode
return wcslen(szString) *2
#endif
}
그리고 어쩌다가 윈도 표준 스트링 함수와 스트링 처리 함수가 충돌하는 경우가 있는데 이런 경우(대표적 예가 _strintf 이다) 다음과 같이 define 형식으로 처리하면서 각각 상황에 맞는 함수를 정의 내릴 수 있다.
// my_stprintf의 등록
#ifdef _MBCS
#define my_stprintf wsprintf
#endif
#ifdef _UNICODE
#define my_stprintf swprintf
#endif
윗 부분을 정의한 다음에 윗 장에서 썼던 예제 소스를 다시 수정하여 넣어보면 적어도 윈도우를 사용하는 어떠한 플랫폼에서도 제대로 컴파일 되고 아무런 문제가 없이 실행됨을 알 수 있다.
다음은 예제 소스이다.
{
TCHAR szTemp1[100] = _T("You are my brother.");
TCHAR szTemp2[100] = _T(" And we are the world.");
TCHAR szTemp3[100] ;
_tcscat(szTemp1, szTemp2);
my_stprintf(szTemp3, _T("%s -> Merge string"), szTemp1);
MessageBox(NULL, szTemp3, _T("Test"), MB_OK);
}
그 외 여러 가지 사용자 정의 함수의 예들을 넣었다. 필자가 초기에 _tcs 계열의 함수들이 미덥지 못해서 만든 함수들인데 비록 모든 함수들이 _tcs(XXX)형식으로 다 있는 것이기는 하지만 예제를 보고 충분히 재활용할 수 있게 소스를 실었다.
// my_strcpy함수: UNICODE와 ANSI 코드 동시 지원
TCHAR inline *my_strcpy(TCHAR* dest, TCHAR* src)
{
#ifdef _MBCS
return strcpy(dest, src);
#endif
#ifdef _UNICODE
return wcscpy(dest, src);
#endif
}
// my_strncpy함수: UNICODE와 ANSI 코드 동시 지원
TCHAR inline *my_strncpy(TCHAR* dest, TCHAR* src, int n)
{
#ifdef _MBCS
return strncpy(dest, src, n);
#endif
#ifdef _UNICODE
return wcsncpy(dest, src, n);
#endif
}
// my_strtok함수: UNICODE와 ANSI 코드 동시 지원
TCHAR inline *my_strtok(TCHAR* buff, TCHAR* token)
{
#ifdef _MBCS
return strtok(buff, token);
#endif
#ifdef _UNICODE
return wcstok(buff, token);
#endif
}
// my_atoi함수: UNICODE와 ANSI 코드 동시 지원
int inline my_atoi(TCHAR* str)
{
#ifdef _MBCS
return atoi(str);
#endif
#ifdef _UNICODE
return _wtoi(str);
#endif
}
// my_strlen함수: UNICODE와 ANSI 코드 동시 지원
int inline my_strlen(TCHAR* str)
{
#ifdef _MBCS
return strlen(str);
#endif
#ifdef _UNICODE
return wcslen(str);
#endif
}
parent.ContentViewer.parseScript('b_388771');
스트링의 선언
- ANSI의 경우(컴파일러 환경에 _MBCS라는 매크로가 정의된 경우)
char string[10];
- Unicode 의 경우(컴파일러 환경에 UNICODE나 _UNICODE라는 매크로가 정의된 경우)
wchar_t string[10];
두 가지를 통합하는 변수타입도 있는데 다음과 같이 선언해주면 ANSI든 Unicode든 상관없이 컴파일러 옵션에서 알아서 처리한다.
TCHAR string[10];
앞으로는 WinCE 의 스트링을 처리할 때는 꼭 'TCHAR'를 기억하자. 참고로 TCHAR는 다음과 같이 선언되어 있다.
#ifdef _UNICODE
#define TCHAR wchar_t
#endif
#ifdef _MBCS // ANSI의 Ascii 코드 방식일 때
#define TCHAR char
#endif
스트링을 선언과 함께 초기화할 때
- ANSI의 경우
char szString[20] = "I am a girl";
- Unicode의 경우
wchar_t szString[20] = L"I am a girl";
유니코드의 경우 쌍따옴표 앞에서 붙은 'L'이라는 매크로를 붙임으로 해서 쌍따옴표 부분이 유니코드로 변환된다. 하지만 실제로 가장 많이 쓰는 변수형은 다음과 같다.
TCHAR szString[20] = _T("I am a girl");
TCHAR szString[20] = TEXT("I am a girl");
_T()와 TEXT()는 사실 같은 역할을 하는 매크로로 컴파일러 환경이 ANSI로 정의되어 있으며 괄호안에 스트링을 그대로 두어 ANSI코드로 만들고 UNICODE로 되어 있으면 'L'이라는 매크로를 앞에 붙여서 괄호안의 스트링을 유니코드로 만드는 것과 같은 역할을 한다.
즉, 다음과 같은 역할을 하는 것이다.
- ANSI의 경우
TCHAR szString[20] = _T("I am a girl");
-> char szString[20] = "I am a gril";
-Unicode의 경우
TCHAR szString[20] = _T("I am a girl");
-> wchar_t szString[20] = L"I am a girl";
결론적으로 가장 중요하게 강조하고 싶은 저은 TCHAR와 _T("")/TEXT("") 매크로로 프로그램이나 모듈을 짜놓으면 개발환경이 ANSI인지 유니코드인지 상관없이 컴파일이 가능한 코드를 작성할 수 있다. 가급적으로 WinCE에서는 이 매크로들만 사용하기를 강하게 추천하는 바이다.
또 주의해야 할 점은 TCHAR와 _T(""), TEXT("") 같은 통합 매크로를 사용했으면 지속적으로 사용해야지 중간에 char, tchar나 'L' 매크로 등을 소스 중간 중간에 써넣으면 나중에 간혹 환경이 다른 상황에서 컴파일 할 때의 자잘한 수 백 개의 컴파일 에러들이 짜증날 가능성이 높다.
스트링 처리 함수
C 프로그램을 짜다가 보면 아마 가장 많이 사용하는 함수 중의 하나가 strcpy, strlen 등의 스트링 처리 함수일 것이다. 하지만 이런 함수들은 기본적으로 1바이트 차계의 스트링들을 처리하기 위한 함수들이므로 WinCE의 유니코드 환경에서 제대로 작동하지 않는다.
- ANSI에서 스트링 처리 함수
strcpy, strncpy, strlen, strcmp, strncmp 등
- Unicode에서 스트링 처리 함수
wcscpy, wcsncpy, wcsnlen, wcscmp 등
즉 str로 시작되는 접두사 부분을 wcs로 바꾸어 프로그램을 짜면 된다. 또 TCHAR형식처럼 ANSI와 유니코드를 동시에 지원하려면 다음 함수들을 사용하면 되며, 모두 'tchar.h'에 정의되어 있다.
_tcscpy, _tcsncpy, _tcsnlen, _tcscmp 등
스트링 입출력 함수
- ANSI : printf, sprintf, scanf
- Unicode : wprintf, swprintf, wscanf
- TCHAR : _tprintf, _stprintf, _tscanf
실제 사용 예제는 다음과 같다.
{
TCHAR szTemp1[100] = _T("You are my brother.");
TCHAR szTemp2[100] = _T(" And we are the world.");
TCHAR szTemp3[100] ;
_tcscat(szTemp1, szTemp2);
_stprintf(szTemp3, _T("%s -> Merge string"), szTemp1);
MessageBox(NULL, szTemp3, _T("Test"), MB_OK);
}
Win32에서는 sprintf를 쓸 수 없고 wsprintf를 써야만 되는 경우가 있어서 위 소스가 컴파일 에러를 낼 수 도 있다. 이 경우 다음의 사용자 정의 스트링 처리 함수 부분을 참조하자.
사용자 정의 스트링 처리 함수
아무리 TCHAR 형식 스트링이 ANSI/유니코드를 동시 지원한다고는 하지만 실제 프로그래밍을 들어가 보면 사용자 정의 형식의 함수가 필요할 때가 아주 많다. 예를 들어 위 스트링 처리 함수들을 응용하고 재조합하는 함수를 만들다가 보면 중간에 별도의 다른 내용의 함수가 필요할 때가 종종 있다.
예를 들어 다음과 같이 Sample이라는 스트링의 실제 문자 수를 알고 싶다면
TCHAR Sample[10] = _T("Test");
ANSI에서는 strlen()함수, 유니코드에서는 wcslen()함수 등을 쓰면 된다. 혹은 _tcslen함수를 써도 마찬가지다. 근데 만약 알고 싶은 것이 실제 문자수가 아니라 스트링이 몇 바이트인지 알고싶을 때는 _tcslen 함수를 사용해도 알 수 없다.
왜냐하면 _tcslen함수는 무조건 4라는 리턴값을 취할 것이기 때문이다. 유니코드 상태에서 Sample이라는 변수의 "Test"란 스트링이 차지하는 바이트 수는 8이다(4개의 문자 * 유니코드 기본바이트 2). 이 경우는 비교적 간단한 경우라서
_tcslen(Sample) * sizeof(TCHAR)
이런 식으로 리턴값을 얻어내면 되겠지만 모든 소스코드 라인에 이런 귀찮은 표현을 타이핑 하기에도 아주 번거로울 것이다. 이런 경우에 대비하여 아예 my_strbyte()란 함수를 만들어두고 필요할 때마다 사용하면 편할 것이다. 다음과 같이 사용자 정의 함수를 만들면 된다.
inline int my_strbyte( TCHAR *szString )
{
#ifdef _MBCS // ANSI
return strlen(szString);
#endif
#ifdef _UNICODE // Unicode
return wcslen(szString) *2
#endif
}
그리고 어쩌다가 윈도 표준 스트링 함수와 스트링 처리 함수가 충돌하는 경우가 있는데 이런 경우(대표적 예가 _strintf 이다) 다음과 같이 define 형식으로 처리하면서 각각 상황에 맞는 함수를 정의 내릴 수 있다.
// my_stprintf의 등록
#ifdef _MBCS
#define my_stprintf wsprintf
#endif
#ifdef _UNICODE
#define my_stprintf swprintf
#endif
윗 부분을 정의한 다음에 윗 장에서 썼던 예제 소스를 다시 수정하여 넣어보면 적어도 윈도우를 사용하는 어떠한 플랫폼에서도 제대로 컴파일 되고 아무런 문제가 없이 실행됨을 알 수 있다.
다음은 예제 소스이다.
{
TCHAR szTemp1[100] = _T("You are my brother.");
TCHAR szTemp2[100] = _T(" And we are the world.");
TCHAR szTemp3[100] ;
_tcscat(szTemp1, szTemp2);
my_stprintf(szTemp3, _T("%s -> Merge string"), szTemp1);
MessageBox(NULL, szTemp3, _T("Test"), MB_OK);
}
그 외 여러 가지 사용자 정의 함수의 예들을 넣었다. 필자가 초기에 _tcs 계열의 함수들이 미덥지 못해서 만든 함수들인데 비록 모든 함수들이 _tcs(XXX)형식으로 다 있는 것이기는 하지만 예제를 보고 충분히 재활용할 수 있게 소스를 실었다.
// my_strcpy함수: UNICODE와 ANSI 코드 동시 지원
TCHAR inline *my_strcpy(TCHAR* dest, TCHAR* src)
{
#ifdef _MBCS
return strcpy(dest, src);
#endif
#ifdef _UNICODE
return wcscpy(dest, src);
#endif
}
// my_strncpy함수: UNICODE와 ANSI 코드 동시 지원
TCHAR inline *my_strncpy(TCHAR* dest, TCHAR* src, int n)
{
#ifdef _MBCS
return strncpy(dest, src, n);
#endif
#ifdef _UNICODE
return wcsncpy(dest, src, n);
#endif
}
// my_strtok함수: UNICODE와 ANSI 코드 동시 지원
TCHAR inline *my_strtok(TCHAR* buff, TCHAR* token)
{
#ifdef _MBCS
return strtok(buff, token);
#endif
#ifdef _UNICODE
return wcstok(buff, token);
#endif
}
// my_atoi함수: UNICODE와 ANSI 코드 동시 지원
int inline my_atoi(TCHAR* str)
{
#ifdef _MBCS
return atoi(str);
#endif
#ifdef _UNICODE
return _wtoi(str);
#endif
}
// my_strlen함수: UNICODE와 ANSI 코드 동시 지원
int inline my_strlen(TCHAR* str)
{
#ifdef _MBCS
return strlen(str);
#endif
#ifdef _UNICODE
return wcslen(str);
#endif
}
parent.ContentViewer.parseScript('b_388771');
Wince에서 cached와 uncached를 사용하는 이유
CPU Core 내부에 Cache Controller 가 있으면 캐쉬를 인에이블시켜 쓰던데 ...
CPU내부 core에서 CPU의 내부에 있는 Register나 SDRAM 또는 NAND 또는 Address로 접근 가능한 장치를 address mapping 할때 cache와 uncache로 구분해서 사용합니다.
Oemaddress Table에는 physical address와 cached address만 기록하면 cached address에서 0x2000_0000만큼 높은 번지는 Uncached address가 됩니다.
가령 physical 0x000__0000을 cached로 0x8000_0000이면 uncached는 0xa000_0000 이됩니다.
WINCE에서 Cached address는 0x8000_0000 ~0x9FFF_FFFF까지 이고 Uncached는 0xA000_0000 ~ 0xB000_0000까지 입니다.
cached로 사용하면 Core에서 Address를 access하는 순간 바로 해당 주소를 access하는 반면 uncached로 addressing 하면 그 즉시 access하지 않고 지연되어 read/write가 됩다.
Uncached를 주로 사용하는 경우는 다음과 같습니다.
- CPU내부 register - DMA descriptor
- CPU외부의 chip selector 에 연결되어 있는 IO device - SDRAM의 특정 영역(global 영역등 sharing 을 위한 목적)
Cached를 주로 사용하는 경우는 다음과 같습니다.
- OS가 access하는 SDRAM
- 대용량 memory share(display area / audio dma area 등등)
Cache와 Uncached 의 가장 큰 차이점은 속도 입니다. Uncached로 선언된 영역을 access하면 core의 command가 나갈때 마다 실제로 memory를 access하여야하는데 이과정에서 속도가 떨어지게됩니다. 왜냐면 만약 core는 400Mhz로 작동하는데 외부 버스는 100Mhz나 50Mhz로 작동되는 상황을 생각해 보시기 바랍니다
CPU내부 core에서 CPU의 내부에 있는 Register나 SDRAM 또는 NAND 또는 Address로 접근 가능한 장치를 address mapping 할때 cache와 uncache로 구분해서 사용합니다.
Oemaddress Table에는 physical address와 cached address만 기록하면 cached address에서 0x2000_0000만큼 높은 번지는 Uncached address가 됩니다.
가령 physical 0x000__0000을 cached로 0x8000_0000이면 uncached는 0xa000_0000 이됩니다.
WINCE에서 Cached address는 0x8000_0000 ~0x9FFF_FFFF까지 이고 Uncached는 0xA000_0000 ~ 0xB000_0000까지 입니다.
cached로 사용하면 Core에서 Address를 access하는 순간 바로 해당 주소를 access하는 반면 uncached로 addressing 하면 그 즉시 access하지 않고 지연되어 read/write가 됩다.
Uncached를 주로 사용하는 경우는 다음과 같습니다.
- CPU내부 register - DMA descriptor
- CPU외부의 chip selector 에 연결되어 있는 IO device - SDRAM의 특정 영역(global 영역등 sharing 을 위한 목적)
Cached를 주로 사용하는 경우는 다음과 같습니다.
- OS가 access하는 SDRAM
- 대용량 memory share(display area / audio dma area 등등)
Cache와 Uncached 의 가장 큰 차이점은 속도 입니다. Uncached로 선언된 영역을 access하면 core의 command가 나갈때 마다 실제로 memory를 access하여야하는데 이과정에서 속도가 떨어지게됩니다. 왜냐면 만약 core는 400Mhz로 작동하는데 외부 버스는 100Mhz나 50Mhz로 작동되는 상황을 생각해 보시기 바랍니다
피드 구독하기:
글 (Atom)