顯示具有 Note 標籤的文章。 顯示所有文章
顯示具有 Note 標籤的文章。 顯示所有文章

2013年4月30日

[Note] Ping協定

大容量輸出(Bulk-out)與控制輸出(Control-out),適用於「Ping協定」。輸出的含意是指從主機端送往裝置端。

「Ping協定」的出發點就是防止長時間大量資料傳送完畢之際,對方竟然傳回NAK信號,要求重新送一次。如此的狀態就代表著介面被佔掉的時間,成為浪費,介面的使用效率不佳。因此,才會規範了這個協定,期待可以提升介面匯流排的使用效率。

他的機制是這樣子的:主機端在傳送64個位元組(如Control Out傳送)或是512位元組(如Bulk Out傳送)的資料到裝置端之前,先行由主機端送出「Ping封包」,觀察其回應是ACK還是NAK,用來確認裝置是否準備就緒。這個概念與網路上的Ping指令是一致的思維。

規格書中,為了詳細描繪「Ping協定」的動作,利用了狀態遷移圖的方式,對主機端的狀態遷移以及HS快速裝置的狀態遷移,有很清楚的交代。

以主機端狀態遷移圖為範例來說,當送出「Ping封包」之後,如果得到NAK的場合,表示裝置端沒有接收的空間,如果執意地將DATA0/1封包丟往裝置端,很有可能的結局就是依然得到NAK的否定確認回應。因此,圖4的主機端狀態遷移圖,顯示如果送出「Ping封包」之後,得到NAK的場合,並不會傳送「OUT封包」以及「DATA封包」,而是再度傳送「Ping封包」,重複確認。

這就是「Ping協定」的基本精神。

接著下來,利用一個具體的實際範例來闡明「Ping協定」動作的細節。

請留意,從主機端送往裝置端時,使用放大鏡來觀察其細部的話,其走過的足跡卻是,從主機端經過USB介面匯流排,到達快速裝置的控制器,再經過裝置內部的局部匯流排(Local Bus),就可以到達讓裝置動作的韌體。其關連性是相當廣泛的。

以大容量輸出傳送(Bulk Out)來說,USB 2.0的主機端(通常是個人電腦),通常是針對裝置端控制器內的特定端點,傳送512位元組的封包。而裝置端控制器的接收端點,一般是利用兩個512位元組的FIFO(FIFO是First In First Out的元件,通常,是作為緩衝的用途)。

當緩衝器接收完主機端送過來的資料之時,會告知裝置內部的韌體,接收封包已經備妥。如此一來內部的韌體就會藉由局部匯流排,實行將緩衝器的資料傳送到系統的記憶體之中。資料傳送完了之際,會通知控制器,那麼控制器就可以騰出緩衝器的空間來。基於這樣子的思考,HS快速裝置,如何來達到介面匯流排使用的最高效率,就是不產生NAK、NYET的情況下,「OUT封包」、「DATA 0/1封包」以及「ACK」的順序遞送。這樣子的時間,有機會是“9.5 us”的光景。

所以,對於一個工程人員來說,韌體撰寫的應答時間以及資料處理時間,該如何地最佳化,是HS快速裝置設計者,要好好下功夫的一道習題。也是重要的一個環節。

2013年4月1日

[Note] USB Device Enumeration Process


<Power Stage>
Device pull high to 3.3V
D+ : Full Speed (High Speed)
D- : Low Speed
Get Port Status Command to hub
Set Port Feature
Reset Device (Pull D+,D- low for 10ms)
Detect full/high speed use chirp J/K
Chirp J : D+
Chirp K : D-
High speed device send Chirp J, Host respond chirp JK to notice device ok.
<Default Stage>
Get Port Status – to see if reset complete
Get Descriptor (Device Type)
Reset
<Address Stage>
Set Address
Get Descriptor
(Device Type) 




2012年12月19日

[Note] HID - Human Interface Device




HID - Human Interface Device
 1. Interrupt IN transfer is necessary in HID
 2. Input Report is also necessary, but Output and Feature Report is optional
 3. Feature reports always use control transfers and are optional
 4. If bInterfaceSubclass = 01h, the device supports a boot interface. A HID with boot interface can communicate with the host even when the host hasn't loaded its HID drivers.
     5. If there is no Report ID item, the report used the default ID of 00h

(Picture from USB bible "USB Complete")






2012年12月9日

[Note] USB firmware development note

1. Host 要求data前,要先將Data放入endpoint的buffer中,中斷發生是通知韌體可以繼續放入下一筆資料,如果認為在提供資料前等待中斷,也許中斷永遠都不會來臨
2. All Control Transfer must have SETUP/STATUS phase, but DATA phase is not necessary.
    The control transfer without DATA phase can be referred to as Control Write.
3. First data in data phase of control transfer is DATA1, the one in setup phase in DATA0
4. Interrupt Transfer中,資料請求必定為Host所送出
5. HUB上有pull-down電阻,Device上有pull-high電阻,Full Speed Device為D+, Low Speed Device在
    D-上,HUB利用D+/D-電壓來監控是否有Device插上,在Host Reset Command(Set Port Feature)
    後,Device會把Pull-up電阻移走,改接上終端電阻(利用Device FW去對USB_enable pin做控
    制,也必須有額外的硬體電路)
6. Control Transfer中如果命令不被裝置所接受,裝置會回應STALL來告知HOST。但是在SETUP
    階段裝置必須回應ACK,因此STALL是在Data或Status回應。盡可能在Data階段回應。
7. Normally a SOF packet (at full speed) or a Keep Alive signal (at low speed) is sent by the host every 1 ms, and this is what keeps the device awake.

[Note] USB2.0 Transfer Architecture

今天整理了一個USB Transfer的架構圖~

Transfer Mode       Data Transaction                 Phase (Packet)
----------------------------------------------------------------
Control Transfer     Setup Stage                        Token   - PID/ADDRESS/ENDPORINT/CRC
(控制傳輸)            (設定階段)                             Data   - PID/DATA/CRC
                                                                            Handshake   - PID
                              --------------------------------------------
                              Data Stage                            Token
                              (資料階段)                             Data
                                                                            Handshake
                              --------------------------------------------
                              Status Stage                         Token
                              (狀態階段)                             Data
                                                                            Handshake
----------------------------------------------------------------
Bulk Transfer         IN/OUT                                Token
(大容量傳輸)       (One or More)                        Data
                                                                            Handshake
----------------------------------------------------------------
Interrupt Transfer   IN/OUT                                Token
(中斷傳輸)           (One or More)                        Data
                                                                            Handshake
----------------------------------------------------------------
Isochronous Transfer   IN/OUT                          Token
(等時傳輸)                 (One or More)                  Data
                                                                            Handshake
----------------------------------------------------------------

1. Control Transfer:

USB中最基本的傳輸單元是Packet,而一筆Transaction則由Token/Data/Handshake 3個packet所構成。 由下面這張Control Transfer的USB trace我們可以看見實際USB運作的情況~與上面的表格去做對應。


圖中Transfer#80為一個Control Transfer,可以進一步拆解成三個Transaction分別為Setup(#49046)/Data(#49048)/Status(#49382),而每一個Transaction又可以再進一步拆解成三個packet(Token/Data/Handshake)。




上圖是一個Token Packet,我們可以看到在一個Token Packet當中主要構成的元素有:
Packet Sync/ PID/ Address/ ENDP/ CRC這五種
1. Packet Sync - 一串K-Chirp,J-Chirp組成,同步封包使用
2. Packet ID - 用來告知Device這次傳送的packet的目的功能是甚麼,常用的有setup/in/out/ack/data0/data1/nack等
3. Address - Device的位置
4. ENDP - 在位置之外,更清楚的標明所要傳送或接收對應的endpoint編號
5. CRC - 錯誤檢查碼



上圖是一個Data Packet,Data Packet構成的元素與Token Packet大同小異,主要有:
Packet Sync/ PID/ Data0/ (Data1)/ CRC這幾種
1. Data0 - Control transfer中的Data phase傳送了8 Bytes的Data,可以分成五個欄位
 => bmRequestType (1 byte) : 命令式樣,資料方向與命令接收對象
           bit7 -> 資料方向。 OUT/沒有Data phase為0,IN為1
           bit6:5 -> 命令式樣。00:標準命令,01:USB device class command,10:廠商自訂命令
           bit4:0 -> 命令接收對象。00000:裝置,00001:機能介面,00010:Endpoint,00011:其他。
 => bmRequest (1 byte) : 命令碼
 => wValue (2 bytes) : 命令相依資訊
 => wIndex (2 bytes) : 命令相依資訊
 => wLength (2 bytes) : 資料階段傳送或者接收的位元數。IN的場合,指最大值


最後是Handshake Packet格式,顧名思義Handshake封包中會利用PID來表示傳送的狀況,
可能會有ACK/NAK/STALL/NYET/ERR等幾種不同的Handshake封包

2012年12月7日

[Note] Cortex-M3 NVIC interrupt priority 基本觀念


     當我們在使用STM32中的NVIC中斷時會發現,中斷的優先等級分成了preemption priority (可搶奪優先等級)與subpriority(副優先等級)兩種,當我們在設定每一個interrupt channel的時候都必須設定這兩組數值。
     到底這兩優先等級有甚麼不一樣:

1. Preemption Priority
    當中斷發生時,擁有較高Preemption priority的interrupt channel可以將較低preemptrion priority的interrupt chnannel打斷優先被處理。假如兩個interrupt channel擁有相同peemption priority,則不會發生中斷被打斷的情況發生,後到的interrupt event必須等到現有的中斷被處理完畢後才能被處理。
 
2. Subpriority 
     在兩個interrupt channel的preemption priority相同的前提下,如果兩個subpriority不同的interrupt event同時發生,則subpriority高的interrupt會先被處理,但是如果低優先等級的interrupt channel event 已經在執行,則不能被打斷,高subpriority的event必須等到現有的event被處理完才能被處理。

     
3. STM32中斷優先等級暫存器 (Interrupt Priority Registers)
  STM32每個Interrupt Channel都擁有屬於自己的interrupt priority register, STM32中每個priority register是4個bit(Cortex-M3中定義8-bits),這4-bits可以依據功能分成下面五組


NVIC_PriorityGroup_0 => 0 bits for pre-emption priority, 4 bits for subpriority  


NVIC_PriorityGroup_1 => 1 bits for pre-emption priority, 3 bits for subpriority  

NVIC_PriorityGroup_2 => 2 bits for pre-emption priority, 2 bits for subpriority  

NVIC_PriorityGroup_3 => 3 bits for pre-emption priority, 1 bits for subpriority  

NVIC_PriorityGroup_4 => 4 bits for pre-emption priority, 0 bits for subpriority  


pre-emption priority與subpriority共用這4bits暫存器位置,因此如果設定成NVIC_PriorityGroup_0,暫存器的值將會被辨識為subpriority必須注意到一件事情,那就是假使priority設定值超過了所選定Group中分配給他的位數,將會導致不可預期的錯誤。



下面用一個範例來說明:

NVIC_InitTypeDef NVIC_InitStructure;
// 定義Priority Group
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);

一開始先定義了Priority Group為NVIC_PriorityGroup_2,因此其中會有2bits是給preemption priority,2bits給subpriority使用因此不論是preemption priority或者subpriority的值範圍都在0~3(2bits可以表是的最大數值),另外假使一個interrupt channel的preempriton prirority與其他所有的interrupt channel都不一樣,則這個interrupt channel的subpriority可以設為任意值。