12.28.2009

地磁

注意事項:
  • 雖然是 1 bytes,但是只有 12 bit 的解析度,high bits (MSB) 都是 0 -- 也就是說,data 都是正值囉。
這一篇 有說,磁棒的形狀細長的話,雙極的磁力比較強。
以下是copy他的說明:

When doing measurements with a gaussmeter, please note that the actual field at the surface of a magnet is at most one half of the rated residual magnetism for that magnetic material. If a rare-earth magnet is rated at 14,000 gauss for example, a bar magnet made from that material will have an actual field of at most 7000 gauss at the north pole and -7000 gauss at the south pole. The readings may be even less than 7000 gauss. If the bar magnet is thin (that is, its length is at least 10 times its diameter) then the field will be close to 7000 gauss. If the bar magnet旧 length is less than 10 times its diameter, the field at either pole will be weaker. For example, if the magnet is in the shape of a cube, the surface field will be 4500 gauss or less. The full 14,000 gauss field can only be created if two bar magnets are in a gap configuration. This means that the magnets are held close together so that one south pole of one magnet is held very close to one north pole of the other. The distance between the magnets (the gap width) must be small compared to the magnet diameters, and each magnet旧 length must be at least 10 times its diameter. Then the field in the gap will be approximately the full value of the magnetic material旧 residual magnetism, which is 14,000 gauss in this example. Magnets that are flat (like a pancake) have a very low surface field. The magnetic pull force between equal magnets or between a magnet and a steel or iron block can be calculated from field strength. This force is approximately [Force in grams] = 0.00016 x [Field on the magnet face in gauss]2 x [Magnet face area in square cm].)
另外這一篇有說,現在地磁的強度,在地球北極(磁南極)是 0.7G (gauss),地球南極是 0.6G。地磁最小的地方是南回歸線,約 0.25G。

  • rang 是 +- 2G,分成 12 bit,所以resolution (sensitivity) 是 1/512 G。
  • 資料寫得非常不清楚,但是由 offset distribution 來看,offset 值是 2048,所以應該都是正的值,0 G 在 2048。
這個網站( http://www.ngdc.noaa.gov/geomagmodels/IGRFWMM.jsp) 可以查世界各城市的磁場強度和傾角。

查到台北地區的資料是:
Lat: 25° 1' 48''
Lon: 121° 30'
Elev: 0.00 m
Declination
+ East - West
Inclination
+ Down - Up
Horizontal Intensity
North Component
+ North - South
East Component
+ East - West
Vertical Component
+ Down - Up
Total Field
12/27/09 - 3° 57' 36° 16' 36,292.4 nT 36,206.2 nT -2500.3 nT 26,633.1 nT 45,016.2 nT
Change per year - 4' per year 0' per year -7.9 nT/year -10.7 nT/year -40.3 nT/year -3.6 nT/year -8.5 nT/year


單位:Wiki說,1 Tesla = 104Gauss

所以Taipei 的地磁通量是 0.45G。

  • 所以 量起來應該是 +- 230
  • Horizontal : 0.36G = 184
  • Vertical : 0.26G = 133



地磁量測 Sensor 通常是利用 AMR (Anisotropoc Magnetorresistive) Sensor:
ref: http://archives.sensorsmag.com/articles/0399/0399_18/main.shtml

大概是利用有磁力的鐵棒,當外部磁力影響,鐵棒變形,電阻改變,所以量測電阻就可以知道外部磁力的大小。

有因為這個鐵棒的磁力會減弱或受大外力作用而改變,所以常常需要重新加磁。

Sensor 也要內建這樣的功能。ref 是說,利用外加線圈在這些鐵棒上,通電產生磁廠就可以。
同時,控制通電的方向,可以變更鐵棒的磁極方向。
  • 這樣的動作叫 SET/RESET - 就是通電


實際量測:
  • X: 23 ~ 263 , rang: 240
  • Y:50 ~ 270, rang: 220
  • Z:

12.18.2009

Change Disk Volume Id

問題:要用 VolumeId改某外接mass storage 的 VolumeId,結果該裝置 report error。

查了一下,發現該裝置的 sector size 是 4096,所以VolumeId request read 512 bytes時,就 fail了。

所以,寫了一個這個:


Change Disk Volume ID
support Disk sector size up to 4k.
For FAT32 only,
ref :MSDN:How FATWorks


/ VolumeId4k.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <stdio.h>
#include <windows.h>

char _toHex(wchar_t High,wchar_t Low)
{
char rc;
if(High>='A')
rc = High-'A'+10;
else
rc = High-'0';

rc <<= 4;

if(Low>='A')
rc |= Low-'A'+10;
else
rc |= Low-'0';

return rc;
}


int _tmain(int argc, _TCHAR* argv[])
{

if( argc < 3){
wprintf(L"Command : VolumeId4k G: 1111-1111\n");
return 1;
}

// convert Driver letter to driver index
TCHAR DriverLetter=argv[1][0];
if(DriverLetter>'Z')
DriverLetter-='a'-'A';
wprintf(L"Driver : %c\n",DriverLetter);

wchar_t _devicename[] = L"\\\\.\\A:";
_devicename[4] += DriverLetter-'A';


// Creating a handle to disk drive using CreateFile () function ..
HANDLE hDevice ;

hDevice = CreateFile(_devicename,
GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, NULL);
if (hDevice == INVALID_HANDLE_VALUE){
wprintf(L"Open Driver %s Failed!\n",argv[1]);
return 1;
}

// Read first sector
char buffer[4096];
DWORD bytesrw;

SetFilePointer (hDevice, 0, NULL, FILE_BEGIN);
if (!ReadFile (hDevice, buffer, 4096, &bytesrw, NULL) ){
wprintf(L"Read 0 sector failed!\n");
goto _exit;
}


// modify the volumeid field - only valid for FAT32
buffer[0x43]=_toHex(argv[2][7],argv[2][8]);
buffer[0x44]=_toHex(argv[2][5],argv[2][6]);
buffer[0x45]=_toHex(argv[2][2],argv[2][3]);
buffer[0x46]=_toHex(argv[2][0],argv[2][1]);


// write back
SetFilePointer (hDevice, 0, NULL, FILE_BEGIN);
if (!WriteFile (hDevice, buffer, 4096, &bytesrw, NULL) ){
wprintf(L"Write Sectpr Faile!\n");
goto _exit;
}


wprintf(L"Success!\n");


_exit:
if(hDevice)
CloseHandle(hDevice);

return 0;
}


* CreateFile 的 devicename 在 windows 和 CE 不一樣,在 CE 下 是:http://realchecko.blogspot.com/2009/04/openstore-is-createfile.html

12.02.2009

又來:SD 的 driver architecture

標準的 SD driver 分為三部份:
  • SDHC : SD Host Controller - depend on hardware
  • SDBUS : 在 SDHC 的上層,負責操控SDHC,做出統一的 SDBUS interface
  • SD Client : SDBUS 依照偵測到的 SD 至,load 進來的 SD 裝置 Driver,一般有 SDMEMORY,SDWIFI..
SDHC 負責 收interrupt,用 "Slot" 來管理physical SD Slot。

SDHC.DLL 在 DllEntry( ) call SDInitializeCardLib( ) 將 SDBUS.DLL export 的 function pointer 放在 g_SDHostFuncs.

然後所有的 exportfunction name 加上 SDHC,變成 SD

12.01.2009

  • Identification Mode : Power ON 後就待在這個Mode, 一直到收到 CMD3(SET_RCA)
  • Interrupt Mode : 允許 card 送出 interrupt service request
  • Data Transfer Mode : Card 收到 CMD3 (SET_RCA) 後,進入這個Mode
CSD Register 內容用來設定 eMMC 的工作模式,但是只有幾個 register 可以設定 (writable)。
設定的方式是要用 CMD6 (SWITCH_COMMAND)。

11.26.2009

for ibus

export GTK_IM_MODULE=ibus
export XMODIFIERS=@im=ibus
export QT_IM_MODULE=ibus

11.25.2009

SD card cannot be identified,

SD card 有一些不能 idenfy。
進入發現是 identification error.

trace initialize procedure:

* CMD0
* CMD8
* ACMD41 - repeat,
* Ready

在 ACMD41 時,一直response not ready。
因為是有 response,不是 timeout,所以 hardware trace layout 應該是OK的。

只有猜是因為 ACMD41 command 後,card要作 voltage switch,猜測是 power 的問題,所以請 hardware 在 SDcard socket 端 power 加上電容,就 OK了。


這個有關 SD card inititlize 的 討論:
http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&p=620292

這一篇說得很清楚,附圖,和 SD spec, 和 procedure
http://blog.chinaunix.net/u1/58780/showart.php?id=673609

這一篇講 ACMD41的動作
http://hi.baidu.com/lizhenqian79/blog/item/620420a10bc7ce88471064bb.html

這一篇也有說ACMD41:
http://www.laogu.com/laogubbs/see_30547.htm

acmd41的返回值中,OCR的bit31为0表明卡此时处于busy状态,*请隔50ms后重新发cmd55,acmd41命令*,重复**部分直到返回的OCR的bit31为1为止.请仔细阅读spec.

這一篇有 SD card spec 的 link
http://hi.baidu.com/hao01222/blog/item/f69a48554c53dec7b745ae9e.html

EBOOT 的 pTOC 變數是由 ROMIMAGE.EXE 賦予初值

KernelRelocate(ROMHDR *const pToc);

Eboot 啟動後,先作這個,但是查code,pToc 只有宣告,並沒有賦予初值。
在 這篇:CE5.0 - romimage.exe如何填充eboot.bin中的pTOC特殊指針生成.nb0 有說明。

原來是 romimage.exe 做的,romimage 為EBOOT.bin 建立 pTOC (ROMHDR),然後在找到 EBOOT.bin 中 的 pTOC token,修改他的初值,改為romimage 建立的 pTOC (ROMHDR)。

所以說,pTOC 的初值是 ROMIMAGE.EXE 給的

根據參考的那一篇,說明這個 romiage--pTOC--KernelRelocate( ) 的配合動作是為了達成類似 C startup function 對各變數region 的初始設定。可以看 KernelRelocate( ) 的 source code 就可以了解,跟 C Startup Code 類似。

11.24.2009

memory relocate file : scat_romboot
分成三個區域:
* 0x70000000 : startup
* 0x8C008000 :wakeup
* 0x00000000 : vectors


0x70000000 是 chip 內建的SRAM 區域。
外接的DDR/SDRAM位址區域是 0xC0000000

startup :

cp15 control : disable mmu. enable i-cache.
SDRAM/DDR
NBOOT 使用 0x00100000:

|-------------------------
| SVC STACK
-------------------------
|0x0400 : L2 cache
--------------------------
|0x4000 : pagetable
--------------------------
原來ARM11有這麼多版本,這個用的是 ARM1136JF-S。
所以有MMU,CP15也有MMU操作指令。

ARM 文件上描述 cp15 operation 的指令是:

mcr/mrc p15, op1, , Rn, Rm, op2

在說明文件中常常用 Rn,op1, Rm, op2 來列表。

基本上好像是利用 Rn 作 block selection, Rm 作 function selectio, op2 才是 register selection
我猜的 :p

ARM cp15 c1,c0, 0 - control register configuration

ARM 的coprocessor cp15 ,可以用

mrc/mcr p15,0,,Cn,Cm,N
來溝通 (read/write)
參考: cp15 instruction

比較常用的:Control Register Configuration:

MRC p15, 0, , c1, c0, 0 Read Control Register configuration data
MCR p15, 0, , c1, c0, 0 Write Control Register configuration data
Control Register 內容參考:c1, Control Register
-- copy 過來,免得以後改位置--

Table 3.24. Control Register bit functions

Bits

Field

Function

[31]

SBZThis field returns a Unpredictable value when read. Should Be Zero.
[30]TE

Determines the state that the processor enters exceptions:

0 = Exceptions entered in ARM state

1 = Exceptions entered in Thumb state.

[29]SBZShould Be Zero. This bit reads as 0 and ignores writes.
[28]SBZShould Be Zero. This bit reads as 0 and ignores writes.
[27]NMI

Determines the state of the non-maskable bit that is set by a configuration pin FIQISNMI:

0 = The processor is backwards compatible and behaves as normal

1 = All attempts to modify the CPSR F bit can only clear it. There is no way to set it in software. The SPSRs remain freely modifiable but copying the SPSR to CPSR can only clear the F bit. FIQs continue to set the F bit automatically.

Note

The status of the FIQISNMI pin is read by Bit 27. Software cannot write to Bit 27.

[26]SBZShould Be Zero. This bit reads as 0 and ignores writes.
[25]EE

Determines how the E bit in the CPSR bit is set on an exception:

0 = CPSR E bit is set to 0 on an exception

1 = CPSR E bit is set to 1 on an exception.

The reset value depends on external signals, see Table 3.25.

[24]VE

Enables the VIC interface to determine interrupt vectors:

0 = Interrupt vectors are fixed

1 = Interrupt vectors are defined by the VIC interface.

See the description of the V bit, bit 13.

[23]SBZShould Be Zero. This bit reads as 0 and ignores writes.
[22]U

Enables unaligned data access operations for mixed little-endian and big-endian operation:

0 = Unaligned data access support disabled

1 = Unaligned data access support enabled.

The A bit has priority over the U bit.

The reset value of the U bit depends on external signals, see Table 3.25.

[21]FI

Configures low latency features for fast interrupts.

0 = All performance features enabled.

1 = Low interrupt latency configuration enabled.

[20]SBZShould Be Zero. This bit reads as 0 and ignores writes.
[19]SBZShould Be Zero. This bit reads as 0 and ignores writes.
[18]SBO

Should Be One. This bit reads as 1 and ignore writes.

[17]SBZShould Be Zero. This bit reads as 0 and ignores writes.
[16]SBO

Should Be One. This bit reads as 1 and ignore writes.

[15]

L4

Determines if the T bit is set for PC load instructions:

0 = Loads to PC set the T bit.

1 = Loads to PC do not set the T bit, ARMv4 behavior.

For more details, see the ARM Architecture Reference Manual.

[14]

RR

Determines the replacement strategy for the cache:

0 = Normal replacement strategy by random replacement

1 = Predictable replacement strategy by round-robin replacement.

[13]

V

Determines the location of exception vectors:

0 = Normal exception vectors selected, address range = 0x00000000-0x0000001C

1 = High exception vectors selected, address range = 0xFFFF0000-0xFFFF001C.

[12]

I

Enable or disable level one instruction cache:

0 = disabled

1 = enabled.

[11]

Z

Enables programme flow prediction:

0 = Program flow prediction disabled

1 = Program flow prediction enabled.

[10:8]SBZShould Be Zero. This bit reads as 0 and ignores writes.
[7]

B

Determines operation as little-endian or big-endian memory system and the names of the low four-byte addresses within a 32-bit word:

0 = Little-endian memory system

1 = Big-endian word-invariant memory system.

The reset value of the B bit depends on external signals, see Table 3.25.

[6:3]SBOShould Be One. This field read as 1 and ignore writes.
[2]

C

Enables or disables level one data cache:

0 = Data cache disabled

1 = Data cache enabled.

[1]

A

Enables strict alignment of data to detect alignment faults in data accesses:

0 = Strict alignment fault checking disabled.

1 = Strict alignment fault checking enabled.

The A bit setting takes priority over the U bit.

[0]

M

Enables or disables the MPU:

0 = MPU disabled

1 = MPU enabled.

11.23.2009

DRAM 起始位址0x8C000000,none-cached address (就是+20000000)是 0xAC000000 。

然後預留 0x2000 給.. interrupt handler ?

接著就是整個 kernel 都可以 access 的 global variable。
利用直接address 定址,大家都可以讀,大家都可以改,所以就是一團混亂!!

管理的方法就是宣告一個 structure,用 structure 來 access 這一塊區域的資料。

11.06.2009

CleanOS

下 CleasOS 時,執行的動作:

Starting Build: cleanos.bat
==============
CLEAN.BAT: Cleaning Sysgen directory "C:\WINCE600\OSDesigns\OSDesign1\OSDesign1\Wince600\TT4X0BD_ARMV4I\cesysgen"
CLEAN.BAT: Cleaning platform directory C:\WINCE600\platform\MyBoard\target\ARMV4I\retail
CLEAN.BAT: Cleaning platform directory C:\WINCE600\platform\MyBoard\lib\ARMV4I\retail
CLEAN.BAT: Cleaning platform common directory C:\WINCE600\platform\common\target\ARMV4I\retail
CLEAN.BAT: Cleaning platform common directory C:\WINCE600\platform\common\lib\ARMV4I\retail
CLEAN.BAT: Cleaning flat release directory "C:\WINCE600\OSDesigns\OSDesign1\OSDesign1\RelDir\MyBoard_ARMV4I_Release"

11.03.2009

missing aygshell.h in CE 6.0 SDK

故事參考這一篇
或是google aygshell.h mfc

使用 VS2005 的 mfc for smart device 竟然會 incluse aygshell.h , shellsdk.h
aygshell.h 要加入 aygshell 這個 component 才能用。但是 aygshell 不屬於 core license (也就是說,加了是要加錢的)。

原來在 CE 5.0 build mfc code 時不會 complain,因為 CE 5.0 的SDK 在產生時,不管你有沒有加 aygshell,都會把 aygshell.h 放進去。

但是到 CE 6.0 後,就不這樣作了。

所以?有人 report 給 MS 了。

在 MS patch 之前 (會有patch嗎?)

只好自己加入 這兩個 header 檔 -- 這樣要加錢嗎?


aygshell.h 在
C:\WINCE600\PUBLIC\SHELLSDK\SDK\INC

shellsdk.h 在
C:\WINCE600\PUBLIC\COMMON\SDK\INC



感想:也只有作MS的programmer 才要考慮這種問題。不要錢的 include 要錢的 component.....唉!

source code location : CE 6.0 control panel applet

CE control panel 裡的 applet 的 source 在

C:\WINCE600\PUBLIC\WCESHELLFE\OAK\CTLPNL\CPLMAIN

切換 usb profile

依照慣例,我又在copy人家的code..:p

這一篇

USB Function profile switcher

示範了application 變更 usb profile 的code:

先說OS 內建支援的 profile 都列在: [HKEY_LOCAL_MACHINE\Drivers\USB\FunctionDrivers]

下面的code sample 就是作者(Nicloas BESSON)提供的,切換activesync 和 mass storage 的 code:
void SwitchUSBFunctionProfile(BOOL bEnableActiveSync)
{
HANDLE hUSBFn;
UFN_CLIENT_INFO info;
DWORD dwBytes;

// Open the USB function driver
hUSBFn = CreateFile(USB_FUN_DEV, DEVACCESS_BUSNAMESPACE,
0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
NULL);

if(bEnableActiveSync)
{
// Enable USB Function profile for activesync
swprintf(info.szName, _T("Serial_Class"));
DeviceIoControl(hUSBFn, IOCTL_UFN_CHANGE_CURRENT_CLIENT,
info.szName, sizeof(info.szName), NULL, 0, &dwBytes, NULL))
}
else
{
// Enable USB Function for mass-storage
swprintf(info.szName, _T("Mass_Storage_Class"));
DeviceIoControl(hUSBFn, IOCTL_UFN_CHANGE_CURRENT_CLIENT,
info.szName, sizeof(info.szName), NULL, 0, &dwBytes, NULL);
}
}

我完整而沒有修改的 copy 過來。

上述使用到的 define value 都在

The defines values are located in %_WINCEROOT%\PUBLIC\COMMON\OAK\INC\usbfnioctl.h

方法大概是用 USB_FUN_DEV 提供的 IOControl -
IOCTL_UFN_CHANGE_CURRENT_CLIENT

來變換,吃的 argument 是 描述 profile 的字串。

10.27.2009

Shame on me

I use the code on

Windows CE: Loading a Driver with ActivateDeviceEx

on my post: http://realchecko.blogspot.com/2009/09/source-load-unload-device-driver.html.
And I didn't mention about it, until the Author : Bruce.Eitman give me a comment.


真對不起,我用了 Bruce Eitman 的 example code 在我的 blog 中,竟然沒有提到。
直到 Bruce. Eitman 在文章的comment 中提醒。我才注意到。



我已經在那篇文章補上 Link 了,同時,另外寫這一篇,來表達我的歉意。

非常對不起。

10.14.2009

location of lib on DLL project created by platform builder

使用 PlatformBuilder (5.0 or VS2005+ 6.0) 的 subproject create DLL project 時,
還是會產生 lib 檔 (工使用者 static link,不必用 dllimport)。

但是位置會在 project 的 obj\ARMV4I\retail\ 下。
Dll 當然就是在 bsp project 的 release folder 下囉


* 這個要感謝 Franz 的教導。

10.13.2009

Add working source folder under subversion

將 工作中的 sourcecode 加入 subversion 的方法:

把 folder 拉到 subversion 中。
再 checkout 出來,用新的名字。
然後把其中的 .svn folder copy 出來,放到原來工作的folder 中。


其實就是要有 .svn 就是.

10.11.2009

忍不住,還是要寫一下。

大約是一年前,發生倫敦交易所大當機事件
現在,新的CEO上任,決定:




這篇說得真是...

他說 原先這套系統設計就是為了達到.

10.08.2009

DllMain in Loading Unloading DLL

DLL 在被 Load 進 memory 後,DLL 的 DllMain( ) 會先被呼叫。
並且傳入參數 ul_reason_for_call。
依次是:
  • DLL_PROCESS_ATTACH
  • DLL_THREAD_ATTACH
DLL 被 unload 的時候,一樣會呼叫 DllMain(),然後傳入參數:
  • DLL_PROCESS_DETACH
嗯,就只有一次。

10.07.2009

USB OTG role decide

USB OTG 是靠 ID PIN 決定 當 Host 還是 Device。

ID -- GND : Host
ID -- FLOAT : Device

ref : Wiki USB On-The-Go
其中描述到 A 就是 Host

10.05.2009

Simple Code : DialogBase, Win32, Change Statics content

就是一個簡單的dialog,兩個 button,一個 static (text)。

DialogApp.rc

// Microsoft Visual C++ generated resource script.
//
#include "resource.h"

#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#define APSTUDIO_HIDDEN_SYMBOLS
#include "windows.h"
#include "RCDef.h"
#undef APSTUDIO_HIDDEN_SYMBOLS

/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS

/////////////////////////////////////////////////////////////////////////////
// Chinese (Taiwan) resources

#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHT)
#ifdef _WIN32
LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL
#pragma code_page(950)
#endif //_WIN32

#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//

2 TEXTINCLUDE
BEGIN
"#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
"#include ""windows.h""\r\n"
"#include ""RCDef.h""\r\n"
"#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"
"\0"
END

1 TEXTINCLUDE
BEGIN
"resource.\0"
END

3 TEXTINCLUDE
BEGIN
"\r\0"
END

#endif // APSTUDIO_INVOKED


/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//

IDD_DIALOG1 DIALOGEX 0, 0, 186, 90
STYLE DS_SETFONT | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Dialog"
//FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
DEFPUSHBUTTON "INC",IDBTNINC,129,7,50,14
PUSHBUTTON "DEC",IDBTNDEC,129,24,50,14
LTEXT "Static",IDC_STATIC,23,14,54,15
END


/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//

#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
IDD_DIALOG1, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 179
TOPMARGIN, 7
BOTTOMMARGIN, 83
END
END
#endif // APSTUDIO_INVOKED

#endif // Chinese (Taiwan) resources
/////////////////////////////////////////////////////////////////////////////



#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//


/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

resource.h

// Microsoft Visual C++ generated include file.
// Used by DialogApp.rc
//
#define IDD_DIALOG1 101
#define IDBTNINC 1000
#define IDBTNDEC 1001
#define IDC_STATIC 1002

// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 102
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1002
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

DialogApp.cpp

// DialogApp.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#include "resource.h"

BOOL CALLBACK DialogProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
static value=100;

switch(uMsg){
case WM_INITDIALOG:
return TRUE;
case WM_CLOSE:
EndDialog(hWnd,0);
return FALSE;
case WM_COMMAND:
switch(wParam){
case IDBTNINC:
value++;
SetDlgItemInt(hWnd,IDC_STATIC,value,FALSE);
break;
case IDBTNDEC:
SetDlgItemInt(hWnd,IDC_STATIC,value,FALSE);
value--;
break;
}
break;
default:
return FALSE;
}
}


int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
// TODO: Place code here.

return DialogBox(hInstance,MAKEINTRESOURCE(IDD_DIALOG1),NULL,DialogProc);
}

主要是用 SetDlgItemInt( ) 來變更 STATIC 的內容

10.02.2009

Add subproject
A Simple WCE program

Add New Item - Resource - Resource File

Open the resource file - right button - add resource - dialog -new
: the resource editor opened.

在 .rc 按 right button - resource includes ..

RDP function for close source Virtualbox

close source version virtualbox 的額外功能除了 usb 以外,還有一個就是 rdp 遠端連線功能。

這個遠端連線是由 Virtualbox 提供的,不是 guest OS。所以即使 guest OS 沒有遠端桌面功能(或是 disable 了遠端連線),我們還是可以經由 virtualbox 的 遠端桌面 連線 guest OS。

在 Setting 的遠端桌面 有一個 port number。
假設 該 server (不是 guest OS) 的 ip 是 192.168.145.72。
port number 是 3389
我們只要用遠端連線程式,連到 192.168.145.72:3389
就可以連過去了。

使用 KITL debug AP

在 KITL 連線中。
先用 VS2005 開啟 AP 的 source ,設定 break point。
因為這時候 AP 還沒 run,所以 break point 會是 "inactive" 的狀態。
然後 launch AP (可以用 click , 或是 s command)。
到了該 break point ,就會停住。

這樣就不用一定在 VS2005 , CE 6.0 OS 中開啟 subproject 的 project 才能 debug。
所有的 program 都能 debug (只要有source code)。

9.29.2009

花在 Tuner driver 的時間

使用單心線跳線導致第2個byte後資料錯亂 - 3 days.
使用新板子,KITL 連不上 - 1 day
fopen 未使用 binary mode,導致 0x0A 變成 0x0D, 0x0A - 3 days.

實際上真正用在 program Tuner I2C, SPI 的部份 - 大約 2 days.


唉~~引以為戒呀!!

9.17.2009

ReadFile Fail

太白痴..

HANDLE CreateFile(
LPCTSTR
lpFileName,
DWORD
dwDesiredAccess,
DWORD
dwShareMode,
LPSECURITY_ATTRIBUTES
lpSecurityAttributes,
DWORD
dwCreationDisposition,
DWORD
dwFlagsAndAttributes,
HANDLE
hTemplateFile
);
dwDesiredAccess 如果沒有設GENERIC_READ,之後對這個 file handle 作 ReadFile( ) 的話,會fail 。

這是在做 Driver 的時候,明明有作 XXX_READ,也有宣告在 XXX.def 中,但是 ReadFile( ) 卻老是return fail,也沒有進入到 XXX_READ function

總而言之,就是自己白痴。
VS2005 直接開啟 NK.BIN 可以看到裡面包的 Registry 和 所有的 檔案(bib)
在 DeviceDriver 中,幾乎所有的 Driver Interface 第一個 argument 都是 pContext。

這個pContext 是交給 programmer 自己處理的:

在 XXX_Init( ) 中, return 的 pointer,在以後 所有 interface 呼叫時,都會被傳進來 - 也就是 pContext。

9.16.2009

Source : Load Unload Device Driver

很對不起,這個code是base on http://www.ucancode.net/Visual_C_Codes/Loading-DLLs-LoadLibrary-GetProcAddress-FreeLibrary-VC-Example.htm
的 load dll function 寫的,竟然沒有提到,真是抱歉。

我猜原 po 應該是在 Bruce Eitman 的 WINCE Blog:

Windows CE: Loading a Driver with ActivateDeviceEx



這個code是以 load unload driver : SST
cpp

#include "stdafx.h"

#include "resource.h"

#define SST_REG_KEY (TEXT("Drivers\\Builtin\\SST"))

typedef struct {
TCHAR *ValueName;
DWORD Type;
DWORD DwordValue;
TCHAR *StringValue;
} RegEntry;

RegEntry RegEntries[]={
{TEXT("Dll"), REG_SZ, 0,TEXT("SST.DLL")},
{TEXT("Prefix"),REG_SZ, 0,TEXT("SST")},
{TEXT("Order"), REG_DWORD,4,NULL},
{TEXT("Index"), REG_DWORD,1,NULL},
{NULL,NULL,NULL,NULL}
};

void AddDriverSSTToRegistry()
{
HKEY hTargetKey;
DWORD dwDisposition;
DWORD RetVal;
DWORD Index=0;
BYTE *Value;
DWORD uSize;

RetVal = RegCreateKeyEx( HKEY_LOCAL_MACHINE,
SST_REG_KEY,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hTargetKey,
&dwDisposition
);
if(RetVal == ERROR_SUCCESS)
{
while(RegEntries[Index].ValueName!=NULL)
{
if(RegEntries[Index].Type == REG_DWORD)
{
RegSetValueEx(hTargetKey,
RegEntries[Index].ValueName,
0,
REG_DWORD,
(const BYTE*)&RegEntries[Index].DwordValue,
sizeof(DWORD));
}
else
{
Value = (BYTE *)RegEntries[Index].StringValue;
uSize = (wcslen(RegEntries[Index].StringValue)+1)*sizeof(TCHAR);

RegSetValueEx(hTargetKey,
RegEntries[Index].ValueName,
0,
REG_SZ,
(const BYTE*)RegEntries[Index].StringValue,
(wcslen(RegEntries[Index].StringValue)+1) * sizeof(TCHAR));

}
Index++;
}
}
}

HANDLE hDriverSST=INVALID_HANDLE_VALUE;

BOOL LoadDriverSST(void)
{
BOOL RetVal = NULL;

if(hDriverSST == INVALID_HANDLE_VALUE)
{
hDriverSST = ActivateDeviceEx( SST_REG_KEY,
NULL,
0,
NULL);
if(hDriverSST != INVALID_HANDLE_VALUE && hDriverSST != 0)
RetVal = TRUE;
else
{
RETAILMSG(1,(TEXT("Fail to load Driver SST\n")));
}
}
return RetVal;
}

void UnloadDriverSST(void)
{
if(hDriverSST!= INVALID_HANDLE_VALUE)
{
DeactivateDevice(hDriverSST);
hDriverSST=INVALID_HANDLE_VALUE;
}
}

BOOL CALLBACK DialogProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
switch(uMsg) {
case WM_INITDIALOG:
return TRUE;
case WM_CLOSE:
EndDialog(hWnd,0);
return FALSE;
case WM_COMMAND:
switch(wParam){
case IDC_BTNLOAD:
LoadDriverSST();
printf("LOAD!");
return TRUE;
case IDC_BTNUNLOAD:
UnloadDriverSST();
printf("UNLOAD");
return TRUE;
case IDC_RESISTRY:
printf("Registry");
AddDriverSSTToRegistry();
return TRUE;
}
break;
default:
return FALSE;
}
}

int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
// TODO: Place code here.

return DialogBox(hInstance,MAKEINTRESOURCE(IDD_DIALOG1),NULL,DialogProc);

return 0;
}

Load Unload Device Driver

要開發 device driver就算是有 Kitl,可以把 driver dll 屏除在 os image 之外。
但是每次 rebuild driver,還是要重新 load OS。
這樣有點麻煩。

所以,需要一個 在runtime load/unload device driver 的方法,配合 kitl 的 "Release Directory Module" 功能。
這樣,每次rebuild driver,就只要 unload, load driver 一次就可以。

但是要unload drive ,必須要有 driver 的 handle:
DeactivateDeviceEx

BOOL DeactivateDevice(
HANDLE hDevice
);

hDevice

[in] Handle to an active device. The ActivateDevice and ActivateDeviceEx functions return this value.

要得到 hDevice 就要作 ActivateDevice。
所以Driver 不可以是 buildin active,要自己 activate,才有辦法拿到。

要把Driver 從 registry 的builtin 拿掉,才不會自動 load進來。

但是 ActivateDeviceEx 又需要Registry 作為 Driver active 的依據:

所以就要在程式中create registry key..

整個就參考這個 : Loading a Driver with ActivateDeviceEx

9.15.2009

Telit 的 application note 有 CMUX 的說明:Telit_CMUX_User_Guide_r3

超複雜,aynchronize buffer between user and kernel space

繼續上一個,從 Memory Marshalling in Windows CE 這一篇,有更囉唆的東西..

上一篇提到的是單純的由 Io control 傳 pointer 給 kernel space。
但是這只適用再 iocontrol function 裡。

如果這個 driver 有 另開 thread,而由 io control 傳進來的 pointer 要給這個 thread 使用。
這樣會導致:

iocontrol 已經 return 了,可以 剛剛傳進來的 pointer ,kernel space 的 thread 依然會用到。

這樣因為權限的問題,要呼叫另一組 funciton 來 remap pointer:
來處理這類的 pointer

MDSN 的最後一段話:
If you are running inside the kernel process and you are using an ARM microprocessor with a virtually tagged cache, you can pass MARSHAL_FORCE_ALIAS as the ArgumentDescriptor. On all other CPUs, inside the kernel process, CeAllocAsynchronousBuffer always creates an alias to the memory with VirtualCopy. On ARM CPUs that use a virtually tagged cache inside the kernel process, CeAllocAsynchronousBuffer will creates a duplicate copy of the memory on the heap by default. On large buffers, creating the duplicate heap can have an effect on performance. To prevent duplication, pass the MARSHAL_FORCE_ALIAS flag to cause CeAllocAsynchronousBuffer to create an alias, instead. However, the creation of aliased memory on ARM CPUs that use a virtually tagged cache cause both the source and destination memory to be accessed as uncached, until the alias is destroyed by CeFreeAsynchronousBuffer. This means that memory accesses become slower at both the source and destination.

Do not use the MARSHAL_FORCE_ALIAS flag unless you are using buffers greater than 16 KB.
大概是說,配合 ARM 的 virtual tagged cache,allocasynch 會用 'copy 一份到 kernel heap' 的方式來實作。 但是這樣就會有 overhead - copy 的動作。

所以 buffer 很大的時候,可以用 MARSHAL_FORCE_ALIAS option 來強迫 Ce 用 alias的方式。
但是因為 ARM 的架構,被alias 的 memory 區塊將無法被 cache,所以 access 的效能會比較差 (應該是差很多)。

所以建議 16k 以上的 size 再指定 MARSHARL_FORCE_ALIAS 比較合算。
其實這個值應該要看 cpu 和 memory 速度的比值比較正卻



--好複雜,好複雜..

Pointer Marshalling in CE 6

就是 這一篇 Windows CE 6 Memory Architecture 的最後一個 section 說的.

CE 6.0 的 memory (addressing space) 管理改變了。
以往 5.0 有 slot 架構,每個 process 佔一個 slot,只有 running process 會switch 到 slot 0。

CE 6.0 沒有 slot,所有 process 都'共用 bottom 2G 的 memory space',但是只有running process 會實際 佔據 memory space。

Kernel 部份, 5.0 和 6.0 一樣,都是佔用 upper 2G space,恆久存在。

這樣的架構,在 user process 和 kernel process 共用 pointer (space) 時會發生問題。
例如 iocontrol 送 pointer 進 kernel driver 處理


雖然 user process 在 call io control 時,他自己一定是在 running state,所以他實際佔有 bottom 2G 的 memory space。
但是萬一在 io control service 中,user process 被 switch 掉了。那麼原來 iocontrol code 拿到的 address 將不再有效(因為 botton 2G 已經換人用了)。

這樣就會發生問題。

所以 6.0 就修改了 mapping user/kernel space 的 方法 (和新function call)。
Manage 的動作就叫 marshalling pointer.
(在MSDN 中可以在很多地方看到這個名字)



其實就是 重新 alloc 一份在 kernel space (所以那一塊 physical memory 被 mapping 到兩個 memory address - 一個在 user space, 一個在 kernel space)。

這樣會佔用 kernel address space,所以 kernel 在'用完' (不再需要 access 那一塊 memory) 時,要呼叫 free? ,釋放掉 kernel address space

這一篇 Memory Marshalling in Windows CE 有圖示的說明。

可以傳遞DWORD資料的 event

CE 的 Event 可以'關聯' 一個DWORD data。

example code , from norains 的 '事件和进程间的数据交换 ' :
# 进程A: 
# DWORD NotifyProc(LPVOID pParam)
# {
# while(TRUE)
# {
# if(IsDataChange() != FALSE)
# {
# //设置关联数据
# SetEventData(hEventNotify,dwData);
#
# PulseEvent(hEventNotify);
# }
# }
# }
#
# 进程B:
# DWORD WaitNotifyProc(LPVOID pParam)
# {
# while(TRUE)
# {
# DWORD dwReturn = WaitForSingleObject(hEventNotify);
# if(dwReturn != WAIT_TIMEOUT)
# {
# //获取关联数据
# dwData = GetEventData(hEventNotify);
# }
# }
# }

從這裡來看, SetEventData/GetEventData的用法有點問題。
因為Set 和 Get 都要分成兩個動作:
  1. SetEventData
  2. PluseEvent

  1. WaitForSingleObject
  2. GetEventData
所以萬一在 WaitForSingleObject 後,GetEventData前被 preempt 掉,讓 A又執行一次 SetEvent Data再 switch 回來,那麼,GetEventData( ) 取得的就是'新'的 data,而不是'上一個' PluseEvent 前 Set 的 Data 了。

而且接下來 又會有一次 PluseEvent。
所以又會再收一次 -- 這樣的結果就是 Get 的 Thread 會收到兩次相同的 EventData 而漏掉 一個 Data。

9.11.2009

GetProcAddresses one time - DLL

蓄上篇 DLL。
這一篇VC++ Example: Loading DLLs LoadLibrary and GetProcAddress and FreeLibrary文章就有用這樣的方法:

BOOL GetProcAddresses( HINSTANCE *hLibrary,
LPCSTR lpszLibrary, INT nCount, ... )
{
va_list va;
va_start( va, nCount );

if ( ( *hLibrary = LoadLibrary( lpszLibrary ) )
!= NULL )
{
FARPROC * lpfProcFunction = NULL;
LPSTR lpszFuncName = NULL;
INT nIdxCount = 0;
while ( nIdxCount < nCount )
{
lpfProcFunction = va_arg( va, FARPROC* );
lpszFuncName = va_arg( va, LPSTR );
if ( ( *lpfProcFunction =
GetProcAddress( *hLibrary,
lpszFuncName ) ) == NULL )
{
lpfProcFunction = NULL;
return FALSE;
}
nIdxCount++;
}
}
else
{
va_end( va );
return FALSE;
}
va_end( va );
return TRUE;
}

使用方法就是:

#include <windows.h>

typedef int ( WINAPI *MESSAGEBOX )
( HWND , LPCSTR, LPCSTR, DWORD );
typedef int ( WINAPI *MESSAGEBOXEX )
( HWND , LPCSTR, LPCSTR, DWORD , WORD );

void main(void)
{
MESSAGEBOX lpfMsgBox = NULL;
MESSAGEBOXEX lpfMsgBoxEx = NULL;
HINSTANCE hLib;
if(GetProcAddresses( &hLib, "User32.dll", 2,
&lpfMsgBox, "MessageBoxA",
&lpfMsgBoxEx, "MessageBoxExA" ) )
{
lpfMsgBox( 0, "Test1", "Test1", MB_OK );
lpfMsgBoxEx( 0, "Test2", "Test2", MB_OK,
MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ) );
}
if ( hLib != NULL )
FreeLibrary( hLib );
}

但是他還是用了typedef,其實直接宣告function pointer就可以了。

DLL invoking - by LoadLibrary

使用 platform builder 作 DLL 的話,不能作auto load 的動作。
只能用 LoadLibrary( ) 來把 DLL 載入。
同時不要用的時候還可以用FreeLibrary( ) Free 掉。

但是要call DLL 中的 funciton 就比較麻煩了。

要用GetProcAddress ( ) 取出 DLL export 的 funciton address。
然後 cast 成 對應的 funciton ,才能使用。

為了..宣告 function pointer,cast funciton pointer,, 所以還是為每一個 export funciton typedef 一個 型別好了!!
所以好麻煩喔!


example 可以用 MSDN 的:
DLL 部份:Creatint a simple dynamic link library

#include <windows.h>
#define EOF (-1)

#ifdef __cplusplus // If used by C++ code,
extern "C" { // we need to export the C interface
#endif

__declspec(dllexport) int __cdecl myPuts(LPWSTR lpszMsg)
{
DWORD cchWritten;
HANDLE hConout;
BOOL fRet;

// Get a handle to the console output device.

hConout = CreateFileW(L"CONOUT$",
GENERIC_WRITE,
FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);

if (INVALID_HANDLE_VALUE == hConout)
return EOF;

// Write a null-terminated string to the console output device.

while (*lpszMsg != L'\0')
{
fRet = WriteConsole(hConout, lpszMsg, 1, &cchWritten, NULL);
if( (FALSE == fRet) || (1 != cchWritten) )
return EOF;
lpszMsg++;
}
return 1;
}

#ifdef __cplusplus
}
#endif

Call AP 要參考:
Using Run-Time dynamic Linking:

#include <windows.h>
#include <stdio.h&t;

typedef int (__cdecl *MYPROC)(LPWSTR);

VOID main(VOID)
{
HINSTANCE hinstLib;
MYPROC ProcAdd;
BOOL fFreeResult, fRunTimeLinkSuccess = FALSE;

// Get a handle to the DLL module.

hinstLib = LoadLibrary(TEXT("MyPuts.dll"));

// If the handle is valid, try to get the function address.

if (hinstLib != NULL)
{
ProcAdd = (MYPROC) GetProcAddress(hinstLib, "myPuts");

// If the function address is valid, call the function.

if (NULL != ProcAdd)
{
fRunTimeLinkSuccess = TRUE;
(ProcAdd) (L"Message sent to the DLL function\n");
}
// Free the DLL module.

fFreeResult = FreeLibrary(hinstLib);
}

// If unable to call the DLL function, use an alternative.
if (! fRunTimeLinkSuccess)
printf("Message printed from executable\n");
}
其實為了用那幾次的typedef 很麻煩,到不如反過來:

int (__cdecl *myPuts)(LPWSTR);

然後

*(FARPROC*)&myPuts = GetProcAddress(hinstLib, "myPuts");

CAST a number to function




(*((void(*)(void))0x0))();

function pointer.
case

KITL download -- no progress

有時候使用KITL download 一直不能成功。
通常是更改過ip address 錯誤後,又改正回來以後造成

就是 connection option 有找到 device,ip。
device 也持續吐出 bootme 255.255.255.255...
但是 download progress 一直沒進步,一直在等待..


這時候就要把MAC Address 也更改一下,才能夠正常download。

是 ARP cache 的關係?

9.10.2009

變更 ActiveSync 裝置在管理員裡的裝置名稱


就是在pc control panel - hardware device 顯示的名字:

usb ActiveSync driver 是依靠 usb 的 PID, VID 來決定 driver 的。

CE 的 USB PID,VID 是在..common.reg:
[HKEY_LOCAL_MACHINE\Drivers\USB\FunctionDrivers\Serial_Class]
; idVendor must be changed. 045E belongs to Microsoft and is only to be used for
; prototype devices in your labs. Visit http://www.usb.org to obtain a vendor id.
"idVendor"=dword:045E
"Manufacturer"="Generic Manufacturer (PROTOTYPE--Remember to change idVendor)"
"idProduct"=dword:00ce
"Product"="Generic Serial (PROTOTYPE--Remember to change idVendor)"
"bcdDevice"=dword:0


PC ActiveSync Driver 要到 MS 去download .. setup.msi。

然後手動解開(不要安裝)..

D:\>msiexec /a d:\setup.msi /qb TARGETDIR=d:\ats

這樣就解開到 d:\ats下..

然後去修改.. d:\ats\Windows\INF\wceusbsh.inf

可以看到一堆廠商的 vid, pid...

9.01.2009

bookmark : install msys and minGW

install mingw + msys 的最佳教學。竟然是 ffmpeg 的文件:Msys MinGW

8.27.2009

VS2006 CE 6.0 Win32 Program with Resource

原來是要用VS2005 Platform Builder 6.0 OS Project 中加一個 Dialog application 的 sub project
但是實際上 run 起來,dialog 都不會出現,

用 kitl trace code,發現是 DialogBox( ) 內找不到 resource。

但是用 platform builder 的 build system 又沒有 Makefile 可以看。所以不知道他有沒有 link resource data.

所以:
  • 修改 sources,把 *.rc 加到 SOURCES = 的 list 中。
之後,在 VS2005 下"Build" 就可以link .res 了。
其實這個只要在 VS2005 的 solution explorer 中的 "source file"選 Add New Item 把 *.rc 加入就可以了。
不是在"resource files" 加入.




但是在command console 下 build 的話,一樣不會 link .res
所以說,VS2005 沒有這麼自動,會把add的 file 自動加到 sources 檔中。

另外,雖然 resource 檔可以利用到 VS2005 的 tool 功能:
  • Resource Include file - 指定產生 .res 中使用到的ID definition
但是必須要是真的由 VS2005 新增的 control 才會被加到 .h 中,還有,刪除的control , .h 的宣告不會消除。

8.25.2009

使用VS2005 + Ce 6.0 + KITL 時,可底指定哪些 module 由 release directory load,而不要從 NK.BIN 中load。

這樣的好處是在作 driver developement 時,可以 build 完 driver 重開機就可以,不用再 makeimg, write to boot media , boot。

8.24.2009

findstr - win32 的 grep

用 findstr /? 可以顯示 help

FINDSTR [/B] [/E] [/L] [/R] [/S] [/I] [/X] [/V] [/N] [/M] [/O] [/P] [/F:file]
[/C:string] [/G:file] [/D:dir list] [/A:color attributes] [/OFF[LINE]]
字串 [[drive:][path]filename[ ...]]

/B 如果是在行的開端,則符合類型。
/E 如果是在行的尾端,則符合類型。
/L 逐字使用搜尋字串。
/R 使用搜尋字串為一般表示式。
/S 在現存目錄及所有的子目錄中
搜尋符合的檔案。
/I 指定搜尋不區分大小寫。
/X 列印完全符合的行數。
/V 只列印不含相符字串的行數。
/N 列印每一行符合的行數前的行編號。
/M 只列印包含相符字串的檔案的檔案名稱。
/O 列印每一個相符行之前的字元位移。
/P 略過沒有可列印字元的檔案
/OFF[LINE] 不要略過有離線屬性組的檔案。
/A:attr 指定有兩個十六進位數字的色彩屬性。請參考 "color /?"
/F:file 從指定的檔案 (/ 代表主控台) 讀取檔案清單。
/C:string 使用特定的字串作為逐字搜尋的字串。
/G:file 從指定的檔案取得搜尋字串(/ 代表主控台)。
strings 要搜尋的文字。
[drive:][path]filename
指定要搜尋的一個或多個檔案。

除非引數的字首有 /C ,否則請以空格將多重搜尋
字串分開。例如,'FINDSTR "hello there" x.y' 將會在檔案 x.y 中搜尋 "hello",或
"there"。'FINDSTR /C:"hello there" x.y' 將會在檔案 x.y 中搜尋
"hello there"。

8.21.2009

timestamp of module on device does not match timestamp of local module.

在用 VS2008 platformbuilder 6.0 debug subproject。
在 load subproject 的symble file 時,會 complain:
timestamp of module on device does not match timestamp of local module.
這好像是因為 這個 sub project 的時間和 kernel 不一樣。

Follow 說明,到
VS2005 -- Tool -- Option -- Platform Builder for CE -- System Debugger -- General

CHECK : "Ignore timestamp mismatched"

8.20.2009

_OEMINCPATH & _ISVINCPATH

用Platform Builder New Project,其中的 sources,雖然有

_ISVINCPATH
_OEMINCPATH
的定義,但是在build得時候並不會參考。

如果要叫 build tool 參考這兩個 宣告,要:

WINCEOEM=1

*可以寫在 sources 的一開頭



其實要加include path,可以在 sub project 的 property 的 C/C++ 裡加。

這樣會加在source 的最後,增加:
CDEFINES=$(_CSPCOMMONPATH)\src\inc;

8.13.2009

Codesnip for platformbuilder

想follow msdn 的
How to Create, Customize, and Debug an Image for the Windows CE 5.0 Emulator
作,發現platformbuilder沒有 codesnip 呀?

結果:就是在msdn 該篇文章開頭,

Windows CE 5.0 Embedded Development Labs.msi

Download 安裝後,就有了。

這個說明有說錯的地方,Walktree是"'WCE Application" 不是 "WCE Console Application"。

Walktree 是 "WCE Application" 然後選 "A simple Windows CE application"。


一定要這樣選,否則從 code clip copy 下來的 sample code 會 build fail。

8.12.2009

memtrack to find memory leak

上次忘了寫,大概紀錄一下。

MSDN 上有提到利用 celog 和 memtrack 作 memoryleak 的分析。

大概的步驟是:
  1. 連上kitl,開啟cesh
  2. 開啟要測試的程式 s testprogram.exe
  3. 開啟memtrack : memtrack on
  4. memtrack 會要你開啟celog。回答Y
  5. 操作 testprogram,run 過你認為有可能發生 leak的動作
  6. 關閉memtrack : memtrack off
  7. 將celog 存到 release folder : celog -flush /release/celog.clg
  8. 到 pc 端,開啟 memalyz 讀入剛剛存的 celog.clg,她會轉成 txt 檔
最後的 txt 檔就會列出在memtrack on -- off 的過程中,有哪些 memory 沒有free掉。




那~有沒有找到memory leak ?

沒有 :)

因為 log 很複雜呀,而且看不懂 XD

8.11.2009

WorkItem in SDBUS driver

SDBUS 中的 CSDWorkItem class 好像只是一個 client/server class, server 介面實做一個 servicecode queue,和一個 wakeup event。

class server 實做在繼承的 MiniThread( ) 上。
class 包裝好 "put service in queue & trigger wakeup event" 在一個 function 中,方便 client 使用。

這樣的目的好像是要做出 asynchroniz 的動作。讓 client 在作某些 SD card 動作時,不會被block著。

至於動作有沒有完成就沒有同步的方法了----

GlobalMemoryStatus

MSDN GlobalMemoryStatus

void GlobalMemoryStatus(
LPMEMORYSTATUS lpBuffer
);

其中傳入/出的structure 是:

typedef struct _MEMORYSTATUS {
DWORD dwLength; - 很莫名其妙,就是 這個structure 的size。
DWORD dwMemoryLoad; - memory loading %
DWORD dwTotalPhys; - 所有的 physical memory size
DWORD dwAvailPhys; - 目前可用的 physical memory size (還沒被 commit 的 memory)
DWORD dwTotalPageFile; - 所有的 disk page size
DWORD dwAvailPageFile; - 目前可用的 disk page size
DWORD dwTotalVirtual; - caller process 的所有 virtual memory address
DWORD dwAvailVirtual; - caller process 目前可用的 virtual memory address space
} MEMORYSTATUS, *LPMEMORYSTATUS;

所以一般看 AvailablePhys 就可以了,代表還有多少實體記憶體可以用。
頂多再看一下 AvailVirtual,看看是不是所有的Virtual Address都被 alloc 掉了 (DLL有這麼多嗎?)


這幾個參數值,可以用 remote performance monitor 看。

8.10.2009

msdn : DirectDraw Blt function.

HRESULT Blt(
LPRECT lpDestRect,
LPDIRECTDRAWSURFACE4 lpDDSrcSurface,
LPRECT lpSrcRect,
DWORD dwFlags,
LPDDBLTFX lpDDBltFx
);

8.06.2009

Fix Windows CE 5.0 KITL after install Windows CE 6.0

因為安裝了 Windows CE 6.0 在 platform builder 5.0 的 PC 上,所以 Platform builder 的 Kitl 不能用了 :(

後來這一篇 有教 - uninstall 6.0 後,5.0 的 connection 不能用的解決方法,照著作後,果然可以連了 (雖然還是有點小問題..)

大概就是:

Windows CE 5.0, 6.0 的連線設定都放在

C:\Documents and Settings\--User-Name--\Local Settings\Application Data\Microsoft\CoreCon\1.0

所以把這個 folder 備份起來 (以免以後 6.0 要用),然後到 5.0 的目錄把 addon folder 和一個 microsoft.xxxxx.xsl copy 過來,重新開 Platform builder 後,其他資料就會自動產生了。

C:\Program Files\Windows CE Platform Builder\5.00\CEPB\BIN\microsoft.platformbuilder500.servicecategory.xsl

C:\Program Files\Windows CE Platform Builder\5.00\CORECON\SDK\XSL\ADDONS

8.05.2009

msdn : clone public code

先bookmark一下..

原來msdn 就有說把public code clone 出來的方法..



Show Software Input Panel (SIP 螢幕小鍵盤)

如果OS有把 software input panel (keyboard) 加到 OS 中,但是沒有把 start bar 顯示出來,可以用下面的code 來顯示:


顯示

HWND hInputWnd = ::FindWindow(_T("SipWndClass"),NULL);
if(hInputWnd != 0)
{
::ShowWindow(hInputWnd,SW_SHOW);
}


關閉


HWND hInputWnd = ::FindWindow(_T("SipWndClass"),NULL);
if(hInputWnd != 0)
{
::ShowWindow(hInputWnd,SW_HIDE);
}

7.23.2009

SD card, Command and Response

SD Card 的 Command 依照SD Card 的"回應"有很多"類型"。
回應就是"Response",一樣利用 SD card interface 的 "CMD" pin 來傳送。
= 所以 CMD line 是雙向 line

host 從CMD 送出command 後,讓 CMD維持 high-impendance,SD card 就可以拉動 CMD line,做出回應。
  • Spec 4.12 Timings 有詳細說明bus 的 timing.
Spec 上用 R1, R2, R3, R6 來區分Response 的內容。
每個 Response 的 data 數量不一樣。

每個Command都有規定的 Response 。

像 CMD2, CMD10 就要回應 R2。

7.21.2009

CE.NET Advance Memory Management

MSDN : CE.NET Advance Memory Management

大概說明空間的利用方式


記憶體管理就是管理記憶體位址空間 (memory address)。
32 bit 有 4G 的 address。
CE分成兩半來用,High-half 給 OS,Low-half給 Process。

Address 決定了,並不會立刻佔用phyical memory,直到這個Address的內容真得被利用到,才會真的把phyical memory mapping過來 (稱為 commit)。

CE 使用記憶體位址的規則是:

每個Process 有 32M 的 address 可以用。 但是要從 0x10000 開始用起。

由下往上依次是:
  1. Program Code
  2. Read Only Data
  3. Read Write Data
  4. Resource
  5. 預留的 Heap 空間
  6. 預留的 Stack 空間
剩下的就是 Free Space 和 RAM-Base DLL 用。

RAM Base DLL 會從 32M 開始往下 Load。

=> 所以 Free Space 是被 Process Code, DATA, STACK 和 RAM-DLL 夾著。

process 在執行過程中如果create seperate heap或call VirtualAlloc 會接在剛剛"預留的STACK空間"上面開始,找第一個符合的位址區。

接著講 VirtualAlloc 這個API.

是以 1k 或 4k 為 alloc 的單位。同時會對齊 64k。 <== 這個點問題,應該要怎樣"以4k 為單位,而且對齊 64k? 對齊 64k 不就是以 64k 為單位?

所以下面的code在CE里會fail:

for(i=0;i<512;i++)
pMem[i] = VirtualAlloc(0,PAGE_SIZE, MEM_RESERVE | MEM_COMMIT, PAGER_READWRITE);

因為這樣實際上 會alloc 掉的記憶體(Address space and physical memory) 是 512 * 64k Byte.
超過 32M.
=>雖然你只需要 512 * 4k Byte

所以要利用 Allocate Address 和 Commite Physical Memory 兩段式動作的方式來作:

pBase = VirtualAlloc (0, 512 * PAGE_SIZE, MEM_RESERVE, PAGE_READWRITE);

for(i=0;i<512;i++)
pMem[i] = VirtualAlloc(pBase+(i*PAGE_SIZE),PAGE_SIZE, MEM_COMMIT, PAGE_READWRITE);
這樣就只會用掉 512*4k的位置空間了。(同時又commit到實際記憶體)

接下來說明Load DLL 的記憶體使用情形

已經知道RAM-DLL 是從每個process的32M邊界往前(下)使用。
除此之外,所謂DLL,就是有"共用"的特性。所以有可以一個DLL被2個 process使用。

因為CE的同一個DLL在不同的Process中需要在相同的Virtual Address (why?)。
所以在load DLL的時候,必須考慮到避開其他process 的 DLL 已經使用的位址。
一個process只有32M已經很慘了,DLL還要考慮自己不用的DLL要避開!!
Process Load A, B DLL -- Memory = A.B
Process Load A, C DLL -- Memory = A.(B).C
Process Load A, D DLL -- Memory = A.(B).(C).D
其中( )的部份在該process看來是空下來的部份


CE 5.0 是不是也是一樣?

7.20.2009

PostThreadMessage

雖然在Message Overview 里都只有說明有Windows 才有的Message/Queue 相關操作,但是從 PostThreadMessage ( ) 這個 function 來看,沒有Windows 的 Thread,也有 Message Queue。

但是有一些限制,Thread的 Message Queue不是在Thread 產生就Create好的,只有在Thread 有 call 過 Message 相關 funciton 後,才會產生。

同時,在Thread 的 Message Queue未產生之前,PostThreadMessage( )給他的話,Message會被丟掉 (同時 return FALSE)。

MSDN 提供兩個方法來避免這個問題:
  1. PostThreadMessage的人check return value,fail 的話就Sleep( )一段時間,等 對方把 MessageQueue 開出來
  2. 利用同步機制(Event) 來同步雙方的動作。 收Message的Thread 啟動時就call一次 PeekMessage( )同時指定不拿出message,
    PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE)
    經過這次呼叫,Thread 的 MessageQueue 就會被 Create,然後用 SetEvent( )通知要PostThreadMessage給他的Thread。範例。
收Message的Thread 有三種收Message的Argument
  1. 收 Post 給 該 Thread 的 Window 的 Message
  2. 收 Post 給 該 Thread 的 Message
  3. 都收
1. 的話,要是有Windows 的Thread 才有效。

7.15.2009

interrupt handling in CE

CE 的 hardware interrupt 由 ISR ,kernel,IST 三者合作。

每個hardware的中斷都會被指定一個ISR來處理 (ISR可以共用)

當中斷發生時,會kernel會呼叫ISR,ISR執行完後,會return一個值。
kernel 由這個值檢查有哪些event 和他相關,set 這些 event。

IST 內會有wait event 的code,這樣就會被通知到。

新支援的 Installtable ISR (IISR)。
可以達成 chain-interrupt 的行為:
kernel 依照該hardware IRQ 註冊的 ISR,一個一個 call,每個 ISR要確認是不是自己要處
理。
如果不是,就return SYS_CHAIN,kernel 就會call下一個 ISR。
如果是,就retrurn 其他的職,kernel 就不會call下一個 ISR。

IISR Sample Code 在 \Public\Common\Oak\Drivers\GIISR

* 有關IRQ disable,enable 的時機,在書中有一張圖說得很清楚。
基本上,就是..一但發生,所有interrupt都disable,ISR處理時,就把其他interrupt打開,自己的還是關。一直到 IST call InterruptDone( ) 該 IRQ 才會再被打開。

6.18.2009

VitualBox VM HD image 重新使用問題

發生一個問題,VirtualBox 其中一個 VM 把 HD 卸掉,然後再掛回來,開機後,竟然是HD image 里作snapshoot 的那一個狀態,雖然在 HD tab 有顯示 snapshoot - 現在狀況 兩個state,而VM也的確是在"現在狀態",但是就是開在 snapshoot 。

結果在 HD table 決定使用的 hd image (*.vdi) 時,溝選 "Show Differencing Hard Disks" 就會發現這個 image 有兩個 hd state,換另一個後就OK了。

6.15.2009

M2M communicatin - by Camera and Display

machine to machine 2 way communication - in visual.

就是利用 display 和 camera 來溝通。
互相用 camera 拍攝對方的 display,
display 上顯示傳遞到對方的資料。對方就可以經由 camera "讀取" 到。

這個在目前"有 video camera"功能的手機上可以實做。
只需要software 的 effort。不需要而外增加 hardware。

顯示的內榮決定傳輸頻寬,可以利用 2D bar code或是單純的 black-white screen。

6.11.2009

mount samba folder

mount samba folder,參考這裡

我是用這個:
mount -t cifs -o username=server_user,password=server_password
//192.168.44.100/share_name /path_to/mount_point

便宜洗大頭照

這個一定要介紹一下,可以幫人洗 自製大頭照,速度又快的商店

洗相片的網路商片
快速洗相片的介紹

6.10.2009

iMX31 PDK build Image and upload

紀錄一下,

iMX31 3 stack board 又叫做 PDK (platform Developement Kit)。
serach IMX31
  • IMX31_SDK_14 : IMX31_SDK_WINCE5_BSP.msi
需要 上 CE QFE patch 到 2008 12 rollup。

安裝一個platform : C:\WINCE500\PLATFORM\3ds

Platform 是 C:\WINCE500\PBWorkspaces\3dsmobility

依照 IMX31_PDK14_UG.pdf 的說明,install, build image:
  • 因為 有上 CE QFE,所以要手動 build ms sd driver
  • 手動build csp
  • sysgen
Build XLDR 和 EBOOT
  • 手動 build. 這兩個 folder 是不會自動 build 的。
燒錄 image 到 PDK 的tool 是 ATK
燒錄 XLDR.NB0
  • 調整 PDK debug board 的 SW (紅色),由左到右,依次是:0.0.0.0.0.0 (download mode)
  • 接 RS232 到 debug board,開機
  • 啟動 ATK - 選 iMX31 TOC02, DDR, Go
  • 第二頁選 Flash Tool,Next
  • NAND - K9K2G08U0A,
  • Erase
  • Program - XLDR.NB0 (start address : 0x0000)
  • Program - EBOOT.NB0 (start addrss : 0x20000)
完成,調整 debug board SW 0.1.0.0.0.0 (Nand boot) - 開啟 hyper terminal 進入 EBOOT。

6.05.2009

Procedure on Installing WINCE6.0 R2

Install VS2005

Install CE6.0 (需要 VS2005)

Install Windows Installer 3.1

Install VS2005 SP1 (需要 Windows Installer 3.1) --- 裝不進去 Q_Q

Install CE6.0 SP1 ( 需要 VS2005 SP1 在 R2 DVD 裡有 TeamSuit 版)

Install CE6.0 R2 (需要 CE 6.0 SP1 - 在 R2 DVD 裡有 )

安裝R2需要將IE設為default browser然後double-cliek DVD,按下 Install R2 才能安裝。
* 如果是forefox 的化,會dowload 下來,這樣會不能安裝

6.03.2009

Uzbl browser

Uzbl 好像很有趣,是新的 lightweight browser也是用 webkit,但是 是用比較新版的 libwebkit-dev.

這一篇 有說安裝新版 libwebkit-dev的方法。
但是不知道安裝後,會不會和現有的衝突?還是會覆蓋掉現有的 version
Uzbl 的理念是..

先研究不傷身體,再講求效果..

不是啦,,是

Uzbl follows the UNIX philosophy - "Write programs that do one thing and do it well. Write programs to work together. Write programs to handle text streams, because that is a universal interface."


6.01.2009

RealView ICE and gdb

參考 RealViewICE Guide
手動安裝 RealView ICE for Linux (其實是 redhat)。
裝完後,會在 /opt/ARM/RVI

執行 /opt/ARM/RVI/RVI/.../linux-pentium/rvconfig 會出現跟 windows 一樣的GUI。
follow windows 的作法,identify 出 JTAG scanchain 上的 cpu.
save : rvi.rvc - copy 到 home 比較方便

執行 /opt/ARM/RVI/RVD/Tools/..../rvigdbconfig -f rvi.rvc
reading file rvi.rvc
Done
connecting to 192.168.144.185
found 192.168.144.185
connected
finished
192.168.144.185 就是 RealView ICE 的 ip

這樣就可以啟動 arm-gdb 了 (用 CodeSourcer) : arm-none-linux-gnueabi-gdb
(gdb) target remote 192.168.144.185:4000
Remote debugging using 192.168.144.185:4000
0x00000000 in ??()
(gdb)

5.30.2009

memo 一下:

姊的NB : Aspire 1621LC 的 display card 其實是 ATi Redan Mobile 5700.
付的CD (和 Acer website )提供的Driver 是 5600,還有"他自己也認為自己是 5600,
所以裝完會有'?' 號,要去download Ati 5700 的 driver,強制安裝。
才會OK.

備份在爸的PC. (和 gmail ?)

5.26.2009

Build - for WINCE5.0

所以如果是 follow MS 的 folder architecture :
  • CSP : 放在 PUBLIC\COMMON\OAK\CSP
  • PQOAL : 放在 PLATFORM\COMMON\SRC
  • BSP : 放在 PLATFORM\
分別有不同的 build 法:
  • CSP : 到 folder 去 build (with clean)
  • PQOAL : sysgen (with clean)
  • BSP : Build and sysgen current BSP

Worklog : iMX31 Demoboard, buid WINCE5.0

iMX31 3 STACK Debug board:
  • Nand : K9F2G08R0A - 256MB
  • DDR 128MB
Boot From Nand 的 Dip SW 設定:
  • SW5 : 0
  • SW6: 1
  • SW7: 0
  • SW8: 0
  • SW9: 0
  • SW10: 0

Demoboard 使用 iMX31 和 MC13783 (PMIC with Audio AMP)。
MC13783 的 size 幾乎和 iMX31 一樣大


CSP 放在 C:\WINCE500\PUBLIC\COMMON\OAK\CSP\FREESCALE
  • MX31 : MX31 相關
  • MXARM11 : 所有MX 系列中 arm11 相關
CE 的 PQOAL 架構,又把一些 oal 放在其他地方 C:\WINCE500\PLATFORM\COMMON\SRC\ARM\FREESCALE\


依照順序來..

Build CSP:

因為 CSP 不會 auto build (是因為在 public 的關係 ?),所以要手動 build。
到 file,favorite,CSP 按右鍵,check "clean before build" then do "build current project"
大概就是到 public\common\oak\csp\freescale 下面作 build -c
build 好的 lib 會在 C:\WINCE500\PUBLIC\COMMON\OAK\LIB\ARMV4I\DEBUG


接下來 build BSP (for the 1st time)
build OS menu :
  • clean before building : X
  • Copy Files to Release Directory After build : V
  • Make Run-Time Image After Build : V
然後就按下 "Sysgen"

要 Clean build 整個 BSP (CSP, PQOAL, BSP) 的話:
  • build CSP - follow 前面的步驟,按右鍵...
  • build PQOAL
    • Clean Before Building : V
    • Copy Files to Release Directory : V
    • Make Image After Build : X
    • 執行 Build OS - sysgen
  • build BSP
    • Clean Before Building : V
    • Copy Files to Release Directory : V
    • Make Image After Build : V
    • 執行 Build OS - Build and sysgen current BSP

如果只有某部份的 code 修改,可以只build 那部份的 code,然後 執行 Build and sysgen current BSP

到 Files :
  • CSP 有修改 : 到修改的 folder 按右鍵- check "Clean before Build" 然後 "Build and sysgen current BSP"
  • PQOAL : 一樣,到 PQOAL folre 按右鍵
然後:
  • Clean before Build : X
  • Copy Files to Release Directory After Build : V
  • Make Run time image after Build : V
  • 執行 : Build and Sysgen Current BSP

5.20.2009

CE Dialup to GPRS

首先要有PPP, Network and Dial-up Connections.

registry 要設定好系統存在的Modem。

現在系統是COM6 外接到 GPRS Modem,所以要自己建
奇怪,找不到 Hayes Modem 的 registry creater,在 platform.reg 里也沒有。

在registry中要設好一個使用COM6的Modem,Dial Up 設定才可以對COM6送command。

接上 GPRS Modem,先用 TXRX 程式測試一下GPRS Modem 對AT Command 是否OK。
ref Linux GPRS
  • AT+CGATT? 確認attach 到 network 後 (回 +CGATT:1 )
  • 先下好 AT+CDGCONT=1,"IP","INTERNET"
設定 dial ip network :
  • new 一個連線
  • 設定 baudrate 115200, 8N1, no flowcontrol.
  • 設定撥號 *99***1#
OK,可以connect!

連線完後,用 CE_Ping.exe 測試一下ping.

5.13.2009

openmoko - flash kernel and rootfs

安裝 usb 連線軟體: dfu-util。
Debian 直接用 apt 安裝就可以。

通常需要
  1. kernel - uImage
  2. rootfs
bootloader 不一定要重燒

rootfs 通常是有 jffs2 在檔名中,kernel 通常就有 uImage 在檔名中。

開機進入 nor boot (nand boot) ? 就可以接上 usb ,和 dfu-util 溝通。

按著hold key 開機,進入nor boot 畫面,插上 usb。dmesg..

[786627.436013] usb 2-3: new full speed USB device using ohci_hcd and address 2
[786627.654996] usb 2-3: configuration #1 chosen from 2 choices
[786627.677190] usb 2-3: New USB device found, idVendor=1d50, idProduct=5119
[786627.677198] usb 2-3: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[786627.677202] usb 2-3: Product: Neo1973 Bootloader U-Boot 1.3.2-moko12
[786627.677205] usb 2-3: Manufacturer: OpenMoko, Inc
[786627.677207] usb 2-3: SerialNumber: 0000000
[786628.281641] cdc_acm: This device cannot do calls on its own. It is no modem.
[786628.281641] cdc_acm 2-3:1.0: ttyACM0: USB ACM device
[786628.288104] usbcore: registered new interface driver cdc_acm
[786628.288112] cdc_acm: v0.26:USB Abstract Control Model driver for USB modems and ISDN adapters
所以應該是有偵測到...

燒錄過程要注意的是...沒有操作30 sec 後,機器會自動 power off。
所以看到螢幕黑掉,就要重新 power on.

rootfs download 比較久。

重開機很花時間,約需要 2 min,約 1min 後才會出現splash screen.然後滅掉..

openmoko new freerunner - boot into nand and nor

Tony新買的Neo Freerunner 換OS後無法開機,停在 openmoko boot screen。
所以可以讓我玩一下..

先follow instruction,檢查一下nor boot 可不可以boot:
  1. .按左上角hold button不放
  2. 按右下角power button開機button不放,, 開機
  3. 放掉左上角hold button
  4. 放到右下角power button
這樣就開進 nor boot。可以看到 lcd 顯示 nor boot version 和 menu。


接著檢查 nand boot 可不可以 boot:
  1. 按著右下角 power button 不放
  2. 馬上按左上角 hold button,維持 5~8 sec,,開機
  3. 都可以放開了
這樣就開進 nand boot,可以看到 lcd 顯示 nand 和 menu

5.08.2009

open port in iptables

用iptables -L 列出目前所有的 rule:

[charles@test ~]$ sudo iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT all -- 6X-7X-2XX-2XX.adsl.static.giga.net.tw anywhere
ACCEPT all -- 6X-2XX-1XX-1XX.hinet-ip.hinet.net anywhere
ACCEPT all -- 1XX.5X.4X.X anywhere
ACCEPT tcp -- anywhere anywhere tcp dpt:http
ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED
DROP all -- anywhere anywhere state INVALID,NEW
DROP all -- anywhere anywhere

Chain FORWARD (policy ACCEPT)
target prot opt source destination

Chain OUTPUT (policy ACCEPT)
target prot opt source destination

Chain icmpfilter (0 references)
target prot opt source destination
DROP icmp -- anywhere anywhere icmp echo-request
ACCEPT icmp -- anywhere anywhere icmp echo-reply
ACCEPT icmp -- anywhere anywhere icmp destination-unreachable
ACCEPT icmp -- anywhere anywhere icmp fragmentation-needed
ACCEPT icmp -- anywhere anywhere icmp source-quench
ACCEPT icmp -- anywhere anywhere icmp time-exceeded
ACCEPT icmp -- anywhere anywhere icmp parameter-problem
ACCEPT icmp -- anywhere anywhere icmp timestamp-reply
ACCEPT icmp -- anywhere anywhere icmp type 16
ACCEPT icmp -- anywhere anywhere icmp address-mask-reply
[charles@test ~]$

現在要把 tcp port 2030 打開,下:

iptables -A INPUT -p tcp --dport 2030 -j ACCEPT
這樣的話,還是沒效,因為rule被 "append" 到後面。
再list一次:

Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT all -- 6X-7X-2XX-2XX.adsl.static.giga.net.tw anywhere
ACCEPT all -- 6X-2XX-1XX-1XX.hinet-ip.hinet.net anywhere
ACCEPT all -- 1XX.5X.4X.X anywhere
ACCEPT tcp -- anywhere anywhere tcp dpt:http
ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED
DROP all -- anywhere anywhere state INVALID,NEW
DROP all -- anywhere anywhere
ACCEPT tcp -- anywhere anywhere tcp dpt:device2
可以看到,是在 DROP all 之後。所以沒效。
要用 "insert" 才有效:

$ sudo iptables -I INPUT 6 -p TCP --dport 2030 -j ACCEPT

這樣,list出來:

Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT all -- 6X-7X-2XX-2XX.adsl.static.giga.net.tw anywhere
ACCEPT all -- 6X-2XX-1XX-1XX.hinet-ip.hinet.net anywhere
ACCEPT all -- 1XX.5X.4X.X anywhere
ACCEPT tcp -- anywhere anywhere tcp dpt:http
ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED
ACCEPT tcp -- anywhere anywhere tcp dpt:device2
DROP all -- anywhere anywhere state INVALID,NEW
DROP all -- anywhere anywhere
可以看到,被插到DROP之前了 (實際上是第6個)。

這樣就打開port 2030 了

5.06.2009

centos log

CentOS 裝完

visudo 把自己加入 ALL(ALL)=ALL

改 .bashrc 把 /sbin 加到 PATH。
用ifconfig 看網路

設定 proxy - 用 UI

設定 yum 使用 proxy:
設定檔是 /etc/yum.conf
加一行:
 proxy=http:\\ip:port
然後 run yum update (要有 root 權限)...等等等..

run 在 virtualbox 的話,follow 這一篇 ( http://forums.virtualbox.org/viewtopic.php?t=4960&highlight=install+guest+addition) 安裝VBoxAddition。

Debian 的 Service 用 /etc/init.d/xxx start| stop
CentOS 提供一個 command 叫 service: service httpd restart

django 可以配合python 2.3~2.6的版本,python 2.5 以後的版本內涵SQLit,可以不必額外在裝database。

5.05.2009

CE: Disk cluster size for FAT

FAT的 資料存取單位是 cluster,cluster 是由 sector (disk 最小存取單位) 組成的。

Disk 在 format 的時候,決定 cluster 的大小。

Cluster size 的決定,CE 有自己的作法。在 msdn 有提到:
1GB-8GB  4KB
8GB-16GB 8KB
16GB-32GB 16KB
32GB 32KB
在 CE 的 source code 中,這段算法的位置在 fatutil.dll
C:\WINCE500\PUBLIC\COMMON\OAK\DRIVERS\FSD\FATUTIL\MAIN\formatdisk.h:
FAT12,16,32 各有不同,FAT32 是:
total sector 數,cluster 應該用的 sector 數:
{
{ 66600, 0}, /* disks up to 32.5 MB, the 0 value for SecPerClusVal trips an error */
{ 532480, 1}, /* disks up to 260 MB, .5k cluster */
{ 16777216, 8}, /* disks up to 8 GB, 4k cluster */
{ 33554432, 16}, /* disks up to 16 GB, 8k cluster */
{ 67108864, 32}, /* disks up to 32 GB, 16k cluster */
{ 0xFFFFFFFF, 64} /* disks greater than 32GB, 32k cluster */
};

4.30.2009

MBR and partition table

Windows CE 有在看 parition table,partition table 的

Disk 的 Driver 要寫好,放在 StorageManager\AutoLoad\
系統啟動後就會自動 load 這個 driver 進來,丟入 disk parameter 要求初始化,
這個 driver 就要讀入 partition table,回應給system。

system 依照 partition table 的內容,filesystem type,load 對應的 driver 進來。

msdn 說 partition table 是 mbr 的一部分,描述 disk 的 partition layout。最多可以包含 4 個 partition。

mbr 會有一個 end mark : 0x55AA。
在這個 end mark 的前面,擺 partition table [4]。

一般的mbr 是 512 bytes,所以parition table 的 offset 就是:
512 - 2 - (16x4) =

partition table 的entry (一個parititon) 的structure 定義在 COMMON\OAK\INC\bootpart.h
typedef struct _PARTENTRY {
BYTE Part_BootInd; // If 80h means this is boot partition
BYTE Part_FirstHead; // Partition starting head based 0
BYTE Part_FirstSector; // Partition starting sector based 1
BYTE Part_FirstTrack; // Partition starting track based 0
BYTE Part_FileSystem; // Partition type signature field
BYTE Part_LastHead; // Partition ending head based 0
BYTE Part_LastSector; // Partition ending sector based 1
BYTE Part_LastTrack; // Partition ending track based 0
DWORD Part_StartSector; // Logical starting sector based 0
DWORD Part_TotalSectors; // Total logical sectors in partition
} PARTENTRY;
size是16 bytes.
Part_BootInd 的value 也定義在 bootpart.h;
// Flags for Part_BootInd
#define PART_IND_ACTIVE 0x1
#define PART_IND_READ_ONLY 0x2
#define PART_IND_HIDDEN 0x4

其中Filesystem 定義在 COMMON\OAK\INC\bootpart.h
#define PART_UNKNOWN            0
#define PART_DOS2_FAT 0x01 // legit DOS partition
#define PART_DOS3_FAT 0x04 // legit DOS partition
#define PART_EXTENDED 0x05 // legit DOS partition
#define PART_DOS4_FAT 0x06 // legit DOS partition
#define PART_DOS32 0x0B // legit DOS partition (FAT32)
#define PART_DOS32X13 0x0C // Same as 0x0B only "use LBA"
#define PART_DOSX13 0x0E // Same as 0x06 only "use LBA"
#define PART_DOSX13X 0x0F // Same as 0x05 only "use LBA"

// CE only partition types for Part_FileSystem

#define PART_CE_HIDDEN 0x18
#define PART_BOOTSECTION 0x20
#define PART_BINFS 0x21 // BINFS file system
#define PART_XIP 0x22 // XIP ROM Image
#define PART_ROMIMAGE 0x22 // XIP ROM Image (same as PART_XIP)
#define PART_RAMIMAGE 0x23 // XIP RAM Image
#define PART_IMGFS 0x25 // IMGFS file system
#define PART_BINARY 0x26 // Raw Binary Data

4.28.2009

geotate 的即時定位技術

將RF收到的 raw data 存到照片中,回去後再用 PC 解出真正的 nmea 資訊,這樣不僅可以省去dsp 與計算的功耗,也可以省掉定位的時間。
利用這樣的方式,所有 相機都只需要增加一點硬體 (GPS RF + AD),就可以有 geotag 的能力。不需要開機等鎖定,也不會多耗很多電池。

ref : interview

4.27.2009

mythbuntu

原來ubuntu有for media center 的版本,叫 mythbuntu , 就是myth + ubuntu

要注意 繁體中文叫 Hanzi(Traditional)

但是看不到什麼feature...大概在Myth吧..

還有 backend 就是 TV card 的意思

Linux GPRS

Linux GPRS Howto 的說明比一些 GPRS Module 的application Notes 還清楚

PDP : packet data protocol. 資料封包 (對應的,語音連線送的是聲音封包)。
APN : Access Point Name。

用minicom 來下 command。要注意 屬於 dialout groupe。

下 AT 回應 OK 代表RS232 線連線 OK. (其實有看到 AT 就代表 正常,因為 AT 也 modem echo back )

下 AT+CPIN? 檢查 pin number 是不是有輸入,回 READY 代表正常。
如果不是,用 AT+CPIN=1234 輸入 pin number (1234)

下 AT+CGATT? 檢查是不是已經attach 到 GPRS network 了,回應 1 是OK。
如果是 0,用 AT+CGATT=1 叫 modem attach。

設定PDP 傳送的 profile,modem 可以設很多 pdp profile,方便user 轉換。
AT+CGDCONT=1,"IP","INTERNET"
  • 1 : profile 1
  • "IP" : PDP type (ip packet, 好像一定要大寫)
  • "INTERNET" : APN (每一家電信公司不一樣)
撥號,GPRS Servie 的 number 固定是:
*99***1#
後面的 " 1" 是 PDP profile 號碼。

ATDT*99***1#
播完號,出現 CONNECT,然後就會看到一堆亂碼。

..到這裡,代表 linux 到 gprs modem 端已經OK了。



接下來設定 linux 的撥接動作。

GPRS Modem 是以 ppp 的方式傳送資料,所以要config ppp。

好像大多數網站都說 wvdial,所以也用wvdial,wvdial 是 ppp 的 front-end,用一個 config 檔而已。

修改 /etc/wvdial.conf:

[Dialer Defaults]
Modem = /dev/ttyS1
Baud = 115200
Init = AT+CGDCONT=1,"IP","INTERNET"
Phone = *99***1#
Username = any
Password = any
Dial Command = ATDT
New PPPD = yes
雖然不檢查username, password,但是還是要填值,否則 wvdial 會 complain。
然後..
 : ~$sudo wvdial
就會出現..
$ sudo wvdial
--> WvDial: Internet dialer version 1.60
--> Initializing modem.
--> Sending: AT+CGDCONT=1,"IP","INTERNET"
AT+CGDCONT=1,"IP","INTERNET"
OK
--> Modem initialized.
--> Sending: ATDT*99***1#
--> Waiting for carrier.
ATDT*99***1#
CONNECT
~[7f]}#@!}!}$} }<}!}$}&@}#}$@#}%}&},<eI}"}&} } } } }'}"}(}"{8~~~
--> Carrier detected. Waiting for prompt.
~[7f]}#@!}!}%} }<}!}$}&@}#}$@#}%}&},<eI}"}&} } } } }'}"}(}"3j~
--> PPP negotiation detected.
--> Starting pppd at Tue Apr 28 11:52:35 2009
--> Pid of pppd: 30572
--> Using interface ppp0
--> local IP address 116.59.14.180
--> remote IP address 10.0.0.1
--> primary DNS address 168.95.1.1
--> secondary DNS address 168.95.192.1
這樣好像連上了..
但是 routing table 好像沒update 耶..

把eth0 斷掉後,重新連線,roue -n
default gateway 是ppp0 (自己)


without flow control and modem signal


如果GPRS Modem 和 Linux 間只有 TX/RX/GND,沒有其他 flow control (CTS, RTS) 和 modem state (CD, DSR, CTR) 信號。

雖然有看到/etc/ppp/options 中有 crtscts 選項可以設,但是好像沒效,wvdial 一定會去 check ctsrts。
所以wvdial 在第一階段,AT+CGDCONT=1,"IP","INTERNET" 就不通了,會反覆兩次,然後fail : Modem No Response。

這樣就需要把 linux 這一端的 RS232 的 CTS 和 RTS 短路 (7-8)。
這樣就可以正確下命令,和撥號,撥通...

但是一但撥通,就會有 carrier lost 的message。
這樣就要將 linux 這一端的 modem status DTR, CD, DSR 短路 (1,4,6)。
這樣就OK了

ref Null Modem




Linux 同時啟動internal network

就是要設定好 routing path.

因為有設定bridge (br0),所以要把 br0 啟動起來,把 eth0 關掉。
把 192.168.0.0 設定 gatway : 192.168.144.254
route add -net 192.168.0.0 netmask 255.255.0.0 gw 192.168.144.254 br0

用錢可以解決的事: 感度與範圍

比較敏感的 Sensor 比較容易飽和 -- 也就是說,量測尺範圍不夠。
量測範圍大的 Sensor,就比較遲鈍 -- 因為刻度變大了。

那要怎麼做出量測範圍大,靈敏度又好的 Sensor 呢?


就裝兩個 Sensor 就好了呀,小Sensor 飽和了就看大Sensor 的值....

0xlab 開張

0xlab 開張了

看看其中 Projects 的網頁,都是一些讓 emebedded system developer 很exciting 的東西。

其中 planet 部份是所有相關blogger 的blog 發佈處,裡面已經有很多有趣的文章了:像..我弄了很久弄不起來的EFL build 介紹,在andriod 中播放 youtube 影片,..

4.24.2009

撥接 GPRS..

撥接gprs 上網的動作到現在還是沒變(ref 2005)..

不同的地方就是 baudrate 變了-- 提昇到 115200。

所以在新建 modem 時,就沒得選了,只好先選一個低baudrate 的 (e.g 9600),create 完後,再將 baudrate 改 115200。

另外撥接的號碼也沒變,還是謎的 *99#
啊~不對,以前是 *99***1#
但是兩個號碼都可以..

接下來就要測 bandwidth 了..

4.23.2009

回顧 - 2006 的期望

今天在找以前作network flooding test 的筆記時,看到自己寫的:

......
想想目前一切需要都可以由網路服務取得。只要能跑firefox,似乎一切就OK。所以 也不介意OS是windows, linux還是OSX。 這樣想想...firefox + google似乎一切就搞定。

真希望會有一種full size keyboard,low speed cpu (enough to run firefox),long battery time,12" display ,wifi + 3G 並且重量輕的裝置。 我想,以目前的技術,應該是絕對可以做出來的吧 :)
這不就是現在的netbook 嗎?

想不到我在 2006 就這樣想了...

4.22.2009

build new rev openocd in msys

新rev 的 openpcd 需要作 bootstrap,(也就是說,需要 aclocal, autoconf, automake..)

follow 這一篇..安裝 msys, minGW 環境。

msys - 先安裝 1.0.10
msys-DTK : 是build 需要的一些 tool,像 perl, autoconf, automake... etc
然後 download msys-core-1.0.11,解開後,覆蓋 msys的安裝目錄。
msys 的 update 就是 untar , overwrite ?
之後安裝新版 autoconf, automake, libtool。
安裝方式都是 download mingw patch 過的 source code, /.configure , make , make install。

http://ftp.gnu.org/gnu/autoconf/autoconf-2.61.tar.bz2

http://ftp.gnu.org/gnu/automake/automake-1.10.tar.bz2

http://ftp.gnu.org/gnu/libtool/libtool-1.5.24.tar.gz

這些tool 會install 在 /usr/local/bin,和原先的 tool 位置 (/bin) 不同。

OK !

可以到 openocd 下作 bootstrap,configure and make.

因為已經是在 mingw 下作,所以 configure 時不用加 CC="gcc -mno-cygwin"
只需要加 -enable-ft2232_libftdi


  1. configure 發生exception ,說找不到 linusb0.dll ,是因為沒有install libusb-win32 driver 的關係,download 那個有 "filter" 字樣的 libusb-win32-exe 下來 安裝就可以。
  2. bootstrap 發生 Can't locate object method "path" via package "Autom4te::Request" at /usr/bin/autom4te line 81.

    說明
    是說把 autom4te.cache 刪掉就可以。
    的確是這樣,刪掉之後,這個 error 就沒了,但是出現其他的 error。

    其實這是 autom4te 版本不一致的關係,安裝過新版的 automake 後就 OK 了 (就不會出現這個 error).

build openocd under mingw - with ftd2232 chip interface

(有 update 喔)
openocd 在 mingw 下 build..

先要 install mingw(gcc for win) 和 msys(unix shell for win)

因為安裝 msys 會尋問 mingw在哪,所以要先install mingw:

mingw 現在以經有像 cygwin那樣的網路安裝了,download MinGW-5.1.4.exe
http://sourceforge.net/project/showfiles.php?group_id=2435&package_id=240780

執行後就會出現問題,選安裝,然後而外的package 選 g++ 和 make..
之後就會 自己 download 和安裝完畢
我裝在 C:\MinGW
裝完後要手動把 c:\mingw\bin 加到 cmd 的環境變數。

這樣裝完後,就可以開啟cmd.exe,run gcc 了

但是要run make 和 bash file需要 msys。 download msys-1.0.10.exe
http://downloads.sourceforge.net/mingw/MSYS-1.0.10.exe

直接執行就可以,中途會問你postinstall,回 y。
然後問你有沒有 MinGW,回答有,並且把剛剛install MinGW的 path 寫出來
!!但是因為在 unix 中,目錄的左右斜線是相反的,要注意。
裝完後就可以在 programfile - MinGW- msys 啟動 msys 環境。



這個openocd 用 ftd232 (usb-232).
所以要 libftdi.a
libftdi.a 會用到 libusb.a

因為是 for windows 版,所以要dowload windows 版 libusb - libusb-win32-device-bin-0.1.12.1.tar.gz
http://libusb-win32.sourceforge.net/

下載的是bin 檔 (prebuild),所以把 usb.h copy 到 /mingw/include 把 libusb.a copy 到 /mingw/lib

還要安裝 libusb-win32 的 dll : libusb-win32-filter-bin-0.1.12.1.exe
http://sourceforge.net/project/downloading.php?group_id=78138&filename=libusb-win32-filter-bin-0.1.12.1.exe&a=96392657

這樣就可以 開始 build libftdi.a - download libftdi-0.15.tar.gz
http://www.intra2net.com/en/developer/libftdi/download.php

解開,到libftdi-0.15 下, /.configure 然後 make
會出現 error,但是 check 一下 error message,會發現 libftdi.a build 完,是 build example 時有 error,所以不管。

把 src/ftdi.h copy 到 /mingw/include
把 src/.libs/libftdi.a copy 到 /mingw/lib


最後就要 build openocd 了..

download trunk 的版本 (release 版支援的 cpu 比較少..)
解開, run ./bootstrap
./configure -enable-ft2232_libftdi CC="gcc -mno-cygwin"
make

4.17.2009

SD Register in SDBUS driver

MS SDBUS driver 的 SD Card Register Structure:
typedef struct _SDCARD_CARD_REGISTERS {
union {
UCHAR OCR[SD_OCR_REGISTER_SIZE]; // SD OCR
UCHAR IO_OCR[SD_IO_OCR_REGISTER_SIZE]; // IO OCR
};
UCHAR CID[SD_CID_REGISTER_SIZE]; // CID
UCHAR CSD[SD_CSD_REGISTER_SIZE]; // CSD
UCHAR SCR[SD_SCR_REGISTER_SIZE]; // SCR
}SDCARD_CARD_REGISTERS, *PSDCARD_CARD_REGISTERS;

在 \\WINCE500\PUBLIC\COMMON\OAK\DRIVERS\SDCARD\SDBUS\sddevice.hpp

這個variable 宣告在 CSDDevice 中:
    SDCARD_CARD_REGISTERS   m_CachedRegisters;      // cached registers

OpenStore is CreateFile.

原來OpenStore("Disk1") 就是 CreateFile("\\StoreMgr\\Disk1",,,);

在 PrivateCode看到的..

但是沒差呀...還是先要知道 Disk1 這個name..

加一些keyword 好了: read raw partition data in windows ce

火車

這次Engadget介紹的火車概念很有趣:http://www.tubularrail.com/background.htm.

不需要鐵軌,只需要一站一站的中間支撐。

他說,這是利用火車車體剛性的原理,就像一隻鉛筆,你可以把鉛筆伸出桌外1/2,鉛筆不會掉下去。

這個idea 他們叫: reinvent the wheel by removing it.

4.16.2009

CE: SDBUS, load SDIO Client Driver

source : \\WINCE500\PUBLIC\COMMON\OAK\DRIVERS\SDCARD

SDBUS 偵測到SD card 插入後,依據 SD card type load client driver (DLL) 的 code:

Slot-HandleAddDevice()
Device-SDLoadDevice()
DeviceFolder-LoadDevice()
ActiveDeviceEx( )

ActiveDeviceEx() 會把 DLL load進來,至於要load哪一個 DLL就要看 Registry 設定。

4.15.2009

plurk

用plurk後blog的文章真的少了 (其實本來也不多)。
因為一些簡單的,少量和bookmark性質的都丟plurk..

在MessageBox 中show 簡體

要show一個MessageBox,其中的Message是簡體。
但是show出來卻有一些是 ??

Loyal 說這是編輯器的問題,evc 把簡體中文顯示成??

但是evc中右眉辦法輸入中文,evc也沒 command line 模式。

所以?

偉大的Loyal 說,改成直接指定character value 好了..

TCHAR showstring[]={0x6546,0x8779,..0x00};
MessageBox(showstring);
這樣就可以了。

至於字串的內碼,可以貼到ultraeditor中,再用 HexMode開。

要注意的是,小Tony說,開始的0xFE, 0xFF是 encoding header,所以要忽略。

4.08.2009

acgenral.dll fault

安裝完 SP2 後,.偶而會出現 "Generic Host Process for Win32" Error。
是 acgenral.dll 發生。

查了一下,要安裝 KB958644 這個 update。

裝完後... 還不確定,到現在還沒發生...

4.07.2009

WPA, WEP in Windows XP

Windows XP 從 SP2 才支援 WPA 。
分辨的方法是在"搜尋到的 AP " 中,使用 WPA 的 AP,會有 (WPA)的標誌在後面。
所以直接輸入 密碼就可以。
換句話說,WPA, WEP是 Windows 決定的。
所以昨天的問題:FON的MyPlace 無法登入,是因為MyPlace 後方沒有(WPA) mark。也就是說,Windows 不認為MyPlace是用 WPA ,所以一直用 WEP 認證。

至於Windows 為什麼不知道 MyPlace 是WPA ?

或許是 FON 使用分裂 MyPlace -- FON_INTERNET 兩個 SSID的方式,Windows 不支援。
或者是..因為在 SP1 (還沒 update 到 SP2) 時,曾經搜尋過 MyPlace,並且連線失敗,所以之後就....