2009年10月2日 星期五

PING 8051 with DM9000 Ethernet

http://class.ruten.com.tw/user/index00.php?s=indiana_jones
I like to share with you how to ping 8051 by ethernet protocol,
It's basic ethernet protocol implementation, and it's not necessory to spend much money to practice it.
If you know How it works in ethernet and ping and TCP/IP protocol, then it 's much helpful to implement
others Internet protocol like UDP , TCP , telent, FTP and http ..
1. Base on my previous article, you should know how to move out from DM9000 a packet , and move in 
   a packt to DM9000 and transmimt it.
   FIFO move in/output is basic function.

2. We can know is IP or ARP from Ethernet header protocol, Then we can implement two function two
   branch this two different protocol.

3. We can easy to use Windows Commander, and type pin 192.168.0.200, then PC will send a broadcast command to etherent , our 8051 will get this packet from DM9000, then know PC is ask DM9000 MAC address. So DM9000 will reply and MAC address to PC.

4. PC will use new MAC address , and send ICMP packet to 8051.

5. When 8051 get new packet from DM9000, and know is IP packet not ARP packet.

6. 8051 will check the IP packet protocol, is ICMP or UDP or TCP and pass to ICMP protocol..

7. 8051 will know hte packe the ICMP request. then prepare another packet to transmit.

8. 8051 well prepare ICMP packet , then Pass back the IP layer .

9. 8051 will prepare IP header and add in front of ICMP Packet , then pass back to Ethernet layer.

10. 8051 move all of IP + ICMP packet and add ethernet header , then move into DM9000, and transmit.

11. PC will get this packet and show delay time.

You can see this, We using DOS windows ping command, to send ICMP packet to 8051+DM9000, Due to 8051 have eto calcute checksum, so it took some times delay ..


We show the meeasge in debug window when 8051+dm9000 got packet or send packet.


you also be able to use wireshark to capture packet, to know your transmit packet are correct or not .

http://class.ruten.com.tw/user/index00.php?s=indiana_jones
if you intersting this toy , you can buy it from this , or contact with me.
jones.hsu@gmail.com ..

2009年10月1日 星期四

PING 8051 Step 0 ( Keil Compiler Bug )

Sometimes you will never think about the bug is there , and hard to image that.
Yester I want to Implement PING function to 8051+DM9000B solution.
I can get a  packet from Ethernet with Broadcast command, but I can't get ICMP packet
Then I started to debug , why  ????

I try to look at the packet read pointer of DM9000, When I got first ARP packet and reply RARP to
Sender, and Sender re-send ICMP packet to me, but I will lost this packet.and there is two possibility:
1. The packet is not correct.
2. my MAC address has problem ..
3. Buffer overflow.

So I try to list down all of input buffer reader pointer, the packet pointer is work fine..
then I try to print it the value of My MAC address, and I found the problem is from My wrong
MAC address..

This is MAC address wirte function, it looks no any problem , is it ?

void dm9k_hash_table(void)
{
UC i;
        for(i = 0; i < 6; i++)
                 iow(DM9000_PAR + i, DEF_MAC_ADDR[i]);

        for(i = 0; i < 8; i++)
                  iow(DM9000_MAR + i, 0x00);
         iow(DM9000_MAR + 7, 0x80);
}

But I try to look at and assemeby CODE, then I got this :

; FUNCTION dm9k_hash_table (BEGIN)

; SOURCE LINE # 81
; SOURCE LINE # 82
; SOURCE LINE # 85

0000 E4              CLR A
0001 F500 R      MOV i,A
0003 ?C0016:
0003 E500 R      MOV A,i
0005 C3             CLR C
0006 9406          SUBB A,#06H
0008 500C         JNC ?C0017

; SOURCE LINE # 86

000A E500 R     MOV A,i
000C 2410         ADD A,#010H
000E 908000     MOV DPTR,#DM9000_Index
0011 F0             MOVX @DPTR,A
0012 0500 R      INC i
0014 80ED         SJMP ?C0016
0016 ?C0017:
0016 7400 R      MOV A,#LOW DEF_MAC_ADDR
0018 2500 R      ADD A,i
001A F8             MOV R0,A
001B E6             MOV A,@R0
001C 908001     MOV DPTR,#DM9000_Data
001F F0             MOVX @DPTR,A

now you should see the problem , Keil C optimize the function, and let separate two block
and only write a data .
So I modify the code as it ..

void dm9k_hash_table(void)

{
UC i;
      for(i = 0; i < 6; i++)
     {
           iow(DM9000_PAR + i, DEF_MAC_ADDR[i]);
      }
      for(i = 0; i < 8; i++)
    {
           iow(DM9000_MAR + i, 0x00);
     }
     iow(DM9000_MAR + 7, 0x80);
}

and I got assemebly as below :

; FUNCTION dm9k_hash_table (BEGIN)

; SOURCE LINE # 81
; SOURCE LINE # 82
; SOURCE LINE # 85
0000 E4              CLR A
0001 F500 R       MOV i,A
0003 ?C0016:
0003 E500 R       MOV A,i
0005 C3              CLR C
0006 9406           SUBB A,#06H
0008 5014           JNC ?C0017
; SOURCE LINE # 86
; SOURCE LINE # 87
000A E500 R      MOV A,i
000C 2410          ADD A,#010H
000E 908000      MOV DPTR,#DM9000_Index
0011 F0              MOVX @DPTR,A
0012 7400 R       MOV A,#LOW DEF_MAC_ADDR
0014 2500 R       ADD A,i
0016 F8              MOV R0,A
0017 E6              MOV A,@R0
0018 A3             INC DPTR
0019 F0             MOVX @DPTR,A

; SOURCE LINE # 88
001A 0500 R      INC i
001C 80E5        SJMP ?C0016

So be careful for coding ...

BR,Jones  joens.hsu@gmail.com

2009年9月27日 星期日

8051 and DM9000 First ARP Packet




Packet in = 0040
Packet Pointer = 3110
Packet Length = 0040
0000 FF FF FF FF FF FF 00 1F C6 37 5B 64 08 06 00 01
0010 08 00 06 04 00 01 00 1F C6 37 5B 64 C0 A8 00 67
0020 00 00 00 00 00 00 C0 A8 00 14 00 00 00 00 00 00
0030 00 00 00 00 00 00 00 00 00 00 00 00 84 7F F9 44

This is first packet which we get from DM9000, When Sender didn’t know target MAC address, sender will send this packet first to ask target MAC address who own this IP address.

a. Ethernet header: Dest MAC + Src MAC + Protocol
First 14 bytes were be define ethernet header, and  0806 is ARM protocol, 0800 is IP protocol.

b. Hardware type:  0001 is Ethernet, 0006 is Token Ring.
c. Protocol Type: 0800 is IP protocol.

d. Hard Address Length:  06 means it has 6 bytes address.

e. Protocol Address length: 04 means it has 4 bytes address.

f. Command: 0001 is ARP request command.

g. Source MAC address:
h. Source IP address:
i. Destination MAC address:
j. Destination IP address:

2009年9月12日 星期六

My New Toy

It's time to share with you my new toy.
Many years ago, I designed TCP/IP protocol in 8051 with AX88796 platform.
It let me upderstood how TCP/IP work, but it only my habit project ...

Now i like introduce it to you, if you interesting in this deisng , then you can follow me to learn
how to design it for your application ..

The Board is base on Megawin MPC82G516 1T 8051 and Davicom DM9000B .
I also put a microSD card connector on board, it can let you store your web page ,
or acqusition data.
If you interesting in it, you can e-mail to me or visit here , i will try my best to upload relative 
information in here ... 

2009年5月25日 星期一

網路通訊協定

1. Ethernet :
乙太網路, 將信號用NRZ 來編碼,並傳至遠方。在通訊的時候主要靠MAC address 來認定傳送封包的發送者或接收者,每一個封包最大1518 個Bytes.

2. MAC addrss :
  為六個BYTES 的數字,每一個乙太網路都需要有這個MAC address, 這六個Bytes 一般表示為 00:21:70:DD:D1:FA 每一Bytes 用冒號來區隔,並為16進制, 廠商可以跟IEEE 來購買此MAC address.

3.IP address:
在網際網路是用IP adress 來定址,此位址為四個Bytes 數字,一般表示為192.168.0.1,每個Bytes 用點號來區隔, 使用0~255 十進制來表示。IP address 在內網可以自己去設定,但是如果要連接WAN網際網路就必須跟ISP (Internet Service Provider)要IP.
我們平常用 ADSL撥號連接,中華電信就會發給我們一個IP address.

3. ARP 通訊協定
網際網路指只認定IP adrress , 但是假如我們是透過Ethernet來傳送IP封包 就必須先知道其MAC address, 此時我們可以透過ARP 封包來查詢此IP address的MAC address.

================== ================================================
在 Ethernet 的實作中當我們收到一個Ethernet 封包時,我們可以透過protocol type 可以得知
此ethernet 封包攜帶著IP 或ARP 或 RARP 的封包。
===================================================================

4. ICMP 通訊協定
我們常用ping ipaddress 來檢查遠方PC 是否有連線, ICMP 則定義了此功能,我們也可以利用此工具得知遠端電腦的反應速度與連線的狀況.

5. TCP 通訊協定
 在TCP通訊協定中定義了port 概念, 兩個bytes 合計65536 個ports, 這些ports 可以把它想像成水管的分支,並傳送給不同的通訊協定。列如port 80 就是HTTP service, Port20 就是FTP service. 但是大部分都是空的,只要兩端指定好就可以相互傳輸資料。TCP 通訊協定有一個重要的特性就是握手式傳輸機制。每一個TCP 封包會有一個Sequence Number 每經過一次傳輸就會將Sequence Number 累加, 系統可以檢查此number 來決定封包是否需要重傳。所以一般我們會說TCP 是必較穩定的傳輸協定,封包也比較不會不見。

6. UDP 通訊協定
 UDP 跟TCP 很類似,唯一的差異就是UDP 不具有握手式的傳輸機制,也就是傳完並不會檢查是否對方已收到所以可靠度就不高但是傳輸效率較高

===================================================================
在TCP/IP實作時,當我們收到一個IP封包時,可以透過IP 封包的欄位知道此IP封包所攜帶的是UDP、TCP還是ICMP的封包!
很多書把ICMP 的方包放在UDP與TCP 的上面, 但實際上已封包的角度來看她其實與 UDP/TCP 同一層...
===================================================================

2009年4月8日 星期三

TTL 的High 與Low

在數位電路中,我們常會用 Logic Gate 來設計,但是由於一般的Logic Gate 都是Push Pull 的結構,所以在設計上要特別注意:
1. 最好使用低電位輸出:在Push Pull 的結構因為high side 電晶體通常考量IC 設計的特性,並不會做大電流的輸出以避免增加IC layout 的面積,但是Low Side 電晶體卻可以承受比較大的電流流入。所以一邊在設計時通常我們會使用Active low 以保證Logic 可以有足夠的能力將輸出拉到low.換句話說,當輸出High 時,由於電流流出,如果此時負載很大,因負載效應他會把輸出倒拉下來此時我們就無法保證書出示不是真正的High.

2. Open Dran or Open collect 有線結及閘的特性,但因為沒有High Side 電晶體所以必須外加提升電阻,而此提升電阻的阻值必須依據實際連接狀況適當加以修改。

3. 雖然TTL input 在open 或沒用到的接腳可以floating ,但在實際電路設計時,強烈建議接到high 或low ,以避免雜訊產生。

4. 承第一點,除了ouput 設計成Low 動作以外我們也建議,在一般的情況,我們也是建議將input 設計成Active Low.

5. 有時序特性的元件,例如D-FF, JK-FF 可以善用RC 充放電的特性,沒用到的接腳加上RC ,以確保開機的啟始狀態。

6. 不同Power source 在互相連接時,最好加一個串聯電組,以避免使用IC 內部的電阻。

2009年4月7日 星期二

幾個電晶體的認知

1. 電晶體是放大器
以前剛開始學電子學的時後,老師總是告訴我們,二極體是PN 元件,只能單存做開關,而電晶體是雙極元件,所以可以做放大。以前也不會覺得有神麼奇怪,總認反正電晶體就是可以做放大器。但是你真正知道瞭解這個放大的意義嗎?在我們的認知中,我們會任為放大就是由小變大,但是各位是否曾想過,如果以物理的質能不滅定律,難道這個小變大的能量是無中生有的嗎?仔細看一下共射極放大電路就可以知道,這個能量是來自於Power Source,電晶體在這裡充其量只能說是一個輸出控制者爾以。

2. 電晶體的工作區
以前老師會教電晶體有三個工作區:飽和區、截止區與工作區,高職時候我們常計算放大率與增益,並總避免讓電晶體工作在飽和區與截止區。但是其實飽和區與截止區卻成為數位電路的基礎,因為電晶體的飽和區與截止區明顯的分別剛好可以用來表是數位電路的0 與1,也因為這樣我們在數位電路中,反而要避免電晶體工作在工作區。

3. 電晶體的VBE
如果電晶體工作在工作區,或應用在放大器電路中,檢查電晶體B,E 兩端是否為0.6V~0.8V,就可以知道電晶體是否有正常工作,所以如果你的擴大機不工作了,檢查一下電晶體的VBE 就可以知道電晶體是否已經燒壞。

4. 電晶體的電壓與電流放大
電晶體可以設計成共射極或共集極放大電路,共射級為電壓放大電路,共集極為電流放大電路,但是在一般根據我們前面所提,電流放大的source 是從power 所提供,所以若當電流放大時,必需選用能承受足夠大電流的電晶體。

2009年3月29日 星期日

差動Differential 的世界

以前念電子學做擴大機的時候,總會用差動放大電路來做前級,不但可以得到比較好的效能,抗雜訊能力也比較好。但是現在我們週遭已經很多產品或介面,利用差動的概念達到高速的傳輸的目的,舉凡USB,PCI-E,SATA,.....



差動應用在傳輸介面相當好用。早期的電腦,由於當時技術不好所以像RS-232 為了達到抗雜訊的能力,就把TTL 準位的的信號,轉成+-12V 的信號。這也就是為神麼PC 當初在訂定規格時還需要有+- 12V 的原因。(後來有些公司覺得負壓很麻煩所以就SWITCHing 的方式轉出+- 10V 的介面IC)。為神麼將TTL 準位的信號轉換成+-12V就可以抗雜訊呢? 舉例來說:如果在TTL 準位中受到2V 雜訊的干擾,讓信號到達臨界電壓,是無法判斷出高電位或低電位的,但轉換到+-12V 之後,就可以輕易分辨出高電位或低電位,但我們並不能一昧拉高電壓,因為半導體也有其最大電壓的設計,所以就有差動傳輸的概念出來。



差動就是利用CMRR共模的效果,透過兩條線(一對雙絞線)來傳輸,並使其絞線在一起,當雜訊來的時候他會同時在兩條線上,且會被互相抵銷,藉以達到抗雜訊的能力。注意:差動傳輸只能解決雜訊的問題,但是線長所造成的衰減是無法徹底解決,這部分必須靠驅動力與終端電阻才可以改善。



1. 最早的差動介面 RS-485, RS422

RS485 與RS422 是RS-232 的延伸應用,由於RS232 雖然可以有幾米的傳輸距離但若是要更遠距離的傳輸,因為線電阻造成的衰減,RS232並不適合遠距離傳輸。由於RS-485 可以將線長延伸到200M~500M 所以在工業界應用相當廣泛,單因為RS-485 只有一對絞線所以只能支援半雙工(就是同一時間只能做傳送或接收)。所以利用兩對信號的RS-422 也常被工業界所使用。http://focus.ti.com/lit/ds/symlink/sn75176a.pdf

在實務應用中,RS485,與RS422 終端電阻很重要,這個端終端電阻不但可以讓穩定電流回路,也有降低雜訊的能力。由時候此電阻也必須看整個BUS 的負載狀況加以調整。



2. CAN-BUS

Can bus 最早被應用在車用控制上,後來也被廣泛應用在工業控制上。最早支援的Can bus 的有Philips (NXP) SJA1000http://www.nxp.com/pip/SJA1000_3.html,目前也有很多MCU 以內建CAN bus interface.



3. Data Highway

Data highway 是CAN BUS 的延伸,只是走不同的通訊協定,傳輸接面是一樣的,常被應用在工業控制的PLC 中。



4. Camera Link

Camera Link 被應用在高速Line CCD 中,主要用於工業檢測。http://www.compumodules.com/pdf/CameraLinkOfficial.pdf



5. LVDS

並應用於LCD controller 與LCD panel 之間的傳輸介面。http://www.national.com/mpf/DS/DS90LV031A.html LVDS 傳送IC 內建了一個7 倍頻的PLL,當CLOCK input 為High 的時候送4 個bits 出去,當Clock input 為Low 的時候送3 個bits ,合計7 個bits。由於PLL 之後接收端無法同步這個新的Clock , 所以在LVDS 信號傳輸中,必須把CLOCK 也輸出到接收介面。

如果3 對LVDS 信號,合計可以傳送21bits , 在6bits Panel ( 18bits total in RGB) 加上LCD panel 的Hsync,Vsync,Data enable 。所以當要傳送24bits 信號時,則需要4 對LVDS 線及一對CLock 線,合計5 對線。

LVDS 介面由於將頻率產生7倍頻率,所以在速度上最高只能到85MHz ,如果要傳送1920x180P@60Hz 的信號必須使用兩組LVDS 介面才可以傳送。



6. DVI, HDMI

DVI 目前應用於VGA 卡 Monitor 的介面,由於傳統VGA 卡與Monitor 介面是Ananlog RGB 信號,以目前數位化的角度來看,VGA 卡做DAC 然後LCD monitor 再做ADC 反而效果更差,所以從VGA卡直接將新號輸出到monitor , 但因24bits 線材與效果不好所以採用類似LVDS 信號的方法將Pixel clock 做被頻,然後用串列的方式來傳輸,理論上倍的頻率越高,所能傳輸的資料量就越大,頻寬需求也越高。在DVI 信號中總計三對資料線,與一對Clock 線,合計四對線。



HDMI傳輸介面是DVI 介面的延伸,都是使用4 對線,唯一的差異就是HDMI 將Audio 也放到這資料中。



7. Ethernet

Ethernet 可以說是最早將差動信號應用在資料通訊上。在Ethernet 中使用兩對線,Tx+,Tx-,RX+,RX- 組合成全雙工。

AT91SAM9263 VGA output to Monitor




在工業控制的場合中,我們常需要Monitor 的輸出,來顯示使用者控制介面,
但因為AT91SAM9263EK 只有連接一片240x320 LCD Pnael,所以我們將LCD 介面的信號拉出來並接一個Video DAC 將LCD 信號轉換成Analog RGB 2的VGA 信號。

其實任何顯示裝置只要是利用掃瞄的方式,其基本的公式即為:
Pixel Clock = H total * V total * Frame Rate

其中 H total = H active + H sync width + H front porch + H back porch
V total =V active + V sync width + V front porch + V back porch

所以一般我們所看到640x480 即為active area (或View area) 其他的都是看不見的區域,那為什麼要這樣做呢,主要的原因在於傳統CRT 螢幕。因為利用電子束來掃瞄所以才會有同步的問題,也因此需要反馳的時間。

Blinking = H sync width + H front porch + H back porch

另一個名詞就是blinking , 當電子束反馳的時候我們不希望看到不該出現的電子束出現,通常我們會產生遮脈信號把輸出給關閉,這個信號我們也稱為Data Enable,真正要輸出的時候為High,其餘時間皆為Low.






很多LCD panel 不需要Hsync 與 Vsync 單靠Data Enable 就可以正確解出Hsync 與Vsync, 而monitor 就沒有Data enable 只有Hsync 與Vsync。聰明的你也許會問,VGA 卡送出HV 時,由於Monitor 不知道位置,且sync 裡面還有 sync width,front porch, back porch, monitor 怎樣決定Active 的起使位置呢?而VESA 就是在規範這些,而大部分LCD monitor 也會有Auto 的機制來偵測畫面的起使位置。

在有些ASIC 中,LCD controller 通常會有一個獨立的PLL 來產生pixel Clock,與真正data 處理的頻率是不一致的,這當中會透過FIFO memory 來中介,所以我們不能認為只要設定好 active, sync width, front porch & back porch,就會得到所要的頻率,通常Pixel clock PLL 都必須設定一個接近的值,因為這樣的除法器通常會有除不盡的現象。
所以上面的公式就很重要,否則出來的換面部會正確!
Pixel Clock = H total * V total * Frame Rate.

在Embedded system 中,我們不需要向PC 可以支援不同的timing, 大部分我們只需要支援單一解析度或單一timing 就可以了!
參考一下這個Web Site 可以知道VESA timing 有哪些了。
http://tinyvga.com/vga-timing
VESA 是一個Monitor 的標準制訂協會,只要是VESA 制訂的timing 大部分monitor 都可以正確的顯示出來。


AT91SAM92的Display LCD controller 的Clock source 是來自於MCLK.
而MCK的頻率則由 Crystal 產生與PLLA做倍頻而來。由於此PLL頻率供給SDRAM re-flesh timing,且AT91SAM9263 最高的執行頻率為240MHz, 而MCLK 頻率的範圍為48~120MHz, 但在LCD Controller 模組也有一個除頻器,公式為:
Pixel Clock = MCLK/((CKVAL+1)*2)
所以我們可以視為此除法器只能支援/2, /4 或/6 ..
在AT91SAM9263EK 的Crystal是 16.36766MHz, 二在我們的板子上是18.432MHz. 所以PLL 的設定也有一些不一樣!
詳細改的地方如下:
1. BootStrap V1.11
#define CRYSTAL_18_432MHZ 1
//#define CRYSTAL_16_36766MHZ 1
#ifdef CRYSTAL_18_432MHZ
#define MASTER_CLOCK (237568000/2)
#define PLL_LOCK_TIMEOUT 1000000
#define PLLA_SETTINGS 0x2073FF09
#define PLLB_SETTINGS 0x10483F0E
( Bootstrap-v1.11/board/at91sam9263ek/dataflash/at92sam9263ek.h)




PLLA 的設定為 73Hex 所以得到CPU Clock 為237.568MHz, 而Master Clock 為118.784MHz。所以我們把Master Clock 除四,就會得到 29.696MHz 的Pixel clock ,而pixel clock 的公式為 Pixel Clock = Master clock / (n+1).當然可們也可以選擇 n 為零,即除2, 但這時候,我們會選擇較高的master Clock 頻率,以得到比較好的Performance.

另外AT91SMA9263 支援兩個EBI Bus, 我們在EBI0 由SDRAM 及Flash 來使用,EBI1 我們加了一個SRAM 來當Display 的Frame Buffer 已經低系統對Memory 的頻寬,所以在BootStrap 我們必須把此SRAM Initial 完成,以讓U-Boot 可以使用此Memory.

void hw_init(void)
{
..
writel(readl(AT91C_BASE_CCFG + CCFG_EBI1CSA) (1 << color="#cc33cc">(Bootstrap-v1.11/board/at91sam9263ek/at92sam9263ek.c)
這裡改完之後,當U-boot Access 0x70000000位址時,9263 即會連結到此SRAM。

2. U-Boot1.3.4
改過BootStrap 之後,u-boot 還必須再改一次,U-boot 會再把一些所使用到的週邊重新再Initial 一次。第一步要先改的是Master clock 與CPU Clock:
#define AT91_MAIN_CLOCK 237568000 /* from 16.367 MHz crystal */
#define AT91_MASTER_CLOCK 118784000 /* peripheral = main / 2 */
(u-boot-1.3.4/include/configs/at91sam9263ek.h)

接下來要改的是 GPIO , 原本AT91sam9263 是連接LCD Panel, 所以要接Video DAC 到Monitor , 就必須有H(水平),V(垂直)sync(同步信號)。
static void at91sam9263ek_lcd_hw_init(void)
{
at91_set_A_periph(AT91_PIN_PC0, 0); /* LCDVSYNC */
at91_set_A_periph(AT91_PIN_PC1, 0); /* LCDHSYNC */
// For VGA output need to enable HV sync
// For some also need to enable some panel not necessory
at91_set_A_periph(AT91_PIN_PC2, 0); /* LCDDOTCK */
..
}
(u-boot-1.3.4/board/atmel/at91sam9263ek/at91sam9263ek.c)




在AT91SAM9263-EK 中,LCD controller 接了一片240x320 的LCD Panel,因其解析度小,所以所需的Frame Buffer 也不需要太大,所以使用Internal 的SRAM 80K 就可以當Frame buffer。Frame buffer 所需要的空間計算公式如下:
Frame buffer = Hwidth * Vheight * bpp
#ifdef Enable_EBI1_SRAM
gd->fb_base = 0x70000000;
#elseif
gd->fb_base = AT91SAM9263_SRAM0_BASE;
#endif



(u-boot-1.3.4/board/atmel/at91sam9263ek/at91sam9263ek.c)

所以我們把Frame buffer 設定在0x70000000 EBI1 的SRAM 上!當然你必須找一的地方把 Enable_EBI1_SRAM #define 成1 或直接改成 gd->fb_base = 0x70000000;

再來就是真正Panel timing的部分,為了得到比較好的執行效率我們把Master Clock 拉到比較高的地方(限制在48~120MHz)所以就沿用前面的Master Clock ,但是這個頻率並不是VESA Standard 的標準頻率,所以要是所接的是LCD monitor , 可能會有Jitter 產生(原因是我們DAC 的頻率,與LCD Monitor 的ADC sampling 的頻率不一致所產生,如果要真正解決這個問題可以依據VESA standard 的頻率來設定PLL 的頻率與Master Clock)
vidinfo_t panel_info = {
vl_col: 640,
vl_row: 480,
vl_clk: 29696000,
vl_sync: ATMEL_LCDC_INVFRAME_INVERTED,
vl_bpix: 3,
vl_tft: 1,
vl_hsync_len: 44,
vl_left_margin: 74,
vl_right_margin: 30,
vl_vsync_len: 2,
vl_upper_margin: 21,
vl_lower_margin: 0,
mmio: AT91SAM9263_LCDC_BASE,
};
(u-boot-1.3.4/board/atmel/at91sam9263ek/at91sam9263ek.c)


3. Linux 2.26.27




static struct resource lcdc_resources[] = {
[0] = {.start = AT91SAM9263_LCDC_BASE,
.end = AT91SAM9263_LCDC_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,},
[1] = {.start = AT91SAM9263_ID_LCDC,
.end = AT91SAM9263_ID_LCDC,
.flags = IORESOURCE_IRQ,},
[2] = {.start = 0x70000000,
.end = 0x700BB800,
.flags = IORESOURCE_MEM,},};
(Linux-2.6.27/arch/march-at91/at91sam9263_device.c)
在LCD 的resource 加入Frame buffer 的resource,讓Linux kernel 可以使用 EBI1 上的SRAM 當Frame Buffer.
當然Kernel 在還是必須將 Vsync 的GPIO 設定一次,但是依據經驗不做也可以,因為U-boot 已經Initial 過了!
void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data)
{
if (!data)
return;
at91_set_A_periph(AT91_PIN_PC0, 0); /* LCDVSYNC */
at91_set_A_periph(AT91_PIN_PC1, 0); /* LCDHSYNC */
at91_set_A_periph(AT91_PIN_PC2, 0); /* LCDDOTCK */
..
}
再把AT92SAM926EK 的PLL 在設定一次
static void __init ek_map_io(void)
{
/* Initialize processor: 16.367 MHz crystal */
/*at91sam9263_initialize(16367660);*/
/* Initialize processor: 18.432000 MHz crystal */
at91sam9263_initialize(18432000);
..
}
接下來就是Kernel LCD controller 真正timing 的部分,這裡的結構與U-boot 不太一樣,需要設定re-flesh rate, 其他的參數也與u-boot 相同!
static struct fb_videomode at91_tft_vga_modes[] = {
{
.name = "Monitor Output @75Hz ",
.refresh = 75,
.xres = 640, .yres = 480,
.pixclock = KHZ2PICOS(29696),

.left_margin = 74, .right_margin = 30,
.upper_margin = 21, .lower_margin = 0,
.hsync_len = 44, .vsync_len = 2,

.sync = FB_SYNC_VERT_HIGH_ACT,
.vmode = FB_VMODE_NONINTERLACED,
},
};
(Linux-2.6.27/arch/march-at91/board-sam9263ek.c)
後記:
Pixel Clock = H total * V total * Frame Rate.
Video 的公式很重要,但三個變數我們怎麼來訂定呢?
在一般的情況我們會先選定Frame rate , 通常我們會選擇60Hz timing, 因這為個timing 不管CRT,LCD 或LCD panel 都可以支援,然後Vtotal , 然後pixel clock 有了這三個參數,我們就可以得到H total。但是在這裡由於AT91SAM9263 的PLL 不是那麼好調,能選到的頻率還必須顧及UART baud rate與執行效率,所以我建議先選pixel Clock有可以接受的執行效率, 看接近哪一個timing, 就用那一個timing 來design ,這麼做會比較保險。

2009年3月19日 星期四

Digital Audio I2S & SPDIF

很多人對於Digital Audio 的介面總是搞不清楚,常常不知怎麼Debug ...

在Digital audio 的介面中常用的 I2S , SPDIF , Fiber Optical, Coaxial ...
在此我們把他們分為機器內與機器外:
1. 機器內:I2S
2. 機器外:SPDIF (有光纖與同軸兩種不同介面)。

I2S 是Philips 與Sony 制訂的規格,信號共有三條:
Bit Clock, Data it or Out, Word Strobe..

當我們對一個單音信號做ADC 轉換時,各位都知道有取樣頻率與解析度的問題,而根據取樣定理,取樣頻率必須大於信號變化頻率的兩倍,以人耳可以聽到20Hz~20KHz 而言,一般40Khz 的取樣頻率就可以得到接近不失真的取樣。在目前我們常用的取樣頻率大部分是44.1Khz , 及48Khz。
如果取樣頻率為48KHz, 則我們會在Word strob 量到48KHz , 因為Word Strobe 的High 代表右升到,Word 為LOW 時代表左聲道,所以假如我們要做左右聲道對調是,只要把Word Strobe 反向就可以了。早期ADC 轉換的IC 有些是16bits , 有些是18bits , 後來漸漸統一,最近的IC 大部分是20 bits .. 為了能向下相容所以大部分IC 會在每一個sample 送出32 bits 的空間,以解決bit 數不一的問題,但是這也帶來另一個問題,到底MSB,LSB 怎麼放的問題。在實際上我們建議實際去上定看看,聲音正常代表設定就正常。
在Debug I2S 時我們從上面我們就可以知道bit clock 為Word Strobe 的64 倍,data bit 如果有播放聲音則會呈現不規則狀態,只要確認信號上的Level 足夠就好了。
在I2S 有分Master 與Slave , 很多人也是搞不清此,以為ADC IC一定是Master , DAC IC 一定是Slave , 答案是錯的。大部分DAC 都是Slave 沒錯,但ADC 不見得一定工作在Master mode。有一個簡單的口訣,當Master 必須送出Word Strobe 及Bit Clock , Slave 的Bit clock ,及word strobe 一定必須設定成輸入。
既然I2S 是在機器內IC 與IC 之間的連接就會有取樣頻率不一樣的問題,ADC 工作於96KHz , DSP 工作於48Khz 這是很常見的,這個時候就必須要有SRC (Sampling Rate converter ) ,將96Khz 轉成48KHz , 這樣的SRC 也是有好壞的分別,如上96Khz 轉成48Khz , 最簡單的作法就是將96Khz 的資料丟掉一半,並將Word Strobe 除2 , 其實他們原本的48Khz 沒神麼兩樣,最好的當然是補償除2 囉!

SPDIF 介面將I2S 做一延伸,為了達簡單連接的的傳輸,所以他吧I2S 的data 做bi-phase 的調變,但基本去樣的原則跟I2S 是一樣的。
SPDIF interface 可以接收32K~192K frames/per second ..意似就是說一秒鐘傳32~192K 個聲音封包, 這個值跟audio I2S 的samling clock 是一樣的, 所以我們可以把spdif 的速度看成audio 的取樣速度。這個取樣頻率就等於I2S Word strobe 的頻率。
在I2S 中因為Word Strobe 有high/low , 所以可以知到是左聲道還是右聲道,但在SPDIF 內,則把每一個frame 分成兩個Sub-Frame, Sub-Frame1 & Sub-Frame 2,每一個Sub-frame 為32 bits ,
這32 bits 包含4bits 旗標, 20bits audio sample , 4 bits 輔助位元4bits 同步偵測位元。
V : Validity bit
U : User bit
C : Channel bit
P : Parity bit
這些flags 每秒會有192bits, 24bytes, 詳細可以參考附件。
另外因為SPDIF 經過bi-phase 的調變,所以用示波器並沒辦法問定的trigger, 可以用頻普分析儀,量到其中心頻率,依據bi-phase 的原理應該是Sampling rate 的兩倍頻率。
如果是48Khz 的sampling rate,則為48Khz * 64*2 = 6.144MHz ..
如果是192KHz 則為 192KHz *64*2 = 24.576MHz
... 不知道怎樣放附件....
Wolfson SPDIF receiver IC spec http://www.wolfsonmicro.com/products/WM8804/
Cirrus logic application note http://www.cirrus.com/en/pubs/appNote/an22.pdf

2009年3月10日 星期二

QT4.5 嘗鮮







1. 下載QT 4.5 for embedded Linux http://www.qtsoftware.com/downloads/embedded-linux-cpp
2. 利用Winscp 複製到Linux 你所建立的root system source code.
3. tar -zxvf qt-embedded-linux-opensource-src-4.5.0.tarqt-embedded-linux-opensource-src-4.5.0.tar
4. cd qt-embedded-linux-opensource-src-4.5.0.tar
5. 檢查一下 qt-embedded-linux-opensource-src-4.5.0.tar/mkspecs/qws/linux-arm-g++/qmake.conf 是不是你所使用的tool chain.
6. ./configure -xplatform qws/linux-arm-g++ -embedded arm -qt-zlib -prefix /qt4 -no-rpath -depths 16,15 -qt-mouse-tslib -I /usr/atmel/arm9.busybox/src/tslib-1.0/install/include -L /usr/atmel/arm9.busybox/src/tslib-1.0/install/lib
重點:利用qt 內的zlib 不要自己編zlib, 16代表支援565 的色盤,15 代表支援555的色盤。
7.make
我用E8400 跑3.2G編了45分鐘左右所以耐心等候。
8. make install
這個也需2~3 分鐘....
9.完成後在/qt4 會有此目錄
10. cd demos/mainwindow
利用arm-linux-objdump -p mainwindow 查詢main 所需的動態Library
NEEDED libQtGui.so.4
NEEDED libts-0.0.so.0
NEEDED libpng12.so.0
NEEDED libQtNetwork.so.4
NEEDED libQtCore.so.4
NEEDED librt.so.1
NEEDED libdl.so.2
NEEDED libpthread.so.0
NEEDED libstdc++.so.6
NEEDED libm.so.6
NEEDED libgcc_s.so.1
NEEDED libc.so.6
在所編譯完成qt4/lib 下,將以上的檔案複製到root file system 目錄下的Library. 並使用連結的方式連結到此library.例如:我們可以複製LibQtCore.so.4.5.0 到目錄下,然後
ln -s libQtCore.so.4.5.0 libQtCore.so.4.0



11. 在/install 目錄下建立/qt4 的目錄,並建立/qt4/bin, 與/qt4/lib



12. 將/qt4/demos/下的執行檔複製到 /install/qt4/bin, 將所需的library 複製到/install/qt4/lib



13. 在/install/qt4/lib/ 建立fonts 目錄,複製c0419bt_.pfb,DejaVuSans-Oblique.ttf到此目錄.
11 重新將root system 包裝成Jffs2 ..



13. mkfs.jffs2 -n -p -s 0x200 -e 0x4000 -r install/ -o rootfsts.jffs2
0x200 是 page size, 0x4000 是 erase block size.



2009年3月8日 星期日

NT9263 與 tslib porint 的問題點

在做tslib 時有一些小東西要注意,因為這些問題造成好幾天失眠:
1. share library 的問題:
當初我開始build root system 時因為沒注意shared library 與static library 的問題,所以一直弄不出來,每次都是kernel panic .., 後來我把build 成static library 就開成,那時候真的很高興。
後來就沒有去注意這件事。但當我把tslib build 完之後, 去發現我的ts_calibrate 怎麼都不會變成綠色,也不能執行,每次都出現command not found ...
在google 上也找了很久,好像也沒有發生這樣的問題,真是 ...為神麼學長build 出來的就能跑我build 出來就不能跑難道....

後來我吧busybox 又重新builde 了一次shared library ,tslib 就可以正常跑起來了。

2. 當ts_calibrate 跑起來之後問題又來了,執行時出現Segamentation fault , 然後網路上也沒正解,後來找了好久找到了一篇, 才發現原來是我雞婆在/etc 建立了一個pointercal 的目錄,
拿掉之後就可以正常執行了。

3. ts_calibrate 可以執行後,發現怎麼怎麼ts_calibrate 沒有等我按就五點跑完了,看起來是tslib 收到了不該收到的東西。ts_test,ts_print 也都不正常。也是找了好久才發現原來event 1 要跟input 1 對應,原本的程式都是對應到event0, 及mknod event0 c 13 64 ..
看了一下kernel 的文件才發現,65 才是對應到event 1, ts_calibrate ,ts_test .. 都是event0 , 所以都必須修改,鼻子摸著,重來一次...

4.這次真的可以執行了,ts_calibrate 的游標停在第一點但是完全不bird 我,不管我輕輕按或用力按就是無動於衷,搞了一個通宵之後,把示波器也搬出來了看一下ADS7843 輸出的波形,奇怪照公板抄怎麼就是不會動。

5. 想了另一個辦法,下載Atmel software package , 還好新的V1.5 有支援touch Screen .. 把他改到我的板子上去。結果還是一樣,都是卡在第一點,ADS7843E的PenIRQ 固定都會產生兩個pulse , 整個信號一直有ground 的產生, 真是忍無可忍,把touch panel 的connector 拆掉....然後再是一次。
6. 說也奇怪,整個touch panel 的動作正常了,真是圈圈叉叉...
下次真該improve 一下,我的焊接技術...

TSLib 在 AT91SAM9263 的Porting

在NT9263 的板子上跟AT91SAM9263-EK 的板子一樣都有一個ADS7843E 來做觸控螢幕的ADC 轉換,ADS7843E 再透過SPI interface 連接到AT91SAM9263.

1. 首先下載最新的tslib 從http://tslib.berlios.de/

2. 在 tslib tar 到你要工作的目錄中(通常是target root source 的子目錄)..

3. 檢查一下Fedora 或ubuntu 系統是否已經安裝了libtool, 及automake

在Fedroa9 下 用yum install libtool, yum install automake

在ubuntu 下用 apt-get install libtool, apt-get install automake

4. 執行 sh autogen.sh

5. $./configure --prefix=$PWD/install CC=arm-linux-gcc --host=arm-linux

這時會產生rpl_malloc未定義的錯誤

6. $./configure --prefix=$PWD/install CC=arm-linux-gcc --host=arm-linuxac_cv_func_malloc_0_nonnull=yes

7. 檢查一下Kernel 系統是否已經將ads7846 driver 選上了,及 Event drive 也開啟了,
若要能成功驅動觸控螢幕,必須確定兩者都選上。若一切都正確linux kernel 會送出如下的字串:
----------------------------------------------
input: gpio-keys as /class/input/input0 ( 這是one 不是o)
ads7846 spi0.3: touchscreen, irq 31
input: ADS784x Touchscreen as /class/input/input1
------------------------------------------------------
搜尋 /test 目錄下的ts_calibrate ,ts_test, test_print,ts_print_raw,ts_harvest 內的event0 的字串,並將其修改成event1, 因為kernel 已經將touch screen 設定成 input1, 如果你的系統是input 2, 你必須改成event2.(這裡很重要,網路上大部分都沒有提到這個)

7. make

8. make install

9. 編譯完成後會自動產生/install 的目錄,我們必須將其複製到系統跟目錄中
bin/ : ts_calibrate, ts_test等校正、測試程式
lib/ : tslib的動態與靜態library
lib/ts/: tslib外加支援的touch screen module
etc/ : tslib的configuration file
10. 建立驅動程式節點
在跟目錄系統 /dev 下建立/input 目錄 mkdir input
並在/input 下 建立一個device 節點 mknod event1 c 13 65 (表示char , input 型的device Driver,
64 代表input 0, 65代表input 1, 這個數字也必須參考linux kenel document 才可以得知)。
11. 修改ts.conf 並複製到系統跟目錄中 /etc 下。
module_raw input
module pthres pmin=1
module variance delta=30
module dejitter delta=100
module linear
12. 修該/etc/rc.d/rc.init 讓 system 可以在開機後自動執行tslib
export TSLIB_TSDEVICE=/dev/input/event1
export TSLIB_CALIBFILE=/etc/pointercal
export TSLIB_CONFFILE=/etc/ts.conf
export TSLIB_PLUGINDIR=/lib/ts
export TSLIB_FBDEVICE=/dev/fb0
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/lib
要特別注意,pointercal 是會自動產生的程式,不需事先建立,事先建立的話會產生Segamentation fault.

13. 使用arm-linux-objdump 來看ts_calibrate,ts_test.. 所使用到的動態連結程式庫,
有些版本可能與你用的版本可能不合,可以使用ln 來做連結會比較解省記憶體:
compiler 之後 :libts-0.0.so.0.1.1
我們用 ln -s libts-0.0.so.0.1.1 libts-0.0.so.0
ln -s libts-0.0.so.0.1.1 libts.so
14. 最後將整個root system 打包成ext2 或Jffs2 都可以!大功告成。

最後要感謝學長助教的幫忙,各位也可以參考他的大作:
http://nabeko-notebook.blogspot.com/